This commit is contained in:
korboduo 2025-12-06 15:43:53 +09:00
commit dc7e8771e6
64 changed files with 1976 additions and 0 deletions

4
.editorconfig Normal file
View File

@ -0,0 +1,4 @@
root = true
[*]
charset = utf-8

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# Godot 4+ specific ignores
.godot/
/android/

36
assets/planar.gdshader Normal file
View File

@ -0,0 +1,36 @@
shader_type spatial;
uniform sampler2D texture_albedo: filter_nearest_mipmap_anisotropic;
uniform vec3 color_albedo:source_color = vec3(1,1,1);
group_uniforms planar;
uniform bool tiling = true;
uniform float tile_scale = 1.0;
uniform float blend_sharpness = 4.0;
varying vec3 world_pos;
varying vec3 world_normal;
void vertex() {
world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
world_normal = normalize(mat3(MODEL_MATRIX) * NORMAL);
}
void fragment() {
vec2 uv = UV;
if (tiling){
vec3 n = normalize(world_normal);
vec3 abs_normal = abs(n);
float top_weight = pow(abs_normal.y, blend_sharpness);
float side_x_weight = pow(abs_normal.x, blend_sharpness);
float side_z_weight = pow(abs_normal.z, blend_sharpness);
float total_weight = top_weight + side_x_weight + side_z_weight;
top_weight /= total_weight;
side_x_weight /= total_weight;
side_z_weight /= total_weight;
vec2 uv_top = world_pos.xz / -tile_scale;
vec2 uv_side_x = world_pos.zy / -tile_scale;
vec2 uv_side_z = world_pos.xy / -tile_scale;
uv = (top_weight > side_x_weight && top_weight > side_z_weight) ? uv_top :
(side_x_weight > side_z_weight) ? uv_side_x : uv_side_z;
}
ALBEDO = texture(texture_albedo, uv).rgb*color_albedo;
}

View File

