├── .gitignore ├── LICENSE ├── README.md ├── addons └── Debug Console │ ├── Build.png │ ├── License.txt │ ├── console.tscn │ └── debug_console.gd └── screenshots ├── .gdignore ├── Debug Draw 1.PNG ├── Debug fxaa 1.PNG ├── Debug graphics_api.PNG ├── Debug help.PNG ├── Debug stats.PNG ├── Debug-Console-Demov1.gif ├── Debug-Console-Update-2.gif ├── Input-2.PNG ├── debug draw 2.PNG ├── debug draw 3.PNG ├── debug fxaa 2.PNG ├── debug msaa 1.PNG ├── debug msaa 2.PNG ├── debug vsync 1.PNG └── debug vsync 2.PNG /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Godot-specific ignores 3 | .import/ 4 | export.cfg 5 | export_presets.cfg 6 | 7 | # Mono-specific ignores 8 | .mono/ 9 | data_*/ 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Nicholas Huelin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Debug Console 2 | A general-purpose debug console for the Godot Engine. 3 | 4 | ![Debug Console](screenshots/Debug-Console-Demov1.gif) 5 | ## Features 6 | - Debugging suite full of useful in-game commands 7 | - Usable in any project 8 | - Lightweight and easy to use 9 | - Persistent across all scenes 10 | 11 | ## Overview 12 | I made this debug console to be a tool used in any type of project by incorporating many useful commands. It has commands to change the resolution, window mode, enable/disable vsync, display useful debug information such as frames per second, memory, cursor position, current resolution, current screen, and more. There's a command to change the time scale, as well as reload the current scene. There's a "help" command that displays a popup with all the commands and more information about them. 13 | 14 | This scene is autoloaded and persistent across all scenes, therefore, you don't need to instance it into every scene, it already exists within every scene by default. When the debug console is brought up it automatically pauses the game, then when it's exited it automatically unpauses the game for you. 15 | 16 | ![Debug Stats](https://raw.githubusercontent.com/SirQuartz/debugconsole/main/screenshots/Debug%20stats.PNG) 17 | 18 | ## Usage 19 | Copy the `addons/Debug Console` folder into your projects directory, Then autoload the `console.tscn` scene within the Debug Console folder. This will make it present in every scene within your game. Next you need to create a new `InputEventAction` by going to Project>Project Settings>Input Map and create an action called "debug" and assign it a key. Press the "debug" action to bring up the console in-game. Be sure to consult the [wiki](https://github.com/SirQuartz/debugconsole/wiki) for more detailed information. 20 | 21 | ## Commands 22 | Below is a list of all available commands that the debug console will accept. It works by typing the prefix followed by a space then enter the value. 23 | - help 24 | - clear 25 | - quit 26 | - shoot 27 | - cr `int,int` 28 | - mw `fullscreen, windowed, borderless, bordered` 29 | - mt `float` 30 | - vsync 31 | - fxaa 32 | - msaa `2, 4, 8, off` 33 | - fov `float` 34 | - debug `name, desc, fps, stats, draw, reload` 35 | 36 | ## License 37 | MIT license. 38 | -------------------------------------------------------------------------------- /addons/Debug Console/Build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/addons/Debug Console/Build.png -------------------------------------------------------------------------------- /addons/Debug Console/License.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Nicholas Huelin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /addons/Debug Console/console.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=2] 2 | 3 | [ext_resource path="res://addons/Debug Console/debug_console.gd" type="Script" id=1] 4 | 5 | [sub_resource type="StyleBoxFlat" id=1] 6 | bg_color = Color( 0, 0, 0, 0.133333 ) 7 | 8 | [sub_resource type="StyleBoxFlat" id=2] 9 | bg_color = Color( 0.6, 0.6, 0.6, 0 ) 10 | 11 | [sub_resource type="StyleBoxFlat" id=3] 12 | bg_color = Color( 1, 1, 1, 0 ) 13 | 14 | [sub_resource type="StyleBoxFlat" id=4] 15 | bg_color = Color( 0, 0, 0, 0 ) 16 | 17 | [sub_resource type="StyleBoxFlat" id=5] 18 | bg_color = Color( 0, 0, 0, 0.133333 ) 19 | 20 | [node name="Debug Layer" type="CanvasLayer"] 21 | pause_mode = 2 22 | layer = 128 23 | __meta__ = { 24 | "_editor_description_": "This is the root canvas layer for all debug controls. It's set to the highest possible value, meaning it will always appear above everything else by default." 25 | } 26 | 27 | [node name="DebugFrame" type="Control" parent="."] 28 | pause_mode = 2 29 | anchor_right = 1.0 30 | anchor_bottom = 1.0 31 | margin_top = 0.499451 32 | margin_bottom = 0.499451 33 | focus_mode = 2 34 | mouse_filter = 2 35 | __meta__ = { 36 | "_edit_use_anchors_": false, 37 | "_editor_description_": "Parent control for the UI elements within the scene." 38 | } 39 | 40 | [node name="Output" type="TextEdit" parent="DebugFrame"] 41 | pause_mode = 2 42 | visible = false 43 | anchor_top = 1.0 44 | anchor_right = 1.0 45 | anchor_bottom = 1.0 46 | margin_top = -190.0 47 | margin_bottom = -35.0 48 | custom_styles/read_only = SubResource( 1 ) 49 | custom_styles/focus = SubResource( 2 ) 50 | custom_styles/normal = SubResource( 3 ) 51 | readonly = true 52 | wrap_enabled = true 53 | __meta__ = { 54 | "_edit_use_anchors_": false, 55 | "_editor_description_": "Output for user commands while in-game." 56 | } 57 | 58 | [node name="GraphicsAPI" type="Label" parent="DebugFrame/Output"] 59 | anchor_left = 1.0 60 | anchor_top = 1.0 61 | anchor_right = 1.0 62 | anchor_bottom = 1.0 63 | margin_left = -40.0 64 | margin_top = -33.0 65 | margin_right = -10.0 66 | grow_horizontal = 0 67 | grow_vertical = 0 68 | custom_colors/font_color = Color( 0.0156863, 0.87451, 0.976471, 0.74902 ) 69 | align = 2 70 | valign = 1 71 | __meta__ = { 72 | "_edit_use_anchors_": false 73 | } 74 | 75 | [node name="Input" type="LineEdit" parent="DebugFrame"] 76 | visible = false 77 | anchor_top = 1.0 78 | anchor_right = 1.0 79 | anchor_bottom = 1.0 80 | margin_top = -35.0 81 | custom_styles/focus = SubResource( 4 ) 82 | custom_styles/normal = SubResource( 5 ) 83 | max_length = 255 84 | placeholder_text = "Type \"help\" for a list of commands" 85 | caret_blink = true 86 | script = ExtResource( 1 ) 87 | __meta__ = { 88 | "_edit_use_anchors_": false, 89 | "_editor_description_": "Input for user commands while in-game." 90 | } 91 | 92 | [node name="DebugLabelVbox" type="VBoxContainer" parent="DebugFrame"] 93 | anchor_left = 1.0 94 | anchor_right = 1.0 95 | anchor_bottom = 1.0 96 | margin_left = -108.471 97 | margin_top = 10.0 98 | margin_right = -9.47083 99 | margin_bottom = -10.0 100 | grow_horizontal = 0 101 | __meta__ = { 102 | "_edit_use_anchors_": false, 103 | "_editor_description_": "Container for the labels that display in-game debug stats/values" 104 | } 105 | 106 | [node name="FPSCounter" type="Label" parent="DebugFrame/DebugLabelVbox"] 107 | visible = false 108 | margin_right = 99.0 109 | margin_bottom = 14.0 110 | align = 2 111 | __meta__ = { 112 | "_edit_use_anchors_": false, 113 | "_editor_description_": "A basic frames per second counter" 114 | } 115 | 116 | [node name="Stats" type="Label" parent="DebugFrame/DebugLabelVbox"] 117 | visible = false 118 | margin_top = 18.0 119 | margin_right = 99.0 120 | margin_bottom = 32.0 121 | align = 2 122 | __meta__ = { 123 | "_editor_description_": "Various stats are displayed here" 124 | } 125 | 126 | [node name="CommandHelp" type="WindowDialog" parent="DebugFrame"] 127 | anchor_left = 0.5 128 | anchor_top = 0.5 129 | anchor_right = 0.5 130 | anchor_bottom = 0.5 131 | margin_left = -260.0 132 | margin_top = -233.0 133 | margin_right = 260.0 134 | margin_bottom = 244.0 135 | window_title = "Help" 136 | resizable = true 137 | __meta__ = { 138 | "_edit_use_anchors_": false, 139 | "_editor_description_": "A popup window that displays the full list of commands and what they do." 140 | } 141 | 142 | [node name="TabContainer" type="TabContainer" parent="DebugFrame/CommandHelp"] 143 | anchor_right = 1.0 144 | anchor_bottom = 1.0 145 | margin_left = 0.49939 146 | margin_right = 0.49939 147 | __meta__ = { 148 | "_edit_use_anchors_": false 149 | } 150 | 151 | [node name="Commands" type="Tabs" parent="DebugFrame/CommandHelp/TabContainer"] 152 | visible = false 153 | anchor_right = 1.0 154 | anchor_bottom = 1.0 155 | margin_left = 4.0 156 | margin_top = 32.0 157 | margin_right = -4.0 158 | margin_bottom = -4.0 159 | __meta__ = { 160 | "_edit_use_anchors_": false 161 | } 162 | 163 | [node name="VSplitContainer" type="VSplitContainer" parent="DebugFrame/CommandHelp/TabContainer/Commands"] 164 | anchor_right = 1.0 165 | anchor_bottom = 1.0 166 | split_offset = 400 167 | dragger_visibility = 2 168 | __meta__ = { 169 | "_edit_use_anchors_": false 170 | } 171 | 172 | [node name="HSplitContainer" type="HSplitContainer" parent="DebugFrame/CommandHelp/TabContainer/Commands/VSplitContainer"] 173 | margin_right = 512.0 174 | margin_bottom = 400.0 175 | split_offset = -125 176 | dragger_visibility = 2 177 | __meta__ = { 178 | "_edit_use_anchors_": false 179 | } 180 | 181 | [node name="Commands" type="RichTextLabel" parent="DebugFrame/CommandHelp/TabContainer/Commands/VSplitContainer/HSplitContainer"] 182 | margin_right = 131.0 183 | margin_bottom = 400.0 184 | grow_horizontal = 0 185 | size_flags_horizontal = 3 186 | custom_constants/line_separation = 10 187 | text = "\"help\" 188 | \"clear\" 189 | \"shoot\" 190 | \"quit\" 191 | \"cr\" 192 | \"fov\" 193 | \"mw\" 194 | \"fxaa\" 195 | \"msaa\" 196 | \"mt\" 197 | \"debug stats\" 198 | \"debug fps\" 199 | \"debug reload\" 200 | \"debug draw\" 201 | \"debug desc\" 202 | \"debug name\" " 203 | __meta__ = { 204 | "_edit_use_anchors_": false, 205 | "_editor_description_": "" 206 | } 207 | 208 | [node name="Descriptions" type="RichTextLabel" parent="DebugFrame/CommandHelp/TabContainer/Commands/VSplitContainer/HSplitContainer"] 209 | margin_left = 131.0 210 | margin_right = 512.0 211 | margin_bottom = 400.0 212 | grow_horizontal = 0 213 | size_flags_horizontal = 3 214 | custom_constants/line_separation = 10 215 | text = "- Displays all available commands 216 | - Clears all output and input text 217 | - Takes a screenshot of the in-game viewport 218 | - Causes the program to quit 219 | - Change resolution, changes the window's resolution 220 | - Field of view, changes the camera's fov in a 3D scene 221 | - Modify window, changes the window state 222 | - Toggle FXAA on or off 223 | - Toggle between MSAA settings (off, 2, 4, 8) 224 | - Mod time, changes the in-game time scale 225 | - Displays useful statistics in-game 226 | - Displays the current frames per second in-game 227 | - Reloads the current scene 228 | - Displays 3D objects in a debug-overdraw mode 229 | - Prints the game's description to the output 230 | - Prints the game's name to the output" 231 | 232 | [node name="Note" type="RichTextLabel" parent="DebugFrame/CommandHelp/TabContainer/Commands/VSplitContainer"] 233 | margin_top = 400.0 234 | margin_right = 512.0 235 | margin_bottom = 441.0 236 | text = "Note: \"debug draw\" will not work if your project is exported, nor will it work if you're not using GLES3." 237 | 238 | [node name="Usage" type="Tabs" parent="DebugFrame/CommandHelp/TabContainer"] 239 | visible = false 240 | anchor_right = 1.0 241 | anchor_bottom = 1.0 242 | margin_left = 4.0 243 | margin_top = 32.0 244 | margin_right = -4.0 245 | margin_bottom = -4.0 246 | 247 | [node name="Label" type="Label" parent="DebugFrame/CommandHelp/TabContainer/Usage"] 248 | anchor_right = 1.0 249 | anchor_bottom = 1.0 250 | text = "In order to use a command you simply have to type it's prefix followed by the value. Some commands only have a prefix, like the \"help\" command. Others like the \"cr\" (short for \"change resolution\") command require the prefix followed by a space, then the value. 251 | 252 | Example: cr 300,400 253 | 254 | This exact command will change the window resolution to be 300x400 pixels. 255 | 256 | 257 | Commands such as \"mw\" (short for \"modify window\") expect a keyword. 258 | 259 | Example: mw fullscreen 260 | 261 | That will set the window into fullscreen mode." 262 | autowrap = true 263 | __meta__ = { 264 | "_edit_use_anchors_": false 265 | } 266 | 267 | [node name="Method Calls" type="Tabs" parent="DebugFrame/CommandHelp/TabContainer"] 268 | anchor_right = 1.0 269 | anchor_bottom = 1.0 270 | margin_left = 4.0 271 | margin_top = 32.0 272 | margin_right = -4.0 273 | margin_bottom = -4.0 274 | 275 | [node name="RichTextLabel" type="RichTextLabel" parent="DebugFrame/CommandHelp/TabContainer/Method Calls"] 276 | anchor_right = 1.0 277 | anchor_bottom = 1.0 278 | margin_left = 1.49829 279 | margin_right = 1.49829 280 | bbcode_enabled = true 281 | text = "You can use the console to manually call methods on any object in your scene, even on singletons. The only two conditions are that the object must exist in your scene somewhere, and it must have the method you've typed. You can call custom methods on nodes with scripts attached to them as well. 282 | 283 | It's important to note that this is case-sensitive, so you must type both the object and method names exactly as they appear in your scenes or scripts. 284 | 285 | ex: Label.hide 286 | 287 | Typing that will call the \"hide\" method on the object \"Label\" within the scene if both exist. 288 | 289 | This can also accept up to 3 optional arguments separated by spaces if the method requires them. 290 | 291 | ex: Label.set_scale Vector2(2, 2) 292 | 293 | One limitation to keep in mind is that if you have multiple nodes with the same name in your scene then whatever method you call will only affect the first instance of that node in your scene tree hierarchy. So it's best to give all your nodes unique names. 294 | 295 | 296 | Note: When debugging your game in the editor, if you call a method without giving it the correct number of expected arguments, your game will crash. However, in an exported game, regardless of if it's in debug mode or not, the method call will simply be ignored if it's missing arguments or they're invalid." 297 | __meta__ = { 298 | "_edit_use_anchors_": false 299 | } 300 | 301 | [node name="About" type="Tabs" parent="DebugFrame/CommandHelp/TabContainer"] 302 | visible = false 303 | anchor_right = 1.0 304 | anchor_bottom = 1.0 305 | margin_left = 4.0 306 | margin_top = 32.0 307 | margin_right = -4.0 308 | margin_bottom = -4.0 309 | 310 | [node name="Label" type="Label" parent="DebugFrame/CommandHelp/TabContainer/About"] 311 | anchor_right = 1.0 312 | anchor_bottom = 1.0 313 | text = "This is a general-purpose debug console designed to be used in a wide variety of projects. It contains universally useful commands that work great for testing many things out mid-game." 314 | align = 1 315 | autowrap = true 316 | __meta__ = { 317 | "_edit_use_anchors_": false 318 | } 319 | 320 | [node name="Timer" type="Timer" parent="DebugFrame"] 321 | pause_mode = 2 322 | wait_time = 0.05 323 | one_shot = true 324 | __meta__ = { 325 | "_editor_description_": "Timer used to wait for screenshot." 326 | } 327 | 328 | [connection signal="cursor_changed" from="DebugFrame/Output" to="DebugFrame/Input" method="_on_Output_cursor_changed"] 329 | [connection signal="text_entered" from="DebugFrame/Input" to="DebugFrame/Input" method="_on_Input_text_entered"] 330 | [connection signal="popup_hide" from="DebugFrame/CommandHelp" to="DebugFrame/Input" method="_on_CommandHelp_popup_hide"] 331 | [connection signal="timeout" from="DebugFrame/Timer" to="DebugFrame/Input" method="_on_Timer_timeout"] 332 | -------------------------------------------------------------------------------- /addons/Debug Console/debug_console.gd: -------------------------------------------------------------------------------- 1 | extends LineEdit 2 | 3 | """ 4 | MIT License 5 | 6 | Copyright © 2021 Nicholas Huelin 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | """ 26 | 27 | 28 | export var enable_console: bool = true # True if the console is enabled 29 | export var mouse_visible_on_unpause: bool = true # Sets mouse visibility on exit 30 | export var user_space: bool = false # Sets whether to use user:// or res:// 31 | 32 | var last_command: String # Temporary var for last input command 33 | var err = OK # Check for errors 34 | var file: String # File name for a screenshot 35 | var screenshot: Image # The actual screenshot 36 | var taking_screenshot: bool # Flag for the console so it knows we're busy 37 | var calling_func: bool # Flag for the console so it knows we're busy 38 | var user_path: String # The user directory either res:// or user:// 39 | 40 | # GUI vars 41 | onready var output = get_parent().get_node("Output") 42 | onready var fps_counter = get_parent().get_node("DebugLabelVbox/FPSCounter") 43 | onready var stats = get_parent().get_node("DebugLabelVbox/Stats") 44 | onready var graphics_api = get_parent().get_node("Output/GraphicsAPI") 45 | onready var viewport = get_tree().get_current_scene().get_viewport() 46 | 47 | 48 | # User input 49 | func _on_Input_text_entered(new_text: String): 50 | var input_text = new_text.to_lower().lstrip(" ").rstrip(" ") # Convert 51 | self.clear() 52 | self.placeholder_text = "" # Get rid of the placeholder text 53 | var command = input_text.to_lower().split(" ") 54 | match input_text: 55 | "help": # Display list of commands 56 | self.placeholder_text = "Here is a list of commands" 57 | get_parent().get_node("CommandHelp").popup() 58 | "clear": # Clear all output 59 | self.clear() 60 | output.text = '' 61 | "quit": # Closes the game 62 | get_tree().quit(0) 63 | if taking_screenshot == true: 64 | file = new_text 65 | self.placeholder_text = "" 66 | screenshot.save_png(user_path + "Screenshots/" + file + ".png") 67 | output.text += "Screenshot " + file + " saved." + '\n' 68 | if "." in new_text: # If were calling a method on an object 69 | var entity = new_text.split(".") 70 | var final_entity = entity[1].split(" ") 71 | var option = new_text.strip_edges().split(" ") 72 | option.remove(0) 73 | call_func(str(entity[0]), str(final_entity[0]), option) 74 | if !taking_screenshot && !calling_func: # If we're not busy, use the command 75 | match command.size(): # Match the command size 76 | 1: 77 | commands(command[0], "", "") 78 | 2: 79 | commands(command[0], command[1]) 80 | 3: 81 | commands(command[0], command[1], command[2]) 82 | _: 83 | last_command = new_text 84 | output.text += "Unknown command, " + "<" + new_text + ">" + \ 85 | " not recognized" + '\n' 86 | calling_func = false 87 | taking_screenshot = false 88 | 89 | 90 | # Make the output text jump to newest line 91 | func _on_Output_cursor_changed(): 92 | var count = output.get_line_count() 93 | output.cursor_set_line(count) 94 | 95 | 96 | # Waits to take a screenshot so that the debug overlay has time to be hidden 97 | func _on_Timer_timeout(): 98 | var img = get_tree().get_current_scene().get_viewport().get_texture()\ 99 | .get_data() # Grab the viewport texture 100 | img.flip_y() # Flip the image vertically so it's upright 101 | var dir = Directory.new() # If screenshots folder doesn't exist, make it 102 | if dir.open(user_path + "Screenshots") != err: 103 | dir.make_dir(user_path + "Screenshots") 104 | self.get_parent().show() # Show the debug overlay again 105 | self.placeholder_text = "Enter a name for the screenshot" 106 | taking_screenshot = true # Let the console know we're busy 107 | screenshot = img # The final image to save 108 | self.grab_focus() 109 | 110 | 111 | func _on_CommandHelp_popup_hide(): 112 | self.placeholder_text = "" 113 | 114 | 115 | func _enter_tree(): 116 | if enable_console == false: # If console is disabled, remove it 117 | self.get_parent().get_parent().queue_free() 118 | if user_space == true: # Sets the user-path based on the user_space flag 119 | user_path = "user://" 120 | else: 121 | user_path = "res://" 122 | 123 | 124 | func _ready(): 125 | var os = OS.get_name() 126 | var api = OS.get_current_video_driver() 127 | match os: # Match the graphics API to the corresponding OS 128 | "HTML5": 129 | if api == 0: 130 | graphics_api.text = "WebGL 2.0" 131 | else: 132 | graphics_api.text = "WebGL 1.0" 133 | "Android", "IOS": 134 | if api == 0: 135 | graphics_api.text = "OpenGL ES 3.0" 136 | else: 137 | graphics_api.text = "OpenGL ES 2.0" 138 | _: 139 | if api == 0: 140 | graphics_api.text = "OpenGL 3.3" 141 | else: 142 | graphics_api.text = "OpenGL 2.1" 143 | 144 | 145 | func _process(delta): # Only FPS needs to be measured as fast as possible 146 | var fps = Engine.get_frames_per_second() 147 | fps_counter.text = "FPS: " + str(fps) 148 | 149 | 150 | func _physics_process(delta): # Process info 151 | var debug_smem = OS.get_static_memory_usage() 152 | var debug_dmem = OS.get_dynamic_memory_usage() 153 | var debug_mouse = get_global_mouse_position() 154 | var debug_size = OS.window_size 155 | var debug_vsync = OS.vsync_enabled 156 | var debug_screen = OS.current_screen 157 | var debug_vid = VisualServer.get_video_adapter_name() 158 | var debug_time = Engine.time_scale 159 | var debug_draw = viewport.get_debug_draw() 160 | var debug_fxaa = viewport.get_use_fxaa() 161 | var debug_msaa = get_msaa_value() 162 | stats.text = "Static Memory: " + \ 163 | str(debug_smem).humanize_size(debug_smem) + '\n' 164 | stats.text += "Dynamic Memory: " + \ 165 | str(debug_dmem).humanize_size(debug_dmem) + '\n' 166 | stats.text += "Cursor: " + str(debug_mouse) + '\n' 167 | stats.text += str(debug_vid) + '\n' 168 | stats.text += "Resolution: " + str(debug_size) + '\n' 169 | stats.text += "Screen: " + str(debug_screen) + '\n' 170 | stats.text += "Vsync: " + str(debug_vsync) + '\n' 171 | stats.text += "FXAA: " + str(debug_fxaa) + '\n' 172 | stats.text += "MSAA: " + str(debug_msaa) + '\n' 173 | stats.text += "Time Scale: " + str(debug_time) + '\n' 174 | 175 | 176 | # Handles the pausing and displaying of the console 177 | func _input(event): 178 | if self.visible == false && enable_console == true: 179 | if event is InputEventKey && event.is_action_released("debug") && \ 180 | !event.is_echo(): 181 | self.grab_focus() 182 | self.visible = true 183 | output.visible = true 184 | Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) 185 | get_tree().paused = !get_tree().paused # Toggle pause 186 | else: 187 | if event is InputEventKey && event.is_action_released("debug") && \ 188 | !event.is_echo(): 189 | self.delete_char_at_cursor() 190 | self.release_focus() 191 | self.visible = false 192 | output.visible = false 193 | if mouse_visible_on_unpause: 194 | Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) 195 | else: 196 | Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN) 197 | get_tree().paused = !get_tree().paused 198 | if event is InputEventKey && event.is_pressed() && !event.is_echo() && \ 199 | event.scancode == KEY_UP: 200 | self.text = last_command 201 | 202 | 203 | # Handles all input commands, uses a prefix-command system, split by a space 204 | func commands(prefix: String, command: String = "", Option: String = ""): 205 | # Write the command to the output window 206 | if !prefix == "clear": # Don't print the clear command to the output log 207 | output.text += prefix + " " + command + '\n' 208 | match prefix: # Match the prefix, then check for the relevant command 209 | "cr", "change_resolution": 210 | var dim_array = command.split(",") 211 | if err == OK && str2var(dim_array[0]) is int \ 212 | && str2var(dim_array[1]) is int: # Make sure they're both an integer 213 | var dimensions = Vector2(dim_array[0], dim_array[1]) 214 | change_dim(dimensions) 215 | else: 216 | output.text += \ 217 | "\"cr\" expects whole integer values, ex: cr 500,500" + "\n" 218 | "mw", "modify_window": 219 | mod_window(command) 220 | "fxaa": 221 | mod_alias("fxaa", Option) 222 | "msaa": 223 | mod_alias("msaa", command) 224 | "vsync": 225 | mod_window("vsync") 226 | "shoot", "screenshot": # Take a screenshot of the viewport 227 | take_screenshot() 228 | "fov", "field_of_view": # Modify the field of view in 3D scenes 229 | mod_fov(command) 230 | "mt", "modify_time": # Modify the in-game time scale relative to ours 231 | mod_time(command) 232 | "debug": 233 | game_info(command) 234 | "help", "clear", "quit", "shoot", "y", "n": # If just a prefix, ignore 235 | pass 236 | _: 237 | output.text += "Unknown command, " + \ 238 | str("<" + prefix + " " + command + ">") + " not recognized." + '\n' 239 | last_command = prefix + " " + command # Set the last command 240 | 241 | 242 | # Changes the window dimensions 243 | func change_dim(command: Vector2): 244 | OS.window_size.x = abs(command.x) 245 | OS.window_size.y = abs(command.y) 246 | 247 | 248 | # Changes the window state 249 | func mod_window(command: String): 250 | match command: 251 | "fullscreen": 252 | OS.window_fullscreen = true 253 | "windowed": 254 | OS.window_fullscreen = false 255 | "borderless": 256 | OS.window_borderless = true 257 | "bordered": 258 | OS.window_borderless = false 259 | "vsync": 260 | if OS.vsync_enabled == false: 261 | OS.set_use_vsync(true) # Enable vsync 262 | output.text += "Vsync enabled" + '\n' 263 | else: 264 | OS.vsync_enabled = false # Disable vsync 265 | output.text += "Vsync disabled" + '\n' 266 | _: 267 | output.text += \ 268 | "Unknown command, " + "<" + command + ">" + " not recognized." +'\n' 269 | 270 | 271 | # Displays debug game info in-game 272 | func game_info(command: String): 273 | match command: 274 | "name": # Return the name of the project 275 | output.text += \ 276 | str(ProjectSettings.get_setting("application/config/name")) + '\n' 277 | "desc": # Return the project's description 278 | output.text += \ 279 | str(ProjectSettings.get_setting("application/config/description"))\ 280 | + '\n' 281 | "fps": # Toggle FPS counter on or off 282 | if fps_counter.visible == false: 283 | output.text += "FPS counter enabled" + '\n' 284 | fps_counter.visible = true 285 | else: 286 | output.text += "FPS counter disabled" + '\n' 287 | fps_counter.visible = false 288 | "stats": # Toggle useful stats on or off 289 | if stats.visible == false: 290 | output.text += "Stats enabled" + '\n' 291 | stats.visible = true 292 | else: 293 | output.text += "Stats disabled" + '\n' 294 | stats.visible = false 295 | "draw": # Toggle overdraw on or off 296 | if OS.get_video_driver_name(1): 297 | output.text += "Debug draw mode only works with a GLES3 " + \ 298 | "render backend." + '\n' 299 | elif viewport.get_debug_draw() != Viewport.DEBUG_DRAW_OVERDRAW \ 300 | && OS.is_debug_build() && OS.get_current_video_driver() == 0: 301 | viewport.set_debug_draw(Viewport.DEBUG_DRAW_OVERDRAW) 302 | output.text += "Debug draw enabled." + '\n' 303 | elif !OS.is_debug_build(): 304 | output.text += "Debug draw doesn't work in non-debug binaries."\ 305 | + '\n' 306 | else: 307 | viewport.set_debug_draw(Viewport.DEBUG_DRAW_DISABLED) 308 | output.text += "Debug draw disabled." + '\n' 309 | "ray": 310 | if get_tree().is_debugging_collisions_hint() == false: 311 | get_tree().set_debug_collisions_hint(true) 312 | get_tree().reload_current_scene() 313 | output.text += "Scene reloaded!" + '\n' 314 | output.text += "Debug ray enabled." + '\n' 315 | elif get_tree().is_debugging_collisions_hint() == true: 316 | get_tree().set_debug_collisions_hint(false) 317 | get_tree().reload_current_scene() 318 | output.text += "Scene reloaded!" + '\n' 319 | output.text += "Debug ray enabled." + '\n' 320 | "reload": # Reload the current scene 321 | get_tree().reload_current_scene() 322 | output.text += "Scene reloaded!" + '\n' 323 | _: 324 | output.text += \ 325 | "Unknown command, " + "<" + command + ">" + " not recognized." +'\n' 326 | 327 | 328 | # Modifies the in-game time scale 329 | func mod_time(command): 330 | if str2var(command) is float: 331 | Engine.set_time_scale(abs(float(command))) 332 | output.text += "Time scale set to " + str(abs(float(command)) * 100) + \ 333 | " %" + '\n' 334 | elif str2var(command) is int: 335 | Engine.set_time_scale(abs(int(command))) 336 | output.text += "Time scale set to " + str(abs(int(command)) * 100) + \ 337 | " %" + '\n' 338 | else: 339 | output.text += "<"+str(command)+">" + \ 340 | " is not a value for modify time." + '\n' 341 | 342 | 343 | # Modifies the in-game field of view for the current 3D camera 344 | func mod_fov(command): 345 | if get_tree().get_current_scene().get_viewport().world: 346 | if float(command) <= 179 && float(command) >= 1: 347 | if get_tree().get_current_scene().get_viewport().get_camera() \ 348 | != null: 349 | get_tree().get_current_scene().get_viewport()\ 350 | .get_camera().set_fov(float(command)) 351 | output.text += "Field of view set to " + str(command) + '\n' 352 | else: 353 | output.text += "There is currently no 3D camera." + '\n' 354 | else: 355 | output.text += "The field of view must be between (including) " + \ 356 | "1 and 179." + '\n' 357 | else: 358 | output.text += "Field of view is not available in a 2D scene." + '\n' 359 | 360 | 361 | # Modifies the anti-aliasing settings for the scene viewport 362 | func mod_alias(command, value = null): 363 | match command: 364 | "msaa": 365 | match value: # Matches the corresponding MSAA value and sets it 366 | "2": 367 | viewport.set_msaa(Viewport.MSAA_2X) 368 | output.text += command + " set to " + value + "x" + '\n' 369 | "4": 370 | viewport.set_msaa(Viewport.MSAA_4X) 371 | output.text += command + " set to " + value + "x" + '\n' 372 | "8": 373 | viewport.set_msaa(Viewport.MSAA_8X) 374 | output.text += command + " set to " + value + "x" + '\n' 375 | "off": 376 | viewport.set_msaa(Viewport.MSAA_DISABLED) 377 | output.text += command + " set to " + value + '\n' 378 | _: 379 | output.text += command + " " + value + " not recognized." \ 380 | + '\n' 381 | "fxaa": 382 | match value: 383 | "": 384 | if viewport.get_use_fxaa() == false: 385 | viewport.set_use_fxaa(true) 386 | output.text += command + " set to on." + '\n' 387 | else: 388 | viewport.set_use_fxaa(false) 389 | output.text += command + " set to off." + '\n' 390 | _: 391 | output.text += command + " " + value + " not recognized." \ 392 | + '\n' 393 | _: 394 | output.text += command + " " + value + " not recognized." + '\n' 395 | 396 | 397 | # Gets the current MSAA setting 398 | func get_msaa_value(): 399 | match viewport.get_msaa(): 400 | Viewport.MSAA_DISABLED: 401 | return "Off" 402 | Viewport.MSAA_2X: 403 | return "2X" 404 | Viewport.MSAA_4X: 405 | return "4X" 406 | Viewport.MSAA_8X: 407 | return "8X" 408 | 409 | 410 | # Hides the debug overlay, starts timer, takes a screenshot of the viewport 411 | func take_screenshot(): 412 | self.get_parent().hide() 413 | var timer = get_parent().get_node("Timer") 414 | timer.start() 415 | 416 | 417 | # Calls a function manually on the first object occurence in the current scene 418 | func call_func(object: String, method: String, option: Array): 419 | calling_func = true # Tell the console we're busy 420 | var a: Node 421 | if get_tree().get_current_scene().find_node(object): # Did you find it? 422 | a = get_tree().get_current_scene().find_node(object) 423 | elif get_tree().get_root().get_node(object): # Is it a singleton? 424 | a = get_tree().get_root().get_node(object) 425 | else: 426 | output.text += "<" + str(object) + ">" + \ 427 | " doesn't exist in the current scene." + '\n' 428 | if method != "" && a != null: # Make sure they actually entered a method 429 | if a.has_method(method): 430 | match option.size(): 431 | 0: # Check if there's any optional argument set 432 | a.call(method) # Call the method on the object 433 | 1: # Use optional arguments if we have any 434 | a.call(method, str2var(option[0])) 435 | 2: 436 | a.call(method, str2var(option[0]), str2var(option[1])) 437 | 3: 438 | a.call(method, str2var(option[0]), str2var(option[1]), \ 439 | str2var(option[2])) 440 | _: 441 | output.text += "You've entered more arguments than " + \ 442 | "the console can process." + '\n' 443 | output.text += str(method) + " called on " + str(object) + '\n' 444 | else: 445 | output.text += "<" + str(object) + ">" + " doesn't have method " \ 446 | + "<" + str(method) + ">." + '\n' 447 | -------------------------------------------------------------------------------- /screenshots/.gdignore: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /screenshots/Debug Draw 1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/screenshots/Debug Draw 1.PNG -------------------------------------------------------------------------------- /screenshots/Debug fxaa 1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/screenshots/Debug fxaa 1.PNG -------------------------------------------------------------------------------- /screenshots/Debug graphics_api.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/screenshots/Debug graphics_api.PNG -------------------------------------------------------------------------------- /screenshots/Debug help.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/screenshots/Debug help.PNG -------------------------------------------------------------------------------- /screenshots/Debug stats.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/screenshots/Debug stats.PNG -------------------------------------------------------------------------------- /screenshots/Debug-Console-Demov1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/screenshots/Debug-Console-Demov1.gif -------------------------------------------------------------------------------- /screenshots/Debug-Console-Update-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/screenshots/Debug-Console-Update-2.gif -------------------------------------------------------------------------------- /screenshots/Input-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/screenshots/Input-2.PNG -------------------------------------------------------------------------------- /screenshots/debug draw 2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/screenshots/debug draw 2.PNG -------------------------------------------------------------------------------- /screenshots/debug draw 3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/screenshots/debug draw 3.PNG -------------------------------------------------------------------------------- /screenshots/debug fxaa 2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/screenshots/debug fxaa 2.PNG -------------------------------------------------------------------------------- /screenshots/debug msaa 1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/screenshots/debug msaa 1.PNG -------------------------------------------------------------------------------- /screenshots/debug msaa 2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/screenshots/debug msaa 2.PNG -------------------------------------------------------------------------------- /screenshots/debug vsync 1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/screenshots/debug vsync 1.PNG -------------------------------------------------------------------------------- /screenshots/debug vsync 2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SirQuartz/debugconsole/85db2e4e0961c1a1928df042639a73bcab00716c/screenshots/debug vsync 2.PNG --------------------------------------------------------------------------------