Merge pull request #4329 from aws-lumberyard-dev/carlitosan/development
Refactor and bug fix Version Explorer (which automatically versions/upgrades ScriptCanvas Editor files).
This commit is contained in:
@@ -110,13 +110,12 @@ namespace ScriptCanvasBuilder
|
||||
const ScriptCanvas::Translation::Result translationResult = TranslateToLua(request);
|
||||
|
||||
auto isSuccessOutcome = translationResult.IsSuccess(ScriptCanvas::Translation::TargetFlags::Lua);
|
||||
|
||||
if (!isSuccessOutcome.IsSuccess())
|
||||
{
|
||||
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<AZ::ScriptAsset> asset;
|
||||
scriptAssetId.m_subId = AZ::ScriptAsset::CompiledAssetSubId;
|
||||
asset.Create(scriptAssetId);
|
||||
@@ -481,6 +480,7 @@ namespace ScriptCanvasBuilder
|
||||
buildEntity->Activate();
|
||||
}
|
||||
|
||||
AZ_Assert(buildEntity->GetState() == AZ::Entity::State::Active, "build entity not active");
|
||||
return sourceGraph;
|
||||
}
|
||||
|
||||
|
||||
@@ -519,7 +519,7 @@ namespace ScriptCanvasEditor
|
||||
|
||||
if (validationResults.HasErrors())
|
||||
{
|
||||
AZ::Interface<IUpgradeRequests>::Get()->GraphNeedsManualUpgrade(sm->m_asset.GetId());
|
||||
sm->MarkError("Failed to Parse");
|
||||
|
||||
for (auto& err : validationResults.GetEvents())
|
||||
{
|
||||
@@ -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 = {};
|
||||
}
|
||||
@@ -735,7 +735,7 @@ namespace ScriptCanvasEditor
|
||||
{
|
||||
AZ::SystemTickBus::Handler::BusDisconnect();
|
||||
|
||||
OnComplete(exitStatus);
|
||||
OnComplete(m_error.empty() ? exitStatus : IState::ExitStatus::Skipped);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -215,21 +215,6 @@ namespace ScriptCanvasEditor
|
||||
|
||||
using EditorLoggingComponentNotificationBus = AZ::EBus<EditorLoggingComponentNotifications>;
|
||||
|
||||
class IUpgradeRequests
|
||||
{
|
||||
public:
|
||||
AZ_TYPE_INFO(IUpgradeRequests, "{D25318F2-4DDA-4E76-98CB-6D561BB6234D}");
|
||||
|
||||
using AssetList = AZStd::list<AZ::Data::AssetInfo>;
|
||||
virtual AssetList& GetAssetsToUpgrade() = 0;
|
||||
|
||||
virtual void ClearGraphsThatNeedUpgrade() = 0;
|
||||
virtual void GraphNeedsManualUpgrade(const AZ::Data::AssetId&) = 0;
|
||||
virtual const AZStd::vector<AZ::Data::AssetId>& GetGraphsThatNeedManualUpgrade() const = 0;
|
||||
virtual bool IsUpgrading() = 0;
|
||||
virtual void SetIsUpgrading(bool isUpgrading) = 0;
|
||||
};
|
||||
|
||||
class UpgradeNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
@@ -237,15 +222,11 @@ namespace ScriptCanvasEditor
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
|
||||
using Bus = AZ::EBus<UpgradeNotifications>;
|
||||
|
||||
virtual void OnUpgradeStart() {}
|
||||
virtual void OnUpgradeComplete() {}
|
||||
virtual void OnUpgradeCancelled() {}
|
||||
|
||||
virtual void OnGraphUpgradeComplete(AZ::Data::Asset<AZ::Data::AssetData>&, bool skipped = false) { (void)skipped; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
using UpgradeNotificationsBus = AZ::EBus<UpgradeNotifications>;
|
||||
}
|
||||
|
||||
@@ -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<IState> m_currentState = nullptr;
|
||||
AZStd::vector<AZStd::shared_ptr<IState>> 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
|
||||
|
||||
@@ -6,46 +6,35 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Jobs/JobFunction.h>
|
||||
#include <AzCore/EBus/Results.h>
|
||||
#include <AzCore/Jobs/JobFunction.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/Utils.h>
|
||||
#include <AzCore/std/string/wildcard.h>
|
||||
|
||||
#include <AzFramework/Entity/EntityContextBus.h>
|
||||
|
||||
#include <AzFramework/IO/FileOperations.h>
|
||||
#include <AzToolsFramework/API/ViewPaneOptions.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/GenericComboBoxCtrl.h>
|
||||
|
||||
#include <GraphCanvas/GraphCanvasBus.h>
|
||||
|
||||
#include <Editor/Framework/ScriptCanvasGraphUtilities.h>
|
||||
#include <Editor/Settings.h>
|
||||
#include <Editor/SystemComponent.h>
|
||||
|
||||
#include <Editor/View/Windows/MainWindow.h>
|
||||
#include <Editor/View/Dialogs/NewGraphDialog.h>
|
||||
#include <Editor/View/Dialogs/SettingsDialog.h>
|
||||
#include <Editor/Settings.h>
|
||||
|
||||
#include <Editor/View/Windows/MainWindow.h>
|
||||
#include <GraphCanvas/GraphCanvasBus.h>
|
||||
#include <LyViewPaneNames.h>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
|
||||
#include <ScriptCanvas/Components/EditorGraph.h>
|
||||
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
|
||||
#include <ScriptCanvas/Core/Datum.h>
|
||||
#include <ScriptCanvas/Data/DataRegistry.h>
|
||||
#include <ScriptCanvas/Libraries/Libraries.h>
|
||||
#include <ScriptCanvas/Variable/VariableCore.h>
|
||||
#include <ScriptCanvas/Components/EditorGraph.h>
|
||||
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
|
||||
|
||||
#include <LyViewPaneNames.h>
|
||||
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <ScriptCanvas/View/EditCtrls/GenericLineEditCtrl.h>
|
||||
#include <Editor/Framework/ScriptCanvasGraphUtilities.h>
|
||||
#include <AzToolsFramework/AssetBrowser/Entries/SourceAssetBrowserEntry.h>
|
||||
|
||||
#include <AzFramework/IO/FileOperations.h>
|
||||
#include <AzCore/Serialization/Utils.h>
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
@@ -54,6 +43,7 @@ namespace ScriptCanvasEditor
|
||||
SystemComponent::SystemComponent()
|
||||
{
|
||||
AzToolsFramework::AssetSeedManagerRequests::Bus::Handler::BusConnect();
|
||||
m_versionExplorer = AZStd::make_unique<VersionExplorer::Model>();
|
||||
}
|
||||
|
||||
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<ScriptCanvasAsset>())
|
||||
{
|
||||
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<ScriptCanvasAsset>())
|
||||
{
|
||||
m_assetsToConvert.push_back(assetInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AzToolsFramework::AssetSeedManagerRequests::AssetTypePairs SystemComponent::GetAssetTypeMapping()
|
||||
{
|
||||
return {
|
||||
|
||||
@@ -9,23 +9,20 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Core/GraphBus.h>
|
||||
#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
|
||||
#include <ScriptCanvas/Bus/ScriptCanvasExecutionBus.h>
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzCore/Jobs/JobContext.h>
|
||||
#include <AzCore/Jobs/JobManager.h>
|
||||
#include <AzCore/UserSettings/UserSettingsProvider.h>
|
||||
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/Asset/AssetSeedManager.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||
#include <AzToolsFramework/Editor/EditorContextMenuBus.h>
|
||||
#include <Core/GraphBus.h>
|
||||
#include <Editor/Assets/ScriptCanvasAssetTracker.h>
|
||||
|
||||
#include <AzToolsFramework/Asset/AssetSeedManager.h>
|
||||
|
||||
#include <AzCore/Jobs/JobManager.h>
|
||||
#include <AzCore/Jobs/JobContext.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/Model.h>
|
||||
#include <ScriptCanvas/Bus/ScriptCanvasBus.h>
|
||||
#include <ScriptCanvas/Bus/ScriptCanvasExecutionBus.h>
|
||||
|
||||
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<IUpgradeRequests>::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() override
|
||||
{
|
||||
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<AZ::Data::AssetId>& 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<AZ::JobManager> m_jobManager;
|
||||
AZStd::unique_ptr<AZ::JobContext> m_jobContext;
|
||||
AZStd::unique_ptr<VersionExplorer::Model> m_versionExplorer;
|
||||
|
||||
AZStd::unordered_set<ScriptCanvas::Data::Type> m_creatableTypes;
|
||||
|
||||
AssetTracker m_assetTracker;
|
||||
|
||||
IUpgradeRequests::AssetList m_assetsToConvert;
|
||||
AZStd::vector<AZ::Data::AssetId> m_assetsThatNeedManualUpgrade;
|
||||
|
||||
bool m_isUpgrading = false;
|
||||
bool m_upgradeDisabled = false;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -104,10 +104,6 @@ namespace ScriptCanvasEditor
|
||||
{
|
||||
DisconnectLambdas();
|
||||
}
|
||||
void OnUpgradeComplete() override
|
||||
{
|
||||
ConnectLambdas();
|
||||
}
|
||||
|
||||
// Asset Node Support
|
||||
void OnRowsInserted(const QModelIndex& parentIndex, int first, int last);
|
||||
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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:
|
||||
@@ -92,7 +92,6 @@ namespace ScriptCanvasEditor
|
||||
|
||||
// UpgradeNotifications::Bus
|
||||
void OnUpgradeStart() override;
|
||||
void OnUpgradeComplete() override;
|
||||
void OnUpgradeCancelled() override;
|
||||
////
|
||||
|
||||
|
||||
@@ -135,7 +135,6 @@
|
||||
#include <Editor/View/Widgets/NodePalette/CreateNodeMimeEvent.h>
|
||||
#include <Editor/View/Widgets/NodePalette/EBusNodePaletteTreeItemTypes.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.h>
|
||||
|
||||
#include <Editor/View/Widgets/VariablePanel/SlotTypeSelectorWidget.h>
|
||||
|
||||
@@ -705,80 +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<IUpgradeRequests>::Get()->GetGraphsThatNeedManualUpgrade().size();
|
||||
QString message = QObject::tr("%1 Graph(s) upgraded<br>%2 graph(s) did not require upgrade").arg(upgradeTool->UpgradedGraphCount()).arg(upgradeTool->SkippedGraphCount());
|
||||
if (assetsThatNeedManualInspection > 0)
|
||||
{
|
||||
message.append(QObject::tr("<br>%1 graph(s) that need manual corrections. You will be prompted to review them after you close this dialog.<br>").arg(assetsThatNeedManualInspection));
|
||||
}
|
||||
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
|
||||
AZ::IO::Path outputFileName;
|
||||
settingsRegistry->Get(outputFileName.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectLogPath);
|
||||
outputFileName /= "ScriptCanvasUpgradeReport.html";
|
||||
// Report
|
||||
AZStd::string urlToReport = AZStd::string::format("For more information see the <a href=\"%s\">Upgrade Report</a>.", outputFileName.c_str());
|
||||
message.append(QObject::tr("<br>%1").arg(urlToReport.c_str()));
|
||||
|
||||
// Backup
|
||||
if (upgradeTool->HasBackup())
|
||||
{
|
||||
AZ::IO::Path outputFileName2;
|
||||
settingsRegistry->Get(outputFileName2.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectUserPath);
|
||||
outputFileName2 /= "ScriptCanvas_BACKUP";
|
||||
|
||||
AZStd::string backupPath = AZStd::string::format("<br>Open the <a href=\"%s\">Backup Folder</a>.", outputFileName.c_str());
|
||||
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()
|
||||
@@ -3510,18 +3436,20 @@ namespace ScriptCanvasEditor
|
||||
|
||||
void MainWindow::RunUpgradeTool()
|
||||
{
|
||||
VersionExplorer* versionExplorer = aznew VersionExplorer(this);
|
||||
using namespace VersionExplorer;
|
||||
auto versionExplorer = aznew VersionExplorer::Controller(this);
|
||||
versionExplorer->exec();
|
||||
|
||||
// Manual correction
|
||||
size_t assetsThatNeedManualInspection = AZ::Interface<IUpgradeRequests>::Get()->GetGraphsThatNeedManualUpgrade().size();
|
||||
|
||||
// If there are graphs that need manual correction, show the helper
|
||||
if (assetsThatNeedManualInspection > 0)
|
||||
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;
|
||||
}
|
||||
|
||||
void MainWindow::OnShowValidationErrors()
|
||||
|
||||
@@ -51,8 +51,7 @@
|
||||
|
||||
#include <Editor/View/Widgets/AssetGraphSceneDataBus.h>
|
||||
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/Controller.h>
|
||||
|
||||
#if SCRIPTCANVAS_EDITOR
|
||||
#include <Include/EditorCoreAPI.h>
|
||||
@@ -99,30 +98,25 @@ 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
|
||||
{
|
||||
AzToolsFramework::AssetBrowser::AssetBrowserComponentNotificationBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void OnUpgradeComplete() override
|
||||
{
|
||||
AzToolsFramework::AssetBrowser::AssetBrowserComponentNotificationBus::Handler::BusConnect();
|
||||
}
|
||||
};
|
||||
|
||||
class OnSaveToast
|
||||
@@ -806,7 +800,5 @@ namespace ScriptCanvasEditor
|
||||
Workspace* m_workspace;
|
||||
|
||||
void OnSaveCallback(bool saveSuccess, AZ::Data::AssetPtr, AZ::Data::AssetId previousFileAssetId);
|
||||
|
||||
void PromptForUpgrade();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,629 @@
|
||||
/*
|
||||
* 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 <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QMessageBox>
|
||||
#include <QProcess>
|
||||
#include <QScrollBar>
|
||||
#include <QToolButton>
|
||||
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzCore/IO/FileIOEventBus.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/UserSettings/UserSettingsProvider.h>
|
||||
#include <AzFramework/Asset/AssetSystemBus.h>
|
||||
#include <AzFramework/IO/FileOperations.h>
|
||||
#include <AzQtComponents/Components/Widgets/CheckBox.h>
|
||||
#include <AzQtComponents/Utilities/DesktopUtilities.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
|
||||
#include <Editor/Settings.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/Controller.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/LogTraits.h>
|
||||
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
|
||||
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
|
||||
#include <ScriptCanvas/Components/EditorGraph.h>
|
||||
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/ui_View.h>
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
namespace VersionExplorer
|
||||
{
|
||||
Controller::Controller(QWidget* parent)
|
||||
: AzQtComponents::StyledDialog(parent)
|
||||
, m_view(new Ui::View())
|
||||
{
|
||||
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::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);
|
||||
|
||||
UpgradeNotificationsBus::Handler::BusConnect();
|
||||
ModelNotificationsBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
Controller::~Controller()
|
||||
{
|
||||
delete m_view;
|
||||
}
|
||||
|
||||
void Controller::AddLogEntries()
|
||||
{
|
||||
const AZStd::vector<AZStd::string>* 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)
|
||||
{
|
||||
textCursor.insertText("\n");
|
||||
textCursor.insertText(entry.c_str());
|
||||
}
|
||||
|
||||
scrollBar->setValue(scrollBar->maximum());
|
||||
m_view->textEdit->moveCursor(QTextCursor::StartOfLine);
|
||||
LogBus::Broadcast(&LogTraits::Clear);
|
||||
}
|
||||
|
||||
void Controller::EnableAllUpgradeButtons()
|
||||
{
|
||||
for (int row = 0; row < m_view->tableWidget->rowCount(); ++row)
|
||||
{
|
||||
if (QPushButton* button = qobject_cast<QPushButton*>(m_view->tableWidget->cellWidget(row, ColumnAction)))
|
||||
{
|
||||
button->setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList<QTableWidgetItem*> Controller::FindTableItems(const AZ::Data::AssetInfo& info)
|
||||
{
|
||||
return m_view->tableWidget->findItems(info.m_relativePath.c_str(), Qt::MatchFlag::MatchExactly);
|
||||
}
|
||||
|
||||
void Controller::OnButtonPressClose()
|
||||
{
|
||||
reject();
|
||||
}
|
||||
|
||||
void Controller::OnButtonPressScan()
|
||||
{
|
||||
// \todo move to another file
|
||||
auto isUpToDate = [this](AZ::Data::Asset<AZ::Data::AssetData> asset)
|
||||
{
|
||||
AZ::Entity* scriptCanvasEntity = nullptr;
|
||||
|
||||
if (asset.GetType() == azrtti_typeid<ScriptCanvasAsset>())
|
||||
{
|
||||
ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs<ScriptCanvasAsset>();
|
||||
if (!scriptCanvasAsset)
|
||||
{
|
||||
AZ_Warning
|
||||
(ScriptCanvas::k_VersionExplorerWindow.data()
|
||||
, false
|
||||
, "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");
|
||||
}
|
||||
|
||||
auto graphComponent = scriptCanvasEntity->FindComponent<ScriptCanvasEditor::Graph>();
|
||||
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;
|
||||
|
||||
SetLoggingPreferences();
|
||||
ModelRequestsBus::Broadcast(&ModelRequestsTraits::Scan, config);
|
||||
}
|
||||
|
||||
void Controller::OnButtonPressUpgrade()
|
||||
{
|
||||
OnButtonPressUpgradeImplementation({});
|
||||
}
|
||||
|
||||
void Controller::OnButtonPressUpgradeImplementation(const AZ::Data::AssetInfo& assetInfo)
|
||||
{
|
||||
auto simpleUpdate = [this](AZ::Data::Asset<AZ::Data::AssetData> asset)
|
||||
{
|
||||
if (asset.GetType() == azrtti_typeid<ScriptCanvasAsset>())
|
||||
{
|
||||
ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs<ScriptCanvasAsset>();
|
||||
AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s"
|
||||
, azrtti_typeid<ScriptCanvasAsset>().template ToString<AZStd::string>().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<ScriptCanvasEditor::Graph>();
|
||||
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;
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
for (auto* item : FindTableItems(info))
|
||||
{
|
||||
int row = item->row();
|
||||
SetRowBusy(row);
|
||||
m_view->tableWidget->setCellWidget(row, ColumnAction, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
for (auto* item : FindTableItems(info))
|
||||
{
|
||||
int row = item->row();
|
||||
|
||||
if (result.errorMessage.empty())
|
||||
{
|
||||
SetRowSucceeded(row);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetRowFailed(row, "");
|
||||
|
||||
if (QPushButton* button = qobject_cast<QPushButton*>(m_view->tableWidget->cellWidget(row, ColumnAction)))
|
||||
{
|
||||
button->setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_view->progressBar->setVisible(true);
|
||||
++m_handledAssetCount;
|
||||
m_view->progressBar->setValue(m_handledAssetCount);
|
||||
AddLogEntries();
|
||||
}
|
||||
|
||||
void Controller::OnGraphUpgradeComplete(AZ::Data::Asset<AZ::Data::AssetData>& 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;
|
||||
m_view->tableWidget->setRowCount(0);
|
||||
m_view->progressBar->setVisible(true);
|
||||
m_view->progressBar->setRange(0, aznumeric_cast<int>(assetCount));
|
||||
m_view->progressBar->setValue(0);
|
||||
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)
|
||||
{
|
||||
m_view->onlyShowOutdated->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()
|
||||
, result.m_loadErrors.size()
|
||||
, result.m_unfiltered.size()
|
||||
, result.m_filteredAssets.size()));
|
||||
|
||||
m_view->spinner->SetText(spinnerText);
|
||||
SetSpinnerIsBusy(false);
|
||||
m_view->progressBar->setVisible(false);
|
||||
EnableAllUpgradeButtons();
|
||||
|
||||
if (!result.m_unfiltered.empty())
|
||||
{
|
||||
m_view->upgradeAllButton->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::OnScanFilteredGraph(const AZ::Data::AssetInfo& info)
|
||||
{
|
||||
OnScannedGraph(info, Filtered::Yes);
|
||||
}
|
||||
|
||||
void Controller::OnScannedGraph(const AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] Filtered filtered)
|
||||
{
|
||||
const int rowIndex = m_view->tableWidget->rowCount();
|
||||
|
||||
if (filtered == Filtered::No || !m_view->onlyShowOutdated->isChecked())
|
||||
{
|
||||
m_view->tableWidget->insertRow(rowIndex);
|
||||
QTableWidgetItem* rowName = new QTableWidgetItem(tr(assetInfo.m_relativePath.c_str()));
|
||||
m_view->tableWidget->setItem(rowIndex, static_cast<int>(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(rowIndex, static_cast<int>(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<int>(ColumnBrowse), browseButton);
|
||||
}
|
||||
|
||||
OnScannedGraphResult(assetInfo);
|
||||
}
|
||||
|
||||
void Controller::OnScannedGraphResult([[maybe_unused]] const AZ::Data::AssetInfo& info)
|
||||
{
|
||||
m_view->progressBar->setValue(aznumeric_cast<int>(m_handledAssetCount));
|
||||
++m_handledAssetCount;
|
||||
AddLogEntries();
|
||||
}
|
||||
|
||||
void Controller::OnScanLoadFailure(const AZ::Data::AssetInfo& info)
|
||||
{
|
||||
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(rowIndex, static_cast<int>(ColumnAsset), rowName);
|
||||
SetRowFailed(rowIndex, "Load failed");
|
||||
OnScannedGraphResult(info);
|
||||
}
|
||||
|
||||
void Controller::OnScanUnFilteredGraph(const AZ::Data::AssetInfo& info)
|
||||
{
|
||||
OnScannedGraph(info, Filtered::No);
|
||||
}
|
||||
|
||||
void Controller::OnUpgradeBegin
|
||||
( const ModifyConfiguration& config
|
||||
, [[maybe_unused]] const WorkingAssets& assets)
|
||||
{
|
||||
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<QPushButton*>(m_view->tableWidget->cellWidget(row, ColumnAction)))
|
||||
{
|
||||
button->setEnabled(false);
|
||||
}
|
||||
|
||||
SetRowBusy(row);
|
||||
}
|
||||
|
||||
spinnerText.append(" all scanned graphs");
|
||||
}
|
||||
|
||||
m_view->spinner->SetText(spinnerText);
|
||||
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);
|
||||
m_view->spinner->SetBusyIconSize(16);
|
||||
}
|
||||
|
||||
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);
|
||||
AddLogEntries();
|
||||
EnableAllUpgradeButtons();
|
||||
m_view->scanButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void Controller::OnUpgradeDependenciesGathered(const AZ::Data::AssetInfo& info, Result result)
|
||||
{
|
||||
for (auto* item : FindTableItems(info))
|
||||
{
|
||||
int row = item->row();
|
||||
|
||||
if (result == Result::Success)
|
||||
{
|
||||
SetRowSucceeded(row);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetRowFailed(row, "");
|
||||
}
|
||||
|
||||
if (QPushButton* button = qobject_cast<QPushButton*>(m_view->tableWidget->cellWidget(row, ColumnAction)))
|
||||
{
|
||||
button->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
m_view->progressBar->setVisible(true);
|
||||
++m_handledAssetCount;
|
||||
m_view->progressBar->setValue(m_handledAssetCount);
|
||||
AddLogEntries();
|
||||
}
|
||||
|
||||
void Controller::OnUpgradeDependencySortBegin
|
||||
( [[maybe_unused]] const ModifyConfiguration& config
|
||||
, const WorkingAssets& 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<QPushButton*>(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::OnUpgradeDependencySortEnd
|
||||
( [[maybe_unused]] const ModifyConfiguration& config
|
||||
, const WorkingAssets& assets
|
||||
, [[maybe_unused]] const AZStd::vector<size_t>& sortedOrder)
|
||||
{
|
||||
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<QPushButton*>(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);
|
||||
AddLogEntries();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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 <AzCore/Component/EntityId.h>
|
||||
#include <AzCore/PlatformDef.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzQtComponents/Components/StyledDialog.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h>
|
||||
#include <ISystem.h>
|
||||
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
|
||||
#include <ScriptCanvas/Core/Core.h>
|
||||
AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option")
|
||||
#include <QProgressBar>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
#endif
|
||||
|
||||
class QPushButton;
|
||||
class QTableWidgetItem;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class View;
|
||||
}
|
||||
|
||||
namespace AzQtComponents
|
||||
{
|
||||
class StyledBusyLabel;
|
||||
}
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
namespace VersionExplorer
|
||||
{
|
||||
//! 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 UpgradeNotificationsBus::Handler
|
||||
, private ModelNotificationsBus::Handler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Controller, AZ::SystemAllocator, 0);
|
||||
|
||||
explicit Controller(QWidget* parent = nullptr);
|
||||
~Controller();
|
||||
|
||||
private:
|
||||
static constexpr int ColumnAsset = 0;
|
||||
static constexpr int ColumnAction = 1;
|
||||
static constexpr int ColumnBrowse = 2;
|
||||
static constexpr int ColumnStatus = 3;
|
||||
|
||||
Ui::View* m_view = nullptr;
|
||||
int m_handledAssetCount = 0;
|
||||
|
||||
void AddLogEntries();
|
||||
void EnableAllUpgradeButtons();
|
||||
QList<QTableWidgetItem*> FindTableItems(const AZ::Data::AssetInfo& assetInfo);
|
||||
|
||||
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<AZ::Data::AssetData>&, bool skipped) override;
|
||||
|
||||
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 class Filtered { No, Yes };
|
||||
void OnScannedGraph(const AZ::Data::AssetInfo& info, Filtered filtered);
|
||||
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 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 WorkingAssets& assets) override;
|
||||
void OnUpgradeDependencySortEnd
|
||||
( const ModifyConfiguration& config
|
||||
, const WorkingAssets& assets
|
||||
, const AZStd::vector<size_t>& 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 SetLoggingPreferences();
|
||||
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);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* 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 <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzCore/IO/FileIOEventBus.h>
|
||||
#include <AzFramework/Asset/AssetSystemBus.h>
|
||||
#include <AzFramework/IO/FileOperations.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/FileSaver.h>
|
||||
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
|
||||
|
||||
namespace FileSaverCpp
|
||||
{
|
||||
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
|
||||
{
|
||||
namespace VersionExplorer
|
||||
{
|
||||
FileSaver::FileSaver
|
||||
( AZStd::function<bool()> onReadOnlyFile
|
||||
, AZStd::function<void(const FileSaveResult& result)> 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<AZ::IO::IStreamer>::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<AZ::IO::IStreamer>::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<AZ::IO::IStreamer>::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<AZ::Data::AssetData> 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::ScriptCanvasAsset>())
|
||||
{
|
||||
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<AZ::Data::AssetData> 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<AZ::IO::IStreamer>::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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 <ScriptCanvas/Core/Core.h>
|
||||
|
||||
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<bool()> onReadOnlyFile
|
||||
, AZStd::function<void(const FileSaveResult& result)> onComplete);
|
||||
|
||||
void Save(AZ::Data::Asset<AZ::Data::AssetData> asset);
|
||||
|
||||
private:
|
||||
AZStd::function<void(const FileSaveResult& result)> m_onComplete;
|
||||
AZStd::function<bool()> m_onReadOnlyFile;
|
||||
|
||||
void OnSourceFileReleased(AZ::Data::Asset<AZ::Data::AssetData> asset);
|
||||
|
||||
void PerformMove
|
||||
( AZStd::string source
|
||||
, AZStd::string target
|
||||
, size_t remainingAttempts);
|
||||
|
||||
AZStd::string RemoveTempFile(AZStd::string_view tempFile);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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 <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
#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<AZStd::string>* GetEntries() const = 0;
|
||||
virtual void SetVersionExporerExclusivity(bool enabled) = 0;
|
||||
virtual void SetVerbose(bool verbosity) = 0;
|
||||
};
|
||||
using LogBus = AZ::EBus<LogTraits>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 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 <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <CryCommon/CrySystemBus.h>
|
||||
#include <Editor/Assets/ScriptCanvasAssetHelpers.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/Model.h>
|
||||
#include <IConsole.h>
|
||||
#include <ISystem.h>
|
||||
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
|
||||
|
||||
namespace ModifierCpp
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
void Model::CacheSettings()
|
||||
{
|
||||
m_settingsCache = AZStd::make_unique<ScriptCanvas::Grammar::SettingsCache>();
|
||||
ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false;
|
||||
ScriptCanvas::Grammar::g_printAbstractCodeModel = false;
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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()
|
||||
, [&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;
|
||||
}
|
||||
|
||||
|
||||
m_state = State::ModifySingle;
|
||||
m_modifier = AZStd::make_unique<Modifier>(modification, WorkingAssets{ *iter }, [this]() { OnModificationComplete(); });
|
||||
}
|
||||
else
|
||||
{
|
||||
auto results = m_scanner->TakeResult();
|
||||
m_state = State::ModifyAll;
|
||||
m_modifier = AZStd::make_unique<Modifier>(modification, AZStd::move(results.m_unfiltered), [this]() { OnModificationComplete(); });
|
||||
}
|
||||
|
||||
m_modResults = {};
|
||||
m_log.Activate();
|
||||
m_keepEditorAlive = AZStd::make_unique<EditorKeepAlive>();
|
||||
}
|
||||
|
||||
void Model::OnModificationComplete()
|
||||
{
|
||||
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeComplete, m_modifier->GetResult());
|
||||
m_modifier.reset();
|
||||
|
||||
if (m_state == State::ModifyAll)
|
||||
{
|
||||
m_scanner.reset();
|
||||
}
|
||||
|
||||
Idle();
|
||||
}
|
||||
|
||||
void Model::OnScanComplete()
|
||||
{
|
||||
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnScanComplete, m_scanner->GetResult());
|
||||
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_log.Activate();
|
||||
m_keepEditorAlive = AZStd::make_unique<EditorKeepAlive>();
|
||||
m_scanner = AZStd::make_unique<Scanner>(config, [this](){ OnScanComplete(); });
|
||||
}
|
||||
|
||||
void Model::RestoreSettings()
|
||||
{
|
||||
m_settingsCache.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 <AzFramework/Asset/AssetCatalogBus.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/Modifier.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/Scanner.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h>
|
||||
#include <ScriptCanvas/Core/Core.h>
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Model, AZ::SystemAllocator, 0);
|
||||
|
||||
Model();
|
||||
|
||||
const ModificationResults* GetResults() override;
|
||||
|
||||
void Modify(const ModifyConfiguration& modification) override;
|
||||
|
||||
void Scan(const ScanConfiguration& config) override;
|
||||
|
||||
private:
|
||||
enum class State
|
||||
{
|
||||
Idle,
|
||||
Scanning,
|
||||
ModifyAll,
|
||||
ModifySingle
|
||||
};
|
||||
|
||||
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<Modifier> m_modifier;
|
||||
AZStd::unique_ptr<Scanner> m_scanner;
|
||||
AZStd::unique_ptr<ScriptCanvas::Grammar::SettingsCache> m_settingsCache;
|
||||
AZStd::unique_ptr<EditorKeepAlive> m_keepEditorAlive;
|
||||
|
||||
ModificationResults m_modResults;
|
||||
|
||||
void CacheSettings();
|
||||
void Idle();
|
||||
bool IsReadyToModify() const;
|
||||
bool IsWorking() const;
|
||||
void OnModificationComplete();
|
||||
void OnScanComplete();
|
||||
void RestoreSettings();
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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 <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
namespace VersionExplorer
|
||||
{
|
||||
struct WorkingAsset
|
||||
{
|
||||
AZ::Data::Asset<AZ::Data::AssetData> asset;
|
||||
AZ::Data::AssetInfo info;
|
||||
};
|
||||
|
||||
using WorkingAssets = AZStd::vector<WorkingAsset>;
|
||||
|
||||
struct ModifyConfiguration
|
||||
{
|
||||
AZStd::function<void(AZ::Data::Asset<AZ::Data::AssetData>)> modification;
|
||||
AZStd::function<bool()> onReadOnlyFile;
|
||||
AZ::Data::AssetInfo modifySingleAsset;
|
||||
bool backupGraphBeforeModification = false;
|
||||
bool successfulDependencyUpgradeRequired = true;
|
||||
};
|
||||
|
||||
struct ModificationResult
|
||||
{
|
||||
AZ::Data::Asset<AZ::Data::AssetData> asset;
|
||||
AZ::Data::AssetInfo assetInfo;
|
||||
AZStd::string errorMessage;
|
||||
};
|
||||
|
||||
struct ModificationResults
|
||||
{
|
||||
AZStd::vector<AZ::Data::AssetInfo> m_successes;
|
||||
AZStd::vector<ModificationResult> m_failures;
|
||||
};
|
||||
|
||||
struct ScanConfiguration
|
||||
{
|
||||
AZStd::function<bool(AZ::Data::Asset<AZ::Data::AssetData>)> filter;
|
||||
bool reportFilteredGraphs = false;
|
||||
};
|
||||
|
||||
struct ScanResult
|
||||
{
|
||||
AZStd::vector<AZ::Data::AssetInfo> m_catalogAssets;
|
||||
WorkingAssets m_unfiltered;
|
||||
AZStd::vector<AZ::Data::AssetInfo> m_filteredAssets;
|
||||
AZStd::vector<AZ::Data::AssetInfo> m_loadErrors;
|
||||
};
|
||||
|
||||
enum Result
|
||||
{
|
||||
Failure,
|
||||
Success
|
||||
};
|
||||
|
||||
class ModificationNotificationsTraits
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
virtual void ModificationComplete(const ModificationResult& result) = 0;
|
||||
};
|
||||
using ModificationNotificationsBus = AZ::EBus<ModificationNotificationsTraits>;
|
||||
|
||||
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<ModelRequestsTraits>;
|
||||
|
||||
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;
|
||||
|
||||
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 WorkingAssets& assets) = 0;
|
||||
virtual void OnUpgradeDependencySortEnd
|
||||
( const ModifyConfiguration& config
|
||||
, const WorkingAssets& assets
|
||||
, const AZStd::vector<size_t>& 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<ModelNotificationsTraits>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
* 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 <Editor/View/Windows/Tools/UpgradeTool/LogTraits.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/Modifier.h>
|
||||
#include <ScriptCanvas/Asset/RuntimeAsset.h>
|
||||
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
|
||||
#include <ScriptCanvas/Core/Graph.h>
|
||||
|
||||
namespace ModifierCpp
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
namespace VersionExplorer
|
||||
{
|
||||
Modifier::Modifier
|
||||
( const ModifyConfiguration& modification
|
||||
, WorkingAssets&& assets
|
||||
, AZStd::function<void()> onComplete)
|
||||
: m_state(State::GatheringDependencies)
|
||||
, m_config(modification)
|
||||
, 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();
|
||||
}
|
||||
|
||||
const AZ::Data::AssetInfo& Modifier::GetCurrentAsset() const
|
||||
{
|
||||
return m_state == State::GatheringDependencies
|
||||
? m_assets[m_assetIndex].info
|
||||
: m_assets[m_dependencyOrderedAssetIndicies[m_assetIndex]].info;
|
||||
}
|
||||
|
||||
AZStd::unordered_set<size_t>& 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<size_t>()).first;
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
const ModificationResults& Modifier::GetResult() const
|
||||
{
|
||||
return m_results;
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
bool anyFailures = false;
|
||||
auto asset = LoadAsset();
|
||||
|
||||
if (asset
|
||||
&& asset.GetAs<ScriptCanvasAsset>()
|
||||
&& asset.GetAs<ScriptCanvasAsset>()->GetScriptCanvasGraph()
|
||||
&& asset.GetAs<ScriptCanvasAsset>()->GetScriptCanvasGraph()->GetGraphData())
|
||||
{
|
||||
auto graphData = asset.GetAs<ScriptCanvasAsset>()->GetScriptCanvasGraph()->GetGraphData();
|
||||
|
||||
auto dependencyGrabber = [this]
|
||||
( void* instancePointer
|
||||
, const AZ::SerializeContext::ClassData* classData
|
||||
, [[maybe_unused]] const AZ::SerializeContext::ClassElement* classElement)
|
||||
{
|
||||
if (auto azTypeId = classData->m_azRtti->GetTypeId();
|
||||
azTypeId == azrtti_typeid<AZ::Data::Asset<ScriptCanvas::SubgraphInterfaceAsset>>())
|
||||
{
|
||||
const auto* subgraphAsset =
|
||||
reinterpret_cast<AZ::Data::Asset<const ScriptCanvas::SubgraphInterfaceAsset>*>(instancePointer);
|
||||
if (subgraphAsset->GetId().IsValid())
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
if (!serializeContext->EnumerateInstanceConst
|
||||
( graphData
|
||||
, azrtti_typeid<ScriptCanvas::GraphData>()
|
||||
, 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();
|
||||
}
|
||||
|
||||
AZ::Data::Asset<AZ::Data::AssetData> Modifier::LoadAsset()
|
||||
{
|
||||
AZ::Data::Asset<AZ::Data::AssetData> asset = AZ::Data::AssetManager::Instance().GetAsset
|
||||
( GetCurrentAsset().m_assetId
|
||||
, azrtti_typeid<ScriptCanvasAsset>()
|
||||
, AZ::Data::AssetLoadBehavior::PreLoad);
|
||||
|
||||
asset.BlockUntilLoadComplete();
|
||||
|
||||
if (asset.IsReady())
|
||||
{
|
||||
return asset;
|
||||
}
|
||||
else
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
ModificationNotificationsBus::Handler::BusDisconnect();
|
||||
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::ReportSaveResult()
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> 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())
|
||||
{
|
||||
VE_LOG
|
||||
( "Temporary file not removed for %s: %s"
|
||||
, m_result.assetInfo.m_relativePath.c_str()
|
||||
, result.tempFileRemovalError.c_str());
|
||||
}
|
||||
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
|
||||
m_modifyState = ModifyState::ReportResult;
|
||||
m_fileSaver.reset();
|
||||
m_fileSaveResult = result;
|
||||
}
|
||||
|
||||
void Modifier::OnSystemTick()
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case State::GatheringDependencies:
|
||||
TickGatherDependencies();
|
||||
break;
|
||||
|
||||
case State::ModifyingGraphs:
|
||||
TickUpdateGraph();
|
||||
break;
|
||||
}
|
||||
|
||||
AZ::Data::AssetManager::Instance().DispatchEvents();
|
||||
AZ::SystemTickBus::ExecuteQueuedEvents();
|
||||
}
|
||||
|
||||
void Modifier::SaveModifiedGraph(const ModificationResult& result)
|
||||
{
|
||||
m_modifyState = ModifyState::Saving;
|
||||
m_fileSaver = AZStd::make_unique<FileSaver>
|
||||
( m_config.onReadOnlyFile
|
||||
, [this](const FileSaveResult& result) { OnFileSaveComplete(result); });
|
||||
m_fileSaver->Save(result.asset);
|
||||
}
|
||||
|
||||
void Modifier::SortGraphsByDependencies()
|
||||
{
|
||||
m_dependencyOrderedAssetIndicies.reserve(m_assets.size());
|
||||
Sorter sorter;
|
||||
sorter.modifier = this;
|
||||
sorter.Sort();
|
||||
}
|
||||
|
||||
ModificationResults&& Modifier::TakeResult()
|
||||
{
|
||||
return AZStd::move(m_results);
|
||||
}
|
||||
|
||||
void Modifier::TickGatherDependencies()
|
||||
{
|
||||
if (m_assetIndex == 0)
|
||||
{
|
||||
if (m_config.successfulDependencyUpgradeRequired)
|
||||
{
|
||||
ModelNotificationsBus::Broadcast(&ModelNotificationsTraits::OnUpgradeDependencySortBegin, m_config, m_assets);
|
||||
m_assetInfoIndexById.reserve(m_assets.size());
|
||||
|
||||
for (size_t index = 0; index != m_assets.size(); ++index)
|
||||
{
|
||||
m_assetInfoIndexById.insert({ m_assets[index].info.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);
|
||||
}
|
||||
|
||||
// go straight into ModifyinGraphs
|
||||
m_assetIndex = m_assets.size();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_assetIndex == m_assets.size())
|
||||
{
|
||||
if (m_config.successfulDependencyUpgradeRequired)
|
||||
{
|
||||
SortGraphsByDependencies();
|
||||
ModelNotificationsBus::Broadcast
|
||||
( &ModelNotificationsTraits::OnUpgradeDependencySortEnd
|
||||
, m_config
|
||||
, m_assets
|
||||
, m_dependencyOrderedAssetIndicies);
|
||||
}
|
||||
|
||||
m_assetIndex = 0;
|
||||
m_state = State::ModifyingGraphs;
|
||||
}
|
||||
else
|
||||
{
|
||||
GatherDependencies();
|
||||
++m_assetIndex;
|
||||
}
|
||||
}
|
||||
|
||||
void Modifier::TickUpdateGraph()
|
||||
{
|
||||
if (m_assetIndex == m_assets.size())
|
||||
{
|
||||
VE_LOG("Modifier: Complete.");
|
||||
AZ::SystemTickBus::Handler::BusDisconnect();
|
||||
|
||||
if (m_onComplete)
|
||||
{
|
||||
m_onComplete();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
|
||||
|
||||
switch (m_modifyState)
|
||||
{
|
||||
case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::Idle:
|
||||
ModifyCurrentAsset();
|
||||
break;
|
||||
case ScriptCanvasEditor::VersionExplorer::Modifier::ModifyState::ReportResult:
|
||||
ReportSaveResult();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const AZStd::unordered_set<size_t>* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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 <AzCore/Component/TickBus.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/FileSaver.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h>
|
||||
#include <ScriptCanvas/Core/Core.h>
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
namespace VersionExplorer
|
||||
{
|
||||
class Modifier
|
||||
: private AZ::SystemTickBus::Handler
|
||||
, private ModificationNotificationsBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Modifier, AZ::SystemAllocator, 0);
|
||||
|
||||
Modifier
|
||||
( const ModifyConfiguration& modification
|
||||
, WorkingAssets&& assets
|
||||
, AZStd::function<void()> onComplete);
|
||||
|
||||
const ModificationResults& GetResult() const;
|
||||
ModificationResults&& TakeResult();
|
||||
|
||||
private:
|
||||
friend class Sorter;
|
||||
|
||||
struct Sorter
|
||||
{
|
||||
Modifier* modifier;
|
||||
AZStd::unordered_set<size_t> markedPermanent;
|
||||
AZStd::unordered_set<size_t> markedTemporary;
|
||||
void Sort();
|
||||
|
||||
private:
|
||||
void Visit(size_t index);
|
||||
const AZStd::unordered_set<size_t>* GetDependencies(size_t index) const;
|
||||
};
|
||||
|
||||
enum class State
|
||||
{
|
||||
GatheringDependencies,
|
||||
ModifyingGraphs
|
||||
};
|
||||
|
||||
enum class ModifyState
|
||||
{
|
||||
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;
|
||||
size_t m_assetIndex = 0;
|
||||
AZStd::function<void()> m_onComplete;
|
||||
// asset infos in scanned order
|
||||
WorkingAssets m_assets;
|
||||
// dependency sorted order indices into the asset vector
|
||||
AZStd::vector<size_t> m_dependencyOrderedAssetIndicies;
|
||||
// dependency indices by asset info index (only exist if graphs have them)
|
||||
AZStd::unordered_map<size_t, AZStd::unordered_set<size_t>> m_dependencies;
|
||||
AZStd::unordered_map<AZ::Uuid, size_t> m_assetInfoIndexById;
|
||||
AZStd::vector<size_t> m_failures;
|
||||
ModifyConfiguration m_config;
|
||||
ModificationResult m_result;
|
||||
ModificationResults m_results;
|
||||
AZStd::unique_ptr<FileSaver> m_fileSaver;
|
||||
FileSaveResult m_fileSaveResult;
|
||||
|
||||
void GatherDependencies();
|
||||
const AZ::Data::AssetInfo& GetCurrentAsset() const;
|
||||
AZStd::unordered_set<size_t>& GetOrCreateDependencyIndexSet();
|
||||
AZ::Data::Asset<AZ::Data::AssetData> LoadAsset();
|
||||
void ModifyCurrentAsset();
|
||||
void ModifyNextAsset();
|
||||
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);
|
||||
void OnSystemTick() override;
|
||||
void TickGatherDependencies();
|
||||
void TickUpdateGraph();
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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 <Editor/View/Windows/Tools/UpgradeTool/Scanner.h>
|
||||
#include <ScriptCanvas/Assets/ScriptCanvasAsset.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/LogTraits.h>
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
namespace VersionExplorer
|
||||
{
|
||||
Scanner::Scanner(const ScanConfiguration& config, AZStd::function<void()> 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<ScriptCanvasAsset>())
|
||||
{
|
||||
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<AZ::Data::AssetData> asset)
|
||||
{
|
||||
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({ asset, 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<AZ::Data::AssetData> Scanner::LoadAsset()
|
||||
{
|
||||
AZ::Data::Asset<AZ::Data::AssetData> asset = AZ::Data::AssetManager::Instance().GetAsset
|
||||
( GetCurrentAsset().m_assetId
|
||||
, azrtti_typeid<ScriptCanvasAsset>()
|
||||
, AZ::Data::AssetLoadBehavior::PreLoad);
|
||||
|
||||
asset.BlockUntilLoadComplete();
|
||||
|
||||
if (asset.IsReady())
|
||||
{
|
||||
return asset;
|
||||
}
|
||||
else
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void Scanner::OnSystemTick()
|
||||
{
|
||||
if (m_catalogAssetIndex == m_result.m_catalogAssets.size())
|
||||
{
|
||||
VE_LOG("Scanner: Complete.");
|
||||
AZ::SystemTickBus::Handler::BusDisconnect();
|
||||
|
||||
if (m_onComplete)
|
||||
{
|
||||
m_onComplete();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
ScanResult&& Scanner::TakeResult()
|
||||
{
|
||||
return AZStd::move(m_result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 <ScriptCanvas/Core/Core.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h>
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
namespace VersionExplorer
|
||||
{
|
||||
class Scanner
|
||||
: private AZ::SystemTickBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Scanner, AZ::SystemAllocator, 0);
|
||||
|
||||
Scanner(const ScanConfiguration& config, AZStd::function<void()> onComplete);
|
||||
|
||||
const ScanResult& GetResult() const;
|
||||
ScanResult&& TakeResult();
|
||||
|
||||
private:
|
||||
size_t m_catalogAssetIndex = 0;
|
||||
AZStd::function<void()> m_onComplete;
|
||||
ScanConfiguration m_config;
|
||||
ScanResult m_result;
|
||||
|
||||
void FilterAsset(AZ::Data::Asset<AZ::Data::AssetData>);
|
||||
const AZ::Data::AssetInfo& GetCurrentAsset() const;
|
||||
AZ::Data::Asset<AZ::Data::AssetData> LoadAsset();
|
||||
void OnSystemTick() override;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -6,37 +6,32 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QMessageBox>
|
||||
#include <QProcess>
|
||||
#include <QDir>
|
||||
#include <QScrollBar>
|
||||
#include <QDateTime>
|
||||
#include <QToolButton>
|
||||
|
||||
#include "UpgradeHelper.h"
|
||||
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/UserSettings/UserSettingsProvider.h>
|
||||
|
||||
#include <AzFramework/Asset/AssetSystemBus.h>
|
||||
#include <AzFramework/IO/FileOperations.h>
|
||||
|
||||
#include <AzQtComponents/Components/Widgets/CheckBox.h>
|
||||
#include <AzQtComponents/Utilities/DesktopUtilities.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
|
||||
|
||||
#include <AzQtComponents/Components/Widgets/CheckBox.h>
|
||||
|
||||
#include <Editor/Assets/ScriptCanvasAssetHelpers.h>
|
||||
#include <Editor/Settings.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/ModelTraits.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/ui_UpgradeHelper.h>
|
||||
|
||||
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
|
||||
#include <ScriptCanvas/Components/EditorGraph.h>
|
||||
#include <AzQtComponents/Utilities/DesktopUtilities.h>
|
||||
#include <Editor/Assets/ScriptCanvasAssetHelpers.h>
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
@@ -52,40 +47,47 @@ namespace ScriptCanvasEditor
|
||||
m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
|
||||
int rows = 0;
|
||||
auto& graphsToUpgrade = AZ::Interface<IUpgradeRequests>::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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,669 +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 <QMessageBox>
|
||||
#include <QDateTime>
|
||||
|
||||
#include "UpgradeTool.h"
|
||||
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/UserSettings/UserSettingsProvider.h>
|
||||
|
||||
#include <AzFramework/Asset/AssetSystemBus.h>
|
||||
#include <AzFramework/IO/FileOperations.h>
|
||||
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
|
||||
|
||||
#include <AzQtComponents/Components/Widgets/CheckBox.h>
|
||||
|
||||
#include <Editor/Settings.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/ui_UpgradeTool.h>
|
||||
|
||||
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
|
||||
#include <ScriptCanvas/Components/EditorGraph.h>
|
||||
|
||||
#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<EditorSettings::ScriptCanvasEditorSettings>(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<EditorKeepAlive>();
|
||||
|
||||
UpdateSettings();
|
||||
|
||||
UpgradeNotifications::Bus::Broadcast(&UpgradeNotifications::OnUpgradeStart);
|
||||
|
||||
m_assetsToUpgrade.clear();
|
||||
|
||||
IUpgradeRequests* upgradeRequests = AZ::Interface<IUpgradeRequests>::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<int>(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]");
|
||||
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
m_backupPath.clear();
|
||||
settingsRegistry->Get(m_backupPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectUserPath);
|
||||
|
||||
m_backupPath = m_backupPath / "ScriptCanvas_BACKUP" / subFolder.toUtf8().data();
|
||||
|
||||
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<int>(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<AZ::Data::AssetData> 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<AZ::Data::AssetData> 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<AZ::Data::AssetData>& 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<ScriptCanvasAsset>())
|
||||
{
|
||||
tmpFilesaved = AZ::Utils::SaveObjectToStream<ScriptCanvas::ScriptCanvasData>(fileStream, AZ::DataStream::ST_XML, &asset.GetAs<ScriptCanvasAsset>()->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<AZ::Data::AssetData>& 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<AZ::IO::IStreamer>::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<AZ::IO::IStreamer>::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<int>(++m_currentAssetIndex));
|
||||
}
|
||||
else
|
||||
{
|
||||
BackupComplete();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
AZ::Data::AssetManager::Instance().DispatchEvents();
|
||||
AZ::SystemTickBus::ExecuteQueuedEvents();
|
||||
|
||||
}
|
||||
|
||||
void UpgradeTool::BackupAsset(const AZ::Data::AssetInfo& assetInfo)
|
||||
{
|
||||
AZ::IO::FixedMaxPath sourceFilePath;
|
||||
|
||||
// Using this to get the watch folder
|
||||
AZStd::string watchFolder;
|
||||
AZ::Data::AssetInfo sourceFileAssetInfo;
|
||||
bool sourceInfoFound{};
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound,
|
||||
&AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath,
|
||||
assetInfo.m_relativePath.c_str(), sourceFileAssetInfo, watchFolder);
|
||||
if (sourceInfoFound)
|
||||
{
|
||||
sourceFilePath = AZ::IO::FixedMaxPath(AZStd::string_view(watchFolder)) / sourceFileAssetInfo.m_relativePath;
|
||||
}
|
||||
|
||||
const auto targetFilePath = m_backupPath / sourceFileAssetInfo.m_relativePath;
|
||||
|
||||
if (AZ::IO::FileIOBase::GetInstance()->Copy(sourceFilePath.c_str(), targetFilePath.c_str()) != AZ::IO::ResultCode::Error)
|
||||
{
|
||||
AZ_TracePrintf("Script Canvas", "Backup: %s -> %s\n", sourceFilePath.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<AZ::Data::AssetData>& asset, bool skipped /*= false*/)
|
||||
{
|
||||
m_ui->progressBar->setValue(aznumeric_cast<int>(++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("@log@/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 = "<html>\n<head>\n<style>\nbody {color:white; background:black;}\n .error { color:red;}\n .warning {color:darkorange;}\n</style>\n</head>\n<body>\n";
|
||||
header.append(AZStd::string::format("Log captured: %s<br>\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<br>", log.c_str());
|
||||
AzFramework::StringFunc::Replace(logText, "\n", "<br>\n");
|
||||
outputFile.Write(logText.data(), logText.size());
|
||||
}
|
||||
AZStd::string footer = "\n</body>\n</html>";
|
||||
outputFile.Write(footer.c_str(), footer.size());
|
||||
|
||||
|
||||
|
||||
outputFile.Close();
|
||||
}
|
||||
|
||||
AZ::Entity* UpgradeTool::AssetUpgradeJob(AZ::Data::Asset<AZ::Data::AssetData>&)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UpgradeTool::RetryMove(AZ::Data::Asset<AZ::Data::AssetData>& 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<AZ::IO::IStreamer>::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("<span class='error'>(Error): %s</span><br>", 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("<span class='warning'>(Warning): %s</span><br>", message);
|
||||
CaptureLogFromTraceBus(window, msg.c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpgradeTool::OnException(const char* message)
|
||||
{
|
||||
AZStd::string msg = AZStd::string::format("<span class='error'>(Exception): %s</span><br>", message);
|
||||
CaptureLogFromTraceBus("Script Canvas", msg.c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UpgradeTool::OnPrintf(const char* window, const char* message)
|
||||
{
|
||||
CaptureLogFromTraceBus(window, message);
|
||||
return false;
|
||||
}
|
||||
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/moc_UpgradeTool.cpp>
|
||||
|
||||
}
|
||||
@@ -1,150 +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 <AzCore/PlatformDef.h>
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option")
|
||||
#include <QProgressBar>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
|
||||
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
|
||||
|
||||
#include <AzQtComponents/Components/StyledDialog.h>
|
||||
|
||||
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
|
||||
|
||||
#include <ISystem.h>
|
||||
#include <IConsole.h>
|
||||
#include <AzCore/Debug/TraceMessageBus.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#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<AZ::Data::AssetData>&, bool skipped = false);
|
||||
|
||||
AZ::Entity* AssetUpgradeJob(AZ::Data::Asset<AZ::Data::AssetData>& asset);
|
||||
|
||||
// SystemTickBus::Handler
|
||||
void OnSystemTick() override;
|
||||
//
|
||||
|
||||
// AssetBus::Handler
|
||||
void OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
|
||||
void OnAssetError(AZ::Data::Asset<AZ::Data::AssetData> 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<AZ::Data::AssetData>&, bool skipped = false) override;
|
||||
|
||||
void RetryMove(AZ::Data::Asset<AZ::Data::AssetData>& 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<AZ::Data::AssetData> m_currentAsset;
|
||||
|
||||
AZStd::unique_ptr<Ui::UpgradeTool> m_ui;
|
||||
AZStd::recursive_mutex m_mutex;
|
||||
|
||||
// AZStd::unique_ptr<EditorKeepAlive> m_keepEditorAlive;
|
||||
|
||||
AZStd::vector<AZStd::string> m_logs;
|
||||
|
||||
AZ::Entity* m_scriptCanvasEntity = nullptr;
|
||||
|
||||
AZ::IO::Path 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<AZ::Data::AssetData>& asset, const AZStd::string& source, const AZStd::string& target);
|
||||
};
|
||||
}
|
||||
@@ -1,260 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>UpgradeTool</class>
|
||||
<widget class="QWidget" name="UpgradeTool">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>801</width>
|
||||
<height>328</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Script Canvas Upgrade</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_3">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>80</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="progressFrame">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(47, 47, 47);</string>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="AzQtComponents::StyledBusyLabel" name="spinner" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="makeBackupCheckbox">
|
||||
<property name="text">
|
||||
<string>Backup my source graphs</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="doNotAskCheckbox">
|
||||
<property name="text">
|
||||
<string>Do not ask me again</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QPushButton" name="upgradeButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Upgrade</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QPushButton" name="notNowButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Not now</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>AzQtComponents::StyledBusyLabel</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">AzQtComponents/Components/StyledBusyLabel.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,996 +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 <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QMessageBox>
|
||||
#include <QProcess>
|
||||
#include <QScrollBar>
|
||||
#include <QToolButton>
|
||||
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzCore/IO/FileIOEventBus.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/UserSettings/UserSettingsProvider.h>
|
||||
#include <AzFramework/Asset/AssetSystemBus.h>
|
||||
#include <AzFramework/IO/FileOperations.h>
|
||||
#include <AzQtComponents/Components/Widgets/CheckBox.h>
|
||||
#include <AzQtComponents/Utilities/DesktopUtilities.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/SourceControl/SourceControlAPI.h>
|
||||
#include <Editor/Settings.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/VersionExplorer.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/ui_VersionExplorer.h>
|
||||
#include <ScriptCanvas/Assets/ScriptCanvasAssetHandler.h>
|
||||
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
|
||||
#include <ScriptCanvas/Components/EditorGraph.h>
|
||||
|
||||
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<EditorKeepAlive>();
|
||||
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<int>(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<int>(m_currentAssetRowIndex), static_cast<int>(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<AZStd::recursive_mutex> 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<QTableWidgetItem*> 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<AzQtComponents::StyledBusyLabel*>(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::SettingsCache>();
|
||||
ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false;
|
||||
ScriptCanvas::Grammar::g_printAbstractCodeModel = false;
|
||||
ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false;
|
||||
AZ::Interface<IUpgradeRequests>::Get()->SetIsUpgrading(true);
|
||||
AZ::Interface<IUpgradeRequests>::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<int>(m_assetsToUpgrade.size()));
|
||||
m_ui->progressBar->setValue(m_upgradeAssetIndex);
|
||||
m_keepEditorAlive = AZStd::make_unique<EditorKeepAlive>();
|
||||
}
|
||||
|
||||
AZStd::string VersionExplorer::BackupGraph(const AZ::Data::Asset<AZ::Data::AssetData>& asset)
|
||||
{
|
||||
if (!m_ui->makeBackupCheckbox->isChecked())
|
||||
{
|
||||
// considered a success
|
||||
return "";
|
||||
}
|
||||
|
||||
auto fileIoBase = AZ::IO::FileIOBase::GetInstance();
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
|
||||
QDateTime theTime = QDateTime::currentDateTime();
|
||||
QString subFolder = theTime.toString("yyyy-MM-dd [HH.mm.ss]");
|
||||
|
||||
AZ::IO::FixedMaxPath projectUserPath;
|
||||
settingsRegistry->Get(projectUserPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectUserPath);
|
||||
|
||||
AZ::IO::FixedMaxPath backupPath = projectUserPath / "ScriptCanvas_BACKUP" / subFolder.toUtf8().data();
|
||||
|
||||
if (!fileIoBase->Exists(backupPath.c_str()))
|
||||
{
|
||||
if (fileIoBase->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 watchFolder;
|
||||
AZ::Data::AssetInfo assetInfo;
|
||||
|
||||
AZ::IO::FixedMaxPath sourceFilePath;
|
||||
bool sourceInfoFound{};
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceInfoFound,
|
||||
&AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath,
|
||||
asset.GetHint().c_str(), assetInfo, watchFolder);
|
||||
if (sourceInfoFound)
|
||||
{
|
||||
sourceFilePath = AZ::IO::FixedMaxPath(AZStd::string_view(watchFolder)) / assetInfo.m_relativePath;
|
||||
}
|
||||
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";
|
||||
}
|
||||
|
||||
const AZ::IO::FixedMaxPath targetFilePath = backupPath / assetInfo.m_relativePath;
|
||||
|
||||
if (fileIoBase->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<AZ::Data::AssetData>& 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* scriptCanvasAsset = asset.GetAs<ScriptCanvasAsset>();
|
||||
AZ_Assert(scriptCanvasAsset, "Unable to get the asset of ScriptCanvasAsset, but received type: %s"
|
||||
, azrtti_typeid<ScriptCanvasAsset>().template ToString<AZStd::string>().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<ScriptCanvasEditor::Graph>();
|
||||
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<AZ::Data::AssetData>& 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<AZ::IO::IStreamer>::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<AZ::Data::AssetData> 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<ScriptCanvasAsset>())
|
||||
{
|
||||
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<AZ::Data::AssetData> 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<AZ::IO::IStreamer>::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<AZ::IO::IStreamer>::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<AZ::IO::IStreamer>::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<AZ::Data::AssetData> asset, OperationResult result, AZStd::string_view message)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> 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<IUpgradeRequests>::Get()->GraphNeedsManualUpgrade(asset.GetId());
|
||||
}
|
||||
|
||||
m_tmpFileName.clear();
|
||||
}
|
||||
|
||||
void VersionExplorer::GraphUpgradeCompleteUIUpdate
|
||||
( const AZ::Data::Asset<AZ::Data::AssetData> asset, OperationResult result, AZStd::string_view message)
|
||||
{
|
||||
QString text = asset.GetHint().c_str();
|
||||
QList<QTableWidgetItem*> 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<IUpgradeRequests>::Get()->GetGraphsThatNeedManualUpgrade().size();
|
||||
if (assetsThatNeedManualInspection > 0)
|
||||
{
|
||||
m_ui->spinner->SetText("<html><head/><body><img src=':/stylesheet/img/UI20/Info.svg' width='16' height='16'/>Some graphs will require manual corrections, you will be prompted to review them upon closing this dialog</body></html>");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui->spinner->SetText("Upgrade complete.");
|
||||
}
|
||||
|
||||
AZ::SystemTickBus::Handler::BusDisconnect();
|
||||
AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
|
||||
UpgradeNotifications::Bus::Handler::BusDisconnect();
|
||||
AZ::Interface<IUpgradeRequests>::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<IUpgradeRequests>::Get();
|
||||
m_assetsToInspect = upgradeRequests->GetAssetsToUpgrade();
|
||||
DoScan();
|
||||
}
|
||||
|
||||
void VersionExplorer::DoScan()
|
||||
{
|
||||
m_state = ProcessState::Scan;
|
||||
m_settingsCache = AZStd::make_unique<ScriptCanvas::Grammar::SettingsCache>();
|
||||
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<int>(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<EditorKeepAlive>();
|
||||
}
|
||||
}
|
||||
|
||||
void VersionExplorer::BackupComplete()
|
||||
{
|
||||
m_currentAssetRowIndex = 0;
|
||||
m_ui->progressBar->setValue(0);
|
||||
DoScan();
|
||||
}
|
||||
|
||||
void VersionExplorer::InspectAsset(AZ::Data::Asset<AZ::Data::AssetData>& asset, AZ::Data::AssetInfo& assetInfo)
|
||||
{
|
||||
Log("InspectAsset: %s", asset.GetHint().c_str());
|
||||
AZ::Entity* scriptCanvasEntity = nullptr;
|
||||
if (asset.GetType() == azrtti_typeid<ScriptCanvasAsset>())
|
||||
{
|
||||
ScriptCanvasAsset* scriptCanvasAsset = asset.GetAs<ScriptCanvasAsset>();
|
||||
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<ScriptCanvasEditor::Graph>();
|
||||
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<int>(m_currentAssetRowIndex));
|
||||
QTableWidgetItem* rowName = new QTableWidgetItem(tr(asset.GetHint().c_str()));
|
||||
m_ui->tableWidget->setItem(static_cast<int>(m_currentAssetRowIndex), static_cast<int>(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<int>(m_currentAssetRowIndex), static_cast<int>(ColumnAction), rowGoToButton);
|
||||
m_ui->tableWidget->setCellWidget(static_cast<int>(m_currentAssetRowIndex), static_cast<int>(ColumnStatus), spinner);
|
||||
}
|
||||
|
||||
char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 };
|
||||
AZStd::string path = AZStd::string::format("@engroot@/%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<int>(m_currentAssetRowIndex), static_cast<int>(ColumnBrowse), browseButton);
|
||||
ScanComplete(asset);
|
||||
++m_inspectedAssets;
|
||||
++m_currentAssetRowIndex;
|
||||
}
|
||||
|
||||
void VersionExplorer::UpgradeSingle
|
||||
( QPushButton* rowGoToButton
|
||||
, AzQtComponents::StyledBusyLabel* spinner
|
||||
, AZ::Data::AssetInfo assetInfo)
|
||||
{
|
||||
AZ::Data::Asset<AZ::Data::AssetData> 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<IUpgradeRequests>::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<AZ::Data::AssetData>& asset)
|
||||
{
|
||||
Log("ScanComplete: %s", asset.GetHint().c_str());
|
||||
m_inProgress = false;
|
||||
m_ui->progressBar->setValue(aznumeric_cast<int>(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<QPushButton*>(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 <Editor/View/Windows/Tools/UpgradeTool/moc_VersionExplorer.cpp>
|
||||
|
||||
}
|
||||
@@ -1,180 +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 <AzCore/PlatformDef.h>
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option")
|
||||
#include <QProgressBar>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzQtComponents/Components/StyledDialog.h>
|
||||
|
||||
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
|
||||
#include <ScriptCanvas/Core/Core.h>
|
||||
|
||||
#include <ISystem.h>
|
||||
#include <IConsole.h>
|
||||
#include <AzCore/Debug/TraceMessageBus.h>
|
||||
#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<AZ::Data::AssetData>&);
|
||||
|
||||
void InspectAsset(AZ::Data::Asset<AZ::Data::AssetData>& 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<AZ::Data::AssetData>, 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<AZ::Data::Asset<AZ::Data::AssetData>>;
|
||||
UpgradeAssets m_assetsToUpgrade;
|
||||
UpgradeAssets::iterator m_inProgressAsset;
|
||||
|
||||
AZ::Data::Asset<AZ::Data::AssetData> m_currentAsset;
|
||||
|
||||
AZStd::unique_ptr<Ui::VersionExplorer> m_ui;
|
||||
|
||||
AZStd::unique_ptr<ScriptCanvas::Grammar::SettingsCache> m_settingsCache;
|
||||
|
||||
// upgrade fields
|
||||
AZStd::recursive_mutex m_mutex;
|
||||
bool m_upgradeComplete = false;
|
||||
AZ::Data::Asset<AZ::Data::AssetData> m_upgradeAsset;
|
||||
int m_upgradeAssetIndex = 0;
|
||||
OperationResult m_upgradeResult;
|
||||
AZStd::string m_upgradeMessage;
|
||||
AZStd::string m_tmpFileName;
|
||||
|
||||
AZStd::unique_ptr<EditorKeepAlive> m_keepEditorAlive;
|
||||
|
||||
AZStd::deque<AZStd::string> 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<AZ::Data::AssetData>&);
|
||||
void UpgradeGraph(const AZ::Data::Asset<AZ::Data::AssetData>&);
|
||||
|
||||
void GraphUpgradeCompleteUIUpdate(const AZ::Data::Asset<AZ::Data::AssetData> asset, OperationResult result, AZStd::string_view message);
|
||||
void OnGraphUpgradeComplete(AZ::Data::Asset<AZ::Data::AssetData>&, bool skipped = false) override;
|
||||
|
||||
void OnSourceFileReleased(AZ::Data::Asset<AZ::Data::AssetData> asset);
|
||||
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
|
||||
bool m_overwriteAll = false;
|
||||
void PerformMove(AZ::Data::Asset<AZ::Data::AssetData> asset, AZStd::string source, AZStd::string target, size_t remainingAttempts);
|
||||
|
||||
void Log(const char* format, ...);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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 <Editor/View/Windows/Tools/UpgradeTool/VersionExplorerLog.h>
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
namespace VersionExplorer
|
||||
{
|
||||
void Log::Activate()
|
||||
{
|
||||
AZ::Debug::TraceMessageBus::Handler::BusConnect();
|
||||
LogBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void Log::Clear()
|
||||
{
|
||||
m_logs.clear();
|
||||
}
|
||||
|
||||
bool Log::CaptureFromTraceBus(const char* window, const char* message)
|
||||
{
|
||||
if (m_isExclusiveReportingEnabled && 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_isExclusiveReportingEnabled;
|
||||
}
|
||||
|
||||
void Log::Deactivate()
|
||||
{
|
||||
AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void Log::Entry(const char* format, ...)
|
||||
{
|
||||
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<AZStd::string>* Log::GetEntries() const
|
||||
{
|
||||
return &m_logs;
|
||||
}
|
||||
|
||||
void Log::SetVersionExporerExclusivity(bool enabled)
|
||||
{
|
||||
m_isExclusiveReportingEnabled = enabled;
|
||||
}
|
||||
|
||||
void Log::SetVerbose(bool verbosity)
|
||||
{
|
||||
m_isVerbose = verbosity;
|
||||
}
|
||||
|
||||
bool Log::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 CaptureFromTraceBus(window, msg.c_str());
|
||||
}
|
||||
|
||||
bool Log::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 CaptureFromTraceBus(window, msg.c_str());
|
||||
}
|
||||
|
||||
bool Log::OnException(const char* message)
|
||||
{
|
||||
AZStd::string msg = AZStd::string::format("(Exception): %s", message);
|
||||
return CaptureFromTraceBus("Script Canvas", msg.c_str());
|
||||
}
|
||||
|
||||
bool Log::OnPrintf(const char* window, const char* message)
|
||||
{
|
||||
return CaptureFromTraceBus(window, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 <ScriptCanvas/Core/Core.h>
|
||||
#include <AzCore/Debug/TraceMessageBus.h>
|
||||
#include <Editor/View/Windows/Tools/UpgradeTool/LogTraits.h>
|
||||
|
||||
namespace ScriptCanvasEditor
|
||||
{
|
||||
namespace VersionExplorer
|
||||
{
|
||||
class Log
|
||||
: private AZ::Debug::TraceMessageBus::Handler
|
||||
, private LogBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Log, AZ::SystemAllocator, 0);
|
||||
|
||||
void Activate() override;
|
||||
void Clear() override;
|
||||
void Deactivate();
|
||||
void Entry(const char* format, ...) override;
|
||||
const AZStd::vector<AZStd::string>* GetEntries() const override;
|
||||
void SetVersionExporerExclusivity(bool enabled) override;
|
||||
void SetVerbose(bool verbosity) override;
|
||||
|
||||
private:
|
||||
bool m_isExclusiveReportingEnabled = false;
|
||||
bool m_isVerbose = false;
|
||||
AZStd::vector<AZStd::string> 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;
|
||||
};
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>VersionExplorer</class>
|
||||
<widget class="QWidget" name="VersionExplorer">
|
||||
<class>View</class>
|
||||
<widget class="QWidget" name="View">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModal</enum>
|
||||
</property>
|
||||
@@ -67,7 +67,7 @@ namespace ScriptCanvas
|
||||
|
||||
void ReceiveScriptEvent::PopulateAsset(AZ::Data::Asset<ScriptEvents::ScriptEventsAsset> asset, SlotIdMapping& populationMapping)
|
||||
{
|
||||
if (CreateHandler(asset))
|
||||
if (InitializeDefinition(asset))
|
||||
{
|
||||
if (!CreateEbus())
|
||||
{
|
||||
@@ -140,7 +140,6 @@ namespace ScriptCanvas
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ReceiveScriptEvent::InitializeEvent(AZ::Data::Asset<ScriptEvents::ScriptEventsAsset> asset, int eventIndex, SlotIdMapping& populationMapping)
|
||||
{
|
||||
if (!m_handler)
|
||||
@@ -353,6 +352,13 @@ namespace ScriptCanvas
|
||||
|
||||
AZStd::optional<size_t> ReceiveScriptEvent::GetEventIndex(AZStd::string eventName) const
|
||||
{
|
||||
if (!m_handler)
|
||||
{
|
||||
const_cast<ReceiveScriptEvent*>(this)->InitializeDefinition(m_asset);
|
||||
const_cast<ReceiveScriptEvent*>(this)->CreateEbus();
|
||||
}
|
||||
|
||||
AZ_Error("ScriptCanvas", m_handler != nullptr, "GetEventIndex called and handler was not created");
|
||||
return m_handler ? AZStd::optional<size_t>(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<ScriptEvents::ScriptEventsAsset> asset)
|
||||
bool ReceiveScriptEvent::InitializeDefinition(AZ::Data::Asset<ScriptEvents::ScriptEventsAsset> asset)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> 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<ScriptEvents::ScriptEventsAsset>& 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)
|
||||
|
||||
@@ -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<ScriptEvents::ScriptEventsAsset> asset);
|
||||
bool InitializeDefinition(AZ::Data::Asset<ScriptEvents::ScriptEventsAsset> asset);
|
||||
void CompleteInitialize(AZ::Data::Asset<ScriptEvents::ScriptEventsAsset> asset);
|
||||
void PopulateAsset(AZ::Data::Asset<ScriptEvents::ScriptEventsAsset> asset, SlotIdMapping& populationMapping);
|
||||
bool m_eventInitComplete = false;
|
||||
@@ -120,7 +120,6 @@ namespace ScriptCanvas
|
||||
bool m_autoConnectToGraphOwner = true;
|
||||
|
||||
bool m_connected;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ScriptEvents::ScriptEventsAsset>(m_scriptEventAssetId, AZ::Data::AssetLoadBehavior::PreLoad);
|
||||
m_asset.BlockUntilLoadComplete();
|
||||
}
|
||||
m_asset = AZ::Data::AssetManager::Instance().GetAsset<ScriptEvents::ScriptEventsAsset>(m_scriptEventAssetId, AZ::Data::AssetLoadBehavior::PreLoad);
|
||||
m_asset.BlockUntilLoadComplete();
|
||||
}
|
||||
|
||||
void ScriptEventBase::OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset)
|
||||
|
||||
@@ -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<size_t> 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<AZStd::string>& namespaces)
|
||||
AZStd::vector<ValidationConstPtr>&& 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<AZStd::string>& 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);
|
||||
|
||||
@@ -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<AZStd::string>& namespaces);
|
||||
void SingleLineComment(Writer& writer);
|
||||
AZStd::vector<ValidationConstPtr>&& 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<AZStd::string>& namespaces);
|
||||
void SingleLineComment(Writer& writer);
|
||||
void WriteCopyright(Writer& writer);
|
||||
void WriteDoNotModify(Writer& writer);
|
||||
void WriteLastWritten(Writer& writer);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,10 +12,11 @@
|
||||
#include <AzCore/Script/ScriptAsset.h>
|
||||
#include <AzCore/std/any.h>
|
||||
#include <ScriptCanvas/Core/Core.h>
|
||||
#include <ScriptCanvas/Data/Data.h>
|
||||
#include <ScriptCanvas/Core/SubgraphInterface.h>
|
||||
#include <ScriptCanvas/Grammar/PrimitivesDeclarations.h>
|
||||
#include <ScriptCanvas/Data/Data.h>
|
||||
#include <ScriptCanvas/Debugger/ValidationEvents/ValidationEvent.h>
|
||||
#include <ScriptCanvas/Grammar/DebugMap.h>
|
||||
#include <ScriptCanvas/Grammar/PrimitivesDeclarations.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -85,7 +86,7 @@ namespace ScriptCanvas
|
||||
AZStd::sys_time_t m_duration;
|
||||
};
|
||||
|
||||
using ErrorList = AZStd::vector<AZStd::string>;
|
||||
using ErrorList = AZStd::vector<ValidationConstPtr>;
|
||||
using Errors = AZStd::unordered_map<TargetFlags, ErrorList>;
|
||||
using Translations = AZStd::unordered_map<TargetFlags, TargetResult>;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -259,15 +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/Controller.cpp
|
||||
Editor/View/Windows/Tools/UpgradeTool/Controller.h
|
||||
Editor/View/Windows/Tools/UpgradeTool/FileSaver.cpp
|
||||
Editor/View/Windows/Tools/UpgradeTool/FileSaver.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/UpgradeTool.cpp
|
||||
Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.h
|
||||
Editor/View/Windows/Tools/UpgradeTool/UpgradeTool.ui
|
||||
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.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
|
||||
|
||||
Reference in New Issue
Block a user