Finished first EA Version #1
@@ -1,6 +1,6 @@
|
|||||||
[gd_scene format=3 uid="uid://cinn18bl736rk"]
|
[gd_scene format=3 uid="uid://cinn18bl736rk"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://Scripts/UI/DSL/NodeDisplays/CraftNodeDisplay.cs" id="1_qemp1"]
|
[ext_resource type="Script" uid="uid://bfosue8mejnr5" path="res://Scripts/UI/DSL/NodeDisplays/CraftNodeDisplay.cs" id="1_qemp1"]
|
||||||
|
|
||||||
[node name="Craft" type="GraphNode" unique_id=908155742]
|
[node name="Craft" type="GraphNode" unique_id=908155742]
|
||||||
offset_right = 158.0
|
offset_right = 158.0
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ public class ForNode : ProgramNode
|
|||||||
{
|
{
|
||||||
amountExecuted = 0;
|
amountExecuted = 0;
|
||||||
}
|
}
|
||||||
return isConditionFulfilled ? NodeResult.CONDITIONFALSE : NodeResult.SUCCESS;
|
return isConditionFulfilled ? NodeResult.SUCCESS : NodeResult.CONDITIONFALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool DetermineCondition()
|
private bool DetermineCondition()
|
||||||
{
|
{
|
||||||
return amountExecuted < amount;
|
return amountExecuted >= amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ProgramNode Duplicate()
|
public override ProgramNode Duplicate()
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ public abstract class ProgramNode
|
|||||||
{
|
{
|
||||||
public ProgramNode nextNode;
|
public ProgramNode nextNode;
|
||||||
public ProgramNode NegativeNode;
|
public ProgramNode NegativeNode;
|
||||||
|
public string EditorNodeId;
|
||||||
public string DisplayText;
|
public string DisplayText;
|
||||||
public string TooltipText;
|
public string TooltipText;
|
||||||
public string lastExecutionMessage;
|
public string lastExecutionMessage;
|
||||||
@@ -13,6 +14,13 @@ public abstract class ProgramNode
|
|||||||
public abstract ProgramNode Duplicate();
|
public abstract ProgramNode Duplicate();
|
||||||
public abstract string Save();
|
public abstract string Save();
|
||||||
|
|
||||||
|
public ProgramNode DuplicateForRuntime(string editorNodeId)
|
||||||
|
{
|
||||||
|
ProgramNode duplicate = Duplicate();
|
||||||
|
duplicate.EditorNodeId = editorNodeId;
|
||||||
|
return duplicate;
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void SetNextNode(
|
public virtual void SetNextNode(
|
||||||
List<Godot.Collections.Dictionary> connections,
|
List<Godot.Collections.Dictionary> connections,
|
||||||
Dictionary<StringName, ProgramNode> availableNodes
|
Dictionary<StringName, ProgramNode> availableNodes
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ public partial class Robot : Node3D
|
|||||||
private const float CooldownTarget = 35f;
|
private const float CooldownTarget = 35f;
|
||||||
private const float MaintenanceLossPerSecond = 0.025f;
|
private const float MaintenanceLossPerSecond = 0.025f;
|
||||||
|
|
||||||
private bool isExecuting = false;
|
public bool isExecuting = false;
|
||||||
|
|
||||||
|
public ProgramNode programStartNode;
|
||||||
public ProgramNode currentNode;
|
public ProgramNode currentNode;
|
||||||
public string currentProgram;
|
public string currentProgram;
|
||||||
public string currentMessage = "";
|
public string currentMessage = "";
|
||||||
@@ -103,6 +104,7 @@ public partial class Robot : Node3D
|
|||||||
if (nodes.Count <= 0) return;
|
if (nodes.Count <= 0) return;
|
||||||
|
|
||||||
isExecuting = true;
|
isExecuting = true;
|
||||||
|
programStartNode = nodes[0];
|
||||||
currentNode = nodes[0];
|
currentNode = nodes[0];
|
||||||
currentMessage = "";
|
currentMessage = "";
|
||||||
}
|
}
|
||||||
@@ -110,6 +112,7 @@ public partial class Robot : Node3D
|
|||||||
public void StopExecution(string message)
|
public void StopExecution(string message)
|
||||||
{
|
{
|
||||||
isExecuting = false;
|
isExecuting = false;
|
||||||
|
programStartNode = null;
|
||||||
currentNode = null;
|
currentNode = null;
|
||||||
currentMessage = message;
|
currentMessage = message;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public partial class TestRunner : Node
|
|||||||
Run("If node evaluates inventory comparisons", TestIfNodeEvaluatesInventoryComparisons);
|
Run("If node evaluates inventory comparisons", TestIfNodeEvaluatesInventoryComparisons);
|
||||||
Run("While node reports false conditions", TestWhileNodeReportsFalseConditions);
|
Run("While node reports false conditions", TestWhileNodeReportsFalseConditions);
|
||||||
Run("For node stops after configured amount", TestForNodeStopsAfterConfiguredAmount);
|
Run("For node stops after configured amount", TestForNodeStopsAfterConfiguredAmount);
|
||||||
|
Run("Runtime node keeps editor id without sharing state", TestRuntimeNodeKeepsEditorIdWithoutSharingState);
|
||||||
Run("Start node succeeds immediately", TestStartNodeSucceedsImmediately);
|
Run("Start node succeeds immediately", TestStartNodeSucceedsImmediately);
|
||||||
Run("Split node connections restore both branches", TestSplitNodeConnectionsRestoreBothBranches);
|
Run("Split node connections restore both branches", TestSplitNodeConnectionsRestoreBothBranches);
|
||||||
Run("Linear node connection restores next node", TestLinearNodeConnectionRestoresNextNode);
|
Run("Linear node connection restores next node", TestLinearNodeConnectionRestoresNextNode);
|
||||||
@@ -479,6 +480,21 @@ public partial class TestRunner : Node
|
|||||||
AssertEqual(NodeResult.SUCCESS, node.Execute(null, 0), "loop finished");
|
AssertEqual(NodeResult.SUCCESS, node.Execute(null, 0), "loop finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TestRuntimeNodeKeepsEditorIdWithoutSharingState()
|
||||||
|
{
|
||||||
|
MoveNode editorNode = new MoveNode
|
||||||
|
{
|
||||||
|
targetPosition = new Vector3I(1, 0, 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
ProgramNode runtimeNode = editorNode.DuplicateForRuntime("MoveNode42");
|
||||||
|
MoveNode runtimeMoveNode = runtimeNode as MoveNode;
|
||||||
|
|
||||||
|
AssertFalse(ReferenceEquals(editorNode, runtimeNode), "runtime node should be a copy");
|
||||||
|
AssertEqual("MoveNode42", runtimeNode.EditorNodeId, "runtime node editor id");
|
||||||
|
AssertEqual(editorNode.targetPosition, runtimeMoveNode.targetPosition, "runtime node parameters");
|
||||||
|
}
|
||||||
|
|
||||||
private void TestStartNodeSucceedsImmediately()
|
private void TestStartNodeSucceedsImmediately()
|
||||||
{
|
{
|
||||||
StartNode node = new StartNode();
|
StartNode node = new StartNode();
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ public partial class CodingWindow : PanelContainer
|
|||||||
|
|
||||||
public System.Collections.Generic.Dictionary<ProgramNode, PackedScene> DSLNodes;
|
public System.Collections.Generic.Dictionary<ProgramNode, PackedScene> DSLNodes;
|
||||||
public NodeDisplay selectedNode;
|
public NodeDisplay selectedNode;
|
||||||
|
public NodeDisplay highlightedNode;
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
@@ -41,11 +42,63 @@ public partial class CodingWindow : PanelContainer
|
|||||||
editorWindow.RemoveChild(selectedNode);
|
editorWindow.RemoveChild(selectedNode);
|
||||||
selectedNode.QueueFree();
|
selectedNode.QueueFree();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (robot != null && Visible && robot.isExecuting)
|
||||||
|
{
|
||||||
|
UpdateCurrentNode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateCurrentNode()
|
||||||
|
{
|
||||||
|
if (robot.currentNode == null)
|
||||||
|
{
|
||||||
|
ClearHighlightedNode();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (highlightedNode != null)
|
||||||
|
{
|
||||||
|
if (IsCurrentRuntimeNode(highlightedNode))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearHighlightedNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Node child in editorWindow.GetChildren())
|
||||||
|
{
|
||||||
|
NodeDisplay nodeDisplay = child as NodeDisplay;
|
||||||
|
if (nodeDisplay == null) continue;
|
||||||
|
|
||||||
|
if (IsCurrentRuntimeNode(nodeDisplay))
|
||||||
|
{
|
||||||
|
nodeDisplay.SetHighlighted(true);
|
||||||
|
highlightedNode = nodeDisplay;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsCurrentRuntimeNode(NodeDisplay nodeDisplay)
|
||||||
|
{
|
||||||
|
return robot.currentNode.EditorNodeId != null
|
||||||
|
&& robot.currentNode.EditorNodeId.Length > 0
|
||||||
|
&& nodeDisplay.Name.ToString() == robot.currentNode.EditorNodeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearHighlightedNode()
|
||||||
|
{
|
||||||
|
if (highlightedNode == null) return;
|
||||||
|
|
||||||
|
highlightedNode.SetHighlighted(false);
|
||||||
|
highlightedNode = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnMapToggled(bool toggledOn)
|
public void OnMapToggled(bool toggledOn)
|
||||||
{
|
{
|
||||||
if(robot == null) return;
|
if (robot == null) return;
|
||||||
robot.showOnMap = toggledOn;
|
robot.showOnMap = toggledOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,6 +186,7 @@ public partial class CodingWindow : PanelContainer
|
|||||||
|
|
||||||
public void ClearWindow()
|
public void ClearWindow()
|
||||||
{
|
{
|
||||||
|
ClearHighlightedNode();
|
||||||
DisconnectAllNodes();
|
DisconnectAllNodes();
|
||||||
RemoveEditorNodes();
|
RemoveEditorNodes();
|
||||||
scriptName.Text = "";
|
scriptName.Text = "";
|
||||||
@@ -210,16 +264,18 @@ public partial class CodingWindow : PanelContainer
|
|||||||
public void LoadTemporaryProgram()
|
public void LoadTemporaryProgram()
|
||||||
{
|
{
|
||||||
if (robot == null) return;
|
if (robot == null) return;
|
||||||
if (robot.currentNode == null) return;
|
ProgramNode rootNode = robot.programStartNode ?? robot.currentNode;
|
||||||
|
if (rootNode == null) return;
|
||||||
|
|
||||||
RunningProgramGraphBuilder builder = new RunningProgramGraphBuilder(
|
RunningProgramGraphBuilder builder = new RunningProgramGraphBuilder(
|
||||||
DSLNodes,
|
DSLNodes,
|
||||||
AddLoadedNode,
|
AddLoadedNode,
|
||||||
ConnectNodes
|
ConnectNodes
|
||||||
);
|
);
|
||||||
builder.Load(robot.currentNode);
|
builder.Load(rootNode);
|
||||||
|
|
||||||
scriptName.Text = robot.currentProgram ?? "";
|
scriptName.Text = robot.currentProgram ?? "";
|
||||||
|
UpdateCurrentNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteProgram()
|
public void DeleteProgram()
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Godot;
|
|||||||
public partial class NodeDisplay : GraphNode
|
public partial class NodeDisplay : GraphNode
|
||||||
{
|
{
|
||||||
public ProgramNode node;
|
public ProgramNode node;
|
||||||
|
private bool isHighlighted = false;
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
@@ -48,6 +49,14 @@ public partial class NodeDisplay : GraphNode
|
|||||||
|
|
||||||
public virtual void ReadParameters() { }
|
public virtual void ReadParameters() { }
|
||||||
|
|
||||||
|
public void SetHighlighted(bool highlighted)
|
||||||
|
{
|
||||||
|
if (isHighlighted == highlighted) return;
|
||||||
|
|
||||||
|
isHighlighted = highlighted;
|
||||||
|
SelfModulate = highlighted ? UIStyle.GetWarningColor() : Colors.White;
|
||||||
|
}
|
||||||
|
|
||||||
public HBoxContainer GetValueContainer()
|
public HBoxContainer GetValueContainer()
|
||||||
{
|
{
|
||||||
return GetNode<HBoxContainer>("./Values");
|
return GetNode<HBoxContainer>("./Values");
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ public class RunningProgramGraphBuilder
|
|||||||
dslNodes
|
dslNodes
|
||||||
);
|
);
|
||||||
if (nodeDisplay == null) return null;
|
if (nodeDisplay == null) return null;
|
||||||
|
if (programNode.EditorNodeId != null && programNode.EditorNodeId.Length > 0)
|
||||||
|
{
|
||||||
|
nodeDisplay.Name = programNode.EditorNodeId;
|
||||||
|
}
|
||||||
|
|
||||||
addNode(nodeDisplay);
|
addNode(nodeDisplay);
|
||||||
loadedNodes.Add(programNode, nodeDisplay);
|
loadedNodes.Add(programNode, nodeDisplay);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using System.Collections.Generic;
|
|||||||
public class ScriptGraphCompiler
|
public class ScriptGraphCompiler
|
||||||
{
|
{
|
||||||
private readonly GraphEdit editorWindow;
|
private readonly GraphEdit editorWindow;
|
||||||
private System.Collections.Generic.Dictionary<StringName, ProgramNode> availableNodes;
|
private System.Collections.Generic.Dictionary<StringName, ProgramNode> runtimeNodes;
|
||||||
|
|
||||||
public ScriptGraphCompiler(GraphEdit editorWindow)
|
public ScriptGraphCompiler(GraphEdit editorWindow)
|
||||||
{
|
{
|
||||||
@@ -22,7 +22,7 @@ public class ScriptGraphCompiler
|
|||||||
return new List<ProgramNode>();
|
return new List<ProgramNode>();
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildAvailableNodeLookup();
|
BuildRuntimeNodeLookup();
|
||||||
return BuildScriptOrder(
|
return BuildScriptOrder(
|
||||||
startNode,
|
startNode,
|
||||||
new List<ProgramNode>(),
|
new List<ProgramNode>(),
|
||||||
@@ -30,9 +30,9 @@ public class ScriptGraphCompiler
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildAvailableNodeLookup()
|
private void BuildRuntimeNodeLookup()
|
||||||
{
|
{
|
||||||
availableNodes = new System.Collections.Generic.Dictionary<StringName, ProgramNode>();
|
runtimeNodes = new System.Collections.Generic.Dictionary<StringName, ProgramNode>();
|
||||||
|
|
||||||
for (int i = 0; i < editorWindow.GetChildCount(); i++)
|
for (int i = 0; i < editorWindow.GetChildCount(); i++)
|
||||||
{
|
{
|
||||||
@@ -40,7 +40,10 @@ public class ScriptGraphCompiler
|
|||||||
if (nodeDisplay == null) continue;
|
if (nodeDisplay == null) continue;
|
||||||
|
|
||||||
nodeDisplay.ReadParameters();
|
nodeDisplay.ReadParameters();
|
||||||
availableNodes.Add(nodeDisplay.Name, nodeDisplay.node);
|
runtimeNodes.Add(
|
||||||
|
nodeDisplay.Name,
|
||||||
|
nodeDisplay.node.DuplicateForRuntime(nodeDisplay.Name.ToString())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,14 +55,16 @@ public class ScriptGraphCompiler
|
|||||||
{
|
{
|
||||||
if (node == null) return program;
|
if (node == null) return program;
|
||||||
if (visitedNodes.Contains(node.Name)) return program;
|
if (visitedNodes.Contains(node.Name)) return program;
|
||||||
|
if (!runtimeNodes.ContainsKey(node.Name)) return program;
|
||||||
|
|
||||||
visitedNodes.Add(node.Name);
|
visitedNodes.Add(node.Name);
|
||||||
program.Add(node.node);
|
ProgramNode runtimeNode = runtimeNodes[node.Name];
|
||||||
|
program.Add(runtimeNode);
|
||||||
|
|
||||||
List<Dictionary> nextConnections = GetOutgoingConnections(node);
|
List<Dictionary> nextConnections = GetOutgoingConnections(node);
|
||||||
if (nextConnections.Count <= 0) return program;
|
if (nextConnections.Count <= 0) return program;
|
||||||
|
|
||||||
node.node.SetNextNode(nextConnections, availableNodes);
|
runtimeNode.SetNextNode(nextConnections, runtimeNodes);
|
||||||
foreach (Dictionary connection in nextConnections)
|
foreach (Dictionary connection in nextConnections)
|
||||||
{
|
{
|
||||||
NodeDisplay nextNode = editorWindow.GetNodeOrNull<NodeDisplay>(
|
NodeDisplay nextNode = editorWindow.GetNodeOrNull<NodeDisplay>(
|
||||||
|
|||||||
Reference in New Issue
Block a user