├── .gitattributes
├── .gitignore
├── LICENSE.md
├── README.md
├── demo
├── .idea
│ ├── .idea.SofiaConsole.dir
│ │ └── .idea
│ │ │ ├── .gitignore
│ │ │ └── indexLayout.xml
│ └── .idea.SofiaConsole
│ │ └── .idea
│ │ ├── .gitignore
│ │ ├── indexLayout.xml
│ │ └── vcs.xml
├── Player.cs
├── PlayerCamera.cs
├── SofiaConsole.csproj
├── SofiaConsole.sln
├── addons
│ └── sofiaconsole
│ │ ├── Commands
│ │ ├── ClearCommand.cs
│ │ ├── DebugCamera.cs
│ │ ├── DebugCameraCommand.cs
│ │ ├── FpsCounterCommand.cs
│ │ ├── HelloWorldCommand.cs
│ │ ├── HelpCommand.cs
│ │ ├── InfoCommand.cs
│ │ ├── ReloadCommand.cs
│ │ ├── TimeCommand.cs
│ │ └── ToggleConsoleCommand.cs
│ │ ├── Console.cs
│ │ ├── Console.tscn
│ │ ├── ConsoleCommandAttribute.cs
│ │ ├── ConsoleCommandReference.cs
│ │ ├── SofiaConsole.cs
│ │ ├── icon.svg
│ │ ├── icon.svg.import
│ │ └── plugin.cfg
├── demo.tscn
├── icon.svg
├── icon.svg.import
├── models
│ ├── LICENSE
│ ├── gdbot
│ │ ├── LICENSE.gdbot.md
│ │ ├── custom_animations
│ │ │ ├── custom_lib.res
│ │ │ └── default_heartbeat.tres
│ │ ├── gdbot.glb
│ │ ├── gdbot.glb.import
│ │ ├── gdbot_face.gd
│ │ ├── gdbot_face.tscn
│ │ ├── gdbot_skin.gd
│ │ ├── gdbot_skin.tscn
│ │ ├── materials
│ │ │ ├── gdbot_face_mat.tres
│ │ │ ├── glass_mat.tres
│ │ │ └── heart_core_mat.tres
│ │ └── texture
│ │ │ ├── closed.png
│ │ │ ├── closed.png.import
│ │ │ ├── open.png
│ │ │ ├── open.png.import
│ │ │ └── parts
│ │ │ ├── eye_close.png
│ │ │ ├── eye_close.png.import
│ │ │ ├── eye_happy.png
│ │ │ ├── eye_happy.png.import
│ │ │ ├── eye_open.png
│ │ │ ├── eye_open.png.import
│ │ │ ├── eye_spiral.png
│ │ │ ├── eye_spiral.png.import
│ │ │ ├── open_mouth.png
│ │ │ ├── open_mouth.png.import
│ │ │ ├── smile.png
│ │ │ └── smile.png.import
│ └── shared
│ │ ├── shaders
│ │ └── screen_shader.gdshader
│ │ └── textures
│ │ ├── eye_mask.png
│ │ └── eye_mask.png.import
└── project.godot
└── docs
├── icon_512.png
└── screenshot.png
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Normalize EOL for all files that Git considers text files.
2 | * text=auto eol=lf
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | demo/.idea/
2 |
3 | # Godot 4+ specific ignores
4 | demo/.godot/
5 |
6 | # Godot-specific ignores
7 | demo/.import/
8 | demo/export.cfg
9 | demo/export_presets.cfg
10 |
11 | # Imported translations (automatically generated from CSV files)
12 | demo/*.translation
13 |
14 | # Mono-specific ignores
15 | demo/.mono/
16 | demo/data_*/
17 | demo/mono_crash.*.json
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright 2023 Laura Sofia Heimann
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SofiaConsole
2 | An easy to use in-game dev console for Godot 4 (C#)
3 |
4 | 
5 |
6 | ## Getting Started
7 | ### How to install
8 | - Copy the `addons/sofiaconsole` folder into your project
9 | - Build your project
10 | - Enable the plugin
11 | - Make sure, that `res://addons/sofiaconsole/Console.tscn` is a global autoload with the name `Console`
12 |
13 | ### How to use
14 | - Press `F3` in-game to open the console
15 | - You can create an input action named "toggle_console" to define a custom key/button
16 |
17 | ## Commands
18 | ### How to add commands
19 | Simply add the `[ConsoleCommand]` attribute to a method to register it as a command. A command must always provide a command name to be executed. You can also optionally provide a `Description` and `Usage` string.
20 |
21 | #### Examples
22 | - `[ConsoleCommand("mycommand")]`
23 | - `[ConsoleCommand("mycommand", Description = "This should describe my command")]`
24 | - `[ConsoleCommand("move", Description = "Moves player", Usage = "move [x] [y] [z]")]`
25 |
26 | #### Helpers
27 | There are a few helper methods your command can call.
28 | - `Console.Instance.ClearConsole();` - clears the console
29 | - `Console.Instance.Space();` - adds a blank line
30 | - `Console.Instance.Space(n);` - adds n blank lines
31 | - `Console.Instance.Print("Hello World");` - adds a string as output (PrintType is Default)
32 | - `Console.Instance.Print("Hello World", Console.PrintType.Default);` - white
33 | - `Console.Instance.Print("Hello World", Console.PrintType.Hint);` - grey
34 | - `Console.Instance.Print("Hello World", Console.PrintType.Warning);` - orange
35 | - `Console.Instance.Print("Hello World", Console.PrintType.Error);` - red
36 | - `Console.Instance.Print("Hello World", Console.PrintType.Success);` - green
37 |
38 | ### Built in commands
39 | We have created a few default commands that are always available.
40 |
41 | - `clear`
42 | - Clears the console history
43 | - `devcam`
44 | - Toggles between the current camera and a free-flying camera
45 | - `fps / togglefps`
46 | - Toggles the FPS counter
47 | - `maxfps [fps]`
48 | - Adds an fps limit, 0 (or no parameter value) disabled the limiter
49 | - `helloworld`
50 | - Prints 'Hello World!' in the console
51 | - `help [command?]`
52 | - Shows all registered commands. If command is specified, it will display the description and usage of a single command
53 | - `info`
54 | - Prints general information about your game, engine and PC
55 | - `reload`
56 | - Reloads the current scene
57 | - `timescale`
58 | - Sets the timescale
59 | - `toggleconsole`
60 | - Toggles the console
61 |
62 | ### Demo Project
63 | This repository contains a demo project that implements a `noclip` console command to showcase the usage of this addon.
--------------------------------------------------------------------------------
/demo/.idea/.idea.SofiaConsole.dir/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Rider ignored files
5 | /modules.xml
6 | /contentModel.xml
7 | /projectSettingsUpdater.xml
8 | /.idea.SofiaConsole.iml
9 | # Editor-based HTTP Client requests
10 | /httpRequests/
11 | # Datasource local storage ignored files
12 | /dataSources/
13 | /dataSources.local.xml
14 |
--------------------------------------------------------------------------------
/demo/.idea/.idea.SofiaConsole.dir/.idea/indexLayout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/demo/.idea/.idea.SofiaConsole/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Rider ignored files
5 | /modules.xml
6 | /contentModel.xml
7 | /.idea.SofiaConsole.iml
8 | /projectSettingsUpdater.xml
9 | # Editor-based HTTP Client requests
10 | /httpRequests/
11 | # Datasource local storage ignored files
12 | /dataSources/
13 | /dataSources.local.xml
14 |
--------------------------------------------------------------------------------
/demo/.idea/.idea.SofiaConsole/.idea/indexLayout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/demo/.idea/.idea.SofiaConsole/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/demo/Player.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 | using media.Laura.SofiaConsole;
3 |
4 | public partial class Player : RigidBody3D
5 | {
6 | private Vector3 _input;
7 | private bool _noclipOn = false;
8 | private Node3D _gdBotSkin;
9 |
10 | public override void _EnterTree()
11 | {
12 | base._EnterTree();
13 |
14 | _gdBotSkin = GetNode("GDbotSkin");
15 | }
16 |
17 | public override void _Process(double delta)
18 | {
19 | _input = Vector3.Zero;
20 |
21 | if (!Console.Instance.Open)
22 | {
23 | if (Input.IsActionPressed("move_left")) _input.X -= 5f;
24 | if (Input.IsActionPressed("move_right")) _input.X += 5f;
25 | if (Input.IsActionPressed("move_forward")) _input.Z -= 5f;
26 | if (Input.IsActionPressed("move_backward")) _input.Z += 5f;
27 |
28 | if (_noclipOn)
29 | {
30 | if (Input.IsActionPressed("move_up")) _input.Y += 5f;
31 | if (Input.IsActionPressed("move_down")) _input.Y -= 5f;
32 | }
33 |
34 | if (Input.IsActionJustPressed("jump"))
35 | {
36 | _gdBotSkin.Call("jump");
37 | ApplyImpulse(Vector3.Up * 10f);
38 | }
39 | }
40 |
41 | if (_input != Vector3.Zero)
42 | {
43 | _gdBotSkin.Call("walk");
44 | }
45 | if (_input == Vector3.Zero)
46 | {
47 | _gdBotSkin.Call("idle");
48 | }
49 |
50 | if (_noclipOn)
51 | {
52 | _gdBotSkin.Call("fall");
53 | }
54 | }
55 |
56 | public override void _IntegrateForces(PhysicsDirectBodyState3D state)
57 | {
58 | base._IntegrateForces(state);
59 |
60 | if(!_noclipOn)
61 | state.LinearVelocity = new Vector3(_input.X, LinearVelocity.Y, _input.Z);
62 | }
63 |
64 | public override void _PhysicsProcess(double delta)
65 | {
66 | base._PhysicsProcess(delta);
67 |
68 | var lookDirection = new Vector3(Position.X + _input.X * 2f, Position.Y, Position.Z + _input.Z * 2f);
69 |
70 | if (lookDirection != Position)
71 | {
72 | LookAt(lookDirection, Vector3.Up);
73 | }
74 |
75 | if (_noclipOn)
76 | {
77 | Position += _input * 2f * (float)delta;
78 | }
79 | }
80 |
81 | [ConsoleCommand("noclip", Description = "Allows you to move the player without physics")]
82 | public void DebugToggleNoclip()
83 | {
84 | _noclipOn = !_noclipOn;
85 |
86 | if (_noclipOn)
87 | {
88 | Freeze = true;
89 | Console.Instance.Print("Noclip on");
90 | }
91 | else
92 | {
93 | Freeze = false;
94 | Console.Instance.Print("Noclip off");
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/demo/PlayerCamera.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 | using System;
3 |
4 | public partial class PlayerCamera : Camera3D
5 | {
6 | [Export] public Node3D FollowTarget;
7 | [Export] public Vector3 Offset;
8 |
9 | public override void _PhysicsProcess(double delta)
10 | {
11 | base._PhysicsProcess(delta);
12 |
13 | Position = FollowTarget.Position + Offset;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/demo/SofiaConsole.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net6.0
4 | true
5 |
6 |
--------------------------------------------------------------------------------
/demo/SofiaConsole.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio 2012
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SofiaConsole", "SofiaConsole.csproj", "{8740F8CA-0EA1-4006-A168-5DD8F84404C8}"
4 | EndProject
5 | Global
6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
7 | Debug|Any CPU = Debug|Any CPU
8 | ExportDebug|Any CPU = ExportDebug|Any CPU
9 | ExportRelease|Any CPU = ExportRelease|Any CPU
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {8740F8CA-0EA1-4006-A168-5DD8F84404C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 | {8740F8CA-0EA1-4006-A168-5DD8F84404C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 | {8740F8CA-0EA1-4006-A168-5DD8F84404C8}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU
15 | {8740F8CA-0EA1-4006-A168-5DD8F84404C8}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU
16 | {8740F8CA-0EA1-4006-A168-5DD8F84404C8}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU
17 | {8740F8CA-0EA1-4006-A168-5DD8F84404C8}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU
18 | EndGlobalSection
19 | EndGlobal
20 |
--------------------------------------------------------------------------------
/demo/addons/sofiaconsole/Commands/ClearCommand.cs:
--------------------------------------------------------------------------------
1 | // ReSharper disable once CheckNamespace
2 | namespace media.Laura.SofiaConsole.Commands;
3 |
4 | public class ClearCommand
5 | {
6 | [ConsoleCommand("clear", Description = "Clears the console history")]
7 | public void ClearConsole()
8 | {
9 | Console.Instance.ClearConsole();
10 | }
11 | }
--------------------------------------------------------------------------------
/demo/addons/sofiaconsole/Commands/DebugCamera.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 | using System;
3 |
4 | public partial class DebugCamera : Camera3D
5 | {
6 | private Vector3 _input;
7 |
8 | public override void _Process(double delta)
9 | {
10 | _input = Vector3.Zero;
11 |
12 | // Forward/Backward/Left/Right
13 | if (Input.IsKeyPressed(Key.Kp8)) _input.Z -= 1f;
14 | if (Input.IsKeyPressed(Key.Kp2)) _input.Z += 1f;
15 | if (Input.IsKeyPressed(Key.Kp4)) _input.X -= 1f;
16 | if (Input.IsKeyPressed(Key.Kp6)) _input.X += 1f;
17 |
18 | // Up/Down
19 | if (Input.IsKeyPressed(Key.Kp7)) _input.Y += 1f;
20 | if (Input.IsKeyPressed(Key.Kp9)) _input.Y -= 1f;
21 |
22 | // Rotate Left/Right
23 | if (Input.IsKeyPressed(Key.Kp1)) RotateY(5f * (float)delta);
24 | if (Input.IsKeyPressed(Key.Kp3)) RotateY(-5f * (float)delta);
25 |
26 | Translate(_input * 5f * (float)delta);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/demo/addons/sofiaconsole/Commands/DebugCameraCommand.cs:
--------------------------------------------------------------------------------
1 | // ReSharper disable once CheckNamespace
2 | namespace media.Laura.SofiaConsole.Commands;
3 |
4 | using Godot;
5 |
6 | public partial class DebugCameraCommand : Node
7 | {
8 | private Camera3D _currentCamera;
9 | private Camera3D _debugCamera;
10 | private bool _active = false;
11 |
12 | public override void _EnterTree()
13 | {
14 | base._EnterTree();
15 |
16 | _debugCamera = GetNode("DebugCamera");
17 | }
18 |
19 | [ConsoleCommand("devcam", Description = "Toggles between the current camera and a free-flying camera")]
20 | public void ToggleDebugCamera()
21 | {
22 | _active = !_active;
23 |
24 | if (_active)
25 | {
26 | _currentCamera = GetViewport().GetCamera3D();
27 |
28 | _debugCamera.Fov = _currentCamera.Fov;
29 | _debugCamera.Position = _currentCamera.Position;
30 | _debugCamera.Rotation = _currentCamera.Rotation;
31 | _debugCamera.Visible = true;
32 | _debugCamera.MakeCurrent();
33 |
34 | Console.Instance.Print("Dev camera on");
35 | }
36 | else
37 | {
38 | _currentCamera.MakeCurrent();
39 | _debugCamera.Visible = false;
40 |
41 | Console.Instance.Print("Dev camera off");
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/demo/addons/sofiaconsole/Commands/FpsCounterCommand.cs:
--------------------------------------------------------------------------------
1 | // ReSharper disable once CheckNamespace
2 | namespace media.Laura.SofiaConsole.Commands;
3 |
4 | using Godot;
5 |
6 | public partial class FpsCounterCommand : Node
7 | {
8 | private CanvasLayer _canvas;
9 | private Label _label;
10 |
11 | public override void _EnterTree()
12 | {
13 | base._EnterTree();
14 |
15 | _canvas = GetNode("CounterCanvas");
16 | _label = GetNode