(WIP) Switch from previous DSL System (UI order based) to a new DSL System (node connection based) still in Progress.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[gd_scene format=3 uid="uid://co7op7et6is8p"]
|
||||
|
||||
[ext_resource type="Script" path="res://Scripts/UI/DSL/NodeDisplays/ForNodeDisplay.cs" id="1_xshi5"]
|
||||
[ext_resource type="Script" uid="uid://gptqyjv5swwc" path="res://Scripts/UI/DSL/NodeDisplays/ForNodeDisplay.cs" id="1_xshi5"]
|
||||
|
||||
[node name="For" type="GraphNode" unique_id=1235671673]
|
||||
offset_right = 229.0
|
||||
@@ -16,7 +16,7 @@ slot/0/right_type = 0
|
||||
slot/0/right_color = Color(1, 1, 1, 1)
|
||||
slot/0/right_icon = null
|
||||
slot/0/draw_stylebox = true
|
||||
slot/1/left_enabled = true
|
||||
slot/1/left_enabled = false
|
||||
slot/1/left_type = 0
|
||||
slot/1/left_color = Color(1, 1, 1, 1)
|
||||
slot/1/left_icon = null
|
||||
@@ -61,7 +61,7 @@ vertical_alignment = 1
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="." unique_id=1677882951]
|
||||
layout_mode = 2
|
||||
text = "Until"
|
||||
text = "Afterwards"
|
||||
fit_content = true
|
||||
autowrap_mode = 0
|
||||
horizontal_alignment = 1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[gd_scene format=3 uid="uid://ctmad6foidkvp"]
|
||||
|
||||
[ext_resource type="Script" path="res://Scripts/UI/DSL/NodeDisplays/IfNodeDisplay.cs" id="1_ygi5c"]
|
||||
[ext_resource type="Script" uid="uid://cngxwfcrim746" path="res://Scripts/UI/DSL/NodeDisplays/IfNodeDisplay.cs" id="1_ygi5c"]
|
||||
|
||||
[node name="If" type="GraphNode" unique_id=821127877]
|
||||
offset_right = 468.0
|
||||
@@ -16,7 +16,7 @@ slot/0/right_type = 0
|
||||
slot/0/right_color = Color(1, 1, 1, 1)
|
||||
slot/0/right_icon = null
|
||||
slot/0/draw_stylebox = true
|
||||
slot/1/left_enabled = true
|
||||
slot/1/left_enabled = false
|
||||
slot/1/left_type = 0
|
||||
slot/1/left_color = Color(1, 1, 1, 1)
|
||||
slot/1/left_icon = null
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
[gd_scene format=3 uid="uid://b1y4r3s7ukmfw"]
|
||||
|
||||
[ext_resource type="Script" path="res://Scripts/UI/DSL/NodeDisplays/StartNodeDisplay.cs" id="1_start"]
|
||||
|
||||
[node name="Start" type="GraphNode" unique_id=2100000001]
|
||||
offset_right = 65.0
|
||||
offset_bottom = 55.0
|
||||
title = "Start"
|
||||
slot/0/left_enabled = false
|
||||
slot/0/left_type = 0
|
||||
slot/0/left_color = Color(1, 1, 1, 1)
|
||||
slot/0/left_icon = null
|
||||
slot/0/right_enabled = true
|
||||
slot/0/right_type = 0
|
||||
slot/0/right_color = Color(1, 1, 1, 1)
|
||||
slot/0/right_icon = null
|
||||
slot/0/draw_stylebox = true
|
||||
script = ExtResource("1_start")
|
||||
|
||||
[node name="Control" type="Control" parent="." unique_id=2100000002]
|
||||
layout_mode = 2
|
||||
@@ -1,6 +1,6 @@
|
||||
[gd_scene format=3 uid="uid://bwiaqvl0d4x8v"]
|
||||
|
||||
[ext_resource type="Script" path="res://Scripts/UI/DSL/NodeDisplays/WhileNodeDisplay.cs" id="1_q0rc7"]
|
||||
[ext_resource type="Script" uid="uid://d3npiur46icru" path="res://Scripts/UI/DSL/NodeDisplays/WhileNodeDisplay.cs" id="1_q0rc7"]
|
||||
|
||||
[node name="While" type="GraphNode" unique_id=2040226700]
|
||||
offset_right = 499.0
|
||||
@@ -16,7 +16,7 @@ slot/0/right_type = 0
|
||||
slot/0/right_color = Color(1, 1, 1, 1)
|
||||
slot/0/right_icon = null
|
||||
slot/0/draw_stylebox = true
|
||||
slot/1/left_enabled = true
|
||||
slot/1/left_enabled = false
|
||||
slot/1/left_type = 0
|
||||
slot/1/left_color = Color(1, 1, 1, 1)
|
||||
slot/1/left_icon = null
|
||||
@@ -82,7 +82,7 @@ vertical_alignment = 1
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="." unique_id=1571031910]
|
||||
layout_mode = 2
|
||||
text = "Until"
|
||||
text = "Afterwards"
|
||||
fit_content = true
|
||||
autowrap_mode = 0
|
||||
horizontal_alignment = 1
|
||||
|
||||
@@ -66,6 +66,7 @@ public partial class ResourceLoader
|
||||
{
|
||||
Dictionary<ProgramNode, PackedScene> nodes = new Dictionary<ProgramNode, PackedScene>()
|
||||
{
|
||||
{ new StartNode(), GD.Load<PackedScene>("res://Prefabs/DSL/StartNode.tscn") },
|
||||
{ new MoveNode(), GD.Load<PackedScene>("res://Prefabs/DSL/MoveNode.tscn") },
|
||||
{ new HarvestNode(), GD.Load<PackedScene>("res://Prefabs/DSL/HarvestNode.tscn") },
|
||||
{ new CraftNode(), GD.Load<PackedScene>("res://Prefabs/DSL/CraftNode.tscn") },
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class ForNode : ProgramNode
|
||||
{
|
||||
@@ -34,4 +35,27 @@ public class ForNode : ProgramNode
|
||||
{
|
||||
return $"Name: {DisplayText}, AmountExecuted: {amountExecuted}, Amount: {amount}";
|
||||
}
|
||||
|
||||
public override void SetNextNode(
|
||||
List<Godot.Collections.Dictionary> connections,
|
||||
Dictionary<StringName, ProgramNode> availableNodes
|
||||
)
|
||||
{
|
||||
nextNode = null;
|
||||
NegativeNode = null;
|
||||
|
||||
foreach (Godot.Collections.Dictionary connection in connections)
|
||||
{
|
||||
int port = (int)connection["from_port"];
|
||||
ProgramNode connectedNode = GetConnectedNode(connection, availableNodes);
|
||||
if (port == 0)
|
||||
{
|
||||
nextNode = connectedNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
NegativeNode = connectedNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class IfNode : ProgramNode
|
||||
{
|
||||
@@ -56,4 +57,27 @@ public class IfNode : ProgramNode
|
||||
{
|
||||
return $"Name: {DisplayText}, Item: {(selectedItem == null ? "Empty" : selectedItem.data.Id)}, Comparator: {comparator}, Amount: {amount}";
|
||||
}
|
||||
|
||||
public override void SetNextNode(
|
||||
List<Godot.Collections.Dictionary> connections,
|
||||
Dictionary<StringName, ProgramNode> availableNodes
|
||||
)
|
||||
{
|
||||
nextNode = null;
|
||||
NegativeNode = null;
|
||||
|
||||
foreach (Godot.Collections.Dictionary connection in connections)
|
||||
{
|
||||
int port = (int)connection["from_port"];
|
||||
ProgramNode connectedNode = GetConnectedNode(connection, availableNodes);
|
||||
if (port == 0)
|
||||
{
|
||||
nextNode = connectedNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
NegativeNode = connectedNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ public class MoveNode : ProgramNode
|
||||
pathPoints.Remove(pathPoints[0]);
|
||||
if (pathPoints.Count <= 0)
|
||||
{
|
||||
pathPoints = null;
|
||||
lastExecutionMessage = "";
|
||||
return NodeResult.SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,37 @@
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public abstract class ProgramNode
|
||||
{
|
||||
public ProgramNode nextNode;
|
||||
public ProgramNode previousNode;
|
||||
public ProgramNode NegativeNode;
|
||||
public string DisplayText;
|
||||
public string lastExecutionMessage;
|
||||
|
||||
public abstract NodeResult Execute(Robot robot, double delta);
|
||||
public abstract ProgramNode Duplicate();
|
||||
public abstract string Save();
|
||||
|
||||
public virtual void SetNextNode(
|
||||
List<Godot.Collections.Dictionary> connections,
|
||||
Dictionary<StringName, ProgramNode> availableNodes
|
||||
)
|
||||
{
|
||||
nextNode = null;
|
||||
|
||||
if (connections.Count <= 0) return;
|
||||
|
||||
nextNode = GetConnectedNode(connections[0], availableNodes);
|
||||
}
|
||||
|
||||
protected ProgramNode GetConnectedNode(
|
||||
Godot.Collections.Dictionary connection,
|
||||
Dictionary<StringName, ProgramNode> availableNodes
|
||||
)
|
||||
{
|
||||
StringName nodeName = connection["to_node"].AsStringName();
|
||||
if (!availableNodes.ContainsKey(nodeName)) return null;
|
||||
|
||||
return availableNodes[nodeName];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
public class StartNode : ProgramNode
|
||||
{
|
||||
public StartNode()
|
||||
{
|
||||
DisplayText = "Start";
|
||||
}
|
||||
|
||||
public override NodeResult Execute(Robot robot, double delta)
|
||||
{
|
||||
return NodeResult.SUCCESS;
|
||||
}
|
||||
|
||||
public override ProgramNode Duplicate()
|
||||
{
|
||||
StartNode duplicate = new StartNode();
|
||||
return duplicate;
|
||||
}
|
||||
|
||||
public override string Save()
|
||||
{
|
||||
return $"Name: {DisplayText}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://d3kyu2j3nxjsh
|
||||
@@ -1,4 +1,5 @@
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class WhileNode : ProgramNode
|
||||
{
|
||||
@@ -57,4 +58,27 @@ public class WhileNode : ProgramNode
|
||||
{
|
||||
return $"Name: {DisplayText}, Item: {(selectedItem == null ? "Empty" : selectedItem.data.Id)}, Comparator: {comparator}, Amount: {amount}";
|
||||
}
|
||||
|
||||
public override void SetNextNode(
|
||||
List<Godot.Collections.Dictionary> connections,
|
||||
Dictionary<StringName, ProgramNode> availableNodes
|
||||
)
|
||||
{
|
||||
nextNode = null;
|
||||
NegativeNode = null;
|
||||
|
||||
foreach (Godot.Collections.Dictionary connection in connections)
|
||||
{
|
||||
int port = (int)connection["from_port"];
|
||||
ProgramNode connectedNode = GetConnectedNode(connection, availableNodes);
|
||||
if (port == 0)
|
||||
{
|
||||
nextNode = connectedNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
NegativeNode = connectedNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,26 +35,11 @@ public partial class Robot : Node3D
|
||||
{
|
||||
if (CanExecute(delta))
|
||||
{
|
||||
GD.Print(currentNode.DisplayText);
|
||||
switch (currentNode.Execute(this, delta))
|
||||
{
|
||||
case NodeResult.SUCCESS:
|
||||
if (currentNode.DisplayText == "Until")
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
currentNode = currentNode.previousNode;
|
||||
if (currentNode == null)
|
||||
{
|
||||
isExecuting = false;
|
||||
break;
|
||||
}
|
||||
if (currentNode.DisplayText == "For" || currentNode.DisplayText == "While") break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
currentNode = currentNode.nextNode;
|
||||
}
|
||||
currentNode = currentNode.nextNode;
|
||||
if (currentNode == null)
|
||||
{
|
||||
isExecuting = false;
|
||||
@@ -70,33 +55,10 @@ public partial class Robot : Node3D
|
||||
currentMessage = "";
|
||||
break;
|
||||
case NodeResult.CONDITIONFALSE:
|
||||
string sourceNode = currentNode.DisplayText;
|
||||
while (true)
|
||||
currentNode = currentNode.NegativeNode;
|
||||
if (currentNode == null)
|
||||
{
|
||||
currentNode = currentNode.nextNode;
|
||||
if (currentNode == null)
|
||||
{
|
||||
isExecuting = false;
|
||||
break;
|
||||
}
|
||||
if (sourceNode == "If")
|
||||
{
|
||||
if (currentNode.DisplayText == "If" || currentNode.DisplayText == "Else") break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentNode.DisplayText == "While" || currentNode.DisplayText == "For" || currentNode.DisplayText == "Until")
|
||||
{
|
||||
if (currentNode.nextNode == null)
|
||||
{
|
||||
isExecuting = false;
|
||||
break;
|
||||
}
|
||||
currentNode = currentNode.nextNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
isExecuting = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -133,6 +95,13 @@ public partial class Robot : Node3D
|
||||
currentMessage = "";
|
||||
}
|
||||
|
||||
public void StopExecution(string message)
|
||||
{
|
||||
isExecuting = false;
|
||||
currentNode = null;
|
||||
currentMessage = message;
|
||||
}
|
||||
|
||||
public float GetMovementSpeed()
|
||||
{
|
||||
return GameData.robotStats.GetMovementSpeed(GameData.robotSpeed)
|
||||
|
||||
@@ -35,6 +35,7 @@ public partial class TestRunner : Node
|
||||
Run("If node evaluates inventory comparisons", TestIfNodeEvaluatesInventoryComparisons);
|
||||
Run("While node reports false conditions", TestWhileNodeReportsFalseConditions);
|
||||
Run("For node stops after configured amount", TestForNodeStopsAfterConfiguredAmount);
|
||||
Run("Start node succeeds immediately", TestStartNodeSucceedsImmediately);
|
||||
Run("Paused world does not drain survival", TestPausedWorldDoesNotDrainSurvival);
|
||||
Run("Open gate hides gate content", TestOpenGateHidesGateContent);
|
||||
Run("Layer generation succeeds above threshold", TestLayerGenerationSuccessRate);
|
||||
@@ -476,6 +477,14 @@ public partial class TestRunner : Node
|
||||
AssertEqual(NodeResult.CONDITIONFALSE, node.Execute(null, 0), "loop finished");
|
||||
}
|
||||
|
||||
private void TestStartNodeSucceedsImmediately()
|
||||
{
|
||||
StartNode node = new StartNode();
|
||||
|
||||
AssertEqual(NodeResult.SUCCESS, node.Execute(null, 0), "start should succeed");
|
||||
AssertEqual("Name: Start", node.Save(), "start save");
|
||||
}
|
||||
|
||||
private void TestPausedWorldDoesNotDrainSurvival()
|
||||
{
|
||||
GameData.isPaused = true;
|
||||
@@ -549,6 +558,18 @@ public partial class TestRunner : Node
|
||||
AssertTrue(GameData.availableItems.ContainsKey("water"), "water item loaded");
|
||||
AssertTrue(GameData.availableResearch.ContainsKey("basics"), "basics research loaded");
|
||||
AssertTrue(GameData.availableResearch.ContainsKey("iron_robotics"), "iron robotics research loaded");
|
||||
|
||||
Dictionary<ProgramNode, PackedScene> dslNodes = ResourceLoader.LoadDSLNodes();
|
||||
bool hasStartNode = false;
|
||||
foreach (ProgramNode node in dslNodes.Keys)
|
||||
{
|
||||
if (node is StartNode)
|
||||
{
|
||||
hasStartNode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
AssertTrue(hasStartNode, "start node prefab loaded");
|
||||
}
|
||||
|
||||
private Layer CreateTestLayer(int level, string collapsedMesh)
|
||||
|
||||
@@ -13,6 +13,7 @@ public partial class CodingWindow : PanelContainer
|
||||
[Export] LineEdit nameInput;
|
||||
|
||||
public System.Collections.Generic.Dictionary<ProgramNode, PackedScene> DSLNodes;
|
||||
private System.Collections.Generic.Dictionary<StringName, ProgramNode> availableNodes;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
@@ -83,10 +84,19 @@ public partial class CodingWindow : PanelContainer
|
||||
private void AddEditorNode(ProgramNode node)
|
||||
{
|
||||
NodeDisplay editorDisplay = DSLNodes[node].Instantiate<NodeDisplay>();
|
||||
editorDisplay.PositionOffset = (editorWindow.ScrollOffset + editorWindow.Size / 2) / editorWindow.Zoom - editorDisplay.Size / 2;
|
||||
editorWindow.AddChild(editorDisplay);
|
||||
RegisterEditorNode(editorDisplay);
|
||||
}
|
||||
|
||||
private void MoveNodeToVisibleGraphCenter(NodeDisplay nodeDisplay)
|
||||
{
|
||||
Vector2 visibleCenter = editorWindow.ScrollOffset
|
||||
+ editorWindow.Size / (2f * editorWindow.Zoom);
|
||||
|
||||
nodeDisplay.PositionOffset = visibleCenter - nodeDisplay.Size / (2f * editorWindow.Zoom);
|
||||
}
|
||||
|
||||
private void RegisterEditorNode(NodeDisplay editorDisplay)
|
||||
{
|
||||
editorDisplay.OnDeleteNode += () =>
|
||||
@@ -121,7 +131,25 @@ public partial class CodingWindow : PanelContainer
|
||||
|
||||
public void CompileProgram()
|
||||
{
|
||||
List<ProgramNode> nodes = new List<ProgramNode>();
|
||||
if (robot == null) return;
|
||||
|
||||
NodeDisplay startNode = FindStartNode();
|
||||
if (startNode == null)
|
||||
{
|
||||
robot.StopExecution("(FAILED) Script needs exactly one Start node");
|
||||
return;
|
||||
}
|
||||
|
||||
availableNodes = BuildAvailableNodeLookup();
|
||||
List<ProgramNode> nodes = BuildScriptOrder(startNode, new List<ProgramNode>());
|
||||
if (nodes.Count > 0) robot.SetupExecution(nodes);
|
||||
robot.currentProgram = scriptName.Text.Length <= 0 ? $"Script{availableScripts.ItemCount}" : scriptName.Text;
|
||||
}
|
||||
|
||||
private System.Collections.Generic.Dictionary<StringName, ProgramNode> BuildAvailableNodeLookup()
|
||||
{
|
||||
System.Collections.Generic.Dictionary<StringName, ProgramNode> availableNodes =
|
||||
new System.Collections.Generic.Dictionary<StringName, ProgramNode>();
|
||||
|
||||
for (int i = 0; i < editorWindow.GetChildCount(); i++)
|
||||
{
|
||||
@@ -129,22 +157,56 @@ public partial class CodingWindow : PanelContainer
|
||||
if (nodeDisplay == null) continue;
|
||||
|
||||
nodeDisplay.ReadParameters();
|
||||
ProgramNode executableNode = nodeDisplay.node.Duplicate();
|
||||
nodes.Add(executableNode);
|
||||
|
||||
if (nodes.Count > 1)
|
||||
{
|
||||
nodes[nodes.Count - 2].nextNode = executableNode;
|
||||
}
|
||||
if (nodes.Count > 1)
|
||||
{
|
||||
executableNode.previousNode = nodes[nodes.Count - 2];
|
||||
}
|
||||
availableNodes.Add(nodeDisplay.Name, nodeDisplay.node);
|
||||
}
|
||||
|
||||
if (robot == null) return;
|
||||
if (nodes.Count > 0) robot.SetupExecution(nodes);
|
||||
robot.currentProgram = scriptName.Text.Length <= 0 ? $"Script{availableScripts.ItemCount}" : scriptName.Text;
|
||||
return availableNodes;
|
||||
}
|
||||
|
||||
private List<ProgramNode> BuildScriptOrder(NodeDisplay node, List<ProgramNode> program)
|
||||
{
|
||||
program.Add(node.node);
|
||||
if (editorWindow.GetConnectionListFromNode(node.Name).Count <= 0) return program;
|
||||
List<Dictionary> nextConnections = CheckNodeConnections(node);
|
||||
if (nextConnections.Count <= 0) return program;
|
||||
node.node.SetNextNode(nextConnections, availableNodes);
|
||||
foreach (Dictionary connection in nextConnections)
|
||||
{
|
||||
program = BuildScriptOrder(
|
||||
editorWindow.GetNode<NodeDisplay>(new NodePath(connection["to_node"].AsStringName())),
|
||||
program
|
||||
);
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
private List<Dictionary> CheckNodeConnections(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;
|
||||
}
|
||||
|
||||
public void SetRobot(Robot robot)
|
||||
@@ -177,14 +239,8 @@ public partial class CodingWindow : PanelContainer
|
||||
if (robot == null) return;
|
||||
if (robot.currentNode == null) return;
|
||||
|
||||
ProgramNode firstNode = robot.currentNode;
|
||||
while (firstNode.previousNode != null)
|
||||
{
|
||||
firstNode = firstNode.previousNode;
|
||||
}
|
||||
|
||||
HashSet<ProgramNode> loadedNodes = new HashSet<ProgramNode>();
|
||||
ProgramNode nodeToLoad = firstNode;
|
||||
ProgramNode nodeToLoad = robot.currentNode;
|
||||
while (nodeToLoad != null && !loadedNodes.Contains(nodeToLoad))
|
||||
{
|
||||
loadedNodes.Add(nodeToLoad);
|
||||
@@ -238,12 +294,10 @@ public partial class CodingWindow : PanelContainer
|
||||
|
||||
public void OnNodeConnect(StringName from, int fromPort, StringName to, int toPort)
|
||||
{
|
||||
GD.Print($"From {fromPort} to {toPort}");
|
||||
if (to == from) return;
|
||||
|
||||
foreach (Dictionary connection in editorWindow.GetConnectionList())
|
||||
{
|
||||
if (connection["to_node"].AsStringName() == to && (int)connection["to_port"] == toPort) return;
|
||||
if (connection["from_node"].AsStringName() == from && (int)connection["from_port"] == fromPort) return;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
public partial class StartNodeDisplay : NodeDisplay
|
||||
{
|
||||
protected override ProgramNode CreateProgramNode()
|
||||
{
|
||||
return new StartNode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://c7w5380k530wb
|
||||
@@ -81,7 +81,7 @@ public class Pathfinding
|
||||
|
||||
if (!aStar.ArePointsConnected(fromId, toId))
|
||||
{
|
||||
aStar.ConnectPoints(fromId, toId);
|
||||
aStar.ConnectPoints(fromId, toId, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ compatibility/default_parent_skeleton_in_mesh_instance_3d=true
|
||||
[application]
|
||||
|
||||
config/name="RuinAdventurer"
|
||||
run/main_scene="uid://dlommaelbbw2b"
|
||||
run/main_scene="res://Scenes/MainMenu.tscn"
|
||||
config/features=PackedStringArray("4.6", "C#", "Forward Plus")
|
||||
config/icon="res://icon.svg"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user