init
4
.editorconfig
Normal file
@ -0,0 +1,4 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# Normalize EOL for all files that Git considers text files.
|
||||
* text=auto eol=lf
|
||||
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# Godot 4+ specific ignores
|
||||
.godot/
|
||||
/android/
|
||||
36
assets/planar.gdshader
Normal 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;
|
||||
}
|
||||
|
||||
1
assets/planar.gdshader.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://cygvk4t4itjpv
|
||||
BIN
assets/prototype/texture_01.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
34
assets/prototype/texture_01.png.import
Normal 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
|
||||
BIN
assets/prototype/texture_01.png:Zone.Identifier
Normal file
BIN
assets/prototype/texture_02.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
34
assets/prototype/texture_02.png.import
Normal 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
|
||||
BIN
assets/prototype/texture_02.png:Zone.Identifier
Normal file
BIN
assets/prototype/texture_03.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
34
assets/prototype/texture_03.png.import
Normal 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
|
||||
BIN
assets/prototype/texture_03.png:Zone.Identifier
Normal file
BIN
assets/prototype/texture_04.png
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
34
assets/prototype/texture_04.png.import
Normal 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
|
||||
BIN
assets/prototype/texture_04.png:Zone.Identifier
Normal file
BIN
assets/prototype/texture_05.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
34
assets/prototype/texture_05.png.import
Normal 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
|
||||
BIN
assets/prototype/texture_05.png:Zone.Identifier
Normal file
BIN
assets/prototype/texture_06.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
34
assets/prototype/texture_06.png.import
Normal 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
|
||||
BIN
assets/prototype/texture_06.png:Zone.Identifier
Normal file
BIN
assets/prototype/texture_07.png
Normal file
|
After Width: | Height: | Size: 635 B |
34
assets/prototype/texture_07.png.import
Normal 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
|
||||
BIN
assets/prototype/texture_07.png:Zone.Identifier
Normal file
BIN
assets/prototype/texture_08.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
35
assets/prototype/texture_08.png.import
Normal 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
|
||||
BIN
assets/prototype/texture_08.png:Zone.Identifier
Normal file
BIN
assets/prototype/texture_09.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
34
assets/prototype/texture_09.png.import
Normal 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
|
||||
BIN
assets/prototype/texture_09.png:Zone.Identifier
Normal file
BIN
assets/prototype/texture_10.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
34
assets/prototype/texture_10.png.import
Normal 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
|
||||
BIN
assets/prototype/texture_10.png:Zone.Identifier
Normal file
BIN
assets/prototype/texture_11.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
34
assets/prototype/texture_11.png.import
Normal 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
|
||||
BIN
assets/prototype/texture_11.png:Zone.Identifier
Normal file
BIN
assets/prototype/texture_12.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
34
assets/prototype/texture_12.png.import
Normal 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
|
||||
BIN
assets/prototype/texture_12.png:Zone.Identifier
Normal file
BIN
assets/prototype/texture_13.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
34
assets/prototype/texture_13.png.import
Normal 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
|
||||
BIN
assets/prototype/texture_13.png:Zone.Identifier
Normal file
1
icon.svg
Normal 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
@ -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
@ -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
@ -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)
|
||||
144
scenes/load/console/console.gd
Normal 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
|
||||
1
scenes/load/console/console.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://dy8h0w873m1ck
|
||||
80
scenes/load/console/console.tscn
Normal 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"]
|
||||
469
scenes/load/console/debug_menu/debug_menu.gd
Normal 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))
|
||||
1
scenes/load/console/debug_menu/debug_menu.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://5w03cxb435ih
|
||||
398
scenes/load/console/debug_menu/debug_menu.tscn
Normal 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
@ -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
@ -0,0 +1 @@
|
||||
uid://bvdc141jjl45c
|
||||
19
scenes/load/game_settings.gd
Normal 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
|
||||
1
scenes/load/game_settings.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://hhhyrxuvf73t
|
||||
13
scenes/load/world.tscn
Normal 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
@ -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
|
||||
1
scenes/player/head.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://da0nthck8novp
|
||||
97
scenes/player/player.gd
Normal 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
|
||||
1
scenes/player/player.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://dmu4p3ty3a1bk
|
||||
31
scenes/player/player.tscn
Normal 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
|
||||