@ -0,0 +1 @@
uid://cygvk4t4itjpv

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d32vex3n66fvc"
path="res://.godot/imported/texture_01.png-7a561ae919880fae6fcd6324ffc9d178.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/prototype/texture_01.png"
dest_files=["res://.godot/imported/texture_01.png-7a561ae919880fae6fcd6324ffc9d178.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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cg6lbwfts577w"
path="res://.godot/imported/texture_02.png-1ea527bfa716785196d479c6b81909de.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/prototype/texture_02.png"
dest_files=["res://.godot/imported/texture_02.png-1ea527bfa716785196d479c6b81909de.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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://byt0c25uubxf3"
path="res://.godot/imported/texture_03.png-75695628e71bab205f2b71558f8188fe.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/prototype/texture_03.png"
dest_files=["res://.godot/imported/texture_03.png-75695628e71bab205f2b71558f8188fe.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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://xq6ha0kitoht"
path="res://.godot/imported/texture_04.png-ca328b3944d1e6cbfd7d4e09efb582b9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/prototype/texture_04.png"
dest_files=["res://.godot/imported/texture_04.png-ca328b3944d1e6cbfd7d4e09efb582b9.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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://da07ahmuh45cd"
path="res://.godot/imported/texture_05.png-13097e9615e0bac3f4c3e8026ce28bd1.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/prototype/texture_05.png"
dest_files=["res://.godot/imported/texture_05.png-13097e9615e0bac3f4c3e8026ce28bd1.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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dbbswwmt5holv"
path="res://.godot/imported/texture_06.png-fe0b461ca07979aaa1bc9ddf6c7c870e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/prototype/texture_06.png"
dest_files=["res://.godot/imported/texture_06.png-fe0b461ca07979aaa1bc9ddf6c7c870e.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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://hqqkc51jh2fy"
path="res://.godot/imported/texture_07.png-d893d636bab2e79a76733fbe709a2381.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/prototype/texture_07.png"
dest_files=["res://.godot/imported/texture_07.png-d893d636bab2e79a76733fbe709a2381.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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://by53qb0l1o51m"
path.s3tc="res://.godot/imported/texture_08.png-e0f6ea5343244945ba2de33bfe0bf210.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://assets/prototype/texture_08.png"
dest_files=["res://.godot/imported/texture_08.png-e0f6ea5343244945ba2de33bfe0bf210.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
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=0

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cqkm2512sx1oc"
path="res://.godot/imported/texture_09.png-415bbd57a7f06a9ceb03e0d59d63e929.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/prototype/texture_09.png"
dest_files=["res://.godot/imported/texture_09.png-415bbd57a7f06a9ceb03e0d59d63e929.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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://co8oehpme6nba"
path="res://.godot/imported/texture_10.png-ff4960421611582062994f1f35b0c955.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/prototype/texture_10.png"
dest_files=["res://.godot/imported/texture_10.png-ff4960421611582062994f1f35b0c955.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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bnq5ma4mj2pi4"
path="res://.godot/imported/texture_11.png-67bd04afc561f82765fff77241d77b07.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/prototype/texture_11.png"
dest_files=["res://.godot/imported/texture_11.png-67bd04afc561f82765fff77241d77b07.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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cq4vb2bg2msfr"
path="res://.godot/imported/texture_12.png-9e7ce31566681fb48eb15062e9aa4f48.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/prototype/texture_12.png"
dest_files=["res://.godot/imported/texture_12.png-9e7ce31566681fb48eb15062e9aa4f48.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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bq7iun0a45ppg"
path="res://.godot/imported/texture_13.png-cdb9f5a2f4deed192c320f9eda8da0c7.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/prototype/texture_13.png"
dest_files=["res://.godot/imported/texture_13.png-cdb9f5a2f4deed192c320f9eda8da0c7.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

Binary file not shown.

1
icon.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>

After

Width:  |  Height:  |  Size: 994 B

37
icon.svg.import Normal file
View File

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://btjgjjgdnhijb"
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

95
project.godot Normal file
View File

@ -0,0 +1,95 @@
; 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="first-person"
run/main_scene="uid://dk7oodthk2rt2"
config/features=PackedStringArray("4.4", "Forward Plus")
config/icon="res://icon.svg"
[autoload]
GameSettings="*res://scenes/load/game_settings.gd"
Game="*res://scenes/load/game.gd"
[display]
window/size/viewport_width=1280
window/size/viewport_height=720
window/stretch/mode="canvas_items"
window/stretch/aspect="expand"
[global_group]
player=""
[input]
up={
"deadzone": 0.2,
"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,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":-1.0,"script":null)
]
}
down={
"deadzone": 0.2,
"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,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":1.0,"script":null)
]
}
left={
"deadzone": 0.2,
"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,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":-1.0,"script":null)
]
}
right={
"deadzone": 0.2,
"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,"location":0,"echo":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":1.0,"script":null)
]
}
jump={
"deadzone": 0.2,
"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,"location":0,"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)
]
}
look_up={
"deadzone": 0.2,
"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":3,"axis_value":-1.0,"script":null)
]
}
look_down={
"deadzone": 0.2,
"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":3,"axis_value":1.0,"script":null)
]
}
look_left={
"deadzone": 0.2,
"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":2,"axis_value":-1.0,"script":null)
]
}
look_right={
"deadzone": 0.2,
"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":2,"axis_value":1.0,"script":null)
]
}
[layer_names]
3d_physics/layer_1="environment"
3d_physics/layer_2="physics"
3d_physics/layer_3="player"
[physics]
common/physics_interpolation=true

65
scenes/level0.tscn Normal file
View File

