Cleaned up project with better structure.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
using Godot;
|
||||
using static GameData;
|
||||
|
||||
public partial class Camera3d : Camera3D
|
||||
{
|
||||
[Export] public float Speed = 7.5f;
|
||||
[Export] public float MouseSensitivity = 0.2f;
|
||||
[Export] public float ScrollStrength = 5.0f;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
Position = new Vector3(0, 0, tileWidth / 2);
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (canMove) MoveCamera(delta);
|
||||
}
|
||||
|
||||
public void MoveCamera(double delta)
|
||||
{
|
||||
float d = (float)delta;
|
||||
|
||||
Vector3 rotation = RotationDegrees;
|
||||
rotation.X = Mathf.Clamp(rotation.X, -90f, 90f);
|
||||
RotationDegrees = rotation;
|
||||
|
||||
Vector3 direction = Vector3.Zero;
|
||||
if (Input.IsActionPressed("move_forward") && Position.Z > 0) direction += Transform.Basis.Z;
|
||||
if (Input.IsActionPressed("move_backward") && Position.Z < layerSize * 6) direction -= Transform.Basis.Z;
|
||||
if (Input.IsActionPressed("move_left") && Position.X > 0) direction -= Transform.Basis.X;
|
||||
if (Input.IsActionPressed("move_right") && Position.X < layerSize * 6) direction += Transform.Basis.X;
|
||||
|
||||
if (direction != Vector3.Zero)
|
||||
{
|
||||
direction = direction.Normalized() * Speed * (Input.IsActionPressed("sprint") ? 2.5f : 1) * d;
|
||||
Translate(direction);
|
||||
}
|
||||
|
||||
if (Position.Y != 10 - visibleLayer * 4)
|
||||
{
|
||||
Position = new Vector3(Position.X, 10 - visibleLayer * 4, Position.Z);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://c7khr6oist3ku
|
||||
@@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Godot;
|
||||
|
||||
public partial class UIHandler : Control
|
||||
{
|
||||
[Export] CodingWindow codingWindow;
|
||||
[Export] RobotList robotList;
|
||||
[Export] Camera3D mainCam;
|
||||
[Export] Map map;
|
||||
[Export] RichTextLabel FPS;
|
||||
[Export] RichTextLabel RAM;
|
||||
[Export] PanelContainer options;
|
||||
[Export] Control uiContent;
|
||||
[Export] PanelContainer menu;
|
||||
[Export] PanelContainer inventory;
|
||||
[Export] ResearchList researchList;
|
||||
[Export] TextureRect robotAlarm;
|
||||
|
||||
private bool receivedRobotJumpSignal = false;
|
||||
public override void _Ready()
|
||||
{
|
||||
robotList.OnRobotJumpTo += OnRobotJumpTo;
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
robotList.OnRobotJumpTo -= OnRobotJumpTo;
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
DisplayStats();
|
||||
DisplayRobotAlarm();
|
||||
|
||||
Control focused = GetViewport().GuiGetFocusOwner();
|
||||
|
||||
if (focused is LineEdit || focused is TextEdit)
|
||||
return;
|
||||
|
||||
if (Input.IsActionJustPressed("map")) HandleMapButton();
|
||||
if (Input.IsActionJustPressed("menu")) HandleMenuButton();
|
||||
if (Input.IsActionJustPressed("robot_list")) HandleRobotListButton();
|
||||
if (Input.IsActionJustPressed("inventory")) HandleInventoryButton();
|
||||
if (Input.IsActionJustPressed("research")) HandleResearchButton();
|
||||
}
|
||||
|
||||
public void HandleMenuButton()
|
||||
{
|
||||
OpenUIElement(menu);
|
||||
}
|
||||
|
||||
public void HandleMenu()
|
||||
{
|
||||
HandleMenuButton();
|
||||
}
|
||||
|
||||
public void ShowOptions()
|
||||
{
|
||||
OpenUIElement(options);
|
||||
}
|
||||
|
||||
public void HandleMapButton()
|
||||
{
|
||||
OpenUIElement(map);
|
||||
if (map.Visible) map.ShowMap();
|
||||
}
|
||||
|
||||
public void HandleRobotListButton()
|
||||
{
|
||||
receivedRobotJumpSignal = false;
|
||||
OpenUIElement(robotList);
|
||||
}
|
||||
|
||||
public void HandleInventoryButton()
|
||||
{
|
||||
OpenUIElement(inventory);
|
||||
}
|
||||
|
||||
public void HandleResearchButton()
|
||||
{
|
||||
OpenUIElement(researchList);
|
||||
if (researchList.Visible) researchList.SetupGraph();
|
||||
}
|
||||
|
||||
public void DisplayStats()
|
||||
{
|
||||
FPS.Text = Engine.GetFramesPerSecond().ToString() + " FPS";
|
||||
double memory = Process.GetCurrentProcess().WorkingSet64 / (1024 * 1024);
|
||||
string memoryDisplay = memory > 1024 ? Math.Round(memory / 1024, 2).ToString() + " GB" : memory.ToString() + " MB";
|
||||
RAM.Text = memoryDisplay;
|
||||
}
|
||||
|
||||
public void ExitGame()
|
||||
{
|
||||
GetTree().ChangeSceneToFile("res://Scenes/MainMenu.tscn");
|
||||
}
|
||||
|
||||
public void OpenUIElement(Control element)
|
||||
{
|
||||
if (element.Visible)
|
||||
{
|
||||
element.Hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
element.Show();
|
||||
}
|
||||
HideUIElements(element);
|
||||
}
|
||||
|
||||
private void HideUIElements(Control element)
|
||||
{
|
||||
foreach (PanelContainer child in uiContent.GetChildren())
|
||||
{
|
||||
if (child == element) continue;
|
||||
child.Visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void DisplayRobotAlarm()
|
||||
{
|
||||
string messages = "";
|
||||
foreach (Robot robot in GameData.robots)
|
||||
{
|
||||
if (robot.currentMessage.Length > 0)
|
||||
{
|
||||
messages += $"{robot.Name}: {robot.currentMessage}\r";
|
||||
}
|
||||
}
|
||||
robotAlarm.Visible = messages.Length > 0;
|
||||
robotAlarm.TooltipText = messages;
|
||||
}
|
||||
|
||||
private void OnRobotJumpTo(Robot robot)
|
||||
{
|
||||
if (receivedRobotJumpSignal) return;
|
||||
|
||||
receivedRobotJumpSignal = true;
|
||||
mainCam.Position = new Vector3(robot.Position.X, mainCam.Position.Y, robot.Position.Z + 3f);
|
||||
codingWindow.SetRobot(robot);
|
||||
OpenUIElement(codingWindow);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://bm7knir4552j5
|
||||
@@ -0,0 +1,165 @@
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public partial class CodingWindow : PanelContainer
|
||||
{
|
||||
private Robot robot;
|
||||
|
||||
[Export] VBoxContainer codeBlocks;
|
||||
[Export] VBoxContainer editorWindow;
|
||||
[Export] OptionButton availableScripts;
|
||||
[Export] LineEdit scriptName;
|
||||
[Export] LineEdit nameInput;
|
||||
|
||||
public Dictionary<ProgramNode, PackedScene> DSLNodes;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
DSLNodes = ResourceLoader.LoadDSLNodes();
|
||||
GenerateCodingBlocks();
|
||||
}
|
||||
|
||||
public override void _Notification(int id)
|
||||
{
|
||||
if (id == NotificationVisibilityChanged)
|
||||
{
|
||||
if (Visible) LoadWindow();
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadWindow()
|
||||
{
|
||||
if (robot == null) return;
|
||||
|
||||
nameInput.Text = robot.Name;
|
||||
SetupScriptOptions();
|
||||
ClearWindow();
|
||||
}
|
||||
|
||||
private void SetupScriptOptions()
|
||||
{
|
||||
availableScripts.Clear();
|
||||
availableScripts.AddItem("Select script to load...");
|
||||
List<string> scripts = FileHandler.LoadProgramNames();
|
||||
scripts.Sort((a, b) => a.CompareTo(b));
|
||||
foreach (string script in scripts)
|
||||
{
|
||||
availableScripts.AddItem(script);
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveRobotName()
|
||||
{
|
||||
if (robot == null) return;
|
||||
|
||||
robot.Name = nameInput.Text;
|
||||
}
|
||||
|
||||
public void CloseWindow()
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
||||
public void GenerateCodingBlocks()
|
||||
{
|
||||
NodeDisplay nodeDisplay;
|
||||
foreach (ProgramNode nodeTemplate in DSLNodes.Keys)
|
||||
{
|
||||
nodeDisplay = DSLNodes[nodeTemplate].Instantiate<NodeDisplay>();
|
||||
nodeDisplay.node = nodeTemplate;
|
||||
codeBlocks.AddChild(nodeDisplay);
|
||||
nodeDisplay.ShowListDisplay();
|
||||
nodeDisplay.listDisplay.Pressed += () =>
|
||||
{
|
||||
AddEditorNode(DSLNodes[nodeTemplate], nodeTemplate.Duplicate());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void AddEditorNode(PackedScene prefab, ProgramNode node)
|
||||
{
|
||||
NodeDisplay editorDisplay = prefab.Instantiate<NodeDisplay>();
|
||||
editorDisplay.node = node;
|
||||
editorWindow.AddChild(editorDisplay);
|
||||
editorDisplay.ShowEditorDisplay();
|
||||
editorDisplay.OnDeleteNode += () =>
|
||||
{
|
||||
editorWindow.RemoveChild(editorDisplay);
|
||||
editorDisplay.QueueFree();
|
||||
};
|
||||
}
|
||||
|
||||
public void ClearWindow()
|
||||
{
|
||||
foreach (Node node in editorWindow.GetChildren())
|
||||
{
|
||||
editorWindow.RemoveChild(node);
|
||||
node.QueueFree();
|
||||
}
|
||||
scriptName.Text = "";
|
||||
}
|
||||
|
||||
public void CompileProgram()
|
||||
{
|
||||
List<ProgramNode> nodes = new List<ProgramNode>();
|
||||
|
||||
for (int i = 0; i < editorWindow.GetChildCount(); i++)
|
||||
{
|
||||
NodeDisplay nodeDisplay = editorWindow.GetChild<NodeDisplay>(i);
|
||||
nodeDisplay.node.ReadParameters(nodeDisplay);
|
||||
nodes.Add(nodeDisplay.node.Duplicate());
|
||||
if (i != 0)
|
||||
{
|
||||
nodes[i - 1].nextNode = nodes[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (robot == null) return;
|
||||
if (nodes.Count > 0) robot.SetupExecution(nodes);
|
||||
robot.currentProgram = scriptName.Text.Length <= 0 ? $"Script{availableScripts.ItemCount}" : scriptName.Text;
|
||||
}
|
||||
|
||||
public void SetRobot(Robot robot)
|
||||
{
|
||||
this.robot = robot;
|
||||
}
|
||||
|
||||
public void LoadProgram(int index)
|
||||
{
|
||||
ClearWindow();
|
||||
string scriptContent = FileHandler.LoadProgram(availableScripts.GetItemText(index));
|
||||
string[] nodes = scriptContent.Split(";");
|
||||
foreach (string node in nodes)
|
||||
{
|
||||
NodeDisplay nodeDisplay = NodeDisplay.Load(node, DSLNodes);
|
||||
if (nodeDisplay != null)
|
||||
{
|
||||
editorWindow.AddChild(nodeDisplay);
|
||||
nodeDisplay.ShowEditorDisplay();
|
||||
nodeDisplay.OnDeleteNode += () =>
|
||||
{
|
||||
editorWindow.RemoveChild(nodeDisplay);
|
||||
nodeDisplay.QueueFree();
|
||||
};
|
||||
}
|
||||
}
|
||||
scriptName.Text = availableScripts.GetItemText(index);
|
||||
availableScripts.Select(0);
|
||||
}
|
||||
|
||||
public void SaveProgram()
|
||||
{
|
||||
string result = "";
|
||||
for (int i = 0; i < editorWindow.GetChildCount(); i++)
|
||||
{
|
||||
NodeDisplay nodeDisplay = editorWindow.GetChild<NodeDisplay>(i);
|
||||
nodeDisplay.node.ReadParameters(nodeDisplay);
|
||||
result += nodeDisplay.node.Save();
|
||||
result += ";\r\n";
|
||||
}
|
||||
if (result.Length <= 0) return;
|
||||
string filename = scriptName.Text.Length <= 0 ? $"Script{availableScripts.ItemCount}" : scriptName.Text;
|
||||
FileHandler.SaveProgram(filename, result);
|
||||
SetupScriptOptions();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://bsd6n6b06a4pe
|
||||
@@ -0,0 +1,135 @@
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
|
||||
public partial class NodeDisplay : PanelContainer
|
||||
{
|
||||
[Export] PanelContainer editorDisplay;
|
||||
[Export] public Button listDisplay;
|
||||
public ProgramNode node;
|
||||
|
||||
[Signal]
|
||||
public delegate void OnDeleteNodeEventHandler();
|
||||
|
||||
public void SetNode(ProgramNode node)
|
||||
{
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
if (node == null) return;
|
||||
|
||||
node.Setup(this);
|
||||
}
|
||||
|
||||
public void ShowListDisplay()
|
||||
{
|
||||
editorDisplay.Visible = false;
|
||||
listDisplay.Visible = true;
|
||||
}
|
||||
|
||||
public void ShowEditorDisplay()
|
||||
{
|
||||
editorDisplay.Visible = true;
|
||||
listDisplay.Visible = false;
|
||||
}
|
||||
|
||||
public void DeleteNodePressed()
|
||||
{
|
||||
EmitSignal(SignalName.OnDeleteNode);
|
||||
}
|
||||
|
||||
public static NodeDisplay Load(string content, Dictionary<ProgramNode, PackedScene> DSLNodes)
|
||||
{
|
||||
string nodeSanitized = content.Replace("\r\n", "").Trim();
|
||||
if (nodeSanitized.Length <= 0) return null;
|
||||
|
||||
string nodeName = nodeSanitized.Split(",")[0].Replace("Name: ", "").ToLower();
|
||||
PackedScene prefab = GetPrefab(nodeName, DSLNodes);
|
||||
if (prefab == null) return null;
|
||||
|
||||
NodeDisplay result = prefab.Instantiate<NodeDisplay>();
|
||||
|
||||
switch (nodeName)
|
||||
{
|
||||
case "move":
|
||||
result.node = new MoveNode();
|
||||
result.LoadMove(nodeSanitized);
|
||||
break;
|
||||
case "harvest":
|
||||
result.node = new HarvestNode();
|
||||
result.LoadHarvest(nodeSanitized);
|
||||
break;
|
||||
case "explore":
|
||||
result.node = new ExploreNode();
|
||||
result.LoadExplore(nodeSanitized);
|
||||
break;
|
||||
case "craft":
|
||||
result.node = new CraftNode();
|
||||
result.LoadCraft(nodeSanitized);
|
||||
break;
|
||||
default:
|
||||
result.QueueFree();
|
||||
return null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static PackedScene GetPrefab(string nodeName, Dictionary<ProgramNode, PackedScene> DSLNodes)
|
||||
{
|
||||
foreach (ProgramNode programNode in DSLNodes.Keys)
|
||||
{
|
||||
if (programNode.DisplayText.ToLower() == nodeName)
|
||||
{
|
||||
return DSLNodes[programNode];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void LoadHarvest(string content)
|
||||
{
|
||||
}
|
||||
|
||||
public void LoadMove(string content)
|
||||
{
|
||||
HBoxContainer valueContainer = GetNode<HBoxContainer>("./EditorDisplay/HBoxContainer/");
|
||||
string[] parts = content.Split(",");
|
||||
string positionValues = parts[1].Replace("Position: ", "").Replace("(", "").Replace(")", "");
|
||||
int posX = int.Parse(positionValues.Split("|")[0]);
|
||||
int posY = int.Parse(positionValues.Split("|")[1]);
|
||||
int posZ = int.Parse(positionValues.Split("|")[2]);
|
||||
valueContainer.GetNode<SpinBox>("./CoordinateX").Value = posX;
|
||||
valueContainer.GetNode<SpinBox>("./CoordinateY").Value = posY;
|
||||
valueContainer.GetNode<SpinBox>("./CoordinateZ").Value = posZ;
|
||||
|
||||
MoveNode moveNode = node as MoveNode;
|
||||
if (moveNode != null)
|
||||
{
|
||||
moveNode.targetPosition = new Vector3I(posX, posY, posZ);
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadExplore(string content)
|
||||
{
|
||||
}
|
||||
|
||||
public void LoadCraft(string content)
|
||||
{
|
||||
HBoxContainer valueContainer = GetNode<HBoxContainer>("./EditorDisplay/HBoxContainer/");
|
||||
string[] parts = content.Split(",");
|
||||
string itemString = parts[1].Replace("Item: ", "").Replace(" ", "");
|
||||
if (itemString.ToLower() != "empty")
|
||||
{
|
||||
CraftNode craftNode = node as CraftNode;
|
||||
if (craftNode != null)
|
||||
{
|
||||
craftNode.selectedItem = new Item { data = GameData.availableItems[itemString] };
|
||||
}
|
||||
}
|
||||
string amountString = parts[2].Replace("Amount: ", "");
|
||||
valueContainer.GetNode<SpinBox>("./Amount").Value = int.Parse(amountString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://b6kxwmuhmruul
|
||||
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using Godot;
|
||||
|
||||
public partial class InventoryDisplay : PanelContainer
|
||||
{
|
||||
private PackedScene itemDisplayPrefab = ResourceLoader.LoadItemDisplay();
|
||||
[Export] VBoxContainer itemList;
|
||||
[Export] RichTextLabel inventorySpace;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
GameData.inventory.OnInventoryUpdate += OnInventoryUpdate;
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
GameData.inventory.OnInventoryUpdate -= OnInventoryUpdate;
|
||||
}
|
||||
|
||||
public override void _Notification(int id)
|
||||
{
|
||||
if (id == NotificationVisibilityChanged)
|
||||
{
|
||||
if (!Visible) return;
|
||||
|
||||
ReloadItems();
|
||||
UpdateInventorySpace();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateInventorySpace()
|
||||
{
|
||||
inventorySpace.Text = $"Used space: {GameData.inventory.items.Count}/{GameData.inventory.maxInventorySize}";
|
||||
}
|
||||
|
||||
public void ReloadItems()
|
||||
{
|
||||
foreach (Node node in itemList.GetChildren())
|
||||
{
|
||||
itemList.RemoveChild(node);
|
||||
node.QueueFree();
|
||||
}
|
||||
|
||||
ItemDisplay display;
|
||||
|
||||
foreach (Item item in GameData.inventory.items)
|
||||
{
|
||||
display = itemDisplayPrefab.Instantiate<ItemDisplay>();
|
||||
display.item = item;
|
||||
display.text.Text = item.data.GetReadableName();
|
||||
display.amount.Text = $"{item.currentAmount}/{item.data.StackSize}";
|
||||
display.texture.Texture = ResourceLoader.LoadPath(item.data.Texture);
|
||||
itemList.AddChild(display);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnInventoryUpdate(object sender, EventArgs args)
|
||||
{
|
||||
ReloadItems();
|
||||
UpdateInventorySpace();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://com0u7nqag6pp
|
||||
@@ -0,0 +1,9 @@
|
||||
using Godot;
|
||||
|
||||
public partial class ItemDisplay : PanelContainer
|
||||
{
|
||||
[Export] public TextureRect texture;
|
||||
[Export] public RichTextLabel text;
|
||||
[Export] public RichTextLabel amount;
|
||||
public Item item;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://qdjn5oqn6p5d
|
||||
@@ -0,0 +1,14 @@
|
||||
using Godot;
|
||||
|
||||
public partial class MainMenu : Control
|
||||
{
|
||||
public void OnPlayPressed()
|
||||
{
|
||||
GetTree().ChangeSceneToFile("res://Scenes/Game.tscn");
|
||||
}
|
||||
|
||||
public void OnQuitPressed()
|
||||
{
|
||||
GetTree().Quit();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://dda0bhhqspbr0
|
||||
@@ -0,0 +1,179 @@
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
public partial class ResearchList : PanelContainer
|
||||
{
|
||||
[Export] private GraphEdit researchGraph;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
RecalculateResearchStates();
|
||||
if (Visible) SetupGraph();
|
||||
}
|
||||
|
||||
public void SetupGraph()
|
||||
{
|
||||
ClearGraph();
|
||||
CreateResearchNodes();
|
||||
CreateResearchConnections();
|
||||
researchGraph.ArrangeNodes();
|
||||
}
|
||||
|
||||
private void ClearGraph()
|
||||
{
|
||||
foreach (Dictionary connection in researchGraph.GetConnectionList())
|
||||
{
|
||||
researchGraph.DisconnectNode(
|
||||
connection["from_node"].AsStringName(),
|
||||
(int)connection["from_port"],
|
||||
connection["to_node"].AsStringName(),
|
||||
(int)connection["to_port"]
|
||||
);
|
||||
}
|
||||
|
||||
foreach (Node child in researchGraph.GetChildren())
|
||||
{
|
||||
if (child is GraphNode)
|
||||
{
|
||||
researchGraph.RemoveChild(child);
|
||||
child.QueueFree();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateResearchNodes()
|
||||
{
|
||||
foreach (Research research in GameData.availableResearch.Values)
|
||||
{
|
||||
GraphNode node = CreateResearchNode(
|
||||
research.data.Id,
|
||||
research.data.Texture,
|
||||
research.state
|
||||
);
|
||||
|
||||
researchGraph.AddChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateResearchConnections()
|
||||
{
|
||||
foreach (Research research in GameData.availableResearch.Values)
|
||||
{
|
||||
string prerequisite = research.data.Research;
|
||||
string current = research.data.Id;
|
||||
|
||||
if (string.IsNullOrEmpty(prerequisite)) continue;
|
||||
|
||||
if (!researchGraph.HasNode(prerequisite) || !researchGraph.HasNode(current)) continue;
|
||||
|
||||
researchGraph.ConnectNode(
|
||||
prerequisite,
|
||||
0,
|
||||
current,
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private GraphNode CreateResearchNode(string id, string texturePath, ResearchState state)
|
||||
{
|
||||
Texture2D texture = GD.Load<Texture2D>(texturePath);
|
||||
Color stateColor = GetColorByState(state);
|
||||
|
||||
TextureRect icon = new TextureRect
|
||||
{
|
||||
Texture = texture,
|
||||
StretchMode = TextureRect.StretchModeEnum.KeepAspectCentered,
|
||||
CustomMinimumSize = new Vector2(64, 64),
|
||||
SelfModulate = stateColor
|
||||
};
|
||||
|
||||
Button button = new Button
|
||||
{
|
||||
Text = "Research",
|
||||
Disabled = state != ResearchState.AVAILABLE
|
||||
};
|
||||
|
||||
button.Pressed += () => OnResearchPressed(id);
|
||||
|
||||
GraphNode node = new GraphNode
|
||||
{
|
||||
Name = id,
|
||||
Title = id,
|
||||
SelfModulate = stateColor
|
||||
};
|
||||
|
||||
node.SetSlot(
|
||||
0,
|
||||
true,
|
||||
0,
|
||||
Colors.White,
|
||||
true,
|
||||
0,
|
||||
Colors.White
|
||||
);
|
||||
|
||||
node.AddChild(icon);
|
||||
node.AddChild(button);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
private void OnResearchPressed(string id)
|
||||
{
|
||||
GameData.availableResearch[id].state = ResearchState.RESEARCHED;
|
||||
RecalculateResearchStates();
|
||||
SetupGraph();
|
||||
}
|
||||
|
||||
private void RecalculateResearchStates()
|
||||
{
|
||||
bool changedState = true;
|
||||
|
||||
while (changedState)
|
||||
{
|
||||
changedState = false;
|
||||
|
||||
foreach (Research research in GameData.availableResearch.Values)
|
||||
{
|
||||
ResearchState newState = GetUpdatedResearchState(research);
|
||||
|
||||
if (research.state == newState) continue;
|
||||
|
||||
research.state = newState;
|
||||
changedState = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ResearchState GetUpdatedResearchState(Research research)
|
||||
{
|
||||
if (research.state == ResearchState.RESEARCHED)
|
||||
{
|
||||
return ResearchState.RESEARCHED;
|
||||
}
|
||||
|
||||
if (research.data.Research.Length <= 0)
|
||||
{
|
||||
return ResearchState.RESEARCHED;
|
||||
}
|
||||
|
||||
if (GameData.availableResearch[research.data.Research].state == ResearchState.RESEARCHED)
|
||||
{
|
||||
return ResearchState.AVAILABLE;
|
||||
}
|
||||
|
||||
return ResearchState.LOCKED;
|
||||
}
|
||||
|
||||
private Color GetColorByState(ResearchState state)
|
||||
{
|
||||
return state switch
|
||||
{
|
||||
ResearchState.AVAILABLE => Colors.White,
|
||||
ResearchState.LOCKED => new Color(0.6f, 0.6f, 0.6f, 0.5f),
|
||||
ResearchState.RESEARCHED => new Color(0.7f, 1f, 0.7f, 1f),
|
||||
_ => Colors.Red
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://drscsrkfphpy7
|
||||
@@ -0,0 +1,24 @@
|
||||
using Godot;
|
||||
|
||||
public partial class RobotDisplay : PanelContainer
|
||||
{
|
||||
[Export] public RichTextLabel listItem;
|
||||
[Export] public RichTextLabel currentScript;
|
||||
[Signal]
|
||||
public delegate void OnRobotJumpToEventHandler(Robot robot);
|
||||
public Robot robot;
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
string programName = robot.currentProgram ?? "";
|
||||
if (programName != currentScript.Text)
|
||||
{
|
||||
currentScript.Text = programName;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnJumpToClicked()
|
||||
{
|
||||
EmitSignal(SignalName.OnRobotJumpTo, robot);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://dcxom1paffp0p
|
||||
@@ -0,0 +1,45 @@
|
||||
using Godot;
|
||||
|
||||
public partial class RobotList : PanelContainer
|
||||
{
|
||||
[Export] VBoxContainer robotList;
|
||||
[Signal]
|
||||
public delegate void OnRobotJumpToEventHandler(Robot robot);
|
||||
private PackedScene robotDisplayPrefab;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
robotDisplayPrefab = ResourceLoader.LoadRobotDisplay();
|
||||
}
|
||||
|
||||
public override void _Notification(int id)
|
||||
{
|
||||
if (id == NotificationVisibilityChanged)
|
||||
{
|
||||
if (Visible) ReloadRobots();
|
||||
}
|
||||
}
|
||||
|
||||
public void ReloadRobots()
|
||||
{
|
||||
foreach (Node node in robotList.GetChildren())
|
||||
{
|
||||
robotList.RemoveChild(node);
|
||||
node.QueueFree();
|
||||
}
|
||||
RobotDisplay display;
|
||||
|
||||
foreach (Robot robotObject in GameData.robots)
|
||||
{
|
||||
display = robotDisplayPrefab.Instantiate<RobotDisplay>();
|
||||
display.robot = robotObject;
|
||||
display.listItem.Text = robotObject.Name;
|
||||
display.OnRobotJumpTo += (robot) =>
|
||||
{
|
||||
EmitSignal(SignalName.OnRobotJumpTo, robot);
|
||||
Visible = false;
|
||||
};
|
||||
robotList.AddChild(display);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://k6vlo7ulvtep
|
||||
Reference in New Issue
Block a user