Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions assets/pixel/themes/Console.tres
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[gd_resource type="StyleBoxFlat" format=3 uid="uid://bs0wxlu2afue2"]

[resource]
bg_color = Color(0.164706, 0.180392, 0.203922, 1)
corner_radius_top_left = 8
corner_radius_top_right = 8
corner_radius_bottom_right = 8
corner_radius_bottom_left = 8
expand_margin_left = 2.0
expand_margin_right = 2.0
shadow_color = Color(0.0784314, 0.0784314, 0.0784314, 1)
shadow_offset = Vector2(1, 2)
9 changes: 9 additions & 0 deletions assets/pixel/themes/ConsoleInput.tres
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[gd_resource type="Theme" load_steps=2 format=3 uid="uid://h368fwjarh3n"]

[ext_resource type="StyleBox" uid="uid://bs0wxlu2afue2" path="res://assets/themes/box.tres" id="1_seonm"]

[resource]
LineEdit/font_sizes/font_size = 16
LineEdit/styles/focus = ExtResource("1_seonm")
LineEdit/styles/normal = ExtResource("1_seonm")
LineEdit/styles/read_only = ExtResource("1_seonm")
24 changes: 24 additions & 0 deletions csharp/Client/UI/ConsoleEnabledControl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Linq;
using ExtractIntoVoid.Managers;
using Godot;

public partial class ConsoleEnabledScene : Control {
public override void _Input(InputEvent @event)
{
base._Input(@event);
if (@event is InputEventKey eKey && eKey.KeyLabel == Key.Quoteleft && eKey.IsReleased())
{
var consoles = GetChildren().OfType<DevConsole>();
if (consoles.Any())
{
var first = consoles.First();

first.Close();
}
else
{
AddChild(ConsoleManager.GetConsole());
}
}
}
}
183 changes: 183 additions & 0 deletions csharp/Client/UI/DevConsole.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
using Godot;
using System;
using System.Linq;
using ExtractIntoVoid.Managers;
using System.Globalization;