@ -0,0 +1,65 @@
[gd_scene load_steps=7 format=3 uid="uid://c5nhw4y7f37ll"]
[ext_resource type="Texture2D" uid="uid://by53qb0l1o51m" path="res://assets/prototype/texture_08.png" id="1_4exd7"]
[ext_resource type="Shader" uid="uid://cygvk4t4itjpv" path="res://assets/planar.gdshader" id="1_ic6my"]
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_ic6my"]
sky_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
ground_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
[sub_resource type="Sky" id="Sky_qsrgx"]
sky_material = SubResource("ProceduralSkyMaterial_ic6my")
[sub_resource type="Environment" id="Environment_2h6oo"]
background_mode = 2
sky = SubResource("Sky_qsrgx")
tonemap_mode = 2
glow_enabled = true
[sub_resource type="ShaderMaterial" id="ShaderMaterial_qsrgx"]
render_priority = 0
shader = ExtResource("1_ic6my")
shader_parameter/texture_albedo = ExtResource("1_4exd7")
shader_parameter/color_albedo = Color(0.303233, 0.303233, 0.303233, 1)
shader_parameter/tiling = true
shader_parameter/tile_scale = 1.0
shader_parameter/blend_sharpness = 4.0
[node name="level0" type="Node3D"]
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_2h6oo")
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
transform = Transform3D(-0.866023, -0.433016, 0.250001, 0, 0.499998, 0.866027, -0.500003, 0.749999, -0.43301, 0, 0, 0)
shadow_enabled = true
[node name="CSGCombiner3D" type="CSGCombiner3D" parent="."]
material_override = SubResource("ShaderMaterial_qsrgx")
use_collision = true
[node name="CSGBox3D" type="CSGBox3D" parent="CSGCombiner3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4.5, 0)
size = Vector3(50, 10, 50)
[node name="CSGBox3D2" type="CSGBox3D" parent="CSGCombiner3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5, 0)
operation = 2
size = Vector3(49, 10, 49)
[node name="CSGBox3D3" type="CSGBox3D" parent="CSGCombiner3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 2.5, 10)
size = Vector3(5, 5, 5)
[node name="CSGBox3D7" type="CSGBox3D" parent="CSGCombiner3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 4.5, 0)
size = Vector3(5, 1, 25)
[node name="CSGBox3D4" type="CSGPolygon3D" parent="CSGCombiner3D"]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 10, 0, 12.5)
polygon = PackedVector2Array(0, 0, 0, 9, 5, 9, 10, 4, 18, 0, 1, 0)
depth = 5.0
[node name="CSGBox3D5" type="CSGBox3D" parent="CSGCombiner3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 2.5, -10)
size = Vector3(5, 5, 5)

View File

@ -0,0 +1,144 @@
extends CanvasLayer
var player_sensor:Node = null
var active:bool = false
var words:Array = []
var PrevCMD:String = ""
var light_reading := Color.BLACK
@onready var panel = $control/panel
@onready var menu = $control/panel/menu
@onready var edit = $control/panel/edit
@onready var states = $control/m
@onready var stats = $control/m/stats
func read_message(message:String):
display_message(message)
words = message.split(" ")
PrevCMD = words[0]
var player = get_tree().get_first_node_in_group("player")
match words[0].to_lower():
"overdraw":
if words.size() > 1 and is_int(1):
player.camera.get_viewport().debug_draw = words[1].to_int()
"max_fps":
if words.size() > 1 and is_float(1):
Engine.max_fps = words[1].to_float()
"vs":
if DisplayServer.window_get_vsync_mode(0) == DisplayServer.VSYNC_DISABLED:
DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_ENABLED)
display_event("VSYNC ON")
else:
DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)
display_event("VSYNC OFF")
"time":
if words.size() > 1:
if is_float(1):
var number = words[1].to_float()
if number >= 0.0 and number < 2.0:
Engine.time_scale = number
else: display_warning("WRONG NUMBER")
else:
display_warning("WRONG NUMBER")
else:
Engine.time_scale = 1
display_event("TIMESCALE RESTARTED")
"fsr":
if get_viewport().scaling_3d_mode == Viewport.SCALING_3D_MODE_FSR2:
display_event("FSR 2.0 OFF")
get_viewport().scaling_3d_mode = Viewport.SCALING_3D_MODE_BILINEAR
else:
display_event("FSR 2.0 ON")
get_viewport().scaling_3d_mode = Viewport.SCALING_3D_MODE_FSR2
"render_scale":
if words.size() > 1:
if is_float(1):
get_viewport().scaling_3d_scale = words[1].to_float()
else:
display_warning("WRONG NUMBER")
else:
get_viewport().scaling_3d_scale = 1
display_event("SCALING RESTARTED")
"fs":
if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
else:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
"q":
get_tree().quit()
panel.hide()
#region Other
func _input(event):
if event is InputEventKey and event.pressed:
match event.physical_keycode:
KEY_QUOTELEFT:
if panel.visible: panel.hide()
else: panel.show()
KEY_F11:
if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
else:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
KEY_F3:
if states.visible: states.hide()
else: states.show()
KEY_F4:
$control/monitor.cycle_debug_menu()
KEY_RIGHT:
if PrevCMD and panel.visible:
edit.set_text(PrevCMD)
edit.set_caret_column(PrevCMD.length())
func _process(_delta):
var player = get_tree().get_first_node_in_group("player")
if states.visible and player:
stats.text ="SPEDOMETER: "+str(snappedf(player.spedometer, 0.01))
func _ready() -> void:
read_message("vs")
read_message("max_fps 144")
func _on_edit_text_submitted(new_text):
read_message(new_text)
edit.clear()
func display_event(message:String):
menu.push_color(Color.AQUAMARINE)
menu.add_text(message+"\n")
func display_message(message:String):
menu.push_color(Color.WHITE)
menu.add_text(message+"\n")
func display_warning(message:String):
menu.push_color(Color.YELLOW)
menu.add_text(message+"\n")
func is_bool(num:int)->bool:
var valid = false
if words.size() > num and words[num].is_valid_int() and \
words[num].to_int() <= 1 and words[num].to_int() >= 0:
valid = true
return valid
display_warning("WRONG NUMBER")
return valid
func is_float(num:int)->bool:
var valid = false
if words.size() > num and words[num].is_valid_float():
valid = true
return valid
return valid
func is_int(num:int)->bool:
var valid = false
if words.size() > num and words[num].is_valid_int():
valid = true
return valid
return valid
func _on_panel_draw():
active = true
edit.grab_focus()
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
func _on_panel_hidden():
active = false
edit.release_focus()
edit.clear()
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
#endregion

View File

@ -0,0 +1 @@
uid://dy8h0w873m1ck

View File

@ -0,0 +1,80 @@
[gd_scene load_steps=6 format=3 uid="uid://dp0qvvwtqxt5r"]
[ext_resource type="Script" uid="uid://dy8h0w873m1ck" path="res://scenes/load/console/console.gd" id="1_1e7mo"]
[ext_resource type="PackedScene" uid="uid://cggqb75a8w8r" path="res://scenes/load/console/debug_menu/debug_menu.tscn" id="2_mnr6t"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_2p7dp"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_60mpv"]
bg_color = Color(0, 0, 0, 0.5)
border_width_top = 1
border_width_bottom = 1
border_color = Color(1, 1, 1, 0.101961)
[sub_resource type="Theme" id="Theme_qg4fp"]
LineEdit/styles/focus = SubResource("StyleBoxEmpty_2p7dp")
LineEdit/styles/normal = SubResource("StyleBoxFlat_60mpv")
LineEdit/styles/read_only = SubResource("StyleBoxFlat_60mpv")
RichTextLabel/styles/focus = SubResource("StyleBoxFlat_60mpv")
RichTextLabel/styles/normal = SubResource("StyleBoxFlat_60mpv")
[node name="console" type="CanvasLayer"]
layer = 2
script = ExtResource("1_1e7mo")
[node name="control" type="Control" parent="."]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 0
size_flags_vertical = 0
mouse_filter = 2
theme = SubResource("Theme_qg4fp")
[node name="monitor" parent="control" instance=ExtResource("2_mnr6t")]
visible = false
layout_mode = 1
[node name="m" type="MarginContainer" parent="control"]
visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
theme_override_constants/margin_left = 25
theme_override_constants/margin_top = 25
theme_override_constants/margin_right = 25
theme_override_constants/margin_bottom = 25
[node name="stats" type="Label" parent="control/m"]
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 0
[node name="panel" type="VBoxContainer" parent="control"]
visible = false
layout_mode = 1
anchors_preset = 10
anchor_right = 1.0
offset_bottom = 127.0
grow_horizontal = 2
mouse_filter = 2
[node name="menu" type="RichTextLabel" parent="control/panel"]
layout_mode = 2
size_flags_vertical = 3
scroll_active = false
scroll_following = true
[node name="edit" type="LineEdit" parent="control/panel"]
layout_mode = 2
[connection signal="draw" from="control/panel" to="." method="_on_panel_draw"]
[connection signal="hidden" from="control/panel" to="." method="_on_panel_hidden"]
[connection signal="text_submitted" from="control/panel/edit" to="." method="_on_edit_text_submitted"]

View File

@ -0,0 +1,469 @@
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
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 <https://tailwindcolor.com/>.
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 <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 cycle_debug_menu() -> void:
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 := 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())
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))

