Initial commit.

This commit is contained in:
2026-09-19 10:06:28 -04:00
commit df09395018
653 changed files with 102225 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
# MIT License
Copyright © 2023-present Hugo Locurcio and contributors
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:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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.
+653
View File
@@ -0,0 +1,653 @@
extends CanvasLayer
@export var fps: Label
@export var frame_time: Label
@export var frame_number: Label
@export var frame_stats: Label
@export var frame_history_total_avg: Label
@export var frame_history_total_min: Label
@export var frame_history_total_max: Label
@export var frame_history_total_last: Label
@export var frame_history_cpu_avg: Label
@export var frame_history_cpu_min: Label
@export var frame_history_cpu_max: Label
@export var frame_history_cpu_last: Label
@export var frame_history_gpu_avg: Label
@export var frame_history_gpu_min: Label
@export var frame_history_gpu_max: Label
@export var frame_history_gpu_last: Label
@export var fps_graph: Panel
@export var total_graph: Panel
@export var cpu_graph: Panel
@export var gpu_graph: Panel
@export var information: Label
@export var settings: Label
## The number of frames to keep in history for graph drawing and best/worst calculations.
## Currently, this also affects how FPS is measured.
const HISTORY_NUM_FRAMES = 150
var GRAPH_SIZE = Vector2(150, 25) # kept uppercase for less code change
const DEFAULT_GRAPH_SIZE = Vector2(150, 25)
const DEFAULT_FONT_SIZE = 12.0
const MIN_FONT_SIZE = 3.0
const MAX_FONT_SIZE = 72.0
const DEFAULT_FONT_OUTLINE_SIZE = 3.0
const DEFAULT_HEADER_WIDTH = 50.0
const GRAPH_MIN_FPS = 10
const GRAPH_MAX_FPS = 160
const GRAPH_MIN_FRAMETIME = 1.0 / GRAPH_MIN_FPS
const GRAPH_MAX_FRAMETIME = 1.0 / GRAPH_MAX_FPS
## Debug menu display style.
enum Style {
HIDDEN, ## Debug menu is hidden.
VISIBLE_COMPACT, ## Debug menu is visible, with only the FPS, FPS cap (if any) and time taken to render the last frame.
VISIBLE_DETAILED, ## Debug menu is visible with full information, including graphs.
MAX, ## Represents the size of the Style enum.
}
## The style to use when drawing the debug menu.
var style := Style.HIDDEN:
set(value):
style = value
match style:
Style.HIDDEN:
visible = false
Style.VISIBLE_COMPACT, Style.VISIBLE_DETAILED:
visible = true
frame_number.visible = style == Style.VISIBLE_DETAILED
frame_stats.visible = style == Style.VISIBLE_DETAILED
$DebugMenu/VBoxContainer/FrameTimeHistory.visible = style == Style.VISIBLE_DETAILED
$DebugMenu/VBoxContainer/FPSGraph.visible = style == Style.VISIBLE_DETAILED
$DebugMenu/VBoxContainer/TotalGraph.visible = style == Style.VISIBLE_DETAILED
$DebugMenu/VBoxContainer/CPUGraph.visible = style == Style.VISIBLE_DETAILED
$DebugMenu/VBoxContainer/GPUGraph.visible = style == Style.VISIBLE_DETAILED
information.visible = style == Style.VISIBLE_DETAILED
settings.visible = style == Style.VISIBLE_DETAILED
var _custom_font_size: int = DEFAULT_FONT_SIZE * 3 # 3x
## Debug menu display size.
enum Display_Size {
SIZE_3, ## 0.25x the default scale
SIZE_6, ## 0.5x the default scale
SIZE_12_DEFAULT, ## 1.0x, the default display size
SIZE_18, ## 1.5x the default scale
SIZE_24, ## 2.0x the default scale
SIZE_30, ## 2.5x the default scale
SIZE_CUSTOM, ## Initially 3.0x the default scale, but overwritten with set_font_size()
MAX, ## Represents the size of the Display_Size enum.
}
## The size to use when drawing the debug menu.
var display_size := Display_Size.SIZE_12_DEFAULT:
set(value):
display_size = value
match display_size:
Display_Size.SIZE_3: # 0.25x
_resize_overlay(DEFAULT_FONT_SIZE * 0.25,
0, # no outline, makes small font look better
DEFAULT_HEADER_WIDTH* 0.25)
Display_Size.SIZE_6: # 0.5x
_resize_overlay(DEFAULT_FONT_SIZE* 0.5,
DEFAULT_FONT_OUTLINE_SIZE * 0.5,
DEFAULT_HEADER_WIDTH* 0.5)
Display_Size.SIZE_12_DEFAULT: # 1.0x
_resize_overlay(DEFAULT_FONT_SIZE,
DEFAULT_FONT_OUTLINE_SIZE,
DEFAULT_HEADER_WIDTH)
Display_Size.SIZE_18: # 1.5x
_resize_overlay(DEFAULT_FONT_SIZE * 1.5,
DEFAULT_FONT_OUTLINE_SIZE * 1.5,
DEFAULT_HEADER_WIDTH * 1.5)
Display_Size.SIZE_24: # 2.0x
_resize_overlay(DEFAULT_FONT_SIZE * 2.0,
DEFAULT_FONT_OUTLINE_SIZE * 2.0,
DEFAULT_HEADER_WIDTH * 2.0)
Display_Size.SIZE_30: # 2.5x
_resize_overlay(DEFAULT_FONT_SIZE * 2.5,
DEFAULT_FONT_OUTLINE_SIZE * 2.5,
DEFAULT_HEADER_WIDTH * 2.5)
Display_Size.SIZE_CUSTOM: # initially is 3.0x, replaced when set_font_size() is called
var new_scale: float = float(_custom_font_size / DEFAULT_FONT_SIZE)
_resize_overlay(DEFAULT_FONT_SIZE * new_scale,
DEFAULT_FONT_OUTLINE_SIZE * new_scale,
DEFAULT_HEADER_WIDTH * new_scale)
# Value of `Time.get_ticks_usec()` on the previous frame.
var last_tick := 0
var thread := Thread.new()
## Returns the sum of all values of an array (use as a parameter to `Array.reduce()`).
var sum_func := func avg(accum: float, number: float) -> float: return accum + number
# History of the last `HISTORY_NUM_FRAMES` rendered frames.
var frame_history_total: Array[float] = []
var frame_history_cpu: Array[float] = []
var frame_history_gpu: Array[float] = []
var fps_history: Array[float] = [] # Only used for graphs.
var frametime_avg := GRAPH_MIN_FRAMETIME
var frametime_cpu_avg := GRAPH_MAX_FRAMETIME
var frametime_gpu_avg := GRAPH_MIN_FRAMETIME
var frames_per_second := float(GRAPH_MIN_FPS)
var frame_time_gradient := Gradient.new()
func _init() -> void:
# This must be done here instead of `_ready()` to avoid having `visibility_changed` be emitted immediately.
visible = false
if not InputMap.has_action("cycle_debug_menu"):
# Create default input action if no user-defined override exists.
# We can't do it in the editor plugin's activation code as it doesn't seem to work there.
InputMap.add_action("cycle_debug_menu")
var event := InputEventKey.new()
event.keycode = KEY_F3
InputMap.action_add_event("cycle_debug_menu", event)
if not InputMap.has_action("cycle_debug_menu_size"):
# Create default input action if no user-defined override exists.
# We can't do it in the editor plugin's activation code as it doesn't seem to work there.
InputMap.add_action("cycle_debug_menu_size")
var event := InputEventKey.new()
event.keycode = KEY_F4
InputMap.action_add_event("cycle_debug_menu_size", event)
if not InputMap.has_action("debug_menu_screenshot"):
# Create default input action if no user-defined override exists.
# We can't do it in the editor plugin's activation code as it doesn't seem to work there.
InputMap.add_action("debug_menu_screenshot")
var event := InputEventKey.new()
event.keycode = KEY_F5
InputMap.action_add_event("debug_menu_screenshot", event)
func _ready() -> void:
# start visibility from project settings
if ProjectSettings.has_setting("DebugMenu/settings/startup_visibility"):
style = ProjectSettings.get_setting("DebugMenu/settings/startup_visibility")
# font size from project settings
if ProjectSettings.has_setting("DebugMenu/settings/font_size"):
set_font_size(ProjectSettings.get_setting("DebugMenu/settings/font_size"))
fps_graph.draw.connect(_fps_graph_draw)
total_graph.draw.connect(_total_graph_draw)
cpu_graph.draw.connect(_cpu_graph_draw)
gpu_graph.draw.connect(_gpu_graph_draw)
fps_history.resize(HISTORY_NUM_FRAMES)
frame_history_total.resize(HISTORY_NUM_FRAMES)
frame_history_cpu.resize(HISTORY_NUM_FRAMES)
frame_history_gpu.resize(HISTORY_NUM_FRAMES)
# NOTE: Both FPS and frametimes are colored following FPS logic
# (red = 10 FPS, yellow = 60 FPS, green = 110 FPS, cyan = 160 FPS).
# This makes the color gradient non-linear.
# Colors are taken from <https://tailwindcolor.com/>.
frame_time_gradient.set_color(0, Color.from_rgba8(239, 68, 68)) # red-500
frame_time_gradient.set_color(1, Color.from_rgba8(56, 189, 248)) # light-blue-400
frame_time_gradient.add_point(0.3333, Color.from_rgba8(250, 204, 21)) # yellow-400
frame_time_gradient.add_point(0.6667, Color.from_rgba8(128, 226, 95)) # 50-50 mix of lime-400 and green-400
get_viewport().size_changed.connect(update_settings_label)
# Display loading text while information is being queried,
# in case the user toggles the full debug menu just after starting the project.
information.text = "Loading hardware information...\n\n "
settings.text = "Loading project information..."
thread.start(
func():
# Disable thread safety checks as they interfere with this add-on.
# This only affects this particular thread, not other thread instances in the project.
# See <https://github.com/godotengine/godot/pull/78000> for details.
# Use a Callable so that this can be ignored on Godot 4.0 without causing a script error
# (thread safety checks were added in Godot 4.1).
if Engine.get_version_info()["hex"] >= 0x040100:
Callable(Thread, "set_thread_safety_checks_enabled").call(false)
# Enable required time measurements to display CPU/GPU frame time information.
# These lines are time-consuming operations, so run them in a separate thread.
RenderingServer.viewport_set_measure_render_time(get_viewport().get_viewport_rid(), true)
update_information_label()
update_settings_label()
)
func _input(event: InputEvent) -> void:
if event.is_action_pressed("cycle_debug_menu"):
style = wrapi(style + 1, 0, Style.MAX) as Style
# Only cycle size/scale when DebugMenu is visible
elif event.is_action_pressed("cycle_debug_menu_size") and style != Style.HIDDEN:
display_size = wrapi(display_size + 1, 0, Display_Size.MAX) as Display_Size
# Only take screen shot if debug menu is displayed (maybe allow this anytime?)
elif event.is_action_pressed("debug_menu_screenshot") and style != Style.HIDDEN:
do_screenshot()
#region Scaling functions by Antz
func _resize_overlay(font_size_in: int, outline_size: int, header_width: float):
# change font size and outline for all labels
for l in get_tree().get_nodes_in_group("debug_menu_label"):
var label : Label = l as Label
label.add_theme_font_size_override("font_size", font_size_in)
# no outline for very small fonts sizes
if font_size_in < 6:
label.add_theme_constant_override("outline_size", 0)
else:
label.add_theme_constant_override("outline_size", outline_size)
# change header widths
for l in get_tree().get_nodes_in_group("debug_menu_header"):
var label : Label = l as Label
label.custom_minimum_size.x = header_width
# main FPS label size is 50% bigger
fps.add_theme_font_size_override("font_size", font_size_in*1.5)
# no outline for very small fonts sizes
if font_size_in < 6:
fps.add_theme_constant_override("outline_size", 0)
else:
fps.add_theme_constant_override("outline_size", outline_size*1.5)
var new_scale: float = font_size_in / DEFAULT_FONT_SIZE
# scale line spacing for multi line labels
settings.add_theme_constant_override("line_spacing", 3 * new_scale)
information.add_theme_constant_override("line_spacing", 3 * new_scale)
# graph re-size
GRAPH_SIZE = DEFAULT_GRAPH_SIZE * new_scale
for p in get_tree().get_nodes_in_group("debug_menu_graph"):
var panel: Panel = p as Panel
panel.custom_minimum_size = GRAPH_SIZE
# this adjusts the label on the left Y minimum size, so that the graphs are spaced
panel.get_parent().find_child("Title").custom_minimum_size.y = GRAPH_SIZE.y + (2.0 * new_scale)
## Set the font size of the Debug Menu overlay
## Sets display_size to Display_Size.SIZE_CUSTOM
## recalculates all GUI elements
func set_font_size(font_size_in: int):
if font_size_in < MIN_FONT_SIZE or font_size_in > MAX_FONT_SIZE:
printerr(str("Font size range for DebugMenu is [", MIN_FONT_SIZE," to ", MAX_FONT_SIZE ,"]"))
return
_custom_font_size = font_size_in
display_size = Display_Size.SIZE_CUSTOM # this triggers the set, where resize_overlay() takes place
#endregion Scaling functions
func _exit_tree() -> void:
if thread.is_started():
thread.wait_to_finish()
## Update hardware information label (this can change at runtime based on window
## size and graphics settings). This is only called when the window is resized.
## To update when graphics settings are changed, the function must be called manually
## using `DebugMenu.update_settings_label()`.
func update_settings_label() -> void:
settings.text = ""
if ProjectSettings.has_setting("application/config/version"):
settings.text += "Project Version: %s\n" % ProjectSettings.get_setting("application/config/version")
var rendering_method := str(ProjectSettings.get_setting_with_override("rendering/renderer/rendering_method"))
var rendering_method_string := rendering_method
match rendering_method:
"forward_plus":
rendering_method_string = "Forward+"
"mobile":
rendering_method_string = "Forward Mobile"
"gl_compatibility":
rendering_method_string = "Compatibility"
settings.text += "Rendering Method: %s\n" % rendering_method_string
var viewport := get_viewport()
# The size of the viewport rendering, which determines which resolution 3D is rendered at.
var viewport_render_size := Vector2i()
if viewport.content_scale_mode == Window.CONTENT_SCALE_MODE_VIEWPORT:
viewport_render_size = viewport.get_visible_rect().size
settings.text += "Viewport: %d×%d, Window: %d×%d\n" % [viewport.get_visible_rect().size.x, viewport.get_visible_rect().size.y, viewport.size.x, viewport.size.y]
else:
# Window size matches viewport size.
viewport_render_size = viewport.size
settings.text += "Viewport: %d×%d\n" % [viewport.size.x, viewport.size.y]
# Display 3D settings only if relevant.
if viewport.get_camera_3d():
var scaling_3d_mode_string := "(unknown)"
match viewport.scaling_3d_mode:
Viewport.SCALING_3D_MODE_BILINEAR:
scaling_3d_mode_string = "Bilinear"
Viewport.SCALING_3D_MODE_FSR:
scaling_3d_mode_string = "FSR 1.0"
Viewport.SCALING_3D_MODE_FSR2:
scaling_3d_mode_string = "FSR 2.2"
var antialiasing_3d_string := ""
if viewport.scaling_3d_mode == Viewport.SCALING_3D_MODE_FSR2:
# The FSR2 scaling mode includes its own temporal antialiasing implementation.
antialiasing_3d_string += (" + " if not antialiasing_3d_string.is_empty() else "") + "FSR 2.2"
if viewport.scaling_3d_mode != Viewport.SCALING_3D_MODE_FSR2 and viewport.use_taa:
# Godot's own TAA is ignored when using FSR2 scaling mode, as FSR2 provides its own TAA implementation.
antialiasing_3d_string += (" + " if not antialiasing_3d_string.is_empty() else "") + "TAA"
if viewport.msaa_3d >= Viewport.MSAA_2X:
antialiasing_3d_string += (" + " if not antialiasing_3d_string.is_empty() else "") + "%d× MSAA" % pow(2, viewport.msaa_3d)
if viewport.screen_space_aa == Viewport.SCREEN_SPACE_AA_FXAA:
antialiasing_3d_string += (" + " if not antialiasing_3d_string.is_empty() else "") + "FXAA"
settings.text += "3D scale (%s): %d%% = %d×%d" % [
scaling_3d_mode_string,
viewport.scaling_3d_scale * 100,
viewport_render_size.x * viewport.scaling_3d_scale,
viewport_render_size.y * viewport.scaling_3d_scale,
]
if not antialiasing_3d_string.is_empty():
settings.text += "\n3D Antialiasing: %s" % antialiasing_3d_string
var environment := viewport.get_camera_3d().get_world_3d().environment
if environment:
if environment.ssr_enabled:
settings.text += "\nSSR: %d Steps" % environment.ssr_max_steps
if environment.ssao_enabled:
settings.text += "\nSSAO: On"
if environment.ssil_enabled:
settings.text += "\nSSIL: On"
if environment.sdfgi_enabled:
settings.text += "\nSDFGI: %d Cascades" % environment.sdfgi_cascades
if environment.glow_enabled:
settings.text += "\nGlow: On"
if environment.volumetric_fog_enabled:
settings.text += "\nVolumetric Fog: On"
var antialiasing_2d_string := ""
if viewport.msaa_2d >= Viewport.MSAA_2X:
antialiasing_2d_string = "%d× MSAA" % pow(2, viewport.msaa_2d)
if not antialiasing_2d_string.is_empty():
settings.text += "\n2D Antialiasing: %s" % antialiasing_2d_string
## Update hardware/software information label (this never changes at runtime).
func update_information_label() -> void:
var adapter_string := ""
# Make "NVIDIA Corporation" and "NVIDIA" be considered identical (required when using OpenGL to avoid redundancy).
if RenderingServer.get_video_adapter_vendor().trim_suffix(" Corporation") in RenderingServer.get_video_adapter_name():
# Avoid repeating vendor name before adapter name.
# Trim redundant suffix sometimes reported by NVIDIA graphics cards when using OpenGL.
adapter_string = RenderingServer.get_video_adapter_name().trim_suffix("/PCIe/SSE2")
else:
adapter_string = RenderingServer.get_video_adapter_vendor() + " - " + RenderingServer.get_video_adapter_name().trim_suffix("/PCIe/SSE2")
# Graphics driver version information isn't always availble.
var driver_info := OS.get_video_adapter_driver_info()
var driver_info_string := ""
if driver_info.size() >= 2:
driver_info_string = driver_info[1]
else:
driver_info_string = "(unknown)"
var release_string := ""
if OS.has_feature("editor"):
# Editor build (implies `debug`).
release_string = "editor"
elif OS.has_feature("debug"):
# Debug export template build.
release_string = "debug"
else:
# Release export template build.
release_string = "release"
var rendering_method := str(ProjectSettings.get_setting_with_override("rendering/renderer/rendering_method"))
var rendering_driver := str(ProjectSettings.get_setting_with_override("rendering/rendering_device/driver"))
var graphics_api_string := rendering_driver
if rendering_method != "gl_compatibility":
if rendering_driver == "d3d12":
graphics_api_string = "Direct3D 12"
elif rendering_driver == "metal":
graphics_api_string = "Metal"
elif rendering_driver == "vulkan":
if OS.has_feature("macos") or OS.has_feature("ios"):
graphics_api_string = "Vulkan via MoltenVK"
else:
graphics_api_string = "Vulkan"
else:
if rendering_driver == "opengl3_angle":
graphics_api_string = "OpenGL via ANGLE"
elif OS.has_feature("mobile") or rendering_driver == "opengl3_es":
graphics_api_string = "OpenGL ES"
elif OS.has_feature("web"):
graphics_api_string = "WebGL"
elif rendering_driver == "opengl3":
graphics_api_string = "OpenGL"
information.text = (
"%s, %d threads\n" % [OS.get_processor_name().replace("(R)", "").replace("(TM)", ""), OS.get_processor_count()]
+ "%s %s (%s %s), %s %s\n" % [OS.get_name(), "64-bit" if OS.has_feature("64") else "32-bit", release_string, "double" if OS.has_feature("double") else "single", graphics_api_string, RenderingServer.get_video_adapter_api_version()]
+ "%s, %s" % [adapter_string, driver_info_string]
)
func _fps_graph_draw() -> void:
var fps_polyline := PackedVector2Array()
fps_polyline.resize(HISTORY_NUM_FRAMES)
for fps_index in fps_history.size():
fps_polyline[fps_index] = Vector2(
remap(fps_index, 0, fps_history.size(), 0, GRAPH_SIZE.x),
remap(clampf(fps_history[fps_index], GRAPH_MIN_FPS, GRAPH_MAX_FPS), GRAPH_MIN_FPS, GRAPH_MAX_FPS, GRAPH_SIZE.y, 0.0)
)
# Don't use antialiasing to speed up line drawing, but use a width that scales with
# viewport scale to keep the line easily readable on hiDPI displays.
fps_graph.draw_polyline(fps_polyline, frame_time_gradient.sample(remap(frames_per_second, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0)), 1.0)
func _total_graph_draw() -> void:
var total_polyline := PackedVector2Array()
total_polyline.resize(HISTORY_NUM_FRAMES)
for total_index in frame_history_total.size():
total_polyline[total_index] = Vector2(
remap(total_index, 0, frame_history_total.size(), 0, GRAPH_SIZE.x),
remap(clampf(frame_history_total[total_index], GRAPH_MIN_FPS, GRAPH_MAX_FPS), GRAPH_MIN_FPS, GRAPH_MAX_FPS, GRAPH_SIZE.y, 0.0)
)
# Don't use antialiasing to speed up line drawing, but use a width that scales with
# viewport scale to keep the line easily readable on hiDPI displays.
total_graph.draw_polyline(total_polyline, frame_time_gradient.sample(remap(1000.0 / frametime_avg, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0)), 1.0)
func _cpu_graph_draw() -> void:
var cpu_polyline := PackedVector2Array()
cpu_polyline.resize(HISTORY_NUM_FRAMES)
for cpu_index in frame_history_cpu.size():
cpu_polyline[cpu_index] = Vector2(
remap(cpu_index, 0, frame_history_cpu.size(), 0, GRAPH_SIZE.x),
remap(clampf(frame_history_cpu[cpu_index], GRAPH_MIN_FPS, GRAPH_MAX_FPS), GRAPH_MIN_FPS, GRAPH_MAX_FPS, GRAPH_SIZE.y, 0.0)
)
# Don't use antialiasing to speed up line drawing, but use a width that scales with
# viewport scale to keep the line easily readable on hiDPI displays.
cpu_graph.draw_polyline(cpu_polyline, frame_time_gradient.sample(remap(1000.0 / frametime_cpu_avg, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0)), 1.0)
func _gpu_graph_draw() -> void:
var gpu_polyline := PackedVector2Array()
gpu_polyline.resize(HISTORY_NUM_FRAMES)
for gpu_index in frame_history_gpu.size():
gpu_polyline[gpu_index] = Vector2(
remap(gpu_index, 0, frame_history_gpu.size(), 0, GRAPH_SIZE.x),
remap(clampf(frame_history_gpu[gpu_index], GRAPH_MIN_FPS, GRAPH_MAX_FPS), GRAPH_MIN_FPS, GRAPH_MAX_FPS, GRAPH_SIZE.y, 0.0)
)
# Don't use antialiasing to speed up line drawing, but use a width that scales with
# viewport scale to keep the line easily readable on hiDPI displays.
gpu_graph.draw_polyline(gpu_polyline, frame_time_gradient.sample(remap(1000.0 / frametime_gpu_avg, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0)), 1.0)
func _process(_delta: float) -> void:
if visible:
fps_graph.queue_redraw()
total_graph.queue_redraw()
cpu_graph.queue_redraw()
gpu_graph.queue_redraw()
# Difference between the last two rendered frames in milliseconds.
var frametime := (Time.get_ticks_usec() - last_tick) * 0.001
frame_history_total.push_back(frametime)
if frame_history_total.size() > HISTORY_NUM_FRAMES:
frame_history_total.pop_front()
# Frametimes are colored following FPS logic (red = 10 FPS, yellow = 60 FPS, green = 110 FPS, cyan = 160 FPS).
# This makes the color gradient non-linear.
frametime_avg = frame_history_total.reduce(sum_func) / frame_history_total.size()
frame_history_total_avg.text = str(frametime_avg).pad_decimals(2)
frame_history_total_avg.modulate = frame_time_gradient.sample(remap(1000.0 / frametime_avg, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0))
var frametime_min: float = frame_history_total.min()
frame_history_total_min.text = str(frametime_min).pad_decimals(2)
frame_history_total_min.modulate = frame_time_gradient.sample(remap(1000.0 / frametime_min, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0))
var frametime_max: float = frame_history_total.max()
frame_history_total_max.text = str(frametime_max).pad_decimals(2)
frame_history_total_max.modulate = frame_time_gradient.sample(remap(1000.0 / frametime_max, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0))
frame_history_total_last.text = str(frametime).pad_decimals(2)
frame_history_total_last.modulate = frame_time_gradient.sample(remap(1000.0 / frametime, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0))
var viewport_rid := get_viewport().get_viewport_rid()
var frametime_cpu := RenderingServer.viewport_get_measured_render_time_cpu(viewport_rid) + RenderingServer.get_frame_setup_time_cpu()
frame_history_cpu.push_back(frametime_cpu)
if frame_history_cpu.size() > HISTORY_NUM_FRAMES:
frame_history_cpu.pop_front()
frametime_cpu_avg = frame_history_cpu.reduce(sum_func) / frame_history_cpu.size()
frame_history_cpu_avg.text = str(frametime_cpu_avg).pad_decimals(2)
frame_history_cpu_avg.modulate = frame_time_gradient.sample(remap(1000.0 / frametime_cpu_avg, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0))
var frametime_cpu_min: float = frame_history_cpu.min()
frame_history_cpu_min.text = str(frametime_cpu_min).pad_decimals(2)
frame_history_cpu_min.modulate = frame_time_gradient.sample(remap(1000.0 / frametime_cpu_min, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0))
var frametime_cpu_max: float = frame_history_cpu.max()
frame_history_cpu_max.text = str(frametime_cpu_max).pad_decimals(2)
frame_history_cpu_max.modulate = frame_time_gradient.sample(remap(1000.0 / frametime_cpu_max, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0))
frame_history_cpu_last.text = str(frametime_cpu).pad_decimals(2)
frame_history_cpu_last.modulate = frame_time_gradient.sample(remap(1000.0 / frametime_cpu, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0))
var frametime_gpu := RenderingServer.viewport_get_measured_render_time_gpu(viewport_rid)
frame_history_gpu.push_back(frametime_gpu)
if frame_history_gpu.size() > HISTORY_NUM_FRAMES:
frame_history_gpu.pop_front()
frametime_gpu_avg = frame_history_gpu.reduce(sum_func) / frame_history_gpu.size()
frame_history_gpu_avg.text = str(frametime_gpu_avg).pad_decimals(2)
frame_history_gpu_avg.modulate = frame_time_gradient.sample(remap(1000.0 / frametime_gpu_avg, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0))
var frametime_gpu_min: float = frame_history_gpu.min()
frame_history_gpu_min.text = str(frametime_gpu_min).pad_decimals(2)
frame_history_gpu_min.modulate = frame_time_gradient.sample(remap(1000.0 / frametime_gpu_min, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0))
var frametime_gpu_max: float = frame_history_gpu.max()
frame_history_gpu_max.text = str(frametime_gpu_max).pad_decimals(2)
frame_history_gpu_max.modulate = frame_time_gradient.sample(remap(1000.0 / frametime_gpu_max, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0))
frame_history_gpu_last.text = str(frametime_gpu).pad_decimals(2)
frame_history_gpu_last.modulate = frame_time_gradient.sample(remap(1000.0 / frametime_gpu, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0))
frames_per_second = 1000.0 / frametime_avg
fps_history.push_back(frames_per_second)
if fps_history.size() > HISTORY_NUM_FRAMES:
fps_history.pop_front()
fps.text = str(floor(frames_per_second)) + " FPS"
var frame_time_color := frame_time_gradient.sample(remap(frames_per_second, GRAPH_MIN_FPS, GRAPH_MAX_FPS, 0.0, 1.0))
fps.modulate = frame_time_color
frame_time.text = str(frametime).pad_decimals(2) + " mspf"
frame_time.modulate = frame_time_color
var vsync_string := ""
match DisplayServer.window_get_vsync_mode():
DisplayServer.VSYNC_ENABLED:
vsync_string = "V-Sync"
DisplayServer.VSYNC_ADAPTIVE:
vsync_string = "Adaptive V-Sync"
DisplayServer.VSYNC_MAILBOX:
vsync_string = "Mailbox V-Sync"
if Engine.max_fps > 0 or OS.low_processor_usage_mode:
# Display FPS cap determined by `Engine.max_fps` or low-processor usage mode sleep duration
# (the lowest FPS cap is used).
var low_processor_max_fps := roundi(1000000.0 / OS.low_processor_usage_mode_sleep_usec)
var fps_cap := low_processor_max_fps
if Engine.max_fps > 0:
fps_cap = mini(Engine.max_fps, low_processor_max_fps)
frame_time.text += " (cap: " + str(fps_cap) + " FPS"
if not vsync_string.is_empty():
frame_time.text += " + " + vsync_string
frame_time.text += ")"
else:
if not vsync_string.is_empty():
frame_time.text += " (" + vsync_string + ")"
frame_number.text = "Frame: " + str(Engine.get_frames_drawn())
frame_stats.text = str(
&"Draw calls: %d" % Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME),
&", Primitives: ", int(Performance.get_monitor(Performance.RENDER_TOTAL_PRIMITIVES_IN_FRAME)),
&", VRAM: %d" % snapped(Performance.get_monitor(Performance.RENDER_VIDEO_MEM_USED) * 0.000001, 1.0), &" MB")
last_tick = Time.get_ticks_usec()
## Captures a screenshot and saves it to the user folder in user://screenshots.
func do_screenshot() -> void:
await RenderingServer.frame_post_draw # Wait until frame is drawn
var image := get_viewport().get_texture().get_image()
# Fix image size for true pixel game, too small image output
if image.get_size().x != get_viewport().size.x or image.get_size().y != get_viewport().size.y:
image.resize(get_viewport().size.x, get_viewport().size.y, Image.INTERPOLATE_NEAREST)
if not image:
printerr("Failed to capture screen.")
return
# Ensure the screenshots directory exists
DirAccess.make_dir_recursive_absolute(ProjectSettings.globalize_path("user://screenshots"))
var path := "user://screenshots/screenshot_%s.png" % Time.get_datetime_string_from_system().replace(":", "_")
var err := image.save_png(ProjectSettings.globalize_path(path))
if err == OK:
print_rich("🖵 [color=yellow]Screenshot saved to:[/color] ", ProjectSettings.globalize_path(path))
OS.shell_show_in_file_manager(ProjectSettings.globalize_path(path))
else:
printerr("Failed to save screenshot:", err)
func _on_visibility_changed() -> void:
if visible:
# Reset graphs to prevent them from looking strange before `HISTORY_NUM_FRAMES` frames
# have been drawn.
var frametime_last := (Time.get_ticks_usec() - last_tick) * 0.001
fps_history.resize(HISTORY_NUM_FRAMES)
fps_history.fill(1000.0 / frametime_last)
frame_history_total.resize(HISTORY_NUM_FRAMES)
frame_history_total.fill(frametime_last)
frame_history_cpu.resize(HISTORY_NUM_FRAMES)
var viewport_rid := get_viewport().get_viewport_rid()
frame_history_cpu.fill(RenderingServer.viewport_get_measured_render_time_cpu(viewport_rid) + RenderingServer.get_frame_setup_time_cpu())
frame_history_gpu.resize(HISTORY_NUM_FRAMES)
frame_history_gpu.fill(RenderingServer.viewport_get_measured_render_time_gpu(viewport_rid))
+1
View File
@@ -0,0 +1 @@
uid://cjifa1oa5wtn4
+396
View File
@@ -0,0 +1,396 @@
[gd_scene format=3 uid="uid://cggqb75a8w8r"]
[ext_resource type="Script" uid="uid://cjifa1oa5wtn4" path="res://addons/debug_menu/debug_menu.gd" id="1_p440y"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ki0n8"]
bg_color = Color(0, 0, 0, 0.25098)
[node name="CanvasLayer" type="CanvasLayer" unique_id=414397422 node_paths=PackedStringArray("fps", "frame_time", "frame_number", "frame_stats", "frame_history_total_avg", "frame_history_total_min", "frame_history_total_max", "frame_history_total_last", "frame_history_cpu_avg", "frame_history_cpu_min", "frame_history_cpu_max", "frame_history_cpu_last", "frame_history_gpu_avg", "frame_history_gpu_min", "frame_history_gpu_max", "frame_history_gpu_last", "fps_graph", "total_graph", "cpu_graph", "gpu_graph", "information", "settings")]
process_mode = 3
layer = 128
script = ExtResource("1_p440y")
fps = NodePath("DebugMenu/VBoxContainer/FPS")
frame_time = NodePath("DebugMenu/VBoxContainer/FrameTime")
frame_number = NodePath("DebugMenu/VBoxContainer/FrameNumber")
frame_stats = NodePath("DebugMenu/VBoxContainer/FrameStats")
frame_history_total_avg = NodePath("DebugMenu/VBoxContainer/FrameTimeHistory/TotalAvg")
frame_history_total_min = NodePath("DebugMenu/VBoxContainer/FrameTimeHistory/TotalMin")
frame_history_total_max = NodePath("DebugMenu/VBoxContainer/FrameTimeHistory/TotalMax")
frame_history_total_last = NodePath("DebugMenu/VBoxContainer/FrameTimeHistory/TotalLast")
frame_history_cpu_avg = NodePath("DebugMenu/VBoxContainer/FrameTimeHistory/CPUAvg")
frame_history_cpu_min = NodePath("DebugMenu/VBoxContainer/FrameTimeHistory/CPUMin")
frame_history_cpu_max = NodePath("DebugMenu/VBoxContainer/FrameTimeHistory/CPUMax")
frame_history_cpu_last = NodePath("DebugMenu/VBoxContainer/FrameTimeHistory/CPULast")
frame_history_gpu_avg = NodePath("DebugMenu/VBoxContainer/FrameTimeHistory/GPUAvg")
frame_history_gpu_min = NodePath("DebugMenu/VBoxContainer/FrameTimeHistory/GPUMin")
frame_history_gpu_max = NodePath("DebugMenu/VBoxContainer/FrameTimeHistory/GPUMax")
frame_history_gpu_last = NodePath("DebugMenu/VBoxContainer/FrameTimeHistory/GPULast")
fps_graph = NodePath("DebugMenu/VBoxContainer/FPSGraph/Graph")
total_graph = NodePath("DebugMenu/VBoxContainer/TotalGraph/Graph")
cpu_graph = NodePath("DebugMenu/VBoxContainer/CPUGraph/Graph")
gpu_graph = NodePath("DebugMenu/VBoxContainer/GPUGraph/Graph")
information = NodePath("DebugMenu/VBoxContainer/Information")
settings = NodePath("DebugMenu/VBoxContainer/Settings")
[node name="DebugMenu" type="Control" parent="." unique_id=346480719]
custom_minimum_size = Vector2(400, 400)
layout_mode = 3
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -416.0
offset_top = 8.0
offset_right = -16.0
offset_bottom = 408.0
grow_horizontal = 0
size_flags_horizontal = 8
size_flags_vertical = 4
mouse_filter = 2
[node name="VBoxContainer" type="VBoxContainer" parent="DebugMenu" unique_id=947897244]
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -300.0
offset_bottom = 374.0
grow_horizontal = 0
mouse_filter = 2
theme_override_constants/separation = 0
[node name="FPS" type="Label" parent="DebugMenu/VBoxContainer" unique_id=997178716 groups=["debug_menu_label"]]
modulate = Color(0, 1, 0, 1)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/line_spacing = 0
theme_override_constants/outline_size = 5
theme_override_font_sizes/font_size = 18
text = "60 FPS"
horizontal_alignment = 2
[node name="FrameTime" type="Label" parent="DebugMenu/VBoxContainer" unique_id=1892289036 groups=["debug_menu_label"]]
modulate = Color(0, 1, 0, 1)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "16.67 mspf (cap: 123 FPS + Adaptive V-Sync)"
horizontal_alignment = 2
[node name="FrameNumber" type="Label" parent="DebugMenu/VBoxContainer" unique_id=1790704468 groups=["debug_menu_label"]]
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "Frame: 1234"
horizontal_alignment = 2
[node name="FrameStats" type="Label" parent="DebugMenu/VBoxContainer" unique_id=805680288 groups=["debug_menu_label"]]
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "Stats:"
horizontal_alignment = 2
[node name="FrameTimeHistory" type="GridContainer" parent="DebugMenu/VBoxContainer" unique_id=209708847]
layout_mode = 2
size_flags_horizontal = 8
mouse_filter = 2
theme_override_constants/h_separation = 0
theme_override_constants/v_separation = 0
columns = 5
[node name="Spacer" type="Control" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=1653573840]
custom_minimum_size = Vector2(60, 0)
layout_mode = 2
mouse_filter = 2
[node name="AvgHeader" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=1515213830 groups=["debug_menu_header", "debug_menu_label"]]
custom_minimum_size = Vector2(50, 0)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "Average"
horizontal_alignment = 2
[node name="MinHeader" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=839075582 groups=["debug_menu_header", "debug_menu_label"]]
custom_minimum_size = Vector2(50, 0)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "Best"
horizontal_alignment = 2
[node name="MaxHeader" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=2001207057 groups=["debug_menu_header", "debug_menu_label"]]
custom_minimum_size = Vector2(50, 0)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "Worst"
horizontal_alignment = 2
[node name="LastHeader" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=145277658 groups=["debug_menu_header", "debug_menu_label"]]
custom_minimum_size = Vector2(50, 0)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "Last"
horizontal_alignment = 2
[node name="TotalHeader" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=684135416 groups=["debug_menu_label"]]
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "Total:"
horizontal_alignment = 2
[node name="TotalAvg" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=1148307968 groups=["debug_menu_label"]]
modulate = Color(0, 1, 0, 1)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "123.45"
horizontal_alignment = 2
[node name="TotalMin" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=807706427 groups=["debug_menu_label"]]
modulate = Color(0, 1, 0, 1)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "123.45"
horizontal_alignment = 2
[node name="TotalMax" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=1552303690 groups=["debug_menu_label"]]
modulate = Color(0, 1, 0, 1)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "123.45"
horizontal_alignment = 2
[node name="TotalLast" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=614568271 groups=["debug_menu_label"]]
modulate = Color(0, 1, 0, 1)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "123.45"
horizontal_alignment = 2
[node name="CPUHeader" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=180318023 groups=["debug_menu_label"]]
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "CPU:"
horizontal_alignment = 2
[node name="CPUAvg" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=1638494409 groups=["debug_menu_label"]]
modulate = Color(0, 1, 0, 1)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "123.45"
horizontal_alignment = 2
[node name="CPUMin" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=1525286902 groups=["debug_menu_label"]]
modulate = Color(0, 1, 0, 1)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "12.34"
horizontal_alignment = 2
[node name="CPUMax" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=1696498522 groups=["debug_menu_label"]]
modulate = Color(0, 1, 0, 1)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "123.45"
horizontal_alignment = 2
[node name="CPULast" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=2040832325 groups=["debug_menu_label"]]
modulate = Color(0, 1, 0, 1)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "123.45"
horizontal_alignment = 2
[node name="GPUHeader" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=15556991 groups=["debug_menu_label"]]
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "GPU:"
horizontal_alignment = 2
[node name="GPUAvg" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=1755091907 groups=["debug_menu_label"]]
modulate = Color(0, 1, 0, 1)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "123.45"
horizontal_alignment = 2
[node name="GPUMin" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=1225652947 groups=["debug_menu_label"]]
modulate = Color(0, 1, 0, 1)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "1.23"
horizontal_alignment = 2
[node name="GPUMax" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=1647337652 groups=["debug_menu_label"]]
modulate = Color(0, 1, 0, 1)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "123.45"
horizontal_alignment = 2
[node name="GPULast" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory" unique_id=900089497 groups=["debug_menu_label"]]
modulate = Color(0, 1, 0, 1)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "123.45"
horizontal_alignment = 2
[node name="FPSGraph" type="HBoxContainer" parent="DebugMenu/VBoxContainer" unique_id=2129193079]
layout_mode = 2
mouse_filter = 2
alignment = 2
[node name="Title" type="Label" parent="DebugMenu/VBoxContainer/FPSGraph" unique_id=1484247768 groups=["debug_menu_label"]]
custom_minimum_size = Vector2(0, 27)
layout_mode = 2
size_flags_horizontal = 8
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "FPS: "
vertical_alignment = 1
[node name="Graph" type="Panel" parent="DebugMenu/VBoxContainer/FPSGraph" unique_id=1324384502 groups=["debug_menu_graph"]]
custom_minimum_size = Vector2(150, 25)
layout_mode = 2
size_flags_vertical = 0
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_ki0n8")
[node name="TotalGraph" type="HBoxContainer" parent="DebugMenu/VBoxContainer" unique_id=1757012220]
layout_mode = 2
mouse_filter = 2
alignment = 2
[node name="Title" type="Label" parent="DebugMenu/VBoxContainer/TotalGraph" unique_id=1749839410 groups=["debug_menu_label"]]
custom_minimum_size = Vector2(0, 27)
layout_mode = 2
size_flags_horizontal = 8
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "Total: "
vertical_alignment = 1
[node name="Graph" type="Panel" parent="DebugMenu/VBoxContainer/TotalGraph" unique_id=1880596791 groups=["debug_menu_graph"]]
custom_minimum_size = Vector2(150, 25)
layout_mode = 2
size_flags_vertical = 0
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_ki0n8")
[node name="CPUGraph" type="HBoxContainer" parent="DebugMenu/VBoxContainer" unique_id=705142964]
layout_mode = 2
mouse_filter = 2
alignment = 2
[node name="Title" type="Label" parent="DebugMenu/VBoxContainer/CPUGraph" unique_id=148522575 groups=["debug_menu_label"]]
custom_minimum_size = Vector2(0, 27)
layout_mode = 2
size_flags_horizontal = 8
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "CPU: "
vertical_alignment = 1
[node name="Graph" type="Panel" parent="DebugMenu/VBoxContainer/CPUGraph" unique_id=964269529 groups=["debug_menu_graph"]]
custom_minimum_size = Vector2(150, 25)
layout_mode = 2
size_flags_vertical = 0
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_ki0n8")
[node name="GPUGraph" type="HBoxContainer" parent="DebugMenu/VBoxContainer" unique_id=796931287]
layout_mode = 2
mouse_filter = 2
alignment = 2
[node name="Title" type="Label" parent="DebugMenu/VBoxContainer/GPUGraph" unique_id=1665497332 groups=["debug_menu_label"]]
custom_minimum_size = Vector2(0, 27)
layout_mode = 2
size_flags_horizontal = 8
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "GPU: "
vertical_alignment = 1
[node name="Graph" type="Panel" parent="DebugMenu/VBoxContainer/GPUGraph" unique_id=168534966 groups=["debug_menu_graph"]]
custom_minimum_size = Vector2(150, 25)
layout_mode = 2
size_flags_vertical = 0
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_ki0n8")
[node name="Information" type="Label" parent="DebugMenu/VBoxContainer" unique_id=811551518 groups=["debug_menu_label"]]
modulate = Color(1, 1, 1, 0.752941)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "12th Gen Intel(R) Core(TM) i0-1234K
Windows 12 64-bit (double precision), Vulkan 1.2.34
NVIDIA GeForce RTX 1234, 123.45.67"
horizontal_alignment = 2
[node name="Settings" type="Label" parent="DebugMenu/VBoxContainer" unique_id=857946198 groups=["debug_menu_label"]]
modulate = Color(0.8, 0.84, 1, 0.752941)
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 3
theme_override_font_sizes/font_size = 12
text = "Project Version: 1.2.3
Rendering Method: Forward+
Window: 1234×567, Viewport: 1234×567
3D Scale (FSR 1.0): 100% = 1234×567
3D Antialiasing: TAA + 2× MSAA + FXAA
SSR: 123 Steps
SSAO: On
SSIL: On
SDFGI: 1 Cascades
Glow: On
Volumetric Fog: On
2D Antialiasing: 2× MSAA"
horizontal_alignment = 2
[connection signal="visibility_changed" from="." to="." method="_on_visibility_changed"]
+7
View File
@@ -0,0 +1,7 @@
[plugin]
name="Antz's Debug Menu"
description="In-game debug menu displaying performance metrics and hardware information"
author="Calinou/Antz"
version="1.3.0"
script="plugin.gd"
+50
View File
@@ -0,0 +1,50 @@
@tool
extends EditorPlugin
func _enter_tree() -> void:
if not ProjectSettings.has_setting("autoload/DebugMenu"):
add_autoload_singleton("DebugMenu", "res://addons/debug_menu/debug_menu.tscn")
if not ProjectSettings.has_setting("application/config/version") or ProjectSettings.get_setting("application/config/version") == "":
ProjectSettings.set_setting("application/config/version", "1.0.0")
print('Debug Menu: Setting "application/config/version" was missing or empty and has been set to "1.0.0".')
ProjectSettings.add_property_info({
name = "application/config/version",
type = TYPE_STRING,
})
ProjectSettings.save()
# Add new Project Setting for font_size
if not ProjectSettings.has_setting("DebugMenu/settings/font_size"):
ProjectSettings.set_setting("DebugMenu/settings/font_size", 12)
var property_info = {
"name": "DebugMenu/settings/font_size",
"type": TYPE_INT,
"hint": PROPERTY_HINT_RANGE,
"hint_string" : "3,72"
}
ProjectSettings.add_property_info(property_info)
ProjectSettings.set_initial_value("DebugMenu/settings/font_size", 12)
ProjectSettings.save()
# Add new Project Setting for startup visibility
if not ProjectSettings.has_setting("DebugMenu/settings/startup_visibility"):
ProjectSettings.set_setting("DebugMenu/settings/startup_visibility", 0)
property_info = {
"name": "DebugMenu/settings/startup_visibility",
"type": TYPE_INT ,
"hint": PROPERTY_HINT_ENUM,
"hint_string" : "hidden,visible compact,visible detailed"
}
ProjectSettings.add_property_info(property_info)
ProjectSettings.set_initial_value("DebugMenu/settings/startup_visibility", 0)
ProjectSettings.save()
func _exit_tree() -> void:
remove_autoload_singleton("DebugMenu")
# Don't remove the project setting's value and input map action,
# as the plugin may be re-enabled in the future.
+1
View File
@@ -0,0 +1 @@
uid://dcxwqe5yhnqon