109 lines
2.6 KiB
C#
109 lines
2.6 KiB
C#
using Godot;
|
|
using Godot.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
public class ScriptGraphCompiler
|
|
{
|
|
private readonly GraphEdit editorWindow;
|
|
private System.Collections.Generic.Dictionary<StringName, ProgramNode> availableNodes;
|
|
|
|
public ScriptGraphCompiler(GraphEdit editorWindow)
|
|
{
|
|
this.editorWindow = editorWindow;
|
|
}
|
|
|
|
public List<ProgramNode> BuildProgram(out string errorMessage)
|
|
{
|
|
errorMessage = "";
|
|
NodeDisplay startNode = FindStartNode();
|
|
if (startNode == null)
|
|
{
|
|
errorMessage = "(FAILED) Script needs exactly one Start node";
|
|
return new List<ProgramNode>();
|
|
}
|
|
|
|
BuildAvailableNodeLookup();
|
|
return BuildScriptOrder(
|
|
startNode,
|
|
new List<ProgramNode>(),
|
|
new HashSet<StringName>()
|
|
);
|
|
}
|
|
|
|
private void BuildAvailableNodeLookup()
|
|
{
|
|
availableNodes = new System.Collections.Generic.Dictionary<StringName, ProgramNode>();
|
|
|
|
for (int i = 0; i < editorWindow.GetChildCount(); i++)
|
|
{
|
|
NodeDisplay nodeDisplay = editorWindow.GetChild(i) as NodeDisplay;
|
|
if (nodeDisplay == null) continue;
|
|
|
|
nodeDisplay.ReadParameters();
|
|
availableNodes.Add(nodeDisplay.Name, nodeDisplay.node);
|
|
}
|
|
}
|
|
|
|
private List<ProgramNode> BuildScriptOrder(
|
|
NodeDisplay node,
|
|
List<ProgramNode> program,
|
|
HashSet<StringName> visitedNodes
|
|
)
|
|
{
|
|
if (node == null) return program;
|
|
if (visitedNodes.Contains(node.Name)) return program;
|
|
|
|
visitedNodes.Add(node.Name);
|
|
program.Add(node.node);
|
|
|
|
List<Dictionary> nextConnections = GetOutgoingConnections(node);
|
|
if (nextConnections.Count <= 0) return program;
|
|
|
|
node.node.SetNextNode(nextConnections, availableNodes);
|
|
foreach (Dictionary connection in nextConnections)
|
|
{
|
|
NodeDisplay nextNode = editorWindow.GetNodeOrNull<NodeDisplay>(
|
|
new NodePath(connection["to_node"].AsStringName())
|
|
);
|
|
program = BuildScriptOrder(
|
|
nextNode,
|
|
program,
|
|
visitedNodes
|
|
);
|
|
}
|
|
|
|
return program;
|
|
}
|
|
|
|
private List<Dictionary> GetOutgoingConnections(NodeDisplay node)
|
|
{
|
|
List<Dictionary> result = new List<Dictionary>();
|
|
Array<Dictionary> connections = editorWindow.GetConnectionListFromNode(node.Name);
|
|
for (int i = 0; i < connections.Count; i++)
|
|
{
|
|
if (connections[i]["from_node"].AsStringName() == node.Name)
|
|
{
|
|
result.Add(connections[i]);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private NodeDisplay FindStartNode()
|
|
{
|
|
NodeDisplay startNode = null;
|
|
for (int i = 0; i < editorWindow.GetChildCount(); i++)
|
|
{
|
|
NodeDisplay nodeDisplay = editorWindow.GetChild(i) as NodeDisplay;
|
|
if (nodeDisplay == null) continue;
|
|
if (nodeDisplay.node is not StartNode) continue;
|
|
if (startNode != null) return null;
|
|
|
|
startNode = nodeDisplay;
|
|
}
|
|
|
|
return startNode;
|
|
}
|
|
}
|