From 7ed5f3155ef741611db4c959c50b39c02718ab6d Mon Sep 17 00:00:00 2001 From: midnight Date: Thu, 26 Oct 2023 15:27:25 +0200 Subject: [PATCH] Initial commit --- .gitattributes | 2 + .gitignore | 2 + addons/debug_menu/LICENSE.md | 21 ++ addons/debug_menu/debug_menu.gd | 462 ++++++++++++++++++++++++++ addons/debug_menu/debug_menu.tscn | 402 ++++++++++++++++++++++ addons/debug_menu/plugin.cfg | 7 + addons/debug_menu/plugin.gd | 29 ++ export_presets.cfg | 102 ++++++ icon.svg | 1 + icon.svg.import | 37 +++ luts/lut_saturated.png | Bin 0 -> 106144 bytes luts/lut_saturated.png.import | 26 ++ prefabs/character.tscn | 41 +++ project.godot | 108 ++++++ readme.md | 8 + scenes/main.tscn | 64 ++++ scenes/main/main_environment.tres | 34 ++ src/character/camera_controller.gd | 29 ++ src/character/character_controller.gd | 52 +++ src/character/physics_interpolate.gd | 28 ++ src/game_manager.gd | 20 ++ src/shaders/ui/blur.gdshader | 10 + src/spawner.gd | 12 + ui/pause_menu.tscn | 61 ++++ ui/src/pause_menu.gd | 7 + 25 files changed, 1565 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 addons/debug_menu/LICENSE.md create mode 100644 addons/debug_menu/debug_menu.gd create mode 100644 addons/debug_menu/debug_menu.tscn create mode 100644 addons/debug_menu/plugin.cfg create mode 100644 addons/debug_menu/plugin.gd create mode 100644 export_presets.cfg create mode 100644 icon.svg create mode 100644 icon.svg.import create mode 100644 luts/lut_saturated.png create mode 100644 luts/lut_saturated.png.import create mode 100644 prefabs/character.tscn create mode 100644 project.godot create mode 100644 readme.md create mode 100644 scenes/main.tscn create mode 100644 scenes/main/main_environment.tres create mode 100644 src/character/camera_controller.gd create mode 100644 src/character/character_controller.gd create mode 100644 src/character/physics_interpolate.gd create mode 100644 src/game_manager.gd create mode 100644 src/shaders/ui/blur.gdshader create mode 100644 src/spawner.gd create mode 100644 ui/pause_menu.tscn create mode 100644 ui/src/pause_menu.gd diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4709183 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Godot 4+ specific ignores +.godot/ diff --git a/addons/debug_menu/LICENSE.md b/addons/debug_menu/LICENSE.md new file mode 100644 index 0000000..54fc020 --- /dev/null +++ b/addons/debug_menu/LICENSE.md @@ -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. diff --git a/addons/debug_menu/debug_menu.gd b/addons/debug_menu/debug_menu.gd new file mode 100644 index 0000000..adce78e --- /dev/null +++ b/addons/debug_menu/debug_menu.gd @@ -0,0 +1,462 @@ +extends Control + +@export var fps: Label +@export var frame_time: Label +@export var frame_number: 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 + +const GRAPH_SIZE = Vector2(150, 25) +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 + $VBoxContainer/FrameTimeHistory.visible = style == Style.VISIBLE_DETAILED + $VBoxContainer/FPSGraph.visible = style == Style.VISIBLE_DETAILED + $VBoxContainer/TotalGraph.visible = style == Style.VISIBLE_DETAILED + $VBoxContainer/CPUGraph.visible = style == Style.VISIBLE_DETAILED + $VBoxContainer/GPUGraph.visible = style == Style.VISIBLE_DETAILED + information.visible = style == Style.VISIBLE_DETAILED + settings.visible = style == Style.VISIBLE_DETAILED + +# 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) + + +func _ready() -> void: + 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 . + frame_time_gradient.set_color(0, Color8(239, 68, 68)) # red-500 + frame_time_gradient.set_color(1, Color8(56, 189, 248)) # light-blue-400 + frame_time_gradient.add_point(0.3333, Color8(250, 204, 21)) # yellow-400 + frame_time_gradient.add_point(0.6667, Color8(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 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 + + +func _exit_tree() -> void: + 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_string := "" + match str(ProjectSettings.get_setting("rendering/renderer/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 antialiasing_3d_string := "" + if viewport.use_taa: + 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" + + var scaling_mode = "Unknown" + match viewport.scaling_3d_mode: + Viewport.SCALING_3D_MODE_BILINEAR: + scaling_mode = "Bilinear" + Viewport.SCALING_3D_MODE_FSR: + scaling_mode = "FSR 1.0" + Viewport.SCALING_3D_MODE_FSR2: + scaling_mode = "FSR 2.2" + + settings.text += "3D scale (%s): %d%% = %d×%d" % [ + scaling_mode, + 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 graphics_api_string := "" + if str(ProjectSettings.get_setting("rendering/renderer/rendering_method")) != "gl_compatibility": + graphics_api_string = "Vulkan" + else: + if OS.has_feature("web"): + graphics_api_string = "WebGL" + elif OS.has_feature("mobile"): + graphics_api_string = "OpenGL ES" + else: + 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()) + + last_tick = Time.get_ticks_usec() + + +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)) diff --git a/addons/debug_menu/debug_menu.tscn b/addons/debug_menu/debug_menu.tscn new file mode 100644 index 0000000..2aaf0c1 --- /dev/null +++ b/addons/debug_menu/debug_menu.tscn @@ -0,0 +1,402 @@ +[gd_scene load_steps=3 format=3 uid="uid://cggqb75a8w8r"] + +[ext_resource type="Script" 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"] +process_mode = 3 +layer = 128 + +[node name="DebugMenu" type="Control" parent="." node_paths=PackedStringArray("fps", "frame_time", "frame_number", "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")] +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 +script = ExtResource("1_p440y") +fps = NodePath("VBoxContainer/FPS") +frame_time = NodePath("VBoxContainer/FrameTime") +frame_number = NodePath("VBoxContainer/FrameNumber") +frame_history_total_avg = NodePath("VBoxContainer/FrameTimeHistory/TotalAvg") +frame_history_total_min = NodePath("VBoxContainer/FrameTimeHistory/TotalMin") +frame_history_total_max = NodePath("VBoxContainer/FrameTimeHistory/TotalMax") +frame_history_total_last = NodePath("VBoxContainer/FrameTimeHistory/TotalLast") +frame_history_cpu_avg = NodePath("VBoxContainer/FrameTimeHistory/CPUAvg") +frame_history_cpu_min = NodePath("VBoxContainer/FrameTimeHistory/CPUMin") +frame_history_cpu_max = NodePath("VBoxContainer/FrameTimeHistory/CPUMax") +frame_history_cpu_last = NodePath("VBoxContainer/FrameTimeHistory/CPULast") +frame_history_gpu_avg = NodePath("VBoxContainer/FrameTimeHistory/GPUAvg") +frame_history_gpu_min = NodePath("VBoxContainer/FrameTimeHistory/GPUMin") +frame_history_gpu_max = NodePath("VBoxContainer/FrameTimeHistory/GPUMax") +frame_history_gpu_last = NodePath("VBoxContainer/FrameTimeHistory/GPULast") +fps_graph = NodePath("VBoxContainer/FPSGraph/Graph") +total_graph = NodePath("VBoxContainer/TotalGraph/Graph") +cpu_graph = NodePath("VBoxContainer/CPUGraph/Graph") +gpu_graph = NodePath("VBoxContainer/GPUGraph/Graph") +information = NodePath("VBoxContainer/Information") +settings = NodePath("VBoxContainer/Settings") + +[node name="VBoxContainer" type="VBoxContainer" parent="DebugMenu"] +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"] +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 = 5 +theme_override_constants/line_spacing = 0 +theme_override_font_sizes/font_size = 18 +text = "60 FPS" +horizontal_alignment = 2 + +[node name="FrameTime" type="Label" parent="DebugMenu/VBoxContainer"] +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"] +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="FrameTimeHistory" type="GridContainer" parent="DebugMenu/VBoxContainer"] +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"] +custom_minimum_size = Vector2(60, 0) +layout_mode = 2 +mouse_filter = 2 + +[node name="AvgHeader" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory"] +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"] +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"] +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"] +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"] +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 = "Total:" +horizontal_alignment = 2 + +[node name="TotalAvg" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory"] +modulate = Color(0, 1, 0, 1) +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 = "123.45" +horizontal_alignment = 2 + +[node name="TotalMin" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory"] +modulate = Color(0, 1, 0, 1) +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 = "123.45" +horizontal_alignment = 2 + +[node name="TotalMax" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory"] +modulate = Color(0, 1, 0, 1) +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 = "123.45" +horizontal_alignment = 2 + +[node name="TotalLast" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory"] +modulate = Color(0, 1, 0, 1) +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 = "123.45" +horizontal_alignment = 2 + +[node name="CPUHeader" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory"] +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 = "CPU:" +horizontal_alignment = 2 + +[node name="CPUAvg" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory"] +modulate = Color(0, 1, 0, 1) +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 = "123.45" +horizontal_alignment = 2 + +[node name="CPUMin" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory"] +modulate = Color(0, 1, 0, 1) +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 = "12.34" +horizontal_alignment = 2 + +[node name="CPUMax" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory"] +modulate = Color(0, 1, 0, 1) +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 = "123.45" +horizontal_alignment = 2 + +[node name="CPULast" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory"] +modulate = Color(0, 1, 0, 1) +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 = "123.45" +horizontal_alignment = 2 + +[node name="GPUHeader" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory"] +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 = "GPU:" +horizontal_alignment = 2 + +[node name="GPUAvg" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory"] +modulate = Color(0, 1, 0, 1) +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 = "123.45" +horizontal_alignment = 2 + +[node name="GPUMin" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory"] +modulate = Color(0, 1, 0, 1) +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 = "1.23" +horizontal_alignment = 2 + +[node name="GPUMax" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory"] +modulate = Color(0, 1, 0, 1) +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 = "123.45" +horizontal_alignment = 2 + +[node name="GPULast" type="Label" parent="DebugMenu/VBoxContainer/FrameTimeHistory"] +modulate = Color(0, 1, 0, 1) +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 = "123.45" +horizontal_alignment = 2 + +[node name="FPSGraph" type="HBoxContainer" parent="DebugMenu/VBoxContainer"] +layout_mode = 2 +mouse_filter = 2 +alignment = 2 + +[node name="Title" type="Label" parent="DebugMenu/VBoxContainer/FPSGraph"] +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"] +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"] +layout_mode = 2 +mouse_filter = 2 +alignment = 2 + +[node name="Title" type="Label" parent="DebugMenu/VBoxContainer/TotalGraph"] +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"] +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"] +layout_mode = 2 +mouse_filter = 2 +alignment = 2 + +[node name="Title" type="Label" parent="DebugMenu/VBoxContainer/CPUGraph"] +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"] +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"] +layout_mode = 2 +mouse_filter = 2 +alignment = 2 + +[node name="Title" type="Label" parent="DebugMenu/VBoxContainer/GPUGraph"] +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"] +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"] +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"] +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="DebugMenu" to="DebugMenu" method="_on_visibility_changed"] diff --git a/addons/debug_menu/plugin.cfg b/addons/debug_menu/plugin.cfg new file mode 100644 index 0000000..851c3da --- /dev/null +++ b/addons/debug_menu/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="Debug Menu" +description="In-game debug menu displaying performance metrics and hardware information" +author="Calinou" +version="1.1.2" +script="plugin.gd" diff --git a/addons/debug_menu/plugin.gd b/addons/debug_menu/plugin.gd new file mode 100644 index 0000000..5ec132e --- /dev/null +++ b/addons/debug_menu/plugin.gd @@ -0,0 +1,29 @@ +@tool +extends EditorPlugin + +func _enter_tree() -> void: + add_autoload_singleton("DebugMenu", "res://addons/debug_menu/debug_menu.tscn") + + # FIXME: This appears to do nothing. +# if not ProjectSettings.has_setting("application/config/version"): +# ProjectSettings.set_setting("application/config/version", "1.0.0") +# +# ProjectSettings.set_initial_value("application/config/version", "1.0.0") +# ProjectSettings.add_property_info({ +# name = "application/config/version", +# type = TYPE_STRING, +# }) +# +# if not InputMap.has_action("cycle_debug_menu"): +# InputMap.add_action("cycle_debug_menu") +# var event := InputEventKey.new() +# event.keycode = KEY_F3 +# InputMap.action_add_event("cycle_debug_menu", event) +# +# 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. diff --git a/export_presets.cfg b/export_presets.cfg new file mode 100644 index 0000000..b65518b --- /dev/null +++ b/export_presets.cfg @@ -0,0 +1,102 @@ +[preset.0] + +name="Windows Desktop" +platform="Windows Desktop" +runnable=true +dedicated_server=false +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="C:/Users/Midnight/Desktop/export2/not_bar.exe" +encryption_include_filters="" +encryption_exclude_filters="" +encrypt_pck=false +encrypt_directory=false + +[preset.0.options] + +custom_template/debug="" +custom_template/release="" +debug/export_console_wrapper=1 +binary_format/embed_pck=false +texture_format/bptc=true +texture_format/s3tc=true +texture_format/etc=false +texture_format/etc2=false +binary_format/architecture="x86_64" +codesign/enable=false +codesign/timestamp=true +codesign/timestamp_server_url="" +codesign/digest_algorithm=1 +codesign/description="" +codesign/custom_options=PackedStringArray() +application/modify_resources=true +application/icon="" +application/console_wrapper_icon="" +application/icon_interpolation=4 +application/file_version="" +application/product_version="" +application/company_name="" +application/product_name="" +application/file_description="" +application/copyright="" +application/trademarks="" +application/export_angle=0 +ssh_remote_deploy/enabled=false +ssh_remote_deploy/host="user@host_ip" +ssh_remote_deploy/port="22" +ssh_remote_deploy/extra_args_ssh="" +ssh_remote_deploy/extra_args_scp="" +ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}' +$action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}' +$trigger = New-ScheduledTaskTrigger -Once -At 00:00 +$settings = New-ScheduledTaskSettingsSet +$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings +Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true +Start-ScheduledTask -TaskName godot_remote_debug +while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 } +Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue" +ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue +Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue +Remove-Item -Recurse -Force '{temp_dir}'" + +[preset.1] + +name="Linux/X11" +platform="Linux/X11" +runnable=true +dedicated_server=false +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="C:/Users/Midnight/Desktop/export2/not_bar.x86_64" +encryption_include_filters="" +encryption_exclude_filters="" +encrypt_pck=false +encrypt_directory=false + +[preset.1.options] + +custom_template/debug="" +custom_template/release="" +debug/export_console_wrapper=1 +binary_format/embed_pck=false +texture_format/bptc=true +texture_format/s3tc=true +texture_format/etc=false +texture_format/etc2=false +binary_format/architecture="x86_64" +ssh_remote_deploy/enabled=false +ssh_remote_deploy/host="user@host_ip" +ssh_remote_deploy/port="22" +ssh_remote_deploy/extra_args_ssh="" +ssh_remote_deploy/extra_args_scp="" +ssh_remote_deploy/run_script="#!/usr/bin/env bash +export DISPLAY=:0 +unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\" +\"{temp_dir}/{exe_name}\" {cmd_args}" +ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash +kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\") +rm -rf \"{temp_dir}\"" diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..b370ceb --- /dev/null +++ b/icon.svg @@ -0,0 +1 @@ + diff --git a/icon.svg.import b/icon.svg.import new file mode 100644 index 0000000..2c51913 --- /dev/null +++ b/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b8fqumed5vu5w" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/luts/lut_saturated.png b/luts/lut_saturated.png new file mode 100644 index 0000000000000000000000000000000000000000..a4ac7da6d805db94138c86e35db29782f94342bf GIT binary patch literal 106144 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%0AQ_RSP>KxyH6uzt@cuk!oK( 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�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 literal 0 HcmV?d00001 diff --git a/luts/lut_saturated.png.import b/luts/lut_saturated.png.import new file mode 100644 index 0000000..fa7f9d6 --- /dev/null +++ b/luts/lut_saturated.png.import @@ -0,0 +1,26 @@ +[remap] + +importer="3d_texture" +type="CompressedTexture3D" +uid="uid://bus418i6c6y3w" +path="res://.godot/imported/lut_saturated.png-bf0a35cafccb1516d07adffb4e04f5f3.ctex3d" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://luts/lut_saturated.png" +dest_files=["res://.godot/imported/lut_saturated.png-bf0a35cafccb1516d07adffb4e04f5f3.ctex3d"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +slices/horizontal=8 +slices/vertical=8 diff --git a/prefabs/character.tscn b/prefabs/character.tscn new file mode 100644 index 0000000..0e87f8d --- /dev/null +++ b/prefabs/character.tscn @@ -0,0 +1,41 @@ +[gd_scene load_steps=6 format=3 uid="uid://c4orppao35wg6"] + +[ext_resource type="Script" path="res://src/character/character_controller.gd" id="1_2yciu"] +[ext_resource type="Script" path="res://src/character/physics_interpolate.gd" id="2_jbufo"] +[ext_resource type="Script" path="res://src/character/camera_controller.gd" id="3_i1tod"] + +[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_m1ch2"] +radius = 0.4 +height = 1.8 + +[sub_resource type="CapsuleMesh" id="CapsuleMesh_64ysj"] +radius = 0.4 +height = 1.8 + +[node name="Character" type="Node"] + +[node name="Physics" type="CharacterBody3D" parent="."] +script = ExtResource("1_2yciu") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Physics"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.9, 0) +shape = SubResource("CapsuleShape3D_m1ch2") + +[node name="Visual" type="Node3D" parent="." node_paths=PackedStringArray("physicsObject")] +script = ExtResource("2_jbufo") +physicsObject = NodePath("../Physics") + +[node name="CameraTarget" type="Node3D" parent="Visual"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.28439, 0) + +[node name="CSGMesh3D" type="CSGMesh3D" parent="Visual"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.9, 0) +gi_mode = 0 +mesh = SubResource("CapsuleMesh_64ysj") + +[node name="CameraArm" type="Node3D" parent="." node_paths=PackedStringArray("target")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.6, 0) +script = ExtResource("3_i1tod") +target = NodePath("../Visual/CameraTarget") + +[node name="Camera3D" type="Camera3D" parent="CameraArm"] diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..82c2f4b --- /dev/null +++ b/project.godot @@ -0,0 +1,108 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="3D Character Controller Template" +config/version="0.0.2" +config/tags=PackedStringArray("3d") +run/main_scene="res://scenes/main.tscn" +config/features=PackedStringArray("4.2", "Forward Plus") +boot_splash/bg_color=Color(0, 0, 0, 1) +config/icon="res://icon.svg" + +[autoload] + +DebugMenu="*res://addons/debug_menu/debug_menu.tscn" +GameManager="*res://src/game_manager.gd" + +[display] + +window/size/mode=4 + +[editor_plugins] + +enabled=PackedStringArray("res://addons/debug_menu/plugin.cfg") + +[input] + +move_left={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":-1.0,"script":null) +] +} +move_right={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":1.0,"script":null) +] +} +move_up={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":-1.0,"script":null) +] +} +move_down={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":1.0,"script":null) +] +} +jump={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":true,"script":null) +] +} +sprint={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":4,"axis_value":1.0,"script":null) +] +} +zoom_in={ +"deadzone": 0.5, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":4,"canceled":false,"pressed":false,"double_click":false,"script":null) +] +} +zoom_out={ +"deadzone": 0.5, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":5,"canceled":false,"pressed":false,"double_click":false,"script":null) +] +} +look_left={ +"deadzone": 0.5, +"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":2,"axis_value":-1.0,"script":null) +] +} +look_right={ +"deadzone": 0.5, +"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":2,"axis_value":1.0,"script":null) +] +} +look_up={ +"deadzone": 0.5, +"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":3,"axis_value":-1.0,"script":null) +] +} +look_down={ +"deadzone": 0.5, +"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":3,"axis_value":1.0,"script":null) +] +} + +[rendering] + +lights_and_shadows/directional_shadow/16_bits=false +scaling_3d/mode=2 +environment/defaults/default_clear_color=Color(0, 0, 0, 1) +environment/defaults/default_environment="res://scenes/main/main_environment.tres" diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..3eaba61 --- /dev/null +++ b/readme.md @@ -0,0 +1,8 @@ +# 3D Character Controller Template + +A simple template to get started with 3D + +## Features + +- Performance menu addon (`F3`) +- First/Third person character controller with basic input maps \ No newline at end of file diff --git a/scenes/main.tscn b/scenes/main.tscn new file mode 100644 index 0000000..437ee7a --- /dev/null +++ b/scenes/main.tscn @@ -0,0 +1,64 @@ +[gd_scene load_steps=7 format=3 uid="uid://dgfh1lgxud87u"] + +[ext_resource type="PackedScene" uid="uid://c4orppao35wg6" path="res://prefabs/character.tscn" id="2_v34ds"] +[ext_resource type="Script" path="res://src/spawner.gd" id="3_xxi2i"] + +[sub_resource type="GDScript" id="GDScript_12xd3"] +script/source = "extends Node3D + +func _ready() -> void: + Input.mouse_mode = Input.MOUSE_MODE_CAPTURED +" + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_xxbnc"] +albedo_color = Color(0.266667, 0.145098, 0.0823529, 1) + +[sub_resource type="PlaneMesh" id="PlaneMesh_uelfv"] +material = SubResource("StandardMaterial3D_xxbnc") +size = Vector2(50, 50) + +[sub_resource type="BoxShape3D" id="BoxShape3D_vbj2x"] +size = Vector3(50, 1, 50) + +[node name="Main" type="Node3D"] +script = SubResource("GDScript_12xd3") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(0.276457, -0.764665, 0.582116, 0.11662, 0.62794, 0.769474, -0.953924, -0.14484, 0.262774, 0, 0, 0) +light_energy = 2.0 +shadow_enabled = true +directional_shadow_fade_start = 1.0 +directional_shadow_max_distance = 50.0 + +[node name="Spawner" type="Node3D" parent="."] +script = ExtResource("3_xxi2i") +object_to_spawn = ExtResource("2_v34ds") + +[node name="CSGMesh3D" type="CSGMesh3D" parent="."] +mesh = SubResource("PlaneMesh_uelfv") + +[node name="StaticBody3D" type="StaticBody3D" parent="CSGMesh3D"] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="CSGMesh3D/StaticBody3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.5, 0) +shape = SubResource("BoxShape3D_vbj2x") + +[node name="CSGCombiner3D" type="CSGCombiner3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +use_collision = true + +[node name="Box" type="CSGBox3D" parent="CSGCombiner3D"] + +[node name="Box5" type="CSGBox3D" parent="CSGCombiner3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.37539, 1.21157, -5.02753) + +[node name="Box2" type="CSGBox3D" parent="CSGCombiner3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 0.5, 0.5) + +[node name="Box4" type="CSGBox3D" parent="CSGCombiner3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.06635, 1.17009, -1.15682) +size = Vector3(1, 1, 4.31364) + +[node name="Box3" type="CSGBox3D" parent="CSGCombiner3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.15636, 1.09924, 0.824171) +size = Vector3(3.28895, 0.716575, 1) diff --git a/scenes/main/main_environment.tres b/scenes/main/main_environment.tres new file mode 100644 index 0000000..51c1ecc --- /dev/null +++ b/scenes/main/main_environment.tres @@ -0,0 +1,34 @@ +[gd_resource type="Environment" load_steps=4 format=3 uid="uid://b8fqed8jo6yqj"] + +[ext_resource type="CompressedTexture3D" uid="uid://bus418i6c6y3w" path="res://luts/lut_saturated.png" id="1_3f5y7"] + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_rxwic"] +sky_top_color = Color(0.317647, 0.415686, 0.643137, 1) +sky_horizon_color = Color(0.878431, 0.929412, 1, 1) +ground_bottom_color = Color(0.439216, 0.290196, 0.239216, 1) +ground_horizon_color = Color(0.988235, 0.890196, 0.823529, 1) +sun_angle_max = 0.0 +sun_curve = 1e-05 + +[sub_resource type="Sky" id="Sky_wbc5y"] +sky_material = SubResource("ProceduralSkyMaterial_rxwic") + +[resource] +background_mode = 2 +sky = SubResource("Sky_wbc5y") +tonemap_mode = 2 +tonemap_white = 6.0 +ssao_enabled = true +ssao_ao_channel_affect = 1.0 +sdfgi_use_occlusion = true +sdfgi_bounce_feedback = 0.9 +glow_enabled = true +glow_levels/4 = 1.0 +glow_levels/6 = 1.0 +glow_levels/7 = 1.0 +glow_blend_mode = 4 +fog_sun_scatter = 0.5 +fog_aerial_perspective = 0.9 +volumetric_fog_albedo = Color(0.960784, 0.984314, 1, 1) +adjustment_enabled = true +adjustment_color_correction = ExtResource("1_3f5y7") diff --git a/src/character/camera_controller.gd b/src/character/camera_controller.gd new file mode 100644 index 0000000..55d0f2e --- /dev/null +++ b/src/character/camera_controller.gd @@ -0,0 +1,29 @@ +extends Node3D + +@export var target : Node3D +@onready var camera = $Camera3D +var lookInput : Vector2 = Vector2.ZERO + +func _input(event): + if event is InputEventMouseMotion: + lookInput.x += event.relative.y + lookInput.y += event.relative.x + return + + var zoom = .0 + if event.is_action_released("zoom_in"): + zoom -= .2 + if event.is_action_released("zoom_out"): + zoom += .2 + + camera.position.z = clamp(camera.position.z + zoom, 0, 4) + +func _process(delta): + lookInput += Input.get_vector('look_left','look_right', 'look_down', 'look_up') + + global_position = target.global_position + + rotation.x = clamp(rotation.x - lookInput.x * delta * 0.3, PI*-0.48, PI*0.2) + rotation.y -= lookInput.y * delta * 0.3 + + lookInput = Vector2.ZERO diff --git a/src/character/character_controller.gd b/src/character/character_controller.gd new file mode 100644 index 0000000..5b301e1 --- /dev/null +++ b/src/character/character_controller.gd @@ -0,0 +1,52 @@ +extends CharacterBody3D + +var input3D : Vector3 + +@export var SPEED = 1.4 +@export var SPRINT_SPEED = 3.0 +@export var JUMP_VELOCITY = 4.5 + +var speed = .0 + +@onready var camera : Camera3D = get_viewport().get_camera_3d() + +var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") + +func _ready(): + process_priority = 2 + +func getCameraRelativeInput() -> Vector3 : + var cam_basis = camera.global_transform.basis + cam_basis.x.y = 0 + cam_basis.x = cam_basis.x.normalized() + cam_basis.z.y = 0 + cam_basis.z = cam_basis.z.normalized() + + var input = Input.get_vector("move_left", "move_right", "move_up", "move_down") + var relativeInput = Vector3.ZERO + relativeInput += input.x * cam_basis.x + relativeInput += input.y * cam_basis.z + + return relativeInput + +func _physics_process(delta): + if not is_on_floor(): + velocity.y -= gravity * delta + + if Input.is_action_just_pressed("jump") and is_on_floor(): + velocity.y = JUMP_VELOCITY + + input3D = getCameraRelativeInput() + + speed = SPEED + Input.get_action_strength("sprint") * SPRINT_SPEED + + var direction = input3D.normalized() + if direction: + velocity.x = direction.x * speed + velocity.z = direction.z * speed + look_at(direction + global_position) + else: + velocity.x = move_toward(velocity.x, 0, speed) + velocity.z = move_toward(velocity.z, 0, speed) + + move_and_slide() diff --git a/src/character/physics_interpolate.gd b/src/character/physics_interpolate.gd new file mode 100644 index 0000000..3098d1f --- /dev/null +++ b/src/character/physics_interpolate.gd @@ -0,0 +1,28 @@ +extends Node3D + +@export var physicsObject : PhysicsBody3D + +var physics_delta : float = 1 + +var target : Transform3D +var prev : Transform3D + +func _ready(): + target = physicsObject.global_transform + prev = physicsObject.global_transform + +var d = 0 +func _process(delta): + d += delta + + var t = d / physics_delta + + global_transform = prev.interpolate_with(target, t) + +func _physics_process(delta): + physics_delta = delta + d = 0 + + global_transform = target + prev = target + target = physicsObject.global_transform diff --git a/src/game_manager.gd b/src/game_manager.gd new file mode 100644 index 0000000..9a6bc98 --- /dev/null +++ b/src/game_manager.gd @@ -0,0 +1,20 @@ +extends Node + +var pause_menu_res = preload('res://ui/pause_menu.tscn') +var pause_menu: PauseMenu + +func _ready() -> void: + pause_menu = pause_menu_res.instantiate() + get_tree().root.add_child.call_deferred(pause_menu) + +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed('ui_cancel'): + pause_game(not get_tree().paused) + +func quit_game(): + get_tree().quit() + +func pause_game(pause = true): + Input.mouse_mode = Input.MOUSE_MODE_VISIBLE if pause else Input.MOUSE_MODE_CAPTURED + get_tree().paused = pause + pause_menu.visible = pause diff --git a/src/shaders/ui/blur.gdshader b/src/shaders/ui/blur.gdshader new file mode 100644 index 0000000..68c5c30 --- /dev/null +++ b/src/shaders/ui/blur.gdshader @@ -0,0 +1,10 @@ +shader_type canvas_item; +render_mode blend_disabled; + +uniform float blur_amount : hint_range(0,5) = 5.0; +uniform vec4 tint : source_color = vec4(.5, .5, .5, 1.0); +uniform sampler2D screen_texture : hint_screen_texture, filter_linear_mipmap; + +void fragment() { + COLOR = textureLod(screen_texture, SCREEN_UV, blur_amount) * tint; +} \ No newline at end of file diff --git a/src/spawner.gd b/src/spawner.gd new file mode 100644 index 0000000..a78cd12 --- /dev/null +++ b/src/spawner.gd @@ -0,0 +1,12 @@ +class_name Spawner extends Node3D + +@export var object_to_spawn: PackedScene +@export var auto_spawn: bool = true + +func _ready() -> void: + if auto_spawn: + spawn.call_deferred() + +func spawn() -> void: + var object = object_to_spawn.instantiate() + get_parent_node_3d().add_child(object) diff --git a/ui/pause_menu.tscn b/ui/pause_menu.tscn new file mode 100644 index 0000000..25bdc77 --- /dev/null +++ b/ui/pause_menu.tscn @@ -0,0 +1,61 @@ +[gd_scene load_steps=4 format=3 uid="uid://dilbjuywlv0mc"] + +[ext_resource type="Shader" path="res://src/shaders/ui/blur.gdshader" id="1_q1q1u"] +[ext_resource type="Script" path="res://ui/src/pause_menu.gd" id="1_qw2fh"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_dcwl4"] +shader = ExtResource("1_q1q1u") +shader_parameter/blur_amount = 3.0 +shader_parameter/tint = Color(0.5, 0.5, 0.5, 1) + +[node name="PauseMenu" type="Control"] +process_mode = 2 +visible = false +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_qw2fh") + +[node name="MainPanel" type="PanelContainer" parent="."] +material = SubResource("ShaderMaterial_dcwl4") +layout_mode = 1 +anchors_preset = 13 +anchor_left = 0.5 +anchor_right = 0.5 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="MarginContainer" type="MarginContainer" parent="MainPanel"] +layout_mode = 2 +theme_override_constants/margin_left = 30 +theme_override_constants/margin_top = 10 +theme_override_constants/margin_right = 30 +theme_override_constants/margin_bottom = 10 + +[node name="VBoxContainer" type="VBoxContainer" parent="MainPanel/MarginContainer"] +custom_minimum_size = Vector2(300, 0) +layout_mode = 2 +alignment = 1 + +[node name="Label" type="Label" parent="MainPanel/MarginContainer/VBoxContainer"] +layout_mode = 2 +theme_type_variation = &"HeaderLarge" +text = "Paused" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="ContinueButton" type="Button" parent="MainPanel/MarginContainer/VBoxContainer"] +layout_mode = 2 +text = "Continue" + +[node name="QuitButton" type="Button" parent="MainPanel/MarginContainer/VBoxContainer"] +layout_mode = 2 +text = "Quit +" + +[connection signal="pressed" from="MainPanel/MarginContainer/VBoxContainer/ContinueButton" to="." method="_on_continue"] +[connection signal="pressed" from="MainPanel/MarginContainer/VBoxContainer/QuitButton" to="." method="_on_quit"] diff --git a/ui/src/pause_menu.gd b/ui/src/pause_menu.gd new file mode 100644 index 0000000..2fc81ab --- /dev/null +++ b/ui/src/pause_menu.gd @@ -0,0 +1,7 @@ +class_name PauseMenu extends Node + +func _on_continue() -> void: + GameManager.pause_game(false) + +func _on_quit() -> void: + GameManager.quit_game()