GraphUpgrade.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Editor/Include/ScriptCanvas/Components/GraphUpgrade.h>
  9. #include <Editor/Include/ScriptCanvas/Components/EditorGraph.h>
  10. #include <Editor/Include/ScriptCanvas/Components/NodeReplacementSystem.h>
  11. #include <Editor/Nodes/NodeDisplayUtils.h>
  12. #include <ScriptCanvas/Bus/RequestBus.h>
  13. #include <GraphCanvas/Components/SceneBus.h>
  14. #include <GraphCanvas/Components/EntitySaveDataBus.h>
  15. #include <ScriptCanvas/Core/ConnectionBus.h>
  16. #include <ScriptCanvas/GraphCanvas/MappingBus.h>
  17. #include <ScriptCanvas/Bus/EditorScriptCanvasBus.h>
  18. #include <GraphCanvas/GraphCanvasBus.h>
  19. #include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
  20. namespace ScriptCanvasEditor
  21. {
  22. namespace Helpers
  23. {
  24. static AZStd::string ConnectionToText(ScriptCanvasEditor::EditorGraph* graph, ScriptCanvas::Endpoint& from, ScriptCanvas::Endpoint& to)
  25. {
  26. AZ_Assert(graph, "A valid graph must be provided");
  27. ScriptCanvas::Node* fromNode = graph->FindNode(from.GetNodeId());
  28. ScriptCanvas::Node* toNode = graph->FindNode(to.GetNodeId());
  29. ScriptCanvas::Slot* fromSlot = fromNode ? fromNode->GetSlot(from.GetSlotId()) : nullptr;
  30. ScriptCanvas::Slot* toSlot = toNode ? toNode->GetSlot(to.GetSlotId()) : nullptr;
  31. AZStd::string fromNodeName = fromNode ? fromNode->GetNodeName() : "Unknown Node";
  32. AZStd::string toNodeName = toNode ? toNode->GetNodeName() : "Unknown Node";
  33. AZStd::string fromSlotName = fromSlot ? fromSlot->GetName() : "Unknown Slot";
  34. AZStd::string toSlotName = toSlot ? toSlot->GetName() : "Unknown Slot";
  35. return AZStd::string::format("%s:%s to %s:%s", fromNodeName.c_str(), fromSlotName.c_str(), toNodeName.c_str(), toSlotName.c_str());
  36. }
  37. }
  38. void Start::OnEnter()
  39. {
  40. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  41. auto* graph = sm->m_graph;
  42. GraphCanvas::GraphCanvasRequestBus::BroadcastResult(graph->m_graphCanvasSceneEntity, &GraphCanvas::GraphCanvasRequests::CreateSceneAndActivate);
  43. if (!graph->m_graphCanvasSceneEntity)
  44. {
  45. // TODO: Need to shut it all down.
  46. }
  47. GraphCanvas::SceneRequestBus::Event(sm->m_graphCanvasGraphId, &GraphCanvas::SceneRequests::SetEditorId, ScriptCanvasEditor::AssetEditorId);
  48. }
  49. void PreventUndo::OnEnter()
  50. {
  51. GeneralRequestBus::Broadcast(&GeneralRequests::PushPreventUndoStateUpdate);
  52. }
  53. void CollectData::Run()
  54. {
  55. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  56. auto* graph = sm->m_graph;
  57. sm->m_scriptCanvasId = graph->GetScriptCanvasId();
  58. // Remove nodes that do not have components, these could be versioning artifacts
  59. // or nodes that are missing due to a missing gem
  60. AZStd::vector<AZ::Entity*> nodesToRemove;
  61. for (auto* node : graph->GetGraphData()->m_nodes)
  62. {
  63. if (node->GetComponents().empty())
  64. {
  65. 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());
  66. nodesToRemove.push_back(node);
  67. }
  68. }
  69. for (AZ::Entity* nodeEntity : nodesToRemove)
  70. {
  71. graph->GetGraphData()->m_nodes.erase(nodeEntity);
  72. }
  73. for (const AZ::EntityId& scriptCanvasNodeId : graph->GetNodes())
  74. {
  75. sm->m_assetSanitizationSet.insert(scriptCanvasNodeId);
  76. ScriptCanvas::Node* scriptCanvasNode = graph->FindNode(scriptCanvasNodeId);
  77. sm->m_graphCanvasGraphId = graph->GetGraphCanvasGraphId();
  78. if (scriptCanvasNode)
  79. {
  80. sm->m_allNodes.insert(scriptCanvasNode);
  81. if (scriptCanvasNode->IsDeprecated())
  82. {
  83. sm->m_deprecatedNodes.insert(scriptCanvasNode);
  84. }
  85. if (scriptCanvasNode->IsOutOfDate(graph->GetVersion()))
  86. {
  87. sm->m_outOfDateNodes.insert(scriptCanvasNode);
  88. }
  89. if (scriptCanvasNode->IsSanityCheckRequired())
  90. {
  91. sm->m_sanityCheckRequiredNodes.insert(scriptCanvasNode);
  92. }
  93. }
  94. }
  95. }
  96. IState::ExitStatus CollectData::OnExit()
  97. {
  98. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  99. Log("---------------------------------------------------------------------\n");
  100. Log("Upgrading\n");
  101. Log("%d Nodes\n", sm->m_allNodes.size());
  102. if (sm->m_deprecatedNodes.size() > 0)
  103. {
  104. Log("%d Deprecated\n", sm->m_deprecatedNodes.size());
  105. }
  106. if (sm->m_outOfDateNodes.size() > 0)
  107. {
  108. Log("%d Out of Date\n", sm->m_outOfDateNodes.size());
  109. }
  110. if (sm->m_sanityCheckRequiredNodes.size() > 0)
  111. {
  112. Log("%d Require Additional Checks\n", sm->m_sanityCheckRequiredNodes.size());
  113. }
  114. Log("---------------------------------------------------------------------\n");
  115. return ExitStatus::Default;
  116. }
  117. void PreRequisites::Run()
  118. {
  119. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  120. auto* graph = sm->m_graph;
  121. graph->m_variableDataModel.Activate(sm->m_scriptCanvasId);
  122. graph->ConnectGraphCanvasBuses();
  123. GraphCanvas::SceneRequestBus::Event(sm->m_graphCanvasGraphId, &GraphCanvas::SceneRequests::SignalLoadStart);
  124. auto saveDataIter = graph->m_graphCanvasSaveData.find(graph->GetEntityId());
  125. if (saveDataIter != graph->m_graphCanvasSaveData.end())
  126. {
  127. GraphCanvas::EntitySaveDataRequestBus::Event(sm->m_graphCanvasGraphId, &GraphCanvas::EntitySaveDataRequests::ReadSaveData, (*saveDataIter->second));
  128. }
  129. }
  130. void UpgradeConnections::Run()
  131. {
  132. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  133. auto* graph = sm->m_graph;
  134. AZStd::vector< AZ::EntityId > connectionIds = graph->GetConnections();
  135. for (const AZ::EntityId& connectionId : connectionIds)
  136. {
  137. ScriptCanvas::Endpoint scriptCanvasSourceEndpoint;
  138. ScriptCanvas::Endpoint scriptCanvasTargetEndpoint;
  139. ScriptCanvas::ConnectionRequestBus::EventResult(scriptCanvasSourceEndpoint, connectionId, &ScriptCanvas::ConnectionRequests::GetSourceEndpoint);
  140. ScriptCanvas::ConnectionRequestBus::EventResult(scriptCanvasTargetEndpoint, connectionId, &ScriptCanvas::ConnectionRequests::GetTargetEndpoint);
  141. Log("Upgrade Connection: %s\n", Helpers::ConnectionToText(graph, scriptCanvasSourceEndpoint, scriptCanvasTargetEndpoint).c_str());
  142. AZ::EntityId graphCanvasSourceNode;
  143. auto scriptCanvasIter = sm->m_scriptCanvasToGraphCanvasMapping.find(scriptCanvasSourceEndpoint.GetNodeId());
  144. if (scriptCanvasIter != sm->m_scriptCanvasToGraphCanvasMapping.end())
  145. {
  146. graphCanvasSourceNode = scriptCanvasIter->second;
  147. }
  148. else
  149. {
  150. AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Could not find ScriptCanvas Node with id %llu", static_cast<AZ::u64>(scriptCanvasSourceEndpoint.GetNodeId()));
  151. }
  152. AZ::EntityId graphCanvasSourceSlotId;
  153. SlotMappingRequestBus::EventResult(graphCanvasSourceSlotId, graphCanvasSourceNode, &SlotMappingRequests::MapToGraphCanvasId, scriptCanvasSourceEndpoint.GetSlotId());
  154. if (!graphCanvasSourceSlotId.IsValid())
  155. {
  156. // For the EBusHandler's I need to remap these to a different visual node.
  157. // Since multiple GraphCanvas nodes depict a single ScriptCanvas EBus node.
  158. if (EBusHandlerNodeDescriptorRequestBus::FindFirstHandler(graphCanvasSourceNode) != nullptr)
  159. {
  160. GraphCanvas::Endpoint graphCanvasEventEndpoint;
  161. EBusHandlerNodeDescriptorRequestBus::EventResult(graphCanvasEventEndpoint, graphCanvasSourceNode, &EBusHandlerNodeDescriptorRequests::MapSlotToGraphCanvasEndpoint, scriptCanvasSourceEndpoint.GetSlotId());
  162. graphCanvasSourceSlotId = graphCanvasEventEndpoint.GetSlotId();
  163. }
  164. if (!graphCanvasSourceSlotId.IsValid())
  165. {
  166. 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());
  167. graph->DisconnectById(connectionId);
  168. continue;
  169. }
  170. }
  171. GraphCanvas::Endpoint graphCanvasTargetEndpoint;
  172. scriptCanvasIter = sm->m_scriptCanvasToGraphCanvasMapping.find(scriptCanvasTargetEndpoint.GetNodeId());
  173. if (scriptCanvasIter != sm->m_scriptCanvasToGraphCanvasMapping.end())
  174. {
  175. graphCanvasTargetEndpoint.m_nodeId = scriptCanvasIter->second;
  176. }
  177. else
  178. {
  179. AZ_Warning(ScriptCanvas::k_VersionExplorerWindow.data(), false, "Could not find ScriptCanvas Node with id %llu", static_cast<AZ::u64>(scriptCanvasSourceEndpoint.GetNodeId()));
  180. }
  181. SlotMappingRequestBus::EventResult(graphCanvasTargetEndpoint.m_slotId, graphCanvasTargetEndpoint.GetNodeId(), &SlotMappingRequests::MapToGraphCanvasId, scriptCanvasTargetEndpoint.GetSlotId());
  182. if (!graphCanvasTargetEndpoint.IsValid())
  183. {
  184. // For the EBusHandler's I need to remap these to a different visual node.
  185. // Since multiple GraphCanvas nodes depict a single ScriptCanvas EBus node.
  186. if (EBusHandlerNodeDescriptorRequestBus::FindFirstHandler(graphCanvasTargetEndpoint.GetNodeId()) != nullptr)
  187. {
  188. EBusHandlerNodeDescriptorRequestBus::EventResult(graphCanvasTargetEndpoint, graphCanvasTargetEndpoint.GetNodeId(), &EBusHandlerNodeDescriptorRequests::MapSlotToGraphCanvasEndpoint, scriptCanvasTargetEndpoint.GetSlotId());
  189. }
  190. if (!graphCanvasTargetEndpoint.IsValid())
  191. {
  192. 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());
  193. graph->DisconnectById(connectionId);
  194. continue;
  195. }
  196. }
  197. AZ::EntityId graphCanvasConnectionId;
  198. GraphCanvas::SlotRequestBus::EventResult(graphCanvasConnectionId, graphCanvasSourceSlotId, &GraphCanvas::SlotRequests::DisplayConnectionWithEndpoint, graphCanvasTargetEndpoint);
  199. if (graphCanvasConnectionId.IsValid())
  200. {
  201. AZStd::any* userData = nullptr;
  202. GraphCanvas::ConnectionRequestBus::EventResult(userData, graphCanvasConnectionId, &GraphCanvas::ConnectionRequests::GetUserData);
  203. if (userData)
  204. {
  205. (*userData) = connectionId;
  206. SceneMemberMappingConfigurationRequestBus::Event(graphCanvasConnectionId, &SceneMemberMappingConfigurationRequests::ConfigureMapping, connectionId);
  207. }
  208. }
  209. }
  210. }
  211. void VerifySaveDataVersion::Run()
  212. {
  213. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  214. auto* graph = sm->m_graph;
  215. GraphCanvas::SceneRequestBus::Event(graph->GetGraphCanvasGraphId(), &GraphCanvas::SceneRequests::ProcessEnableDisableQueue);
  216. if (graph->m_graphCanvasSaveVersion != GraphCanvas::EntitySaveDataContainer::CurrentVersion)
  217. {
  218. for (auto saveDataPair : graph->m_graphCanvasSaveData)
  219. {
  220. auto graphCanvasIter = sm->m_scriptCanvasToGraphCanvasMapping.find(saveDataPair.first);
  221. graph->OnSaveDataDirtied(graphCanvasIter->second);
  222. }
  223. graph->m_graphCanvasSaveVersion = GraphCanvas::EntitySaveDataContainer::CurrentVersion;
  224. sm->m_graphNeedsDirtying = true;
  225. }
  226. }
  227. void SanityChecks::Run()
  228. {
  229. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  230. if (!sm->m_sanityCheckRequiredNodes.empty())
  231. {
  232. sm->m_graphNeedsDirtying = true;
  233. }
  234. for (auto node : sm->m_sanityCheckRequiredNodes)
  235. {
  236. if (node)
  237. {
  238. node->SanityCheckDynamicDisplay();
  239. }
  240. }
  241. }
  242. IState::ExitStatus SanityChecks::OnExit()
  243. {
  244. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  245. GraphCanvas::SceneRequestBus::Event(sm->m_graphCanvasGraphId, &GraphCanvas::SceneRequests::SignalLoadEnd);
  246. EditorGraphNotificationBus::Event(sm->m_scriptCanvasId, &EditorGraphNotifications::OnGraphCanvasSceneDisplayed);
  247. return IState::ExitStatus::Default;
  248. }
  249. void UpgradeScriptEvents::Run()
  250. {
  251. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  252. auto* graph = sm->m_graph;
  253. auto currentIter = graph->GetGraphData()->m_scriptEventAssets.begin();
  254. while (currentIter != graph->GetGraphData()->m_scriptEventAssets.end())
  255. {
  256. if (sm->m_assetSanitizationSet.find(currentIter->first) == sm->m_assetSanitizationSet.end())
  257. {
  258. currentIter->second = ScriptEvents::ScriptEventsAssetPtr{};
  259. currentIter = graph->GetGraphData()->m_scriptEventAssets.erase(currentIter);
  260. sm->m_graphNeedsDirtying = true;
  261. }
  262. else
  263. {
  264. ++currentIter;
  265. }
  266. }
  267. }
  268. void FixLeakedData::Run()
  269. {
  270. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  271. auto* graph = sm->m_graph;
  272. // Fix up leaked data elements
  273. auto mapIter = graph->m_graphCanvasSaveData.begin();
  274. while (mapIter != graph->m_graphCanvasSaveData.end())
  275. {
  276. // 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
  277. // of old save data for no reason.
  278. //
  279. // Need to bypass our internal save data for graph canvas information
  280. if (sm->m_scriptCanvasToGraphCanvasMapping.find(mapIter->first) == sm->m_scriptCanvasToGraphCanvasMapping.end()
  281. && mapIter->first != graph->GetEntityId())
  282. {
  283. delete mapIter->second;
  284. mapIter = graph->m_graphCanvasSaveData.erase(mapIter);
  285. }
  286. else
  287. {
  288. ++mapIter;
  289. }
  290. }
  291. }
  292. void UpdateOutOfDateNodes::Run()
  293. {
  294. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  295. auto* graph = sm->m_graph;
  296. AZStd::unordered_set< AZ::EntityId > graphCanvasNodesToDelete;
  297. for (auto scriptCanvasNode : sm->m_outOfDateNodes)
  298. {
  299. graph->OnVersionConversionBegin((*scriptCanvasNode));
  300. auto graphCanvasNodeId = sm->m_scriptCanvasToGraphCanvasMapping[scriptCanvasNode->GetEntityId()];
  301. ScriptCanvas::UpdateResult updateResult = scriptCanvasNode->UpdateNode();
  302. graph->OnVersionConversionEnd((*scriptCanvasNode));
  303. switch (updateResult)
  304. {
  305. case ScriptCanvas::UpdateResult::DeleteNode:
  306. {
  307. sm->m_graphNeedsDirtying = true;
  308. sm->m_deletedNodes.insert(scriptCanvasNode->GetEntityId());
  309. graphCanvasNodesToDelete.insert(graphCanvasNodeId);
  310. break;
  311. }
  312. default:
  313. {
  314. sm->m_graphNeedsDirtying = true;
  315. break;
  316. }
  317. }
  318. }
  319. if (!graphCanvasNodesToDelete.empty())
  320. {
  321. for (auto& nodeId : sm->m_deletedNodes)
  322. {
  323. ScriptCanvas::Node* node = graph->FindNode(nodeId);
  324. if (node)
  325. {
  326. Log("Deleted: %s\n", node->GetNodeName().c_str());
  327. }
  328. }
  329. GraphCanvas::SceneRequestBus::Event(sm->m_graphCanvasGraphId, &GraphCanvas::SceneRequests::Delete, graphCanvasNodesToDelete);
  330. }
  331. }
  332. void ReplaceDeprecatedConnections::Run()
  333. {
  334. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  335. auto* graph = sm->m_graph;
  336. if (!sm->m_updateReport.IsEmpty())
  337. {
  338. // currently, it is expected that there are no deleted old slots, those need manual correction
  339. AZ_Error(ScriptCanvas::k_VersionExplorerWindow.data(), sm->m_updateReport.m_deletedOldSlots.empty(), "Graph upgrade path: If old slots are deleted, manual upgrading is required");
  340. UpdateConnectionStatus(*graph, sm->m_updateReport);
  341. }
  342. }
  343. void ReplaceDeprecatedNodes::Run()
  344. {
  345. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  346. auto* graph = sm->m_graph;
  347. for (auto& node : sm->m_deprecatedNodes)
  348. {
  349. ScriptCanvas::NodeReplacementConfiguration nodeConfig;
  350. auto replacementId = ScriptCanvasEditor::NodeReplacementSystem::GenerateReplacementId(node);
  351. ScriptCanvasEditor::NodeReplacementRequestBus::BroadcastResult(
  352. nodeConfig, &ScriptCanvasEditor::NodeReplacementRequestBus::Events::GetNodeReplacementConfiguration, replacementId);
  353. if (!nodeConfig.IsValid())
  354. {
  355. nodeConfig = node->GetReplacementNodeConfiguration();
  356. }
  357. if (nodeConfig.IsValid())
  358. {
  359. auto nodeEntity = node->GetEntityId();
  360. ScriptCanvas::NodeUpdateReport nodeUpdateReport;
  361. ScriptCanvasEditor::NodeReplacementRequestBus::BroadcastResult(nodeUpdateReport,
  362. &ScriptCanvasEditor::NodeReplacementRequestBus::Events::ReplaceNodeByReplacementConfiguration,
  363. graph->GetScriptCanvasId(), node, nodeConfig);
  364. if (!nodeUpdateReport.IsEmpty())
  365. {
  366. ScriptCanvas::MergeUpdateSlotReport(nodeEntity, sm->m_updateReport, nodeUpdateReport);
  367. sm->m_allNodes.erase(node);
  368. sm->m_outOfDateNodes.erase(node);
  369. sm->m_sanityCheckRequiredNodes.erase(node);
  370. sm->m_graphNeedsDirtying = true;
  371. auto replacedNode = nodeUpdateReport.m_newNode;
  372. sm->m_allNodes.insert(replacedNode);
  373. if (replacedNode->IsOutOfDate(graph->GetVersion()))
  374. {
  375. sm->m_outOfDateNodes.insert(replacedNode);
  376. }
  377. if (replacedNode->IsSanityCheckRequired())
  378. {
  379. sm->m_sanityCheckRequiredNodes.insert(replacedNode);
  380. }
  381. Log("Replaced node (%s)\n", replacedNode->GetNodeName().c_str());
  382. }
  383. }
  384. }
  385. }
  386. void BuildGraphCanvasMapping::Run()
  387. {
  388. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  389. auto* graph = sm->m_graph;
  390. for (auto& scriptCanvasNode : sm->m_allNodes)
  391. {
  392. auto scriptCanvasNodeId = scriptCanvasNode->GetEntityId();
  393. AZ::EntityId graphCanvasNodeId = Nodes::DisplayScriptCanvasNode(sm->m_graphCanvasGraphId, scriptCanvasNode);
  394. sm->m_scriptCanvasToGraphCanvasMapping[scriptCanvasNodeId] = graphCanvasNodeId;
  395. auto saveDataIter = graph->m_graphCanvasSaveData.find(scriptCanvasNodeId);
  396. if (saveDataIter != graph->m_graphCanvasSaveData.end())
  397. {
  398. GraphCanvas::EntitySaveDataRequestBus::Event(graphCanvasNodeId, &GraphCanvas::EntitySaveDataRequests::ReadSaveData, (*saveDataIter->second));
  399. }
  400. AZ::Vector2 position;
  401. GraphCanvas::GeometryRequestBus::EventResult(position, graphCanvasNodeId, &GraphCanvas::GeometryRequests::GetPosition);
  402. GraphCanvas::SceneRequestBus::Event(sm->m_graphCanvasGraphId, &GraphCanvas::SceneRequests::AddNode, graphCanvasNodeId, position, false);
  403. // If the node is deprecated, we want to stomp whatever style it had saved and apply the deprecated style
  404. if (scriptCanvasNode->IsDeprecated())
  405. {
  406. Log("Marking node deprecated: %s\n", scriptCanvasNode->GetNodeName().c_str());
  407. GraphCanvas::NodeTitleRequestBus::Event(graphCanvasNodeId, &GraphCanvas::NodeTitleRequests::SetPaletteOverride, "DeprecatedNodeTitlePalette");
  408. }
  409. }
  410. }
  411. void ParseGraph::Run()
  412. {
  413. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  414. auto* graph = sm->m_graph;
  415. ScriptCanvas::ValidationResults validationResults;
  416. // Disable the g_saveRawTranslationOuputToFile CVar during Parse (not needed for upgrade) and restore to its set value after
  417. bool saveRawTranslationOuputToFile = ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile;
  418. ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = false;
  419. // save parsing status before after, just because it didn't parse after doesn't mean it didn't before
  420. graph->Parse(validationResults);
  421. ScriptCanvas::Grammar::g_saveRawTranslationOuputToFile = saveRawTranslationOuputToFile;
  422. if (validationResults.HasErrors())
  423. {
  424. if (!sm->GetConfig().saveParseErrors)
  425. {
  426. sm->MarkError("Failed to Parse");
  427. }
  428. for (auto& err : validationResults.GetEvents())
  429. {
  430. // Register this graph as needing manual updates
  431. Log("%s: %s\n", err->GetIdentifier().c_str(), err->GetDescription().data());
  432. }
  433. }
  434. }
  435. void RestoreUndo::Run()
  436. {
  437. GeneralRequestBus::Broadcast(&GeneralRequests::PopPreventUndoStateUpdate);
  438. }
  439. void Finalize::Run()
  440. {
  441. EditorGraphUpgradeMachine* sm = GetStateMachine<EditorGraphUpgradeMachine>();
  442. auto* graph = sm->m_graph;
  443. if (sm->m_graphNeedsDirtying)
  444. {
  445. graph->SignalDirty();
  446. }
  447. graph->MarkVersion();
  448. }
  449. void DisplayReport::Run()
  450. {
  451. Log("Upgrade Complete\n\n\n");
  452. }
  453. void Skip::Run()
  454. {
  455. Log("Up to date (skipped)\n");
  456. }
  457. // Transitions
  458. int Start::EvaluateTransition()
  459. {
  460. return PreventUndo::StateID();
  461. }
  462. int PreventUndo::EvaluateTransition()
  463. {
  464. return PreRequisites::StateID();
  465. }
  466. int PreRequisites::EvaluateTransition()
  467. {
  468. return CollectData::StateID();
  469. }
  470. int CollectData::EvaluateTransition()
  471. {
  472. return ReplaceDeprecatedNodes::StateID();
  473. }
  474. int ReplaceDeprecatedNodes::EvaluateTransition()
  475. {
  476. return BuildGraphCanvasMapping::StateID();
  477. }
  478. int BuildGraphCanvasMapping::EvaluateTransition()
  479. {
  480. return ReplaceDeprecatedConnections::StateID();
  481. }
  482. int ReplaceDeprecatedConnections::EvaluateTransition()
  483. {
  484. return UpdateOutOfDateNodes::StateID();
  485. }
  486. int UpdateOutOfDateNodes::EvaluateTransition()
  487. {
  488. return UpgradeConnections::StateID();
  489. }
  490. int UpgradeConnections::EvaluateTransition()
  491. {
  492. return FixLeakedData::StateID();
  493. }
  494. int FixLeakedData::EvaluateTransition()
  495. {
  496. return UpgradeScriptEvents::StateID();
  497. }
  498. int UpgradeScriptEvents::EvaluateTransition()
  499. {
  500. return SanityChecks::StateID();
  501. }
  502. int SanityChecks::EvaluateTransition()
  503. {
  504. return VerifySaveDataVersion::StateID();
  505. }
  506. int VerifySaveDataVersion::EvaluateTransition()
  507. {
  508. return RestoreUndo::StateID();
  509. }
  510. int RestoreUndo::EvaluateTransition()
  511. {
  512. return Finalize::StateID();
  513. }
  514. int Finalize::EvaluateTransition()
  515. {
  516. return ParseGraph::StateID();
  517. }
  518. int ParseGraph::EvaluateTransition()
  519. {
  520. return DisplayReport::StateID();
  521. }
  522. int DisplayReport::EvaluateTransition()
  523. {
  524. return EXIT_STATE_ID;
  525. }
  526. int Skip::EvaluateTransition()
  527. {
  528. return EXIT_STATE_ID;
  529. }
  530. //
  531. #define RegisterState(stateName) m_states.emplace_back(new stateName(this));
  532. EditorGraphUpgradeMachine::EditorGraphUpgradeMachine(EditorGraph* graph)
  533. : m_graph(graph)
  534. {
  535. RegisterState(Start);
  536. RegisterState(PreRequisites);
  537. RegisterState(PreventUndo);
  538. RegisterState(CollectData);
  539. RegisterState(ReplaceDeprecatedNodes);
  540. RegisterState(ReplaceDeprecatedConnections);
  541. RegisterState(VerifySaveDataVersion);
  542. RegisterState(SanityChecks);
  543. RegisterState(UpgradeScriptEvents);
  544. RegisterState(UpdateOutOfDateNodes);
  545. RegisterState(UpgradeConnections);
  546. RegisterState(BuildGraphCanvasMapping);
  547. RegisterState(FixLeakedData);
  548. RegisterState(RestoreUndo);
  549. RegisterState(Finalize);
  550. RegisterState(DisplayReport);
  551. RegisterState(Skip);
  552. RegisterState(ParseGraph);
  553. }
  554. void EditorGraphUpgradeMachine::SetAsset(SourceHandle& asset)
  555. {
  556. if (m_asset != asset)
  557. {
  558. m_asset = asset;
  559. SetDebugPrefix(asset.RelativePath().c_str());
  560. }
  561. }
  562. void EditorGraphUpgradeMachine::OnComplete(IState::ExitStatus exitStatus)
  563. {
  564. UpgradeNotificationsBus::Broadcast(&UpgradeNotifications::OnGraphUpgradeComplete, m_asset, exitStatus == IState::ExitStatus::Skipped);
  565. // releasing the asset at this stage of the system tick causes a memory crash
  566. // m_asset = {};
  567. }
  568. //////////////////////////////////////////////////////////////////////
  569. // State Machine Internals
  570. const UpgradeGraphConfig& StateMachine::GetConfig() const
  571. {
  572. return m_config;
  573. }
  574. void StateMachine::OnSystemTick()
  575. {
  576. IState::ExitStatus exitStatus = IState::ExitStatus::Default;
  577. if (m_currentState)
  578. {
  579. m_currentState->Run();
  580. int targetState = m_currentState->EvaluateTransition();
  581. if (targetState != IState::EXIT_STATE_ID)
  582. {
  583. exitStatus = m_currentState->Exit();
  584. 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; });
  585. if (state != m_states.end())
  586. {
  587. m_currentState = *state;
  588. m_currentState->Enter();
  589. }
  590. else
  591. {
  592. AZ_Assert(false, "Target State ID: %d Not Registered (From: %s)", targetState, m_currentState->GetName());
  593. m_currentState = nullptr;
  594. }
  595. }
  596. else
  597. {
  598. exitStatus = m_currentState->Exit();
  599. m_currentState = nullptr;
  600. }
  601. }
  602. if (!m_currentState)
  603. {
  604. AZ::SystemTickBus::Handler::BusDisconnect();
  605. OnComplete(m_error.empty() ? exitStatus : IState::ExitStatus::Skipped);
  606. }
  607. }
  608. void StateMachine::Run(int startStateID)
  609. {
  610. 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; });
  611. if (startState != m_states.end())
  612. {
  613. m_currentState = *startState;
  614. m_currentState->Enter();
  615. AZ::SystemTickBus::Handler::BusConnect();
  616. }
  617. }
  618. void StateMachine::SetConfig(const UpgradeGraphConfig& config)
  619. {
  620. m_config = config;
  621. }
  622. const AZStd::string& StateMachine::GetDebugPrefix() const
  623. {
  624. return m_debugPrefix;
  625. }
  626. void StateMachine::SetDebugPrefix(AZStd::string_view prefix)
  627. {
  628. m_debugPrefix = prefix;
  629. }
  630. }