using Godot; using Godot.Collections; using System; public class ScriptGraphSerializer { private readonly GraphEdit editorWindow; private readonly System.Collections.Generic.Dictionary dslNodes; private readonly Action addNode; private readonly Action connectNodes; public ScriptGraphSerializer( GraphEdit editorWindow, System.Collections.Generic.Dictionary dslNodes, Action addNode, Action connectNodes ) { this.editorWindow = editorWindow; this.dslNodes = dslNodes; this.addNode = addNode; this.connectNodes = connectNodes; } public void Load(string scriptContent) { Variant parsedScript = Json.ParseString(scriptContent); if (parsedScript.VariantType != Variant.Type.Dictionary) return; Dictionary scriptData = parsedScript.AsGodotDictionary(); if (!scriptData.ContainsKey("Nodes")) return; System.Collections.Generic.Dictionary loadedNodes = new System.Collections.Generic.Dictionary(); Godot.Collections.Array nodes = scriptData["Nodes"].AsGodotArray(); for (int i = 0; i < nodes.Count; i++) { Dictionary nodeData = nodes[i].AsGodotDictionary(); NodeDisplay nodeDisplay = LoadNode(nodeData); if (nodeDisplay == null) continue; addNode(nodeDisplay); RegisterLoadedNode(nodeData, nodeDisplay, loadedNodes); } LoadConnections(scriptData, loadedNodes); } public string Save() { Array savedNodes = BuildSavedNodes(); if (savedNodes.Count <= 0) return ""; Dictionary scriptData = new Dictionary(); scriptData["Nodes"] = savedNodes; scriptData["Connections"] = BuildSavedConnections(); return Json.Stringify(scriptData); } private NodeDisplay LoadNode(Dictionary nodeData) { if (!nodeData.ContainsKey("Type")) return null; if (!nodeData.ContainsKey("Content")) return null; string type = nodeData["Type"].AsString(); string content = nodeData["Content"].AsString(); NodeDisplay nodeDisplay = NodeDisplay.Load(type, content, dslNodes); if (nodeDisplay == null) return null; if (nodeData.ContainsKey("Id")) { nodeDisplay.Name = nodeData["Id"].AsString(); } if (nodeData.ContainsKey("PositionX") && nodeData.ContainsKey("PositionY")) { float positionX = (float)nodeData["PositionX"].AsDouble(); float positionY = (float)nodeData["PositionY"].AsDouble(); nodeDisplay.PositionOffset = new Vector2(positionX, positionY); } return nodeDisplay; } private void RegisterLoadedNode( Dictionary nodeData, NodeDisplay nodeDisplay, System.Collections.Generic.Dictionary loadedNodes ) { string nodeId = nodeDisplay.Name.ToString(); if (nodeData.ContainsKey("Id")) { nodeId = nodeData["Id"].AsString(); } if (!loadedNodes.ContainsKey(nodeId)) { loadedNodes.Add(nodeId, nodeDisplay); } } private void LoadConnections( Dictionary scriptData, System.Collections.Generic.Dictionary loadedNodes ) { if (!scriptData.ContainsKey("Connections")) return; Godot.Collections.Array connectionData = scriptData["Connections"].AsGodotArray(); for (int i = 0; i < connectionData.Count; i++) { Dictionary savedConnection = connectionData[i].AsGodotDictionary(); if (!IsConnectionDataValid(savedConnection)) continue; ScriptConnection connection = CreateConnection(savedConnection); ConnectLoadedNodes(connection, loadedNodes); } } private bool IsConnectionDataValid(Dictionary savedConnection) { return savedConnection.ContainsKey("From") && savedConnection.ContainsKey("To") && savedConnection.ContainsKey("FromPort") && savedConnection.ContainsKey("ToPort"); } private ScriptConnection CreateConnection(Dictionary savedConnection) { return new ScriptConnection { FromNodeId = savedConnection["From"].AsString(), FromPort = savedConnection["FromPort"].AsInt32(), ToNodeId = savedConnection["To"].AsString(), ToPort = savedConnection["ToPort"].AsInt32() }; } private void ConnectLoadedNodes( ScriptConnection connection, System.Collections.Generic.Dictionary loadedNodes ) { if (!loadedNodes.ContainsKey(connection.FromNodeId)) return; if (!loadedNodes.ContainsKey(connection.ToNodeId)) return; NodeDisplay fromDisplay = loadedNodes[connection.FromNodeId]; NodeDisplay toDisplay = loadedNodes[connection.ToNodeId]; connectNodes(fromDisplay.Name, connection.FromPort, toDisplay.Name, connection.ToPort); } private Array BuildSavedNodes() { Array savedNodes = new Array(); for (int i = 0; i < editorWindow.GetChildCount(); i++) { NodeDisplay nodeDisplay = editorWindow.GetChild(i) as NodeDisplay; if (nodeDisplay == null) continue; nodeDisplay.ReadParameters(); Dictionary savedNode = new Dictionary(); savedNode["Id"] = nodeDisplay.Name.ToString(); savedNode["Type"] = nodeDisplay.node.DisplayText.ToLower(); savedNode["Content"] = nodeDisplay.node.Save(); savedNode["PositionX"] = nodeDisplay.PositionOffset.X; savedNode["PositionY"] = nodeDisplay.PositionOffset.Y; savedNodes.Add(savedNode); } return savedNodes; } private Array BuildSavedConnections() { Array savedConnections = new Array(); foreach (Dictionary connection in editorWindow.GetConnectionList()) { Dictionary savedConnection = new Dictionary(); savedConnection["From"] = connection["from_node"].AsStringName().ToString(); savedConnection["FromPort"] = (int)connection["from_port"]; savedConnection["To"] = connection["to_node"].AsStringName().ToString(); savedConnection["ToPort"] = (int)connection["to_port"]; savedConnections.Add(savedConnection); } return savedConnections; } }