You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
773 lines
28 KiB
C++
773 lines
28 KiB
C++
/*
|
|
* 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/Include/ScriptCanvas/Components/GraphUpgrade.h>
|
|
#include <Editor/Include/ScriptCanvas/Components/EditorGraph.h>
|
|
|
|
#include <Editor/Nodes/NodeDisplayUtils.h>
|
|
#include <ScriptCanvas/Bus/RequestBus.h>
|
|
#include <GraphCanvas/Components/SceneBus.h>
|
|
#include <GraphCanvas/Components/EntitySaveDataBus.h>
|
|
#include <ScriptCanvas/Core/ConnectionBus.h>
|
|
#include <ScriptCanvas/GraphCanvas/MappingBus.h>
|
|
#include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
|
|
#include <GraphCanvas/GraphCanvasBus.h>
|
|
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
|
|
|
|
namespace ScriptCanvasEditor
|
|
{
|
|
|
|
namespace Helpers
|
|
{
|
|
static AZStd::string ConnectionToText(ScriptCanvasEditor::EditorGraph* graph, ScriptCanvas::Endpoint& from, ScriptCanvas::Endpoint& to)
|
|
{
|
|
AZ_Assert(graph, "A valid graph must be provided");
|
|
|
|
ScriptCanvas::Node* fromNode = graph->FindNode(from.GetNodeId());
|
|
ScriptCanvas::Node* toNode = graph->FindNode(to.GetNodeId());
|
|
|
|
ScriptCanvas::Slot* fromSlot = fromNode ? fromNode->GetSlot(from.GetSlotId()) : nullptr;
|
|
ScriptCanvas::Slot* toSlot = toNode ? toNode->GetSlot(to.GetSlotId()) : nullptr;
|
|
|
|
AZStd::string fromNodeName = fromNode ? fromNode->GetNodeName() : "Unknown Node";
|
|
AZStd::string toNodeName = toNode ? toNode->GetNodeName() : "Unknown Node";
|
|
|
|
AZStd::string fromSlotName = fromSlot ? fromSlot->GetName() : "Unknown Slot";
|
|
AZStd::string toSlotName = toSlot ? toSlot->GetName() : "Unknown Slot";
|
|
|
|
return AZStd::string::format("%s:%s to %s:%s", fromNodeName.c_str(), fromSlotName.c_str(), toNodeName.c_str(), toSlotName.c_str());
|
|
}
|
|
}
|
|
|
|
void Start::OnEnter()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
auto* graph = sm->m_graph;
|
|
|
|
GraphCanvas::GraphCanvasRequestBus::BroadcastResult(graph->m_graphCanvasSceneEntity, &GraphCanvas::GraphCanvasRequests::CreateSceneAndActivate);
|
|
|
|
if (!graph->m_graphCanvasSceneEntity)
|
|
{
|
|
// TODO: Need to shut it all down.
|
|
}
|
|
|
|
GraphCanvas::SceneRequestBus::Event(sm->m_graphCanvasGraphId, &GraphCanvas::SceneRequests::SetEditorId, ScriptCanvasEditor::AssetEditorId);
|
|
}
|
|
|
|
void PreventUndo::OnEnter()
|
|
{
|
|
GeneralRequestBus::Broadcast(&GeneralRequests::PushPreventUndoStateUpdate);
|
|
}
|
|
|
|
void CollectData::Run()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
auto* graph = sm->m_graph;
|
|
|
|
sm->m_scriptCanvasId = graph->GetScriptCanvasId();
|
|
|
|
// Remove nodes that do not have components, these could be versioning artifacts
|
|
// or nodes that are missing due to a missing gem
|
|
AZStd::vector<AZ::Entity*> nodesToRemove;
|
|
for (auto* node : graph->GetGraphData()->m_nodes)
|
|
{
|
|
if (node->GetComponents().empty())
|
|
{
|
|
AZ_TracePrintf(ScriptCanvas::k_VersionExplorerWindow.data(), "Removing node due to missing components: %s\nVerify that all gems that this script relies on are enabled\n", node->GetName().c_str());
|
|
|
|
nodesToRemove.push_back(node);
|
|
}
|
|
}
|
|
|
|
for (AZ::Entity* nodeEntity : nodesToRemove)
|
|
{
|
|
graph->GetGraphData()->m_nodes.erase(nodeEntity);
|
|
}
|
|
|
|
for (const AZ::EntityId& scriptCanvasNodeId : graph->GetNodes())
|
|
{
|
|
sm->m_assetSanitizationSet.insert(scriptCanvasNodeId);
|
|
|
|
ScriptCanvas::Node* scriptCanvasNode = graph->FindNode(scriptCanvasNodeId);
|
|
|
|
sm->m_graphCanvasGraphId = graph->GetGraphCanvasGraphId();
|
|
|
|
if (scriptCanvasNode)
|
|
{
|
|
sm->m_allNodes.insert(scriptCanvasNode);
|
|
|
|
if (scriptCanvasNode->IsDeprecated())
|
|
{
|
|
sm->m_deprecatedNodes.insert(scriptCanvasNode);
|
|
}
|
|
|
|
if (scriptCanvasNode->IsOutOfDate(graph->GetVersion()))
|
|
{
|
|
sm->m_outOfDateNodes.insert(scriptCanvasNode);
|
|
}
|
|
|
|
if (scriptCanvasNode->IsSanityCheckRequired())
|
|
{
|
|
sm->m_sanityCheckRequiredNodes.insert(scriptCanvasNode);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
IState::ExitStatus CollectData::OnExit()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
|
|
Log("---------------------------------------------------------------------\n");
|
|
Log("Upgrading\n");
|
|
Log("%d Nodes\n", sm->m_allNodes.size());
|
|
|
|
if (sm->m_deprecatedNodes.size() > 0)
|
|
{
|
|
Log("%d Deprecated\n", sm->m_deprecatedNodes.size());
|
|
}
|
|
|
|
if (sm->m_outOfDateNodes.size() > 0)
|
|
{
|
|
Log("%d Out of Date\n", sm->m_outOfDateNodes.size());
|
|
}
|
|
|
|
if (sm->m_sanityCheckRequiredNodes.size() > 0)
|
|
{
|
|
Log("%d Require Additional Checks\n", sm->m_sanityCheckRequiredNodes.size());
|
|
}
|
|
Log("---------------------------------------------------------------------\n");
|
|
|
|
return ExitStatus::Default;
|
|
}
|
|
|
|
void PreRequisites::Run()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
auto* graph = sm->m_graph;
|
|
|
|
graph->m_variableDataModel.Activate(sm->m_scriptCanvasId);
|
|
|
|
graph->ConnectGraphCanvasBuses();
|
|
|
|
GraphCanvas::SceneRequestBus::Event(sm->m_graphCanvasGraphId, &GraphCanvas::SceneRequests::SignalLoadStart);
|
|
|
|
auto saveDataIter = graph->m_graphCanvasSaveData.find(graph->GetEntityId());
|
|
|
|
if (saveDataIter != graph->m_graphCanvasSaveData.end())
|
|
{
|
|
GraphCanvas::EntitySaveDataRequestBus::Event(sm->m_graphCanvasGraphId, &GraphCanvas::EntitySaveDataRequests::ReadSaveData, (*saveDataIter->second));
|
|
}
|
|
}
|
|
|
|
void UpgradeConnections::Run()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
auto* graph = sm->m_graph;
|
|
|
|
AZStd::vector< AZ::EntityId > connectionIds = graph->GetConnections();
|
|
|
|
for (const AZ::EntityId& connectionId : connectionIds)
|
|
{
|
|
ScriptCanvas::Endpoint scriptCanvasSourceEndpoint;
|
|
ScriptCanvas::Endpoint scriptCanvasTargetEndpoint;
|
|
|
|
ScriptCanvas::ConnectionRequestBus::EventResult(scriptCanvasSourceEndpoint, connectionId, &ScriptCanvas::ConnectionRequests::GetSourceEndpoint);
|
|
ScriptCanvas::ConnectionRequestBus::EventResult(scriptCanvasTargetEndpoint, connectionId, &ScriptCanvas::ConnectionRequests::GetTargetEndpoint);
|
|
|
|
Log("Upgrade Connection: %s\n", Helpers::ConnectionToText(graph, scriptCanvasSourceEndpoint, scriptCanvasTargetEndpoint).c_str());
|
|
|
|
AZ::EntityId graphCanvasSourceNode;
|
|
|
|
auto scriptCanvasIter = sm->m_scriptCanvasToGraphCanvasMapping.find(scriptCanvasSourceEndpoint.GetNodeId());
|
|
|
|
if (scriptCanvasIter != sm->m_scriptCanvasToGraphCanvasMapping.end())
|
|
{
|
|
graphCanvasSourceNode = scriptCanvasIter->second;
|
|
}
|
|
else
|
|
{
|
|
AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Could not find ScriptCanvas Node with id %llu", static_cast<AZ::u64>(scriptCanvasSourceEndpoint.GetNodeId()));
|
|
}
|
|
|
|
AZ::EntityId graphCanvasSourceSlotId;
|
|
SlotMappingRequestBus::EventResult(graphCanvasSourceSlotId, graphCanvasSourceNode, &SlotMappingRequests::MapToGraphCanvasId, scriptCanvasSourceEndpoint.GetSlotId());
|
|
|
|
if (!graphCanvasSourceSlotId.IsValid())
|
|
{
|
|
// For the EBusHandler's I need to remap these to a different visual node.
|
|
// Since multiple GraphCanvas nodes depict a single ScriptCanvas EBus node.
|
|
if (EBusHandlerNodeDescriptorRequestBus::FindFirstHandler(graphCanvasSourceNode) != nullptr)
|
|
{
|
|
GraphCanvas::Endpoint graphCanvasEventEndpoint;
|
|
EBusHandlerNodeDescriptorRequestBus::EventResult(graphCanvasEventEndpoint, graphCanvasSourceNode, &EBusHandlerNodeDescriptorRequests::MapSlotToGraphCanvasEndpoint, scriptCanvasSourceEndpoint.GetSlotId());
|
|
|
|
graphCanvasSourceSlotId = graphCanvasEventEndpoint.GetSlotId();
|
|
}
|
|
|
|
if (!graphCanvasSourceSlotId.IsValid())
|
|
{
|
|
AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), sm->m_deletedNodes.count(scriptCanvasSourceEndpoint.GetNodeId()) > 0, "Could not create connection(%s) for Node(%s).", connectionId.ToString().c_str(), scriptCanvasSourceEndpoint.GetNodeId().ToString().c_str());
|
|
graph->DisconnectById(connectionId);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
GraphCanvas::Endpoint graphCanvasTargetEndpoint;
|
|
|
|
scriptCanvasIter = sm->m_scriptCanvasToGraphCanvasMapping.find(scriptCanvasTargetEndpoint.GetNodeId());
|
|
|
|
if (scriptCanvasIter != sm->m_scriptCanvasToGraphCanvasMapping.end())
|
|
{
|
|
graphCanvasTargetEndpoint.m_nodeId = scriptCanvasIter->second;
|
|
}
|
|
else
|
|
{
|
|
AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Could not find ScriptCanvas Node with id %llu", static_cast<AZ::u64>(scriptCanvasSourceEndpoint.GetNodeId()));
|
|
}
|
|
|
|
SlotMappingRequestBus::EventResult(graphCanvasTargetEndpoint.m_slotId, graphCanvasTargetEndpoint.GetNodeId(), &SlotMappingRequests::MapToGraphCanvasId, scriptCanvasTargetEndpoint.GetSlotId());
|
|
|
|
if (!graphCanvasTargetEndpoint.IsValid())
|
|
{
|
|
// For the EBusHandler's I need to remap these to a different visual node.
|
|
// Since multiple GraphCanvas nodes depict a single ScriptCanvas EBus node.
|
|
if (EBusHandlerNodeDescriptorRequestBus::FindFirstHandler(graphCanvasTargetEndpoint.GetNodeId()) != nullptr)
|
|
{
|
|
EBusHandlerNodeDescriptorRequestBus::EventResult(graphCanvasTargetEndpoint, graphCanvasTargetEndpoint.GetNodeId(), &EBusHandlerNodeDescriptorRequests::MapSlotToGraphCanvasEndpoint, scriptCanvasTargetEndpoint.GetSlotId());
|
|
}
|
|
|
|
if (!graphCanvasTargetEndpoint.IsValid())
|
|
{
|
|
AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), sm->m_deletedNodes.count(scriptCanvasTargetEndpoint.GetNodeId()) > 0, "Could not create connection(%s) for Node(%s).", connectionId.ToString().c_str(), scriptCanvasTargetEndpoint.GetNodeId().ToString().c_str());
|
|
graph->DisconnectById(connectionId);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
AZ::EntityId graphCanvasConnectionId;
|
|
GraphCanvas::SlotRequestBus::EventResult(graphCanvasConnectionId, graphCanvasSourceSlotId, &GraphCanvas::SlotRequests::DisplayConnectionWithEndpoint, graphCanvasTargetEndpoint);
|
|
|
|
if (graphCanvasConnectionId.IsValid())
|
|
{
|
|
AZStd::any* userData = nullptr;
|
|
GraphCanvas::ConnectionRequestBus::EventResult(userData, graphCanvasConnectionId, &GraphCanvas::ConnectionRequests::GetUserData);
|
|
|
|
if (userData)
|
|
{
|
|
(*userData) = connectionId;
|
|
|
|
SceneMemberMappingConfigurationRequestBus::Event(graphCanvasConnectionId, &SceneMemberMappingConfigurationRequests::ConfigureMapping, connectionId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void VerifySaveDataVersion::Run()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
auto* graph = sm->m_graph;
|
|
|
|
GraphCanvas::SceneRequestBus::Event(graph->GetGraphCanvasGraphId(), &GraphCanvas::SceneRequests::ProcessEnableDisableQueue);
|
|
|
|
if (graph->m_graphCanvasSaveVersion != GraphCanvas::EntitySaveDataContainer::CurrentVersion)
|
|
{
|
|
for (auto saveDataPair : graph->m_graphCanvasSaveData)
|
|
{
|
|
auto graphCanvasIter = sm->m_scriptCanvasToGraphCanvasMapping.find(saveDataPair.first);
|
|
graph->OnSaveDataDirtied(graphCanvasIter->second);
|
|
}
|
|
|
|
graph->m_graphCanvasSaveVersion = GraphCanvas::EntitySaveDataContainer::CurrentVersion;
|
|
sm->m_graphNeedsDirtying = true;
|
|
}
|
|
}
|
|
|
|
void SanityChecks::Run()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
if (!sm->m_sanityCheckRequiredNodes.empty())
|
|
{
|
|
sm->m_graphNeedsDirtying = true;
|
|
}
|
|
|
|
for (auto node : sm->m_sanityCheckRequiredNodes)
|
|
{
|
|
if (node)
|
|
{
|
|
node->SanityCheckDynamicDisplay();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
IState::ExitStatus SanityChecks::OnExit()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
|
|
GraphCanvas::SceneRequestBus::Event(sm->m_graphCanvasGraphId, &GraphCanvas::SceneRequests::SignalLoadEnd);
|
|
EditorGraphNotificationBus::Event(sm->m_scriptCanvasId, &EditorGraphNotifications::OnGraphCanvasSceneDisplayed);
|
|
|
|
return IState::ExitStatus::Default;
|
|
}
|
|
|
|
void UpgradeScriptEvents::Run()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
auto* graph = sm->m_graph;
|
|
|
|
auto currentIter = graph->GetGraphData()->m_scriptEventAssets.begin();
|
|
|
|
while (currentIter != graph->GetGraphData()->m_scriptEventAssets.end())
|
|
{
|
|
if (sm->m_assetSanitizationSet.find(currentIter->first) == sm->m_assetSanitizationSet.end())
|
|
{
|
|
currentIter->second = ScriptEvents::ScriptEventsAssetPtr{};
|
|
currentIter = graph->GetGraphData()->m_scriptEventAssets.erase(currentIter);
|
|
sm->m_graphNeedsDirtying = true;
|
|
}
|
|
else
|
|
{
|
|
++currentIter;
|
|
}
|
|
}
|
|
}
|
|
|
|
void FixLeakedData::Run()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
auto* graph = sm->m_graph;
|
|
|
|
// Fix up leaked data elements
|
|
auto mapIter = graph->m_graphCanvasSaveData.begin();
|
|
|
|
while (mapIter != graph->m_graphCanvasSaveData.end())
|
|
{
|
|
// Deleted using the wrong id, which orphaned the SaveData. For now we want to go through and sanitize our save data to avoid keeping around a bunch
|
|
// of old save data for no reason.
|
|
//
|
|
// Need to bypass our internal save data for graph canvas information
|
|
if (sm->m_scriptCanvasToGraphCanvasMapping.find(mapIter->first) == sm->m_scriptCanvasToGraphCanvasMapping.end()
|
|
&& mapIter->first != graph->GetEntityId())
|
|
{
|
|
delete mapIter->second;
|
|
mapIter = graph->m_graphCanvasSaveData.erase(mapIter);
|
|
}
|
|
else
|
|
{
|
|
++mapIter;
|
|
}
|
|
}
|
|
}
|
|
|
|
void UpdateOutOfDateNodes::Run()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
auto* graph = sm->m_graph;
|
|
|
|
AZStd::unordered_set< AZ::EntityId > graphCanvasNodesToDelete;
|
|
|
|
for (auto scriptCanvasNode : sm->m_outOfDateNodes)
|
|
{
|
|
graph->OnVersionConversionBegin((*scriptCanvasNode));
|
|
|
|
auto graphCanvasNodeId = sm->m_scriptCanvasToGraphCanvasMapping[scriptCanvasNode->GetEntityId()];
|
|
ScriptCanvas::UpdateResult updateResult = scriptCanvasNode->UpdateNode();
|
|
|
|
graph->OnVersionConversionEnd((*scriptCanvasNode));
|
|
|
|
switch (updateResult)
|
|
{
|
|
case ScriptCanvas::UpdateResult::DeleteNode:
|
|
{
|
|
sm->m_graphNeedsDirtying = true;
|
|
sm->m_deletedNodes.insert(scriptCanvasNode->GetEntityId());
|
|
graphCanvasNodesToDelete.insert(graphCanvasNodeId);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
sm->m_graphNeedsDirtying = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!graphCanvasNodesToDelete.empty())
|
|
{
|
|
for (auto& nodeId : sm->m_deletedNodes)
|
|
{
|
|
ScriptCanvas::Node* node = graph->FindNode(nodeId);
|
|
if (node)
|
|
{
|
|
Log("Deleted: %s\n", node->GetNodeName().c_str());
|
|
}
|
|
}
|
|
|
|
GraphCanvas::SceneRequestBus::Event(sm->m_graphCanvasGraphId, &GraphCanvas::SceneRequests::Delete, graphCanvasNodesToDelete);
|
|
}
|
|
}
|
|
|
|
void ReplaceDeprecatedConnections::Run()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
auto* graph = sm->m_graph;
|
|
|
|
if (!sm->m_updateReport.IsEmpty())
|
|
{
|
|
// currently, it is expected that there are no deleted old slots, those need manual correction
|
|
AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), sm->m_updateReport.m_deletedOldSlots.empty(), "Graph upgrade path: If old slots are deleted, manual upgrading is required");
|
|
UpdateConnectionStatus(*graph, sm->m_updateReport);
|
|
}
|
|
}
|
|
|
|
void ReplaceDeprecatedNodes::Run()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
auto* graph = sm->m_graph;
|
|
|
|
for (auto& node : sm->m_deprecatedNodes)
|
|
{
|
|
ScriptCanvas::NodeConfiguration nodeConfig = node->GetReplacementNodeConfiguration();
|
|
if (nodeConfig.IsValid())
|
|
{
|
|
ScriptCanvas::NodeUpdateSlotReport nodeUpdateSlotReport;
|
|
auto nodeEntity = node->GetEntityId();
|
|
auto nodeOutcome = graph->ReplaceNodeByConfig(node, nodeConfig, nodeUpdateSlotReport);
|
|
if (nodeOutcome.IsSuccess())
|
|
{
|
|
ScriptCanvas::MergeUpdateSlotReport(nodeEntity, sm->m_updateReport, nodeUpdateSlotReport);
|
|
|
|
sm->m_allNodes.erase(node);
|
|
sm->m_outOfDateNodes.erase(node);
|
|
sm->m_sanityCheckRequiredNodes.erase(node);
|
|
sm->m_graphNeedsDirtying = true;
|
|
|
|
auto replacedNode = nodeOutcome.GetValue();
|
|
sm->m_allNodes.insert(replacedNode);
|
|
|
|
if (replacedNode->IsOutOfDate(graph->GetVersion()))
|
|
{
|
|
sm->m_outOfDateNodes.insert(replacedNode);
|
|
}
|
|
|
|
if (replacedNode->IsSanityCheckRequired())
|
|
{
|
|
sm->m_sanityCheckRequiredNodes.insert(replacedNode);
|
|
}
|
|
|
|
Log("Replaced node (%s)\n", replacedNode->GetNodeName().c_str());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void BuildGraphCanvasMapping::Run()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
auto* graph = sm->m_graph;
|
|
|
|
for (auto& scriptCanvasNode : sm->m_allNodes)
|
|
{
|
|
auto scriptCanvasNodeId = scriptCanvasNode->GetEntityId();
|
|
|
|
AZ::EntityId graphCanvasNodeId = Nodes::DisplayScriptCanvasNode(sm->m_graphCanvasGraphId, scriptCanvasNode);
|
|
sm->m_scriptCanvasToGraphCanvasMapping[scriptCanvasNodeId] = graphCanvasNodeId;
|
|
|
|
auto saveDataIter = graph->m_graphCanvasSaveData.find(scriptCanvasNodeId);
|
|
|
|
if (saveDataIter != graph->m_graphCanvasSaveData.end())
|
|
{
|
|
GraphCanvas::EntitySaveDataRequestBus::Event(graphCanvasNodeId, &GraphCanvas::EntitySaveDataRequests::ReadSaveData, (*saveDataIter->second));
|
|
}
|
|
|
|
AZ::Vector2 position;
|
|
GraphCanvas::GeometryRequestBus::EventResult(position, graphCanvasNodeId, &GraphCanvas::GeometryRequests::GetPosition);
|
|
|
|
GraphCanvas::SceneRequestBus::Event(sm->m_graphCanvasGraphId, &GraphCanvas::SceneRequests::AddNode, graphCanvasNodeId, position, false);
|
|
|
|
// If the node is deprecated, we want to stomp whatever style it had saved and apply the deprecated style
|
|
if (scriptCanvasNode->IsDeprecated())
|
|
{
|
|
Log("Marking node deprecated: %s\n", scriptCanvasNode->GetNodeName().c_str());
|
|
GraphCanvas::NodeTitleRequestBus::Event(graphCanvasNodeId, &GraphCanvas::NodeTitleRequests::SetPaletteOverride, "DeprecatedNodeTitlePalette");
|
|
}
|
|
}
|
|
}
|
|
|
|
void ParseGraph::Run()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
auto* graph = sm->m_graph;
|
|
|
|
ScriptCanvas::ValidationResults validationResults;
|
|
|
|
// Disable the g_saveRawTranslationOuputToFile CVar during Parse (not needed for upgrade) and restore to its set value after
|
|
bool saveRawTranslationOuputToFile = ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile;
|
|
ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false;
|
|
|
|
|
|
// save parsing status before after, just because it didn't parse after doesn't mean it didn't before
|
|
graph->Parse(validationResults);
|
|
|
|
ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = saveRawTranslationOuputToFile;
|
|
|
|
if (validationResults.HasErrors())
|
|
{
|
|
sm->MarkError("Failed to Parse");
|
|
|
|
for (auto& err : validationResults.GetEvents())
|
|
{
|
|
// Register this graph as needing manual updates
|
|
Log("%s: %s\n", err->GetIdentifier().c_str(), err->GetDescription().data());
|
|
}
|
|
}
|
|
}
|
|
|
|
void RestoreUndo::Run()
|
|
{
|
|
GeneralRequestBus::Broadcast(&GeneralRequests::PopPreventUndoStateUpdate);
|
|
}
|
|
|
|
void Finalize::Run()
|
|
{
|
|
EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
|
|
auto* graph = sm->m_graph;
|
|
|
|
if (sm->m_graphNeedsDirtying)
|
|
{
|
|
graph->SignalDirty();
|
|
}
|
|
|
|
graph->MarkVersion();
|
|
}
|
|
|
|
void DisplayReport::Run()
|
|
{
|
|
Log("Upgrade Complete\n\n\n");
|
|
}
|
|
|
|
void Skip::Run()
|
|
{
|
|
Log("Up to date (skipped)\n");
|
|
}
|
|
|
|
// Transitions
|
|
int Start::EvaluateTransition()
|
|
{
|
|
return PreventUndo::StateID();
|
|
}
|
|
|
|
int PreventUndo::EvaluateTransition()
|
|
{
|
|
return PreRequisites::StateID();
|
|
}
|
|
|
|
int PreRequisites::EvaluateTransition()
|
|
{
|
|
return CollectData::StateID();
|
|
}
|
|
|
|
int CollectData::EvaluateTransition()
|
|
{
|
|
return ReplaceDeprecatedNodes::StateID();
|
|
}
|
|
|
|
int ReplaceDeprecatedNodes::EvaluateTransition()
|
|
{
|
|
return BuildGraphCanvasMapping::StateID();
|
|
}
|
|
|
|
int BuildGraphCanvasMapping::EvaluateTransition()
|
|
{
|
|
return ReplaceDeprecatedConnections::StateID();
|
|
}
|
|
|
|
int ReplaceDeprecatedConnections::EvaluateTransition()
|
|
{
|
|
return UpdateOutOfDateNodes::StateID();
|
|
}
|
|
|
|
int UpdateOutOfDateNodes::EvaluateTransition()
|
|
{
|
|
return UpgradeConnections::StateID();
|
|
}
|
|
|
|
int UpgradeConnections::EvaluateTransition()
|
|
{
|
|
return FixLeakedData::StateID();
|
|
}
|
|
|
|
int FixLeakedData::EvaluateTransition()
|
|
{
|
|
return UpgradeScriptEvents::StateID();
|
|
}
|
|
|
|
int UpgradeScriptEvents::EvaluateTransition()
|
|
{
|
|
return SanityChecks::StateID();
|
|
}
|
|
|
|
int SanityChecks::EvaluateTransition()
|
|
{
|
|
return VerifySaveDataVersion::StateID();
|
|
}
|
|
|
|
int VerifySaveDataVersion::EvaluateTransition()
|
|
{
|
|
return RestoreUndo::StateID();
|
|
}
|
|
|
|
int RestoreUndo::EvaluateTransition()
|
|
{
|
|
return Finalize::StateID();
|
|
}
|
|
|
|
int Finalize::EvaluateTransition()
|
|
{
|
|
return ParseGraph::StateID();
|
|
}
|
|
|
|
int ParseGraph::EvaluateTransition()
|
|
{
|
|
return DisplayReport::StateID();
|
|
}
|
|
|
|
int DisplayReport::EvaluateTransition()
|
|
{
|
|
return EXIT_STATE_ID;
|
|
}
|
|
|
|
int Skip::EvaluateTransition()
|
|
{
|
|
return EXIT_STATE_ID;
|
|
}
|
|
//
|
|
|
|
|
|
#define RegisterState(stateName) m_states.emplace_back(new stateName(this));
|
|
|
|
EditorGraphUpgradeMachine::EditorGraphUpgradeMachine(EditorGraph* graph)
|
|
: m_graph(graph)
|
|
{
|
|
RegisterState(Start);
|
|
RegisterState(PreRequisites);
|
|
RegisterState(PreventUndo);
|
|
RegisterState(CollectData);
|
|
RegisterState(ReplaceDeprecatedNodes);
|
|
RegisterState(ReplaceDeprecatedConnections);
|
|
RegisterState(VerifySaveDataVersion);
|
|
RegisterState(SanityChecks);
|
|
RegisterState(UpgradeScriptEvents);
|
|
RegisterState(UpdateOutOfDateNodes);
|
|
RegisterState(UpgradeConnections);
|
|
RegisterState(BuildGraphCanvasMapping);
|
|
RegisterState(FixLeakedData);
|
|
RegisterState(RestoreUndo);
|
|
RegisterState(Finalize);
|
|
RegisterState(DisplayReport);
|
|
RegisterState(Skip);
|
|
RegisterState(ParseGraph);
|
|
}
|
|
|
|
void EditorGraphUpgradeMachine::SetAsset(SourceHandle& asset)
|
|
{
|
|
if (m_asset != asset)
|
|
{
|
|
m_asset = asset;
|
|
SetDebugPrefix(asset.Path().c_str());
|
|
}
|
|
}
|
|
|
|
void EditorGraphUpgradeMachine::OnComplete(IState::ExitStatus exitStatus)
|
|
{
|
|
UpgradeNotificationsBus::Broadcast(&UpgradeNotifications::OnGraphUpgradeComplete, m_asset, exitStatus == IState::ExitStatus::Skipped);
|
|
// releasing the asset at this stage of the system tick causes a memory crash
|
|
// m_asset = {};
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// State Machine Internals
|
|
bool StateMachine::GetVerbose() const
|
|
{
|
|
return m_isVerbose;
|
|
}
|
|
|
|
void StateMachine::OnSystemTick()
|
|
{
|
|
IState::ExitStatus exitStatus = IState::ExitStatus::Default;
|
|
|
|
if (m_currentState)
|
|
{
|
|
m_currentState->Run();
|
|
|
|
int targetState = m_currentState->EvaluateTransition();
|
|
if (targetState != IState::EXIT_STATE_ID)
|
|
{
|
|
exitStatus = m_currentState->Exit();
|
|
|
|
auto state = AZStd::find_if(m_states.begin(), m_states.end(), [targetState](AZStd::shared_ptr<IState>& state) { if (state->GetStateId() == targetState) { return true; } return false; });
|
|
|
|
if (state != m_states.end())
|
|
{
|
|
m_currentState = *state;
|
|
m_currentState->Enter();
|
|
}
|
|
else
|
|
{
|
|
AZ_Assert(false, "Target State ID: %d Not Registered (From: %s)", targetState, m_currentState->GetName());
|
|
m_currentState = nullptr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
exitStatus = m_currentState->Exit();
|
|
m_currentState = nullptr;
|
|
}
|
|
}
|
|
|
|
if (!m_currentState)
|
|
{
|
|
AZ::SystemTickBus::Handler::BusDisconnect();
|
|
|
|
OnComplete(m_error.empty() ? exitStatus : IState::ExitStatus::Skipped);
|
|
}
|
|
}
|
|
|
|
void StateMachine::Run(int startStateID)
|
|
{
|
|
auto startState = AZStd::find_if(m_states.begin(), m_states.end(), [startStateID](AZStd::shared_ptr<IState>& state) { if (state->GetStateId() == startStateID) { return true; } return false; });
|
|
if (startState != m_states.end())
|
|
{
|
|
m_currentState = *startState;
|
|
|
|
m_currentState->Enter();
|
|
|
|
AZ::SystemTickBus::Handler::BusConnect();
|
|
}
|
|
}
|
|
|
|
void StateMachine::SetVerbose(bool isVerbose)
|
|
{
|
|
m_isVerbose = isVerbose;
|
|
}
|
|
|
|
const AZStd::string& StateMachine::GetDebugPrefix() const
|
|
{
|
|
return m_debugPrefix;
|
|
}
|
|
|
|
void StateMachine::SetDebugPrefix(AZStd::string_view prefix)
|
|
{
|
|
m_debugPrefix = prefix;
|
|
}
|
|
|
|
|
|
}
|