Big project cleanup with overhaul of file responsibilities (KISS) and code (DRY, YAGNI)
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user