View File

@ -0,0 +1 @@
uid://5w03cxb435ih

View File

@ -0,0 +1,398 @@
[gd_scene load_steps=3 format=3 uid="uid://cggqb75a8w8r"]
[ext_resource type="Script" uid="uid://5w03cxb435ih" path="res://load/console/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="DebugMenu" type="Control" 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/AvgHeader")
frame_history_total_min = NodePath("VBoxContainer/FrameTimeHistory/MinHeader")
frame_history_total_max = NodePath("VBoxContainer/FrameTimeHistory/MaxHeader")
frame_history_total_last = NodePath("VBoxContainer/FrameTimeHistory/LastHeader")
frame_history_cpu_avg = NodePath("VBoxContainer/FrameTimeHistory/TotalAvg")
frame_history_cpu_min = NodePath("VBoxContainer/FrameTimeHistory/TotalMin")
frame_history_cpu_max = NodePath("VBoxContainer/FrameTimeHistory/TotalMax")
frame_history_cpu_last = NodePath("VBoxContainer/FrameTimeHistory/TotalLast")
frame_history_gpu_avg = NodePath("VBoxContainer/FrameTimeHistory/GPUHeader")
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="."]
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="VBoxContainer"]
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="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="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="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="VBoxContainer/FrameTimeHistory"]
custom_minimum_size = Vector2(60, 0)
layout_mode = 2
mouse_filter = 2
[node name="AvgHeader" type="Label" parent="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="VBoxContainer"]
layout_mode = 2
mouse_filter = 2
alignment = 2
[node name="Title" type="Label" parent="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="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="VBoxContainer"]
layout_mode = 2
mouse_filter = 2
alignment = 2
[node name="Title" type="Label" parent="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="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="VBoxContainer"]
layout_mode = 2
mouse_filter = 2
alignment = 2
[node name="Title" type="Label" parent="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="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="VBoxContainer"]
layout_mode = 2
mouse_filter = 2
alignment = 2
[node name="Title" type="Label" parent="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="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="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="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="." to="." method="_on_visibility_changed"]

13
scenes/load/game.gd Normal file
View File

@ -0,0 +1,13 @@
extends Node
func lerp_toward(current, target, speed: float, delta: float):
return current + (target - current) * (1.0 - exp(-speed * delta))
func lerp_toward_angle(current: float, target: float, speed: float, delta: float) -> float:
var difference = wrapf(target - current, -PI, PI)
return current + difference * (1.0 - exp(-speed * delta))
func move_toward_angle(from : float, to: float, delta : float):
var ans = fposmod(to - from, TAU)
if ans > PI: ans -= TAU
return from + ans * delta

1
scenes/load/game.gd.uid Normal file
View File

@ -0,0 +1 @@
uid://bvdc141jjl45c

View File

@ -0,0 +1,19 @@
extends Node
var mouse_sens := 1.75
var toggle_crouch:=false
var stick_sens := 0.15
var stick_smoothing := 0.25
var stick_deadzone := 0.25
var using_gamedpad:=false:
set(is_true):
if using_gamedpad != is_true:
using_gamedpad = is_true
controller_changed.emit()
signal controller_changed
func _input(event: InputEvent) -> void:
if event is InputEventMouseButton or event is InputEventMouseMotion or event is InputEventKey:
using_gamedpad = false
elif event is InputEventJoypadButton or event is InputEventJoypadMotion:
using_gamedpad = true

View File

@ -0,0 +1 @@
uid://hhhyrxuvf73t

13
scenes/load/world.tscn Normal file
View File

@ -0,0 +1,13 @@
[gd_scene load_steps=4 format=3 uid="uid://dk7oodthk2rt2"]
[ext_resource type="PackedScene" uid="uid://blm3k1grnn01j" path="res://scenes/player/player.tscn" id="1_g33ix"]
[ext_resource type="PackedScene" uid="uid://c5nhw4y7f37ll" path="res://scenes/level0.tscn" id="2_whu81"]
[ext_resource type="PackedScene" uid="uid://dp0qvvwtqxt5r" path="res://scenes/load/console/console.tscn" id="3_whu81"]
[node name="world" type="Node"]
[node name="player" parent="." instance=ExtResource("1_g33ix")]
[node name="level0" parent="." instance=ExtResource("2_whu81")]
[node name="console" parent="." instance=ExtResource("3_whu81")]

19
scenes/player/head.gd Normal file
View File

@ -0,0 +1,19 @@
extends Node3D
@export var headbob_frequency = 3.5
@export var headbob_amplitude = 0.01
var _headbob_time:float
func _physics_process(delta: float) -> void:
var headbob = _head_bob(delta) as Vector3
%eyes.position = headbob
func _head_bob(delta)->Vector3:
var headbob_vector:Vector3
var time_multipliers = owner.spedometer * float(owner.is_on_floor())
var speed_normal = owner.spedometer/owner.mult_speed
_headbob_time += delta * time_multipliers
headbob_vector.y = cos(_headbob_time*headbob_frequency)*headbob_amplitude
headbob_vector.x = sin(_headbob_time*headbob_frequency/2)*headbob_amplitude
var result = Vector3.ZERO.lerp(headbob_vector, speed_normal)
return result

View File

@ -0,0 +1 @@
uid://da0nthck8novp

97
scenes/player/player.gd Normal file
View File

@ -0,0 +1,97 @@
extends CharacterBody3D
#region Variables
@export var desired_jump_height : float = 1.0
@export var gravity_multiplier : float = 2.0
@onready var collision: CollisionShape3D = $collision
@onready var neck: Node3D = $head/neck
signal fallen
signal camera_rotated(rotation_vector:Vector2)
var jump_vel: float
var _gamepad_look_vector:Vector2
var _collison_height_origin := 0.0
var input_dir:Vector2
var mult_speed:=3.75
var friction = 8
var spedometer:float
#endregion
#region Private Variables
func _ready():
#------------------------------------------------Set gravity
var default_gravity = ProjectSettings.get_setting("physics/3d/default_gravity")*gravity_multiplier
jump_vel = sqrt(2 * default_gravity * desired_jump_height)
_collison_height_origin = collision.shape.height
#------------------------------------------------Set mouse
Input.set_use_accumulated_input(false)
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _unhandled_input(event):
if event is InputEventMouseMotion and not GameSettings.using_gamedpad \
and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
_rotate_player(_gather_mouse_input(event))
func _rotate_player(motion:Vector2):
if motion == Vector2.ZERO: return
camera_rotated.emit(motion)
%head.rotate_y(motion.x)
collision.rotation.y = %head.rotation.y
neck.rotate_x(motion.y)
const mouseLimit = deg_to_rad(80)
neck.rotation.x = clamp(neck.rotation.x, -mouseLimit, mouseLimit)
func _locomotion(delta):
input_dir = Input.get_vector("left", "right", "up", "down", GameSettings.stick_deadzone)
var direction = (%head.global_basis * Vector3(input_dir.x, 0, input_dir.y))
if direction:
velocity.x = Game.lerp_toward(velocity.x, direction.x*mult_speed,friction,delta)
velocity.z = Game.lerp_toward(velocity.z, direction.z*mult_speed,friction,delta)
else:
velocity.x = Game.lerp_toward(velocity.x, 0.0, friction, delta)
velocity.z = Game.lerp_toward(velocity.z, 0.0, friction, delta)
func _gather_mouse_input(event: InputEventMouseMotion) -> Vector2:
var viewport_size = get_viewport().get_visible_rect().size
var normalized_input = event.relative / viewport_size.length()
normalized_input *= GameSettings.mouse_sens
return -normalized_input
func _gather_stick_input(delta):
var input_vector = Input.get_vector("look_right", "look_left", "look_down", "look_up",
GameSettings.stick_deadzone)
var sens_intepolated = lerpf(0.001, 0.1,GameSettings.stick_sens)
input_vector *= sens_intepolated
var smooting_interpolated = lerpf(20,2,GameSettings.stick_smoothing)
_gamepad_look_vector = Game.lerp_toward(_gamepad_look_vector, input_vector,smooting_interpolated, delta)
_rotate_player(input_vector if GameSettings.stick_smoothing == 0.0 else _gamepad_look_vector)
func _recrouch(height:float):
collision.shape.height = height
collision.position.y = collision.shape.height/2
func _process(delta: float) -> void:
if GameSettings.using_gamedpad: _gather_stick_input(delta)
func _physics_process(delta):
#------------------------------------------------Jumping
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y += jump_vel
#------------------------------------------------Movement
_locomotion(delta)
_move_and_check(delta)
func _move_and_check(delta):
#------------------------------------------------Gravity
if is_on_floor(): friction = 8
else:
var gravity = get_gravity().y*gravity_multiplier
friction = 1
velocity.y += gravity * delta
#------------------------------------------------Speed
var real_speed = get_real_velocity()
spedometer = Vector2(real_speed.x, real_speed.z).length()
#------------------------------------------------Move and Check
var prev_fall = velocity.y
move_and_slide()
if prev_fall < -10 and velocity.y >= 0:
fallen.emit()
#endregion

View File

@ -0,0 +1 @@
uid://dmu4p3ty3a1bk

31
scenes/player/player.tscn Normal file
View File

@ -0,0 +1,31 @@
[gd_scene load_steps=4 format=3 uid="uid://blm3k1grnn01j"]
[ext_resource type="Script" uid="uid://dmu4p3ty3a1bk" path="res://scenes/player/player.gd" id="1_4flbx"]
[ext_resource type="Script" uid="uid://da0nthck8novp" path="res://scenes/player/head.gd" id="2_dovo2"]
[sub_resource type="CylinderShape3D" id="CylinderShape3D_75vfm"]
margin = 0.01
height = 1.8
radius = 0.3
[node name="player" type="CharacterBody3D" groups=["player"]]
collision_layer = 32772
collision_mask = 3
floor_block_on_wall = false
script = ExtResource("1_4flbx")
[node name="collision" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.9, 0)
shape = SubResource("CylinderShape3D_75vfm")
[node name="head" type="Node3D" parent="."]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.44, 0)
script = ExtResource("2_dovo2")
[node name="neck" type="Node3D" parent="head"]
[node name="eyes" type="Camera3D" parent="head/neck"]
unique_name_in_owner = true
cull_mask = 1048063
current = true