// ReSharper disable CheckNamespace
// ReSharper disable MemberCanBePrivate.Global
public partial class DevConsole : Window
{
// Called when the node enters the scene tree for the first time.

private TextEdit Output => GetNode<TextEdit>("./Control/Output");
private LineEdit Input => GetNode<LineEdit>("Control/InputArea/InputField");

public override void _Ready()
{
CloseRequested += () =>
{
Close();
};
Open();
//ConsoleManager.Console = this;
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
public override void _Process(double delta)
{
if (Visible && Output.Text != ConsoleManager.Contents)
Output.Text = ConsoleManager.Contents;
}
private void OnInputSubmitted(string input)
{


var split = input.Split(' ');
var command = split.First();
var args = split.Skip(1).ToArray();//TakeLast(input.Split(' ').Length - 1).ToArray();
Input.Text = "";
Print("> " + input);

HandleCommand(command, args);

}
public override void _Input(InputEvent @event)
{
if (@event is InputEventKey eventKey && eventKey.Pressed && eventKey.Keycode == Key.Tab && Input.Text != "")
{
var types = ConsoleManager.GetAll();
if (!types.Keys.Any(s => s.StartsWith(Input.Text)))
{
return;
}
//Print(_cTypes.Keys.FirstOrDefault(s => s.StartsWith(Input.Text)));
var suggestions = new PopupMenu()
{
Size = new Vector2I(0, 0),
Position = new Vector2I((int)Input.GetScreenPosition().X, (int)Input.GetScreenPosition().Y + 24)
};
foreach (var item in types.Where(s => s.Key.StartsWith(Input.Text)))
{
var context = new CommandContext(this, null);

var value = "";
if (item.Value is CVar<string> cVarString)
{
value += " " + cVarString.Get(context);
}
if (item.Value is CVar<bool> cVarBool)
{
value += " " + cVarBool.Get(context);
}
if (item.Value is CVar<int> cVarInt)
{
value += " " + cVarInt.Get(context);
}
if (item.Value is CVar<float> cVarFloat)
{
value += " " + cVarFloat.Get(context);
}
suggestions.AddItem($"{item.Key}{value}");
}
suggestions.IdPressed += delegate (long id)
{
Input.Text = suggestions.GetItemText((int)id).Split(" ").First();
Input.CaretColumn = Input.Text.Length;
};
suggestions.SetFocusedItem(0);
Input.AddChild(suggestions);
suggestions.Popup();
//_cTypes.Keys.Where(s => s.StartsWith(Input.Text));
}
base._Input(@event);
}

public void Close()
{
Visible = false;
Godot.Input.MouseMode = ConsoleManager.CachedMouse;
QueueFree();
}

private void Open()
{
ConsoleManager.CachedMouse = Godot.Input.MouseMode;
Visible = true;
Godot.Input.MouseMode = Godot.Input.MouseModeEnum.Visible;
}
public void HandleCommand(string inputCommand, string[] args)
{
if (ConsoleManager.TryGet(inputCommand, out var command))
{
var context = new CommandContext(this, args);
if (command is CFunc cFunc)
{
cFunc.Call(context);
}
if (command is CVar<string> cVarString)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably export this to new func with type probably HandleVar(T varType, comman

{
if (args.Length == 0)
{
Print(cVarString.Get(context));
}else {
cVarString.Set(context, string.Join(" ", args));
}
}
if (command is CVar<bool> cVarBool)
{
if (args.Length == 0)
{
Print(cVarBool.Get(context));
}else {
try {
cVarBool.Set(context, Convert.ToBoolean(args[0]));

}
catch (FormatException) {
Print($"Invalid input \"{args[0]}\", must be True or False");
}
}
}
if (command is CVar<int> cVarInt)
{
if (args.Length == 0)
{
Print(cVarInt.Get(context));
}else {
try {
cVarInt.Set(context, Convert.ToInt32(args[0]));

}
catch (FormatException) {
Print($"Invalid input \"{args[0]}\", must be an integer");
}
}
}
if (command is CVar<float> cVarFloat)
{
if (args.Length == 0)
{
Print(cVarFloat.Get(context));
}else {
try {
cVarFloat.Set(context, float.Parse(args[0], CultureInfo.InvariantCulture));

}
catch (FormatException) {
Print($"Invalid input \"{args[0]}\", must be a float");
}
}
}
}
}
public void Print(object what)
{
ConsoleManager.Contents += what;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can simplify here by $"{what}\n";

ConsoleManager.Contents += '\n';
Output.ScrollVertical = Output.GetVScrollBar().MaxValue;

}



}
107 changes: 107 additions & 0 deletions csharp/Managers/ConsoleManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// o7 This is all legacy code from Origin Framework

// ReSharper disable CheckNamespace
// ReSharper disable MemberCanBePrivate.Global
using System;
using System.Collections.Generic;
using Godot;
using Serilog.Core;
using Serilog.Events;

namespace ExtractIntoVoid.Managers;

public static class ConsoleManager
{
public static string Contents = "* Extract Into Void Developer Console *\nPress TAB for autocomplete.\n'help' to see all commands.\n";
public static Godot.Input.MouseModeEnum CachedMouse = Godot.Input.MouseModeEnum.Visible;

public static Node GetConsole()
{
var console = SceneManager.GetPackedScene("DevConsole").Instantiate() as DevConsole;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do additional checks if exists, if does not disable the console

return console;
}
private static Dictionary<string, Command> _commands = new();
/// <summary>
/// Registers a new Command.
/// </summary>
/// <param name="name">The name of the command</param>
/// <param name="CFuncOrCVar">A CVar or CFunc Command</param>
public static void Register(string name, Command CFuncOrCVar)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have an unregister

{
_commands.TryAdd(name, CFuncOrCVar);
}
public static bool TryGet(string name, out Command CFuncOrCVar)
{
return _commands.TryGetValue(name, out CFuncOrCVar);
}
public static Dictionary<string, Command> GetAll()
{
return new Dictionary<string, Command>(_commands);
}
}
public abstract class Command
{
public string Description = "";

}
public class CommandContext
{
public readonly DevConsole Console;
public readonly Control Scene;
public readonly string[] Args;

public CommandContext(DevConsole console, string[] args)
{
Console = console;
Scene = console.GetParent() as Control;
Args = args;
}
}
public class CFunc : Command
{
private Action<CommandContext> _function;
public CFunc(string description, Action<CommandContext> function)
{
Description = description;
_function = function;
}
public void Call(CommandContext ctx)
{
_function.Invoke(ctx);
}

}
public class CVar<T> : Command
{
private Func<CommandContext, T> _getter;
private Action<CommandContext, T> _setter;
public CVar(string description, Func<CommandContext, T> getter, Action<CommandContext, T> setter)
{
Description = description;
// Check at runtime if the type is one of the allowed types
if (typeof(T) != typeof(int) && typeof(T) != typeof(float) &&
typeof(T) != typeof(bool) && typeof(T) != typeof(string))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to use any number type. [interface exist for it]
string, bool is good

{
throw new InvalidOperationException("Invalid type. Only int, float, bool, and string are allowed.");
}
_getter = getter;
_setter = setter;
}
public T Get(CommandContext ctx)
{
return _getter.Invoke(ctx);
}
public void Set(CommandContext ctx, T value)
{
_setter.Invoke(ctx, value);
}

}
public class ConsoleSink : ILogEventSink
{

public void Emit(LogEvent logEvent)
{
ConsoleManager.Contents += logEvent.RenderMessage();
}
}
1 change: 1 addition & 0 deletions csharp/Managers/SceneManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ static SceneManager()
{ "ConnectionScreen", "res://scenes/Menu/ConnectionScreen.tscn" },
{ "InputScene", "res://scenes/Menu/InputScene.tscn" },
{ "LobbyScene", "res://scenes/Menu/LobbyScene.tscn" },
{ "DevConsole", "res://scenes/UI/DevConsole.tscn" },
// soon
// { "Inventory", "res://scenes/Menu/Inventory.tscn" },
// { "Escape", "res://scenes/Menu/EscapeScene.tscn" },
Expand Down
30 changes: 29 additions & 1 deletion csharp/Menus/MainMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,38 @@

namespace ExtractIntoVoid.Menus;

public partial class MainMenu : Control
public partial class MainMenu : ConsoleEnabledScene
{
public override void _Ready()
{
ConsoleManager.Register("help", new CFunc("Shows all commands.", (ctx) =>
{
foreach(var command in ConsoleManager.GetAll())
ctx.Console.Print($"{command.Key} ({(command.Value is CFunc ? "func" : "var")})\t {command.Value.Description}");
}));
ConsoleManager.Register("close", new CFunc("Closes the console window.", (ctx) =>
{
ctx.Console.Close();
}));
ConsoleManager.Register("version", new CFunc("Prints the game's version", (ctx) =>
{
ctx.Console.Print(BuildDefined.FullVersion);
}));
ConsoleManager.Register("exit", new CFunc("Closes the game", (ctx) =>
{
GetTree().Quit();
}));
ConsoleManager.Register("title", new CVar<string>("The console window's title",
(ctx) =>{
return ctx.Console.Title;
},
(ctx, value) =>{
ctx.Console.Title = value;
}));

//AddChild(ConsoleManager.GetConsole());
//AddChild(SceneManager.GetPackedScene("DevConsole").Instantiate());
//ConsoleManager.Console.Visible = true;
GameManager.Instance.UIManager.LoadScreenStop();
GetNode<Label>("VersionLabel").Text = BuildDefined.FullVersion;
}
Expand Down
Loading