Compare commits

..

2 Commits

Author SHA1 Message Date
5b0202183c Improved and added blockouts and added a few shaders
- Added a indev magician model.
- Added a screen shader.
- Also updated the project to 4.7.
- Added new custom dev texture.
2026-06-22 02:05:20 +02:00
94beee112e Some script improvements, clean-up and refactoring
- Refactored VibrationComponent (RumbleComponent)
-- Now supports multiple vibrations and adjustable curves.
-- Inspired by the RumblePak addon.

- Added a new startup scene.
2026-06-22 01:52:04 +02:00
114 changed files with 5451 additions and 406 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://do0hwliflux8t"
path.s3tc="res://.godot/imported/1.png-1f991f3705ac1082ff9d82d3e2ed5b1e.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://_development/ayuroo/1.png"
dest_files=["res://.godot/imported/1.png-1f991f3705ac1082ff9d82d3e2ed5b1e.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bfpejnu6cgdxu"
path.s3tc="res://.godot/imported/2.png-8409fc094e571d6b5be9a0cd5d4b9275.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://_development/ayuroo/2.png"
dest_files=["res://.godot/imported/2.png-8409fc094e571d6b5be9a0cd5d4b9275.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://45ojpbq1fgma"
path.s3tc="res://.godot/imported/3.png-12f24a8a454d2de1fd2c82bec9d6f6d0.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://_development/ayuroo/3.png"
dest_files=["res://.godot/imported/3.png-12f24a8a454d2de1fd2c82bec9d6f6d0.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c05itxl06xaqv"
path.s3tc="res://.godot/imported/4.png-ebcdbaf983a3247c5576e2633ca1606b.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://_development/ayuroo/4.png"
dest_files=["res://.godot/imported/4.png-ebcdbaf983a3247c5576e2633ca1606b.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

View File

@ -0,0 +1,45 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://by0624f6cg0q8"
path="res://.godot/imported/Magician.glb-b3e97b357119296b241a9368f32c6515.scn"
[deps]
source_file="res://_development/ayuroo/Magician.glb"
dest_files=["res://.godot/imported/Magician.glb-b3e97b357119296b241a9368f32c6515.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=2
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=1
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
gltf/texture_map_mode=0

View File

@ -7,7 +7,8 @@
[ext_resource type="AnimationLibrary" uid="uid://dhcvtj55pdbi0" path="res://_development/ayuroo/maestro/_mo_anim.tres" id="4_q2x38"]
[ext_resource type="Script" uid="uid://cx1nws4t8hs2u" path="res://src/core/rhythm/tempo_section_info.gd" id="4_we4r8"]
[ext_resource type="Material" uid="uid://c38215ysnknyk" path="res://assets/dev/dark/dark_01.tres" id="7_6lemm"]
[ext_resource type="Script" uid="uid://bbwtct3hoxwws" path="res://src/core/vibration_component.gd" id="9_yut28"]
[ext_resource type="Script" uid="uid://dwwingj0dsxdg" path="res://src/core/controller_rumble/rumble_config.gd" id="9_51o3i"]
[ext_resource type="Script" uid="uid://bbwtct3hoxwws" path="res://src/core/controller_rumble/rumble_component.gd" id="9_yut28"]
[sub_resource type="Resource" id="Resource_gvx8b"]
script = ExtResource("3_7lyik")
@ -30,6 +31,19 @@ height = 0.3
radius = 0.15
height = 0.3
[sub_resource type="Resource" id="Resource_51o3i"]
script = ExtResource("9_51o3i")
duration = 0.1
weak_intensity = 0.575
strong_intensity = 0.75
[sub_resource type="Resource" id="Resource_ploqb"]
script = ExtResource("9_51o3i")
duration = 0.175
weak_intensity = 0.375
strong_intensity = 0.0
metadata/_custom_type_script = "uid://dwwingj0dsxdg"
[sub_resource type="BoxShape3D" id="BoxShape3D_gsfaw"]
size = Vector3(14, 5, 1)
@ -96,6 +110,7 @@ material = ExtResource("7_6lemm")
[node name="HeavyBeatVibration" type="Node" parent="." unique_id=1136863204]
script = ExtResource("9_yut28")
data = SubResource("Resource_51o3i")
duration = 0.1
sync_to_audio = true
weak_magnitude = 0.575
@ -103,6 +118,7 @@ strong_magnitude = 0.75
[node name="LightBeatVibration" type="Node" parent="." unique_id=2006943016]
script = ExtResource("9_yut28")
data = SubResource("Resource_ploqb")
duration = 0.175
sync_to_audio = true
weak_magnitude = 0.375

View File

@ -0,0 +1,103 @@
[gd_resource type="Resource" script_class="SongInfo" format=3 uid="uid://dbbihkptrkayx"]
[ext_resource type="AudioStream" uid="uid://bnjxnvw1yvkmc" path="res://_development/ayuroo/rhythm_test/【Touhou Full Flavor】Hyper banquet【OriginalHartmann's Youkai Girl】.ogg" id="1_epns7"]
[ext_resource type="Script" uid="uid://c5mqtmsvgt4e8" path="res://src/core/rhythm/song_info.gd" id="2_w75k2"]
[ext_resource type="Script" uid="uid://cx1nws4t8hs2u" path="res://src/core/rhythm/tempo_section_info.gd" id="3_w75k2"]
[sub_resource type="Resource" id="Resource_w75k2"]
script = ExtResource("3_w75k2")
time = 64.0
bpm = 100.0
beats_per_bar = 2
metadata/_custom_type_script = "uid://cx1nws4t8hs2u"
[sub_resource type="Resource" id="Resource_1n4y5"]
script = ExtResource("3_w75k2")
time = 83.25
bpm = 105.0
beats_per_bar = 2
metadata/_custom_type_script = "uid://cx1nws4t8hs2u"
[sub_resource type="Resource" id="Resource_4gg2m"]
script = ExtResource("3_w75k2")
time = 120.75
bpm = 110.0
metadata/_custom_type_script = "uid://cx1nws4t8hs2u"
[sub_resource type="Resource" id="Resource_lc2vk"]
script = ExtResource("3_w75k2")
time = 140.1
bpm = 128.0
beats_per_bar = 2
metadata/_custom_type_script = "uid://cx1nws4t8hs2u"
[sub_resource type="Resource" id="Resource_w8o65"]
script = ExtResource("3_w75k2")
time = 170.1
bpm = 135.0
metadata/_custom_type_script = "uid://cx1nws4t8hs2u"
[sub_resource type="Resource" id="Resource_hykbg"]
script = ExtResource("3_w75k2")
time = 184.2
bpm = 145.0
metadata/_custom_type_script = "uid://cx1nws4t8hs2u"
[sub_resource type="Resource" id="Resource_mowqw"]
script = ExtResource("3_w75k2")
time = 197.55
bpm = 150.0
metadata/_custom_type_script = "uid://cx1nws4t8hs2u"
[sub_resource type="Resource" id="Resource_hgv85"]
script = ExtResource("3_w75k2")
time = 210.3
bpm = 160.0
metadata/_custom_type_script = "uid://cx1nws4t8hs2u"
[sub_resource type="Resource" id="Resource_kkirn"]
script = ExtResource("3_w75k2")
time = 222.45
bpm = 85.0
metadata/_custom_type_script = "uid://cx1nws4t8hs2u"
[sub_resource type="Resource" id="Resource_3vv7d"]
script = ExtResource("3_w75k2")
time = 233.55
bpm = 170.0
metadata/_custom_type_script = "uid://cx1nws4t8hs2u"
[sub_resource type="Resource" id="Resource_afrdg"]
script = ExtResource("3_w75k2")
time = 244.95
bpm = 230.0
metadata/_custom_type_script = "uid://cx1nws4t8hs2u"
[sub_resource type="Resource" id="Resource_es6lf"]
script = ExtResource("3_w75k2")
time = 288.25
bpm = 200.0
metadata/_custom_type_script = "uid://cx1nws4t8hs2u"
[resource]
script = ExtResource("2_w75k2")
audio_stream = ExtResource("1_epns7")
bpm = 200.0
tempo_infos = Array[ExtResource("3_w75k2")]([SubResource("Resource_w75k2"), SubResource("Resource_1n4y5"), SubResource("Resource_4gg2m"), SubResource("Resource_lc2vk"), SubResource("Resource_w8o65"), SubResource("Resource_hykbg"), SubResource("Resource_mowqw"), SubResource("Resource_hgv85"), SubResource("Resource_kkirn"), SubResource("Resource_3vv7d"), SubResource("Resource_afrdg"), SubResource("Resource_es6lf")])
tempo_sections_in_seconds = Dictionary[float, float]({
64.05: 100.0,
83.25: 105.0,
120.75: 110.0,
140.1: 128.0,
170.1: 135.0,
184.2: 145.0,
197.55: 150.0,
210.3: 160.0,
222.45: 85.0,
233.55: 170.0,
244.95: 230.0,
288.0: 200.0
})
tempo_section_round_to_bar = false
tempo_section_round_to_beat = true
metadata/_custom_type_script = "uid://c5mqtmsvgt4e8"

View File

@ -0,0 +1,19 @@
[remap]
importer="oggvorbisstr"
type="AudioStreamOggVorbis"
uid="uid://bnjxnvw1yvkmc"
path="res://.godot/imported/【Touhou Full Flavor】Hyper banquet【OriginalHartmann's Youkai Girl】.ogg-b37c0c7b42b148574992946b8233af7e.oggvorbisstr"
[deps]
source_file="res://_development/ayuroo/rhythm_test/【Touhou Full Flavor】Hyper banquet【OriginalHartmann's Youkai Girl】.ogg"
dest_files=["res://.godot/imported/【Touhou Full Flavor】Hyper banquet【OriginalHartmann's Youkai Girl】.ogg-b37c0c7b42b148574992946b8233af7e.oggvorbisstr"]
[params]
loop=false
loop_offset=0
bpm=0
beat_count=0
bar_beats=4

Binary file not shown.

View File

@ -0,0 +1,45 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://kv7l3mduufdp"
path="res://.godot/imported/rogue.glb-d798aaaf475cf399c199660c9c12c49a.scn"
[deps]
source_file="res://_development/ayuroo/shader_test/rogue.glb"
dest_files=["res://.godot/imported/rogue.glb-d798aaaf475cf399c199660c9c12c49a.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=2
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=1
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
gltf/texture_map_mode=0

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,44 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dcyassqm6y2fr"
path.s3tc="res://.godot/imported/rogue_rogue_texture.png-8ca39e6282cc83c9ae3765b25ccd9c4e.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
generator_parameters={
"md5": "5b6fbb4d6c67e8c66dd2dffbb40f8812"
}
[deps]
source_file="res://_development/ayuroo/shader_test/rogue_rogue_texture.png"
dest_files=["res://.godot/imported/rogue_rogue_texture.png-8ca39e6282cc83c9ae3765b25ccd9c4e.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@ -0,0 +1,9 @@
[gd_resource type="StandardMaterial3D" format=3 uid="uid://c4kd1lw7mblwy"]
[ext_resource type="Texture2D" uid="uid://dcyassqm6y2fr" path="res://_development/ayuroo/shader_test/rogue_rogue_texture.png" id="1_gutgp"]
[resource]
resource_name = "rogue_texture"
cull_mode = 2
albedo_texture = ExtResource("1_gutgp")
roughness = 0.5

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://4p6u7tq4ou3e"
path.bptc="res://.godot/imported/something_awesome.png-1ea2e8f813bc0a98c809c72a0cc45803.bptc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://_development/ayuroo/something_awesome.png"
dest_files=["res://.godot/imported/something_awesome.png-1ea2e8f813bc0a98c809c72a0cc45803.bptc.ctex"]
[params]
compress/mode=2
compress/high_quality=true
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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.

After

Width:  |  Height:  |  Size: 91 KiB

View File

@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bw601ojecdibg"
path.bptc="res://.godot/imported/something_awesome_high.png-903ab067dfb0232139af597d7ae26bf0.bptc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://_development/ayuroo/something_awesome_high.png"
dest_files=["res://.godot/imported/something_awesome_high.png-903ab067dfb0232139af597d7ae26bf0.bptc.ctex"]
[params]
compress/mode=2
compress/high_quality=true
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@ -232,4 +232,3 @@ func _show_confirmation(text: String, on_confirmed: Callable):
confirmation_dialogue.confirmed.connect(on_confirmed, CONNECT_ONE_SHOT)
confirmation_dialogue.popup_centered()
confirmation_dialogue.dialog_text = text

View File

@ -1,16 +1,16 @@
[gd_scene load_steps=4 format=3 uid="uid://cyfxysds8uhnx"]
[gd_scene format=3 uid="uid://cyfxysds8uhnx"]
[ext_resource type="Script" path="res://addons/anim_player_refactor/scenes/refactor_dialogue/refactor_dialogue.gd" id="1_nkqdl"]
[ext_resource type="Script" path="res://addons/anim_player_refactor/scenes/refactor_dialogue/components/anim_player_tree.gd" id="2_7pqfs"]
[ext_resource type="Script" path="res://addons/anim_player_refactor/scenes/refactor_dialogue/components/node_select.gd" id="3_87x4i"]
[ext_resource type="Script" uid="uid://ft8r8earybjw" path="res://addons/anim_player_refactor/scenes/refactor_dialogue/refactor_dialogue.gd" id="1_nkqdl"]
[ext_resource type="Script" uid="uid://bk2ganon2sasp" path="res://addons/anim_player_refactor/scenes/refactor_dialogue/components/anim_player_tree.gd" id="2_7pqfs"]
[ext_resource type="Script" uid="uid://4alsx2krjeo8" path="res://addons/anim_player_refactor/scenes/refactor_dialogue/components/node_select.gd" id="3_87x4i"]
[node name="RefactorDialogue" type="AcceptDialog"]
[node name="RefactorDialogue" type="AcceptDialog" unique_id=480531508]
title = "Refactor Animations"
size = Vector2i(400, 599)
ok_button_text = "Close"
script = ExtResource("1_nkqdl")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=960944020]
offset_left = 8.0
offset_top = 8.0
offset_right = 392.0
@ -19,20 +19,20 @@ size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 8
[node name="TreeContainer" type="VBoxContainer" parent="VBoxContainer"]
[node name="TreeContainer" type="VBoxContainer" parent="VBoxContainer" unique_id=1854530831]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/TreeContainer"]
[node name="Label" type="Label" parent="VBoxContainer/TreeContainer" unique_id=524900720]
layout_mode = 2
text = "Properties:"
[node name="FilterInput" type="LineEdit" parent="VBoxContainer/TreeContainer"]
[node name="FilterInput" type="LineEdit" parent="VBoxContainer/TreeContainer" unique_id=309777513]
layout_mode = 2
placeholder_text = "Filter..."
caret_blink = true
caret_blink_interval = 0.5
[node name="AnimPlayerTree" type="Tree" parent="VBoxContainer/TreeContainer"]
[node name="AnimPlayerTree" type="Tree" parent="VBoxContainer/TreeContainer" unique_id=222752454]
unique_name_in_owner = true
custom_minimum_size = Vector2(300, 400)
layout_mode = 2
@ -41,95 +41,95 @@ hide_root = true
scroll_horizontal_enabled = false
script = ExtResource("2_7pqfs")
[node name="RootNodeContainer" type="VBoxContainer" parent="VBoxContainer"]
[node name="RootNodeContainer" type="VBoxContainer" parent="VBoxContainer" unique_id=646228580]
layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/RootNodeContainer"]
[node name="Label" type="Label" parent="VBoxContainer/RootNodeContainer" unique_id=1112656841]
layout_mode = 2
text = "Root Node"
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/RootNodeContainer"]
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/RootNodeContainer" unique_id=1988478185]
layout_mode = 2
[node name="ChangeRoot" type="Button" parent="VBoxContainer/RootNodeContainer/HBoxContainer"]
[node name="ChangeRoot" type="Button" parent="VBoxContainer/RootNodeContainer/HBoxContainer" unique_id=162815316]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "Change Root"
[node name="EditDialogue" type="ConfirmationDialog" parent="."]
[node name="EditDialogue" type="ConfirmationDialog" parent="." unique_id=2018114141]
unique_name_in_owner = true
title = "Renaming"
position = Vector2i(0, 36)
size = Vector2i(230, 239)
[node name="VBoxContainer" type="VBoxContainer" parent="EditDialogue"]
[node name="VBoxContainer" type="VBoxContainer" parent="EditDialogue" unique_id=1119827862]
offset_left = 8.0
offset_top = 8.0
offset_right = 222.0
offset_bottom = 190.0
[node name="HBoxContainer" type="HBoxContainer" parent="EditDialogue/VBoxContainer"]
[node name="HBoxContainer" type="HBoxContainer" parent="EditDialogue/VBoxContainer" unique_id=935198969]
layout_mode = 2
[node name="EditDialogueButton" type="Button" parent="EditDialogue/VBoxContainer/HBoxContainer"]
[node name="EditDialogueButton" type="Button" parent="EditDialogue/VBoxContainer/HBoxContainer" unique_id=456759932]
unique_name_in_owner = true
layout_mode = 2
focus_mode = 0
[node name="EditInput" type="LineEdit" parent="EditDialogue/VBoxContainer"]
[node name="EditInput" type="LineEdit" parent="EditDialogue/VBoxContainer" unique_id=2101598468]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 0
[node name="HBoxContainer2" type="HBoxContainer" parent="EditDialogue/VBoxContainer"]
[node name="HBoxContainer2" type="HBoxContainer" parent="EditDialogue/VBoxContainer" unique_id=1105990044]
layout_mode = 2
[node name="Label" type="Label" parent="EditDialogue/VBoxContainer/HBoxContainer2"]
[node name="Label" type="Label" parent="EditDialogue/VBoxContainer/HBoxContainer2" unique_id=1241184059]
layout_mode = 2
text = "Used in:"
[node name="EditFullPathToggle" type="CheckButton" parent="EditDialogue/VBoxContainer/HBoxContainer2"]
[node name="EditFullPathToggle" type="CheckButton" parent="EditDialogue/VBoxContainer/HBoxContainer2" unique_id=1158699283]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 10
text = "Edit full path"
[node name="MarginContainer" type="MarginContainer" parent="EditDialogue/VBoxContainer"]
[node name="MarginContainer" type="MarginContainer" parent="EditDialogue/VBoxContainer" unique_id=1578839664]
custom_minimum_size = Vector2(0, 100)
layout_mode = 2
[node name="ColorRect" type="ColorRect" parent="EditDialogue/VBoxContainer/MarginContainer"]
[node name="ColorRect" type="ColorRect" parent="EditDialogue/VBoxContainer/MarginContainer" unique_id=1203243085]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
color = Color(0, 0, 0, 0.211765)
[node name="ScrollContainer" type="ScrollContainer" parent="EditDialogue/VBoxContainer/MarginContainer"]
[node name="ScrollContainer" type="ScrollContainer" parent="EditDialogue/VBoxContainer/MarginContainer" unique_id=1073527380]
layout_mode = 2
size_flags_vertical = 3
horizontal_scroll_mode = 0
[node name="MarginContainer" type="MarginContainer" parent="EditDialogue/VBoxContainer/MarginContainer/ScrollContainer"]
[node name="MarginContainer" type="MarginContainer" parent="EditDialogue/VBoxContainer/MarginContainer/ScrollContainer" unique_id=1889816102]
layout_mode = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="EditAnimationList" type="Label" parent="EditDialogue/VBoxContainer/MarginContainer/ScrollContainer/MarginContainer"]
[node name="EditAnimationList" type="Label" parent="EditDialogue/VBoxContainer/MarginContainer/ScrollContainer/MarginContainer" unique_id=1056061212]
unique_name_in_owner = true
layout_mode = 2
text = "Test
Test 2"
[node name="NodeSelectDialogue" type="ConfirmationDialog" parent="."]
[node name="NodeSelectDialogue" type="ConfirmationDialog" parent="." unique_id=1598902309]
unique_name_in_owner = true
title = "Select a node..."
size = Vector2i(616, 557)
ok_button_text = "Change"
[node name="NodeSelect" type="Tree" parent="NodeSelectDialogue"]
[node name="NodeSelect" type="Tree" parent="NodeSelectDialogue" unique_id=1495313424]
unique_name_in_owner = true
custom_minimum_size = Vector2(600, 500)
offset_left = 8.0
@ -139,7 +139,7 @@ offset_bottom = 508.0
scroll_horizontal_enabled = false
script = ExtResource("3_87x4i")
[node name="ConfirmationDialog" type="ConfirmationDialog" parent="."]
[node name="ConfirmationDialog" type="ConfirmationDialog" parent="." unique_id=585191931]
unique_name_in_owner = true
size = Vector2i(300, 200)
ok_button_text = "Delete"

View File

@ -420,16 +420,16 @@ func _stitch_texture():
# For multi prompts, we need to generate a texture
var _dirty := true
var _texture_3d: Texture
func _get_rid():
func _get_rid() -> RID:
if _dirty:
if not _is_stitching_texture:
# FIXME: Function may await, but because this is an internal engine call, we can't do anything about it.
# This results in a one-frame white texture being displayed, which is not ideal. Investigate later.
_stitch_texture()
if _is_stitching_texture:
return 0
return RID()
else:
return 0
return RID()
return _texture_3d.get_rid() if not _textures.is_empty() else 0
#endregion

View File

@ -0,0 +1,9 @@
[gd_resource type="StandardMaterial3D" format=3 uid="uid://ue5qf3r3ockm"]
[ext_resource type="Texture2D" uid="uid://dw3af4ir446rk" path="res://assets/dev/dark/texture_13.png" id="1_oojfm"]
[resource]
albedo_texture = ExtResource("1_oojfm")
uv1_triplanar = true
uv1_world_triplanar = true
texture_filter = 5

View File

@ -0,0 +1,9 @@
[gd_resource type="StandardMaterial3D" format=3 uid="uid://drt5pgwhl46jp"]
[ext_resource type="Texture2D" uid="uid://cxh5yba7f2ctl" path="res://assets/dev/dark/texture_14.png" id="1_sct2a"]
[resource]
albedo_texture = ExtResource("1_sct2a")
uv1_triplanar = true
uv1_world_triplanar = true
texture_filter = 5

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cxh5yba7f2ctl"
path.s3tc="res://.godot/imported/texture_14.png-da61ff330ad9ecd1e066c870b67b2f00.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://assets/dev/dark/texture_14.png"
dest_files=["res://.godot/imported/texture_14.png-da61ff330ad9ecd1e066c870b67b2f00.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@ -0,0 +1,9 @@
[gd_resource type="StandardMaterial3D" format=3 uid="uid://6ig12dvmlntx"]
[ext_resource type="Texture2D" uid="uid://bwo1s4wl34tyt" path="res://assets/dev/red/texture_02.png" id="1_6vpc0"]
[resource]
albedo_texture = ExtResource("1_6vpc0")
uv1_triplanar = true
uv1_world_triplanar = true
texture_filter = 5

View File

@ -16,6 +16,8 @@ dest_files=["res://.godot/imported/street_rat_8k.gltf-ffb4cacdc2ea7b70689db7cfeb
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
@ -40,3 +42,4 @@ materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
gltf/texture_map_mode=0

View File

@ -16,6 +16,8 @@ dest_files=["res://.godot/imported/tree_small_02_8k.gltf-d03a6f17531c439f939f9b1
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
@ -40,3 +42,4 @@ materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
gltf/texture_map_mode=0

View File

@ -16,6 +16,8 @@ dest_files=["res://.godot/imported/studio_light_framing_02.glb-9f2ff22ec5f0e1faa
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
@ -40,3 +42,4 @@ materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
gltf/texture_map_mode=0

View File

@ -16,6 +16,8 @@ dest_files=["res://.godot/imported/studio_spot_light.glb-8d4c4ec1913c84aa7647ba0
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
@ -40,3 +42,4 @@ materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
gltf/texture_map_mode=0

View File

@ -16,6 +16,8 @@ dest_files=["res://.godot/imported/studio_spot_light_framing_01.glb-6cf086edc9ca
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
@ -40,3 +42,4 @@ materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
gltf/texture_map_mode=0

View File

@ -16,6 +16,8 @@ dest_files=["res://.godot/imported/godot_plush_v2.glb-e624ef71e577808b1466a37f95
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
@ -68,3 +70,4 @@ _subresources={
}
gltf/naming_version=2
gltf/embedded_image_handling=0
gltf/texture_map_mode=0

View File

@ -0,0 +1,106 @@
shader_type spatial;
render_mode unshaded, blend_add;
global uniform float time;
uniform vec4 color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform bool use_second_color = false;
uniform vec4 second_color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform float cone_start_width : hint_range(0.0, 1.0, 0.01) = 0.02;
uniform float cone_curve : hint_range(0, 1.0, 0.01) = 0.3;
uniform float beam_sharpness : hint_range(0.01, 1.0, 0.01) = 0.25;
uniform float beam_fade : hint_range(0.1, 10.0, 0.1) = 4.0;
uniform bool use_gradient = false;
uniform sampler2D gradient: source_color, repeat_disable;
uniform float proximity_fade_distance : hint_range(0.0, 4096.0, 0.01) = 0.75;
uniform sampler2D depth_texture : hint_depth_texture, repeat_disable, filter_nearest;
uniform float z_fade_start : hint_range(0.0, 1.0, 0.01) = 0.5;
uniform float z_fade_end : hint_range(0.0, 1.0, 0.01) = 0.8;
uniform bool use_noise = false;
uniform sampler2D noise_texture : source_color, filter_linear_mipmap, repeat_enable;
uniform float noise_scale : hint_range(0.1, 10.0, 0.1) = 1.0;
uniform float noise_intensity : hint_range(0.0, 1.0, 0.01) = 0.5;
uniform vec2 noise_scroll_speed = vec2(0.01, 0.01);
uniform float noise_distortion_intensity : hint_range(0.0, 0.1, 0.001) = 0.01;
uniform vec2 noise_distortion_scroll_speed = vec2(-0.02, -0.01);
varying float z_axis_fade;
void vertex() {
vec3 local_z = normalize(MODEL_MATRIX[2].xyz);
vec3 to_camera = normalize(CAMERA_POSITION_WORLD - NODE_POSITION_WORLD);
vec3 local_x = normalize(cross(to_camera, local_z));
vec3 local_y = normalize(cross(local_z, local_x));
MODELVIEW_MATRIX = VIEW_MATRIX * mat4(
vec4(local_x * length(MODEL_MATRIX[0].xyz), 0.0),
vec4(local_y * length(MODEL_MATRIX[1].xyz), 0.0),
MODEL_MATRIX[2],
MODEL_MATRIX[3]
);
z_axis_fade = smoothstep(z_fade_end, z_fade_start, abs(dot(to_camera, local_z)));
}
void fragment() {
vec2 uv = UV;
vec3 input_color;
float input_alpha;
if (use_second_color) {
input_color = mix(color.rgb, second_color.rgb, uv.y);
input_alpha = mix(color.a, second_color.a, uv.y);
} else {
input_color = color.rgb;
input_alpha = color.a;
}
// Calculate cone width at current position along the cone length
float cone_progress_y = pow(uv.y, 1.0 - cone_curve);
float width = mix(cone_start_width, 1.0, cone_progress_y);
float half_width = width * 0.5;
// Create horizontal mask
float distance_from_center_x = abs(uv.x - 0.5);
float beam_edge_start = half_width - (half_width * (1.0 - beam_sharpness));
float horizontal_mask = 1.0 - smoothstep(beam_edge_start, half_width, distance_from_center_x);
// Create vertical mask
float vertical_mask = pow(max(1.0 - uv.y, 0.001), beam_fade);
vertical_mask *= smoothstep(0.0, cone_start_width * 0.5, uv.y);
// Overlay gradient
if (use_gradient) {
float gradient_coord = distance_from_center_x / half_width;
float gradient_value = texture(gradient, vec2(gradient_coord, 0.5)).r;
horizontal_mask *= mix(1.0, gradient_value, 1.0 - (vertical_mask * vertical_mask));
}
// Overlay noise
if (use_noise) {
vec2 distortion_offset = noise_distortion_scroll_speed * time + NODE_POSITION_WORLD.xz;
vec2 distortion_sample = texture(noise_texture, uv * noise_scale + distortion_offset).rg;
vec2 distortion_uv = uv + (distortion_sample - 0.5) * 2.0 * noise_distortion_intensity;
vec2 scroll_offset1 = noise_scroll_speed * time + NODE_POSITION_WORLD.xz;
vec2 scroll_offset2 = vec2(-noise_scroll_speed.x * 0.7, noise_scroll_speed.y * 1.3) * time + NODE_POSITION_WORLD.xz;
float noise_sample1 = texture(noise_texture, distortion_uv * noise_scale + scroll_offset1).r;
float noise_sample2 = texture(noise_texture, distortion_uv * noise_scale + scroll_offset2).r;
float combined_noise = mix(1.0, noise_sample1 * noise_sample2, 1.0 - vertical_mask);
horizontal_mask *= mix(1.0, combined_noise, noise_intensity);
}
ALBEDO = input_color;
ALPHA = horizontal_mask * vertical_mask * input_alpha * z_axis_fade;
// Proximity Fade
float proximity_depth_tex = textureLod(depth_texture, SCREEN_UV, 0.0).r;
vec4 proximity_view_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, proximity_depth_tex, 1.0);
proximity_view_pos.xyz /= proximity_view_pos.w;
ALPHA *= clamp(1.0 - smoothstep(proximity_view_pos.z + proximity_fade_distance, proximity_view_pos.z, VERTEX.z), 0.0, 1.0);
}

View File

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

View File

@ -0,0 +1,44 @@
[gd_resource type="ShaderMaterial" format=3 uid="uid://d8pyatjxy2yj"]
[ext_resource type="Shader" uid="uid://c77hfyht2fpxt" path="res://assets/shaders/lightbeam.gdshader" id="1_4nd3r"]
[sub_resource type="Gradient" id="Gradient_h2jn1"]
interpolation_mode = 2
offsets = PackedFloat32Array(0.004115226, 0.11728395, 0.18724279, 0.28189301, 0.38477367, 0.4341564, 0.63786006, 1)
colors = PackedColorArray(1, 1, 1, 1, 0.923899, 0.9239001, 0.9238985, 1, 0.90349716, 0.90349704, 0.90349674, 1, 0.8460438, 0.846044, 0.84604335, 1, 0.696885, 0.6968867, 0.6968853, 1, 0.6556004, 0.6556013, 0.65559965, 1, 0.6364806, 0.63648057, 0.6364794, 1, 0.061926693, 0.061926708, 0.061926648, 1)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_0fp8q"]
gradient = SubResource("Gradient_h2jn1")
[sub_resource type="FastNoiseLite" id="FastNoiseLite_h2jn1"]
noise_type = 0
fractal_weighted_strength = 0.3
domain_warp_enabled = true
domain_warp_frequency = 0.01
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_0fp8q"]
noise = SubResource("FastNoiseLite_h2jn1")
seamless = true
[resource]
render_priority = 0
shader = ExtResource("1_4nd3r")
shader_parameter/color = Color(0.8084624, 0.97797644, 1.0627335, 1)
shader_parameter/use_second_color = true
shader_parameter/second_color = Color(0.637, 0.6734, 0.91, 1)
shader_parameter/cone_start_width = 0.02
shader_parameter/cone_curve = 0.0999999977648
shader_parameter/beam_sharpness = 0.00999999977648
shader_parameter/beam_fade = 3.0000000447036004
shader_parameter/use_gradient = true
shader_parameter/gradient = SubResource("GradientTexture1D_0fp8q")
shader_parameter/proximity_fade_distance = 1.499999966472
shader_parameter/z_fade_start = 0.499999988824
shader_parameter/z_fade_end = 0.8
shader_parameter/use_noise = true
shader_parameter/noise_texture = SubResource("NoiseTexture2D_0fp8q")
shader_parameter/noise_scale = 1.0000000149012
shader_parameter/noise_intensity = 0.5
shader_parameter/noise_scroll_speed = Vector2(0.01, 0.01)
shader_parameter/noise_distortion_intensity = 0.01
shader_parameter/noise_distortion_scroll_speed = Vector2(-0.02, -0.01)

View File

@ -0,0 +1,52 @@
shader_type canvas_item;
global uniform float time;
const int SCRIBBLES = 4;
uniform sampler2D albedo_texture;
uniform bool use_linear_color_space = false;
uniform float scribble_switch_speed = 3.0;
uniform float scribble_intensity = 0.05;
group_uniforms ScribbleTextures;
uniform sampler2D scribbles_1 : hint_normal;
uniform sampler2D scribbles_2 : hint_normal;
uniform sampler2D scribbles_3 : hint_normal;
uniform sampler2D scribbles_4 : hint_normal;
void fragment() {
// Called for every pixel the material is visible on.
float wrapped_time = mod(time * scribble_switch_speed, float(SCRIBBLES));
vec2 uv = UV;
vec3 scribbles;
switch (int(wrapped_time))
{
case 0:
scribbles = texture(scribbles_1, uv).rgb;
break;
case 1:
scribbles = texture(scribbles_2, uv).rgb;
break;
case 2:
scribbles = texture(scribbles_3, uv).rgb;
break;
case 3:
scribbles = texture(scribbles_4, uv).rgb;
break;
}
uv.x += (scribbles.x - 0.5) * scribble_intensity;
uv.y += (scribbles.y - 0.5) * scribble_intensity;
vec4 tex = texture(albedo_texture, uv);
if (use_linear_color_space)
tex.rgb = pow(tex.rgb, vec3(2.0)); // sRGB to linear
// linear to sRGB: tex.rgb = pow(tex.rgb, vec3(1.0 / 2.2));
COLOR = tex;
//COLOR.rgb = scribbles;
}

View File

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

View File

@ -0,0 +1,61 @@
shader_type spatial;
render_mode unshaded;
global uniform float time;
const int SCRIBBLES = 4;
uniform sampler2D albedo_texture;
uniform float scribble_switch_speed = 3.0;
uniform float scribble_intensity = 0.05;
group_uniforms ScribbleTextures;
uniform sampler2D scribbles_1 : hint_normal;
uniform sampler2D scribbles_2 : hint_normal;
uniform sampler2D scribbles_3 : hint_normal;
uniform sampler2D scribbles_4 : hint_normal;
uniform sampler2D scribbles_1_1 : hint_normal;
uniform sampler2D scribbles_2_2 : hint_normal;
uniform sampler2D scribbles_3_3 : hint_normal;
uniform sampler2D scribbles_4_4 : hint_normal;
void vertex() {
// Called for every vertex the material is visible on.
}
void fragment() {
// Called for every pixel the material is visible on.
//float duration = scribble_switch_speed * float(SCRIBBLES);
float wrapped_time = mod(time * scribble_switch_speed, float(SCRIBBLES));
vec2 uv = UV;
vec3 scribbles;
switch (int(wrapped_time))
{
case 0:
scribbles = texture(scribbles_1, UV).rgb;
break;
case 1:
scribbles = texture(scribbles_2, UV).rgb;
break;
case 2:
scribbles = texture(scribbles_3, UV).rgb;
break;
case 3:
scribbles = texture(scribbles_4, UV).rgb;
break;
}
uv.x += (scribbles.x - 0.5) * scribble_intensity;
uv.y += (scribbles.y - 0.5) * scribble_intensity;
vec4 albedo = texture(albedo_texture, uv).rgba;
ALBEDO = albedo.rgb;
//ALBEDO = scribbles.rgb;
ALPHA = albedo.a;
}
//void light() {
// // Called for every pixel for every light affecting the material.
// // Uncomment to replace the default light processing function with this one.
//}

View File

@ -0,0 +1 @@
uid://04ru6gsowkpm

BIN
game/cat_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

40
game/cat_icon.png.import Normal file
View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d1mdvq16ybsto"
path="res://.godot/imported/cat_icon.png-6eadea7917f99524f95be2d9e3bc277c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://cat_icon.png"
dest_files=["res://.godot/imported/cat_icon.png-6eadea7917f99524f95be2d9e3bc277c.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@ -13,7 +13,7 @@ config_version=5
config/name="MagicNStuff"
config/tags=PackedStringArray("game", "horror", "open_world", "story")
run/main_scene="uid://ga0d5817hbc8"
config/features=PackedStringArray("4.6", "Forward Plus")
config/features=PackedStringArray("4.7", "Forward Plus")
config/icon="uid://d1mdvq16ybsto"
[audio]
@ -29,6 +29,7 @@ ControllerIcons="*uid://bdosbfkp568je"
ShaderGlobals="*uid://d2lr860r1ysrm"
LimboConsole="*uid://dyxornv8vwibg"
SettingsHandler="*uid://dj1t6rc6fpiti"
RumbleConductor="*uid://by4n7qykdds0o"
[debug]
@ -192,6 +193,10 @@ limbo_console_search_history={
]
}
[input_devices]
joypads/ignore_joypad_on_unfocused_application=true
[internationalization]
locale/translations=PackedStringArray("res://localization/localization.en.translation", "res://localization/localization.de.translation", "res://localization/localization.es.translation", "res://localization/localization.ja.translation")
@ -239,3 +244,7 @@ time={
"type": "float",
"value": 0.0
}
is_editor_hint={
"type": "bool",
"value": false
}

View File

@ -34,7 +34,6 @@ func _set_handle(id: int, secondary: bool, camera: Camera3D, point: Vector2) ->
var position: Vector3 = _aabb.position
func _redraw() -> void:
clear()
@ -88,7 +87,7 @@ func _box_commit_handle(
func _box_get_handle_name(id: int) -> String:
match id:
0,2,4:
0, 2, 4:
return ""
1:
return "Size X"
@ -102,7 +101,7 @@ func _box_get_handle_name(id: int) -> String:
func _box_set_handle(segment: Vector3, id: int, size: Vector3, position: Vector3) -> void:
var axis: int = id / 2
var sign = id % 2 * -2 + 1
var sign: float = id % 2 * -2 + 1
var _initial_size: Vector3 = initial_value
var neg_end: float = _initial_size[axis] * -0.5
var pos_end: float = _initial_size[axis] * 0.5

View File

@ -45,7 +45,9 @@ func release_mouse() -> void:
func is_keyboard_or_mouse_event(event: InputEvent) -> bool:
return (
event is InputEventMouseButton or event is InputEventMouseMotion or event is InputEventKey
event is InputEventMouseButton
or event is InputEventMouseMotion
or event is InputEventKey
)

View File

@ -69,8 +69,8 @@ func apply_settings() -> void:
if not Engine.is_embedded_in_editor():
DisplayServer.window_set_mode(get_setting("video", "window_mode", DisplayServer.WindowMode.WINDOW_MODE_FULLSCREEN))
# Controls
VibrationComponent.min_weak_magnitude_threshold = get_setting("controls", "vibration_min_weak_threshold", 0.0)
VibrationComponent.min_strong_magnitude_threshold = get_setting("controls", "vibration_min_strong_threshold", 0.0)
RumbleConductor.min_weak_magnitude_threshold = get_setting("controls", "vibration_min_weak_threshold", 0.0)
RumbleConductor.min_strong_magnitude_threshold = get_setting("controls", "vibration_min_strong_threshold", 0.0)
func commit_settings() -> void:

View File

@ -12,9 +12,16 @@ var user_offset_ms: float = 0.0
func _notification(what: int) -> void:
# Just in case.
if what == NOTIFICATION_EDITOR_PRE_SAVE:
# Just in case.
RenderingServer.global_shader_parameter_set(&"time", 0.0)
RenderingServer.global_shader_parameter_set(&"is_editor_hint", false)
elif what == NOTIFICATION_EDITOR_POST_SAVE:
RenderingServer.global_shader_parameter_set(&"is_editor_hint", Engine.is_editor_hint())
func _ready() -> void:
RenderingServer.global_shader_parameter_set(&"is_editor_hint", Engine.is_editor_hint())
func _process(delta: float) -> void:

View File

@ -1,5 +1,5 @@
@tool
class_name VibrationComponent
class_name RumbleComponent
extends Node
## A small helper node to quickly perform controller vibrations.
@ -10,10 +10,13 @@ extends Node
#static var total_weak_vibration: float = 0.0
#static var total_strong_vibration: float = 0.0
#static var _vibration_handled: bool = false
static var min_weak_magnitude_threshold: float = 0.0
static var min_strong_magnitude_threshold: float = 0.0
#static var min_weak_magnitude_threshold: float = 0.0
#static var min_strong_magnitude_threshold: float = 0.0
#static var min_duration_threshold: float = 0.0
@export var data: RumbleConfig
## If [code]false[/code], calling [method vibrate] will not start a controller vibration.
@export var enabled: bool = true:
get = is_enabled,
@ -28,8 +31,7 @@ static var min_strong_magnitude_threshold: float = 0.0
@export var device: int = 0:
get = get_device,
set = set_device
## Delay the vibration by this amount.
@export var delay: float = 0.0
@export var sync_to_audio: bool = false
#region Editor tooling
@ -65,18 +67,26 @@ var animated_strong_magnitude: float = 0.0:
animated_strong_magnitude = clampf(value, 0.0, 1.0)
func _process(delta: float) -> void:
func _init() -> void:
if not is_instance_valid(data):
data = RumbleConfig.new()
func _physics_process(delta: float) -> void:
if (
can_vibrate()
and not is_zero_approx(animated_weak_magnitude + animated_strong_magnitude)
can_vibrate()
and not is_zero_approx(animated_weak_magnitude + animated_strong_magnitude)
):
var _weak_magnitude: float = animated_weak_magnitude
var _strong_magnitude: float = animated_strong_magnitude
var config := RumbleConfig.new()
config.weak_intensity = animated_weak_magnitude
config.strong_intensity = animated_strong_magnitude
config.duration = delta
_weak_magnitude = remap(_weak_magnitude, 0.0, 1.0, min_weak_magnitude_threshold * float(_weak_magnitude > 0.0), 1.0)
_strong_magnitude = remap(_strong_magnitude, 0.0, 1.0, min_strong_magnitude_threshold * float(_strong_magnitude > 0.0), 1.0)
#_weak_magnitude = remap(_weak_magnitude, 0.0, 1.0, min_weak_magnitude_threshold * float(_weak_magnitude > 0.0), 1.0)
#_strong_magnitude = remap(_strong_magnitude, 0.0, 1.0, min_strong_magnitude_threshold * float(_strong_magnitude > 0.0), 1.0)
Input.start_joy_vibration.call_deferred(device, _weak_magnitude, _strong_magnitude, delta)
RumbleConductor.add_rumble(config, device)
#Input.start_joy_vibration.call_deferred(device, _weak_magnitude, _strong_magnitude, delta)
animated_weak_magnitude = 0.0
animated_strong_magnitude = 0.0
@ -87,20 +97,20 @@ func vibrate() -> void:
if not can_vibrate():
return
if delay > 0.0:
await get_tree().create_timer(delay).timeout
if sync_to_audio:
var last_mix_time: float = AudioServer.get_time_since_last_mix()
var output_latency: float = AudioServer.get_output_latency()
#SPrint.print_msg("Audio Delay: %s" % (last_mix_time + output_latency))
await get_tree().create_timer(last_mix_time + output_latency).timeout
data.rumble(device)
return
var _weak_magnitude: float = clampf(weak_magnitude * magnitude_multiplier, 0.0, 1.0)
var _strong_magnitude: float = clampf(strong_magnitude * magnitude_multiplier, 0.0, 1.0)
_weak_magnitude = remap(_weak_magnitude, 0.0, 1.0, min_weak_magnitude_threshold * float(_weak_magnitude > 0.0), 1.0)
_strong_magnitude = remap(_strong_magnitude, 0.0, 1.0, min_strong_magnitude_threshold * float(_strong_magnitude > 0.0), 1.0)
#_weak_magnitude = remap(_weak_magnitude, 0.0, 1.0, min_weak_magnitude_threshold * float(_weak_magnitude > 0.0), 1.0)
#_strong_magnitude = remap(_strong_magnitude, 0.0, 1.0, min_strong_magnitude_threshold * float(_strong_magnitude > 0.0), 1.0)
#duration = maxf(duration, min_duration_threshold)

View File

@ -0,0 +1,64 @@
@tool
extends Node
# Inspired by the RumblePak addon by Elliptical
# (https://store.godotengine.org/asset/elliptical/rumblepak/)
static var min_weak_magnitude_threshold: float = 0.0
static var min_strong_magnitude_threshold: float = 0.0
var vibrations: Array[RumbleData] = []
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
for device: int in Input.get_connected_joypads():
var total_rumble := Vector2.ZERO
for i: int in range(vibrations.size() - 1, -1, -1):
var rumble_data: RumbleData = vibrations.get(i)
if rumble_data.device != device:
continue
var config: RumbleConfig = rumble_data.config
var time_elapsed: float = rumble_data.time_elapsed
if not is_instance_valid(config) or time_elapsed > config.duration:
vibrations.remove_at(i)
continue
var rumble := Vector2(config.weak_intensity, config.strong_intensity)
var curve_offset: Vector2
if is_instance_valid(config.weak_curve):
curve_offset.x = config.weak_curve.max_domain * (time_elapsed / config.duration)
rumble.x = config.weak_curve.sample_baked(curve_offset.x) * config.weak_intensity
if is_instance_valid(config.strong_curve):
curve_offset.y = config.strong_curve.max_domain * (time_elapsed / config.duration)
rumble.y = config.strong_curve.sample_baked(curve_offset.y) * config.strong_intensity
rumble.x = remap(rumble.x, 0.0, 1.0, min_weak_magnitude_threshold * float(rumble.x > 0.0), 1.0)
rumble.y = remap(rumble.y, 0.0, 1.0, min_strong_magnitude_threshold * float(rumble.y > 0.0), 1.0)
rumble *= config.intensity
total_rumble = (total_rumble + rumble).clampf(0.0, 1.0)
rumble_data.time_elapsed += delta
Input.start_joy_vibration(device, total_rumble.x, total_rumble.y)
func add_rumble(rumble_config: RumbleConfig, device: int = 0) -> void:
var rumble_data := RumbleData.new()
rumble_data.config = rumble_config
rumble_data.device = device
vibrations.append(rumble_data)
class RumbleData:
var config: RumbleConfig
var time_elapsed: float = 0.0
var device: int = 0

View File

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

View File

@ -0,0 +1,22 @@
@tool
class_name RumbleConfig
extends Resource
@warning_ignore("unused_private_class_variable")
@export_tool_button("Test Rumble", "Noise")
var _editor_test_vibration: Callable = rumble
@export_range(0.0, 1.0) var intensity: float = 1.0
@export_range(0.0, 1.0, 0.001, "or_greater", "suffix:s") var duration: float = 0.15
@export_group("Weak Magnitude", "weak_")
@export_range(0.0, 1.0) var weak_intensity: float = 1.0
@export var weak_curve: Curve
@export_group("Strong Magnitude", "strong_")
@export_range(0.0, 1.0) var strong_intensity: float = 1.0
@export var strong_curve: Curve
func rumble(device: int = 0) -> void:
RumbleConductor.add_rumble(self, device)

View File

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

View File

@ -6,7 +6,8 @@ var _node_hash: String = ""
func _init(node: Node, world: World) -> void:
assert(is_instance_valid(world), "world must be valid. Are you sure you have defined set the reference?")
assert(is_instance_valid(world),
"'world' must be valid. Are you sure you have defined/set the reference correctly?")
_node = node
_node_hash = str(world.get_path_to(node).hash())
_world = world

View File

@ -26,7 +26,7 @@ func load_threaded(path: String) -> Resource:
while ResourceLoader.load_threaded_get_status(path) != ResourceLoader.THREAD_LOAD_LOADED:
match ResourceLoader.load_threaded_get_status(path, load_progress):
ResourceLoader.THREAD_LOAD_FAILED || ResourceLoader.THREAD_LOAD_INVALID_RESOURCE:
ResourceLoader.THREAD_LOAD_FAILED or ResourceLoader.THREAD_LOAD_INVALID_RESOURCE:
#SPrint.print_msg("[Interactive Loader] load failed.", -1.0, SPrint.WARNING)
return null

View File

@ -2,8 +2,8 @@ class_name RhythmListener
extends Node
signal beat_tick(beat_index: int)
signal bar_tick(bar_index: int)
signal beat_ticked(beat_index: int)
signal bar_ticked(bar_index: int)
@export_range(0.0, 1.0, 0.001, "or_greater", "or_less") var phase_shift: float = 0.0
@export_range(0.0, 1.0, 0.001, "or_greater", "or_less") var phase_multiplier: float = 1.0
@ -29,12 +29,12 @@ func _process(_delta: float) -> void:
var bar_index: int = floori(bar)
if _last_beat_index != beat_index:
on_beat_tick(beat_index)
on_beat_ticked(beat_index)
_last_beat_index = beat_index
_last_beat_time = RhythmPlayer.song_time + phase_shift
if _last_bar_index != bar_index:
on_bar_tick(bar_index)
on_bar_ticked(bar_index)
_last_bar_index = bar_index
_last_bar_time = RhythmPlayer.song_time + phase_shift
@ -57,11 +57,11 @@ func get_time_to_next_bar() -> float:
#
func on_beat_tick(beat_index: int) -> void:
func on_beat_ticked(beat_index: int) -> void:
#SPrint.print_msg("Beat received %s" % beat_index, 0.75)
beat_tick.emit(beat_index)
beat_ticked.emit(beat_index)
func on_bar_tick(bar_index: int) -> void:
func on_bar_ticked(bar_index: int) -> void:
#SPrint.print_msg("Bar received %s" % bar_index, 1.0)
bar_tick.emit(bar_index)
bar_ticked.emit(bar_index)

View File

@ -1,8 +1,8 @@
class_name RhythmPlayer
extends Node
signal beat_tick(beat_index: int)
signal bar_tick(bar_index: int)
signal beat_ticked(beat_index: int)
signal bar_ticked(bar_index: int)
signal finished
static var user_offset_ms: float = 0.0: set = set_user_offset_ms
@ -172,11 +172,11 @@ func _update_playback() -> void:
#SPrint.print_msgf("Bar: %s (%s) bar on beat: %s" % [bar_to_signature(bar_index, _bars), bar_index, bar_index % _bars == 0])
if _last_beat != beat_index:
beat_tick.emit(beat_index)
beat_ticked.emit(beat_index)
_last_beat = beat_index
if _last_bar != bar_index:
bar_tick.emit(bar_index)
bar_ticked.emit(bar_index)
_last_bar = bar_index

View File

@ -136,7 +136,8 @@ func recalculate_times() -> void:
var seconds: float = beat_delta * 60.0 / previous.bpm
current.time = previous.time + seconds
print_rich("- [b]%s[/b] [i]bpm[/i] ([b]1/%s[/b]) at [b]%s[/b] [i]seconds[/i] (beat delta: [b]%s[/b], seconds delta: [b]%s[/b])." % [current.bpm, current.beats_per_bar, current.time, beat_delta, seconds])
print_rich("- [b]%s[/b] [i]bpm[/i] ([b]1/%s[/b]) at [b]%s[/b] [i]seconds[/i] (beat delta: [b]%s[/b], seconds delta: [b]%s[/b])."
% [current.bpm, current.beats_per_bar, current.time, beat_delta, seconds])
func get_beat_at_time(time: float) -> float:

View File

@ -2,7 +2,7 @@ class_name SignalGroup
## @tutorial(Small Modified Version from ShaggyDev): https://shaggydev.com/2025/06/12/godot-awaiting-signals/
signal _all_complete
signal _all_completed
var _counter: int = 0
#var _watched_signals: Array[Signal] = []
@ -36,7 +36,7 @@ func all(signals: Array[Signal], custom_count: int = -1) -> Array[Signal]:
_on_signal_complete(sig)
), CONNECT_ONE_SHOT)
await _all_complete
await _all_completed
return _signals_in_order
@ -52,7 +52,7 @@ func _on_signal_complete(sig: Signal) -> void:
_signals_in_order.append(sig)
if _counter == 0:
_all_complete.emit()
_all_completed.emit()
#class Probe extends RefCounted:

View File

@ -99,8 +99,7 @@ static func full_rotation_float(
static func get_uid(path: String) -> int:
var uid: int = ResourceUID.text_to_id(ResourceUID.path_to_uid(path))
return uid
return ResourceUID.text_to_id(ResourceUID.path_to_uid(path))
## Converts any given uid (as an [int] or [code]uid://[/code] path)

View File

@ -8,5 +8,3 @@ shader = ExtResource("1_1ceck")
shader_parameter/base_color = Color(0.3, 1, 0.3, 0.15)
shader_parameter/edge_color = Color(1, 1, 0.3, 0.8)
shader_parameter/edge_power = 3.0
shader_parameter/box_center = Vector3(0, 0, 0)
shader_parameter/box_extents = Vector3(0, 0, 0)

View File

@ -9,18 +9,28 @@ signal loading_finished
@export var enabled: bool = true: set = set_enabled
@export var threaded_loading: bool = true
@export var prevent_unloading: bool = false
@export var unload_delay: float = 3.0
@export var handles_level_visibility: bool = true
@export_range(0.0, 10.0, 0.001, "or_greater", "suffix:s") var unload_delay: float = 3.0
@export var level_id: StringName = &"":
set(value):
level_id = value
update_configuration_warnings()
@export_file("*.tscn", "*.scn") var scene_path: String:
set(value):
scene_path = value
update_configuration_warnings()
@export_tool_button("Edit Level", "Edit") var editor_edit_level: Callable = _editor_edit_level
@export_tool_button("Load Level", "Load") var editor_load_level: Callable = _editor_load_level
@export_tool_button("Unload Level", "Clear") var editor_unload_level: Callable = _editor_unload_level
@export_tool_button("Edit Level", "Edit")
var editor_edit_level: Callable = _editor_edit_level
# alternative icons: 'Load', 'Override'
@export_tool_button("Load Level", "FileAccess")
var editor_load_level: Callable = _editor_load_level
@export_tool_button("Unload Level", "Clear")
var editor_unload_level: Callable = _editor_unload_level
@export var load_aabbs: Array[AABB] = []:
set(value):
load_aabbs = value
@ -33,11 +43,16 @@ signal loading_finished
#clear_gizmos()
#for aabb: AABB in load_aabbs:
#add_gizmo.call_deferred(AABBGizmo.new(aabb, self))
@export_tool_button("Auto Generate AABB", "CSGBox3D") var editor_auto_gen_aabb: Callable = _editor_auto_gen_aabb
@export var editor_visualize_aabbs_with_box: bool = true: set = _editor_set_visualize_aabbs_with_box
@export_tool_button("Auto Generate AABB", "CSGBox3D")
var editor_auto_gen_aabb: Callable = _editor_auto_gen_aabb
@export var editor_visualize_aabbs_with_box: bool = true:
set = _editor_set_visualize_aabbs_with_box
var loaded_level: Node
var is_loading_level: bool = false
var editor_force_draw_debug: bool = false
var _unload_time_left: float = 0.0
var _precomputed_aabb: AABB # Big bounding box covering all [_precomputed_aabbs] for faster checking.
var _precomputed_aabbs: Array[AABB]
@ -49,8 +64,8 @@ static func get_node_aabb(node: Node3D = null, ignore_top_level: bool = true, bo
var aabb: AABB
var _transform: Transform3D
# We are going down the child chain,
# we want the aabb of each subsequent node to be on the same axis as the parent.
# We are going down the child chain,
# we want the aabb of each subsequent node to be on the same axis as the parent.
if bounds_transform.is_equal_approx(Transform3D()):
_transform = node.global_transform
else:
@ -128,7 +143,10 @@ func _process(delta: float) -> void:
elif not prevent_unloading and is_level_loaded():
_unload_time_left = maxf(_unload_time_left - delta, 0.0)
if _unload_time_left == 0.0:
if handles_level_visibility:
loaded_level.hide()
if is_zero_approx(_unload_time_left):
unload_level()
@ -152,14 +170,20 @@ func get_precomputed_aabbs() -> Array[AABB]:
func load_level() -> void:
_unload_time_left = unload_delay
if is_level_loaded() or is_loading_level:
if is_loading_level:
return
if is_level_loaded():
loaded_level.show()
return
is_loading_level = true
assert(ResourceLoader.exists(scene_path, "PackedScene"), "'scene_path' is invalid or not a PackedScene.")
var scene: PackedScene = await load_scene_threaded() if threaded_loading else load(scene_path)
loaded_level = scene.instantiate()
add_child(loaded_level)
add_child(loaded_level, true)
is_loading_level = false
loading_finished.emit()
@ -175,7 +199,7 @@ func is_level_loaded() -> bool:
func load_scene_threaded() -> PackedScene:
var interactive_loader := InteractiveLoader.create_oneshot(self)
var interactive_loader := InteractiveLoader.create_oneshot_and_bind(self)
var resource: Resource = await interactive_loader.load_threaded(scene_path)
return resource as PackedScene
@ -183,6 +207,7 @@ func load_scene_threaded() -> PackedScene:
func get_camera() -> Camera3D:
var camera: Camera3D = get_viewport().get_camera_3d()
# also prevent godot's override in-game camera from affecting the loading.
if not is_instance_valid(camera) or camera.name == &"OverrideCamera3D":
return _previous_camera
@ -259,7 +284,7 @@ func _editor_unload_level() -> void:
func _editor_process_gizmo() -> void:
var editor_selection: Object = Engine.get_singleton(&"EditorInterface").get_selection()
if editor_selection.get_selected_nodes().has(self):
if editor_selection.get_selected_nodes().has(self) or editor_force_draw_debug:
_draw_debug()
return

View File

@ -1,7 +1,7 @@
class_name WorldProxy
extends Node
signal world_changed
signal world_changed(new_world: World)
static var world_proxies: Array[WorldProxy] = []

View File

@ -22,6 +22,7 @@ signal world_unload_requested(do_save: bool)
@export var debug_load_levels_based_on_player_position: bool = true
var world_state: WorldState
var game: Game
func _exit_tree() -> void:
@ -31,7 +32,7 @@ func _exit_tree() -> void:
func _ready() -> void:
if debug_enabled:
if get_tree().current_scene == self:
_setup_world_debug()
_setup_debug_world_state()
if is_instance_valid(world_state):
await apply_world_state()
@ -83,8 +84,8 @@ func apply_world_state() -> void:
if is_instance_valid(player):
player.process_mode = Node.PROCESS_MODE_DISABLED
if is_instance_valid(player) and player.has_method(&"apply_orientation"):
player.apply_orientation(world_state.player_transform)
if player.has_method(&"apply_orientation"):
player.apply_orientation(world_state.player_transform)
await _load_levels()
@ -210,7 +211,7 @@ func _load_levels() -> void:
await SignalGroup.await_signals(signals)
func _setup_world_debug() -> void:
func _setup_debug_world_state() -> void:
world_state = debug_world_state if is_instance_valid(debug_world_state) else WorldState.new()
if is_instance_valid(debug_player_position):

View File

@ -4,22 +4,24 @@ extends Node
## TODO: sicherungskasten minigames (Kabel verbinden, oder draufhauen und geht wieder)
const SAVE_DIR: String = "user://saves/%s/"
const USER_SETTINGS_PATH: String = "user://settings.ini"
const SAVE_DIR: String = "user://saves/%d/" # TODO "user://ch1/saves/%d/ # Chapter 1
const SAVE_PATH: String = SAVE_DIR + "%s"
const INITIAL_SAVE_DATA: SaveData = preload("uid://b8ojagpq5pxr2")
static var is_debug: bool = true
@export_file("*.tscn", "*.scn") var initial_setup_path: String = "uid://8bxv3c5f8d2j"
@export_file("*.tscn", "*.scn") var startup_scene: String = "uid://0kd77tbv1p3s"
@export_file("*.tscn", "*.scn") var main_menu_path: String = "uid://7v62dybcabgw"
var current_save_slot: int = 0
var current_save_data: SaveData = INITIAL_SAVE_DATA.duplicate()
var save_slot: int = 0
var save_data: SaveData = INITIAL_SAVE_DATA.duplicate()
var world: World
var main_menu: MainMenu
@onready var world_container: Node = %WorldContainer
var _os_dialog_window_result: int = -1
@onready var world_holder: Node = %WorldHolder
@onready var loading_screen: LoadingScreen = %LoadingScreen
@ -28,39 +30,46 @@ static func _static_init() -> void:
static func debug_draw(draw_shape: String, args: Array) -> void:
if is_debug and Engine.has_singleton(&"DebugDraw3D"):
Engine.get_singleton(&"DebugDraw3D").callv("draw_" + draw_shape, args)
const DD3D: StringName = &"DebugDraw3D"
if is_debug and Engine.has_singleton(DD3D):
Engine.get_singleton(DD3D).callv("draw_" + draw_shape, args)
## Turns res://example.tscn into example.tres (and .scn -> .res) and uid://1234567 into 1234567.tres.
static func convert_path_to_resource_filename(path: String) -> String:
path = ResourceUID.path_to_uid(path)
if path.begins_with("res://"):
return path.get_file().replace(".tscn", ".tres").replace(".scn", ".res")
return path.replace("uid://", "") + ".tres"
func _ready() -> void:
if not Engine.is_editor_hint():
if needs_game_setup():
load_initial_setup()
else:
load_main_menu()
load_startup()
register_commands()
func load_game(save_data: SaveData, save_slot: int) -> void:
current_save_data = save_data.duplicate()
current_save_slot = save_slot
func load_game(_save_data: SaveData, _save_slot: int) -> void:
if not await check_computer_hash(save_data.com_hash):
return
save_data = _save_data.duplicate()
save_slot = _save_slot
InputManager.capture_mouse()
load_world(current_save_data.current_world, false)
load_world(save_data.current_world, false)
func save_game() -> Error:
if not is_instance_valid(world):
return ERR_DOES_NOT_EXIST
var save_slot: String = str(current_save_slot)
var file_name: String = "save_data.tres"
if is_instance_valid(world):
current_save_data.current_world = ResourceUID.path_to_uid(world.scene_file_path)
save_data.current_world = ResourceUID.path_to_uid(world.scene_file_path)
DirAccess.make_dir_recursive_absolute(SAVE_DIR % save_slot)
return ResourceSaver.save(current_save_data, SAVE_PATH % [save_slot, file_name])
return ResourceSaver.save(save_data, SAVE_PATH % [save_slot, file_name])
func load_world(world_path: String, save_previous: bool = true, load_from_save: bool = true) -> Error:
@ -87,7 +96,7 @@ func load_world(world_path: String, save_previous: bool = true, load_from_save:
world.change_world_requested.connect(load_world)
world.world_unload_requested.connect(_on_unload_world_request)
world_container.add_child.call_deferred(world)
world_holder.add_child.call_deferred(world)
await world.loaded
loading_screen.fade_out()
return OK
@ -110,8 +119,7 @@ func save_world_state() -> Error:
world.update_world_state()
var world_state: WorldState = world.world_state
var save_slot: String = str(current_save_slot)
var file_name: String = _get_world_save_file_name_from_world_path(world_state.world_path)
var file_name: String = convert_path_to_resource_filename(world_state.world_path)
print("File name: ", file_name)
print(SAVE_PATH % [save_slot, file_name])
DirAccess.make_dir_recursive_absolute(SAVE_DIR % save_slot)
@ -120,8 +128,7 @@ func save_world_state() -> Error:
func load_world_state(world_path: String) -> WorldState:
var save_slot: String = str(current_save_slot)
var file_name: String = _get_world_save_file_name_from_world_path(world_path)
var file_name: String = convert_path_to_resource_filename(world_path)
var file_path: String = SAVE_PATH % [save_slot, file_name]
if not ResourceLoader.exists(file_path):
return null
@ -136,29 +143,18 @@ func load_main_menu() -> void:
_main_menu.load_game_request.connect(load_game)
_main_menu.quit_request.connect(quit_game)
main_menu = _main_menu
world_container.add_child(main_menu)
world_holder.add_child(main_menu)
func load_initial_setup() -> void:
var setup_menu: InitialSetupMenu = load(initial_setup_path).instantiate()
setup_menu.setup_finished.connect(func() -> void:
setup_menu.queue_free()
var config: ConfigFile = Utils.load_config(MainMenu.USER_SETTINGS_PATH)
config.set_value("save", "needs_setup", false)
config.save(MainMenu.USER_SETTINGS_PATH)
func load_startup() -> void:
var startup: StartupScene = load(startup_scene).instantiate()
startup.startup_finished.connect(func() -> void:
startup.queue_free()
await loading_screen.fade_in(0.0)
load_main_menu()
loading_screen.fade_out()
)
add_child(setup_menu)
func needs_game_setup() -> bool:
var config := ConfigFile.new()
if config.load(MainMenu.USER_SETTINGS_PATH) != OK:
return true
return config.get_value("save", "needs_setup", true)
add_child(startup)
func unload_main_menu() -> void:
@ -194,13 +190,3 @@ func _on_unload_world_request(do_save: bool) -> void:
await load_main_menu()
loading_screen.fade_out()
func _get_world_save_file_name_from_world_path(world_path: String) -> String:
world_path = ResourceUID.path_to_uid(world_path)
print("World path: ", world_path)
if world_path.begins_with("res://"):
return world_path.get_file().replace(".tscn", ".tres").replace(".scn", ".res")
return world_path.replace("uid://", "") + ".tres"

View File

@ -7,7 +7,7 @@
script = ExtResource("1_7uq6d")
metadata/_custom_type_script = "uid://cl1u038dbrou2"
[node name="WorldContainer" type="Node" parent="." unique_id=1835125942]
[node name="WorldHolder" type="Node" parent="." unique_id=1835125942]
unique_name_in_owner = true
[node name="CanvasLayer" type="CanvasLayer" parent="." unique_id=919699501]

View File

@ -103,7 +103,7 @@ func _process_input(delta: float) -> void:
if not using_controller and mouse_acceleration:
rotational_velocity = _lerp_rotational_velocity(get_sensitivity() / 10, mouse_friction, delta)
elif using_controller and controller_acceleration:
rotational_velocity = _lerp_rotational_velocity(get_sensitivity(), controller_friction,delta)
rotational_velocity = _lerp_rotational_velocity(get_sensitivity(), controller_friction, delta)
apply_rotation(rotational_velocity)
else:
rotational_velocity = Vector2.ZERO

View File

@ -1,6 +1,9 @@
class_name Hud
extends CanvasLayer
const _CROSSHAIR_ANIM_TO_DOT: StringName = &"to_dot"
const _CROSSHAIR_ANIM_TO_HOLLOW: StringName = &"to_hollow"
@export var interaction_ray: InteractionRay: set = set_interaction_ray
@onready var interaction_prompt: RichTextLabel = $InteractionPrompt
@ -8,7 +11,7 @@ extends CanvasLayer
func _ready() -> void:
crosshair.play(&"to_dot", 1.0, true)
crosshair.play(_CROSSHAIR_ANIM_TO_DOT, 1.0, true)
func set_interaction_ray(ray: InteractionRay) -> void:
@ -27,15 +30,15 @@ func _on_interaction_ray_focused(area: InteractionArea) -> void:
if is_instance_valid(area):
area.hint_prompts_changed.connect(_populate_focused_hints.bind(area))
_populate_focused_hints(area)
_play_crosshair_anim(&"to_hollow")
_play_crosshair_anim(_CROSSHAIR_ANIM_TO_HOLLOW)
else:
interaction_prompt.clear()
_play_crosshair_anim(&"to_dot")
_play_crosshair_anim(_CROSSHAIR_ANIM_TO_DOT)
func _on_interaction_ray_focus_lost(area: InteractionArea) -> void:
interaction_prompt.clear()
_play_crosshair_anim(&"to_dot")
_play_crosshair_anim(_CROSSHAIR_ANIM_TO_DOT)
if is_instance_valid(area):
area.hint_prompts_changed.disconnect(_populate_focused_hints)

View File

@ -10,8 +10,6 @@ const ACTION_MOVE_FORWARD: StringName = &"move_forward"
const ACTION_MOVE_BACKWARD: StringName = &"move_backward"
const ACTION_INTERACT: StringName = &"interact"
static var player: PlayerCharacter
@export var flashlight_manager: FlashlightManager
@export_group("Crouching")
@ -41,10 +39,6 @@ var _flying: bool = false
@onready var flashlight: Flashlight = %Flashlight
func _init() -> void:
player = self
func _exit_tree() -> void:
LimboConsole.unregister_command("player_fly")
LimboConsole.remove_alias("noclip")
@ -112,13 +106,11 @@ func _physics_process(delta: float) -> void:
SPrint.print_msgf(
"Player on floor: %s (was on floor: %s)\nPlayer Horizontal-Velocity: %s\nPlayer Vertical-Velocity: %s"
% [is_on_floor(), was_on_floor, (velocity * Utils.VEC3_HOR).length(), velocity.y],
true,
)
% [is_on_floor(), was_on_floor, (velocity * Utils.VEC3_HOR).length(), velocity.y], true)
func align(with_node: Node3D, reset_velocity: bool = true) -> void:
assert(is_instance_valid(with_node), "with_node is invalid.")
assert(is_instance_valid(with_node), "'with_node' is invalid.")
apply_orientation(with_node.global_transform)
if reset_velocity:

View File

@ -170,12 +170,13 @@ unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.9, 0)
shape = SubResource("CylinderShape3D_bdj5f")
[node name="Head" type="Node3D" parent="." unique_id=647306642 node_paths=PackedStringArray("camera", "character")]
[node name="Head" type="Node3D" parent="." unique_id=142233175 node_paths=PackedStringArray("camera", "character")]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.6, 0)
script = ExtResource("2_fjt7c")
camera = NodePath("EffectsRoot/ShakingCamera")
character = NodePath("..")
metadata/_custom_type_script = "uid://2y3gnaqtrfnx"
[node name="Flashlight" type="Node3D" parent="Head" unique_id=884032976 node_paths=PackedStringArray("light")]
unique_name_in_owner = true
@ -257,10 +258,11 @@ shape = SubResource("CylinderShape3D_ntkcp")
[node name="FootstepComponent" type="Node" parent="." unique_id=2134975877]
script = ExtResource("4_vq0uu")
[node name="Hud" type="CanvasLayer" parent="." unique_id=1113094340 node_paths=PackedStringArray("interaction_ray")]
[node name="Hud" type="CanvasLayer" parent="." unique_id=1906436973 node_paths=PackedStringArray("interaction_ray")]
layer = 0
script = ExtResource("11_y2ktv")
interaction_ray = NodePath("../Head/InteractionRay")
metadata/_custom_type_script = "uid://gvuvxikepb2r"
[node name="InteractionPrompt" type="RichTextLabel" parent="Hud" unique_id=745008513]
anchors_preset = -1

View File

@ -0,0 +1,71 @@
shader_type spatial;
render_mode unshaded;
global uniform float time;
uniform vec4 background_color : source_color = vec4(1.0, 0.68, 0.23, 1.0);
uniform vec4 circle_color : source_color = vec4(1.0, 0.4, 0.28, 1.0);
uniform sampler2D overlay_texture : hint_default_transparent;
uniform float scale = 10.0;
uniform float rotation = 0.5;
uniform float spacing = 0.5;
uniform float time_scale = 0.25;
uniform float cutoff_wave_height = 0.95;
uniform float cutoff_wave_scale = 0.25;
uniform float cutoff_wave_length = 1.0;
uniform float cutoff_wave_time_scale = 0.5;
uniform float cutoff_rim = 0.05;
uniform vec4 cutoff_rim_color : source_color = vec4(1.0);
//uniform float brightness = 0.5;
varying vec3 world_pos;
void vertex() {
world_pos = VERTEX;
}
float ellipse_shape(vec2 uv, float width, float height){
float _distance = length((uv * 2.0 - 1.0) / vec2(width, height));
return clamp((1.0 - _distance) / fwidth(_distance), 0.0, 1.0);
}
mat2 rot(float a) {
float s = sin(a);
float c = cos(a);
return mat2(vec2(c, -s), vec2(s, c));
}
void fragment() {
vec2 uv = world_pos.xy * vec2(1.0, -1.0);
vec4 tex = texture(overlay_texture, UV).rgba;
if (uv.y + cutoff_wave_height < sin((uv.x * cutoff_wave_length) + time * cutoff_wave_time_scale) * cutoff_wave_scale) {
if (uv.y + cutoff_wave_height + cutoff_rim < sin((uv.x * cutoff_wave_length) + time * cutoff_wave_time_scale) * cutoff_wave_scale) {
ALBEDO = mix(background_color.rgb, tex.rgb, tex.a);
} else {
ALBEDO = mix(cutoff_rim_color.rgb, tex.rgb, cutoff_rim_color.a * tex.a);
}
} else {
uv = rot(rotation) * uv;
uv.x += time * time_scale;
//uv += vec2(
//sin(world_pos.z + time) * 0.15,
//cos(world_pos.x + time) * 0.1
//);
// tile
uv *= scale;
uv = fract(uv);
float c = ellipse_shape(uv, spacing, spacing);
ALBEDO = mix(mix(background_color.rgb, circle_color.rgb, c), tex.rgb, tex.a);
}
}
void light() {
//DIFFUSE_LIGHT = clamp(ALBEDO + LIGHT_COLOR, vec3(0.0), vec3(1.0));
}

View File

@ -0,0 +1 @@
uid://356ennreusvw

View File

@ -0,0 +1,125 @@
[gd_resource type="VisualShader" format=3 uid="uid://booqiuk2iqxb3"]
[ext_resource type="Script" uid="uid://1qs57krus8p6" path="res://addons/ShaderLib/Procedural/Shapes/Ellipse.gd" id="1_ai6cr"]
[ext_resource type="Script" uid="uid://b83lviuldeleg" path="res://addons/ShaderLib/UV/RotateUV.gd" id="2_rtdtt"]
[sub_resource type="VisualShaderNodeInput" id="VisualShaderNodeInput_rtdtt"]
input_name = "time"
[sub_resource type="VisualShaderNodeVectorDecompose" id="VisualShaderNodeVectorDecompose_8g4dx"]
default_input_values = [0, Vector2(0, 0)]
op_type = 0
[sub_resource type="VisualShaderNodeFloatOp" id="VisualShaderNodeFloatOp_1jwe0"]
[sub_resource type="VisualShaderNodeCustom" id="VisualShaderNodeCustom_gtut6"]
output_port_for_preview = 0
default_input_values = [1, Vector2(0.5, 0.5), 2, 0.0, 3, false]
initialized = true
script = ExtResource("2_rtdtt")
[sub_resource type="VisualShaderNodeFloatOp" id="VisualShaderNodeFloatOp_trvij"]
operator = 2
[sub_resource type="VisualShaderNodeCustom" id="VisualShaderNodeCustom_xwicf"]
output_port_for_preview = 0
default_input_values = [1, 0.5, 2, 0.5]
initialized = true
script = ExtResource("1_ai6cr")
[sub_resource type="VisualShaderNodeFloatParameter" id="VisualShaderNodeFloatParameter_i6t7a"]
parameter_name = "TimeScale"
default_value_enabled = true
default_value = 0.25
[sub_resource type="VisualShaderNodeVectorCompose" id="VisualShaderNodeVectorCompose_jfb5c"]
op_type = 0
[sub_resource type="VisualShaderNodeVectorFunc" id="VisualShaderNodeVectorFunc_jwwq8"]
output_port_for_preview = 0
function = 18
[sub_resource type="VisualShaderNodeUVFunc" id="VisualShaderNodeUVFunc_8aycm"]
output_port_for_preview = 0
default_input_values = [1, Vector2(5, 5), 2, Vector2(0.5, 0.5)]
function = 1
[sub_resource type="VisualShaderNodeFloatParameter" id="VisualShaderNodeFloatParameter_homgf"]
parameter_name = "CircleScaling"
default_value_enabled = true
default_value = 10.0
[sub_resource type="VisualShaderNodeFloatParameter" id="VisualShaderNodeFloatParameter_w2jlr"]
parameter_name = "CircleSpacing"
default_value_enabled = true
default_value = 0.5
[sub_resource type="VisualShaderNodeVaryingGetter" id="VisualShaderNodeVaryingGetter_ai6cr"]
varying_name = "vertex_vertex"
varying_type = 4
[sub_resource type="VisualShaderNodeColorParameter" id="VisualShaderNodeColorParameter_rmq8c"]
parameter_name = "BackgroundColor"
default_value_enabled = true
default_value = Color(1, 0.6862745, 0.23137255, 1)
[sub_resource type="VisualShaderNodeMix" id="VisualShaderNodeMix_u37xu"]
output_port_for_preview = 0
default_input_values = [0, Vector3(0, 0, 0), 1, Vector3(1, 1, 1), 2, Vector3(0.5, 0.5, 0.5)]
op_type = 3
[sub_resource type="VisualShaderNodeColorParameter" id="VisualShaderNodeColorParameter_n3jp6"]
parameter_name = "CircleColor"
default_value_enabled = true
default_value = Color(1, 0.4, 0.2784314, 1)
[sub_resource type="VisualShaderNodeVaryingSetter" id="VisualShaderNodeVaryingSetter_dbsar"]
varying_name = "vertex_vertex"
varying_type = 4
[sub_resource type="VisualShaderNodeInput" id="VisualShaderNodeInput_c0w0f"]
input_name = "vertex"
[resource]
flags/unshaded = true
varyings/vertex_vertex = "0,4"
nodes/vertex/0/position = Vector2(220, 180)
nodes/vertex/6/node = SubResource("VisualShaderNodeVaryingSetter_dbsar")
nodes/vertex/6/position = Vector2(-40, 260)
nodes/vertex/7/node = SubResource("VisualShaderNodeInput_c0w0f")
nodes/vertex/7/position = Vector2(-440, 280)
nodes/vertex/connections = PackedInt32Array(7, 0, 6, 0)
nodes/fragment/0/position = Vector2(660, 140)
nodes/fragment/2/node = SubResource("VisualShaderNodeCustom_xwicf")
nodes/fragment/2/position = Vector2(120, 300)
nodes/fragment/4/node = SubResource("VisualShaderNodeColorParameter_rmq8c")
nodes/fragment/4/position = Vector2(20, -200)
nodes/fragment/5/node = SubResource("VisualShaderNodeMix_u37xu")
nodes/fragment/5/position = Vector2(360, 100)
nodes/fragment/6/node = SubResource("VisualShaderNodeColorParameter_n3jp6")
nodes/fragment/6/position = Vector2(20, 20)
nodes/fragment/15/node = SubResource("VisualShaderNodeInput_rtdtt")
nodes/fragment/15/position = Vector2(-1940, -40)
nodes/fragment/16/node = SubResource("VisualShaderNodeVectorDecompose_8g4dx")
nodes/fragment/16/position = Vector2(-1640, 140)
nodes/fragment/17/node = SubResource("VisualShaderNodeFloatOp_1jwe0")
nodes/fragment/17/position = Vector2(-1400, 20)
nodes/fragment/18/node = SubResource("VisualShaderNodeCustom_gtut6")
nodes/fragment/18/position = Vector2(-1860, 160)
nodes/fragment/19/node = SubResource("VisualShaderNodeFloatOp_trvij")
nodes/fragment/19/position = Vector2(-1600, -100)
nodes/fragment/20/node = SubResource("VisualShaderNodeFloatParameter_i6t7a")
nodes/fragment/20/position = Vector2(-1960, -280)
nodes/fragment/21/node = SubResource("VisualShaderNodeVectorCompose_jfb5c")
nodes/fragment/21/position = Vector2(-1180, 120)
nodes/fragment/22/node = SubResource("VisualShaderNodeVectorFunc_jwwq8")
nodes/fragment/22/position = Vector2(-540, 180)
nodes/fragment/23/node = SubResource("VisualShaderNodeUVFunc_8aycm")
nodes/fragment/23/position = Vector2(-820, 200)
nodes/fragment/24/node = SubResource("VisualShaderNodeFloatParameter_homgf")
nodes/fragment/24/position = Vector2(-1260, 380)
nodes/fragment/25/node = SubResource("VisualShaderNodeFloatParameter_w2jlr")
nodes/fragment/25/position = Vector2(-240, 440)
nodes/fragment/29/node = SubResource("VisualShaderNodeVaryingGetter_ai6cr")
nodes/fragment/29/position = Vector2(-2100, 160)
nodes/fragment/connections = PackedInt32Array(6, 0, 5, 1, 4, 0, 5, 0, 16, 1, 21, 1, 17, 0, 21, 0, 16, 0, 17, 1, 19, 0, 17, 0, 15, 0, 19, 1, 20, 0, 19, 0, 25, 0, 2, 1, 25, 0, 2, 2, 2, 0, 5, 2, 24, 0, 23, 1, 23, 0, 22, 0, 21, 0, 23, 0, 5, 0, 0, 0, 22, 0, 2, 0, 29, 0, 18, 0, 18, 0, 16, 0)

View File

@ -0,0 +1,7 @@
[gd_scene format=3 uid="uid://de3eyl4pxtjm4"]
[node name="ScreenViewport" type="SubViewport" unique_id=182359296]
disable_3d = true
transparent_bg = true
use_hdr_2d = true
gui_disable_input = true

View File

@ -61,7 +61,7 @@ light_surface_material = SubResource("ShaderMaterial_nqu5b")
[node name="StudioSpotLight" parent="." unique_id=449918207 instance=ExtResource("1_3cilv")]
[node name="Cylinder" parent="StudioSpotLight" index="0" unique_id=142845931]
[node name="Cylinder" parent="StudioSpotLight" index="0" unique_id=35052532]
surface_material_override/1 = SubResource("ShaderMaterial_nqu5b")
[node name="StudioSpotLightFraming01" parent="." unique_id=2007355874 instance=ExtResource("3_otype")]

View File

@ -30,9 +30,8 @@ func _unhandled_input(event: InputEvent) -> void:
func try_turn_on() -> void:
if is_instance_valid(manager):
if manager.is_drained():
return
if is_instance_valid(manager) and manager.is_drained():
return
turn_on()

View File

@ -42,7 +42,7 @@ func _exit_tree() -> void:
func _ready() -> void:
world = await _world_proxy.wait_for_world()
_instance_persister= InstancePersister.new(self, world)
_instance_persister = InstancePersister.new(self, world)
power = _instance_persister.get_property(&"power", initial_power)
is_flashlight_active = _instance_persister.get_property(&"is_flashlight_active", is_flashlight_active)

View File

@ -10,14 +10,14 @@ enum DrainModes {
@export var allowed_bodies: Array[Node3D]
@export var trigger_once: bool = true
var world: World
var _world_proxy: WorldProxy
@export var drain_mode := DrainModes.SET
@export var drain_value: float = 0.3
@export var change_manager_drain_mode: bool = false
@export var manager_drain_mode := FlashlightManager.DrainModes.MANUAL
var world: World
var _world_proxy: WorldProxy
func _enter_tree() -> void:
_world_proxy = WorldProxy.new()

View File

@ -1,6 +1,7 @@
class_name FusePickup
extends Node3D
signal picked_up
@export var power_box: PowerBox
@ -23,4 +24,5 @@ func _ready() -> void:
func _on_picked_up() -> void:
power_box.on_fuse_picked_up()
InstancePersister.new(self, world).set_property(&"is_collected", true)
picked_up.emit()
queue_free()

View File

@ -80,10 +80,10 @@ func _on_interaction_interacted() -> void:
#start_minigame()
pass
if not is_active:
turn_on()
else:
if is_active:
turn_off()
else:
turn_on()
# TODO

View File

@ -4,9 +4,8 @@ extends Control
signal load_game_request(save_data: SaveData, slot_index: int)
signal quit_request
const USER_SETTINGS_PATH: String = "user://settings.ini"
const SAVES_DIR: String = "user://saves/"
const SAVE_DATA_PATH: String = SAVES_DIR + "%s/save_data.tres"
const SAVE_DATA_PATH: String = SAVES_DIR + "%d/save_data.tres"
@onready var continue_button: Button = %ContinueButton
@onready var load_button: Button = %LoadButton
@ -27,7 +26,7 @@ static func get_save_slots() -> PackedInt32Array:
var index: int = 0
while index < dirs.size():
var dir_name: String = dirs[index]
var dir_name: String = dirs.get(index)
if dir_name.is_valid_int() and not (dir_name.begins_with("+") or dir_name.begins_with("-")):
index += 1
else:
@ -73,7 +72,7 @@ func _ready() -> void:
func has_last_save_slot() -> bool:
var config: ConfigFile = Utils.load_config(USER_SETTINGS_PATH)
var config: ConfigFile = Utils.load_config(Game.USER_SETTINGS_PATH)
return config.has_section_key("save", "last_slot")
@ -88,7 +87,7 @@ func populate_save_entries() -> void:
func _on_continue_pressed() -> void:
var config: ConfigFile = Utils.load_config(USER_SETTINGS_PATH)
var config: ConfigFile = Utils.load_config(Game.USER_SETTINGS_PATH)
var slot: int = config.get_value("save", "last_slot", 0)
var path: String = get_save_path(slot)
@ -100,7 +99,7 @@ func _on_continue_pressed() -> void:
return
config.set_value("save", "last_slot", slot)
config.save(USER_SETTINGS_PATH)
config.save(Game.USER_SETTINGS_PATH)
var save_data: SaveData = load(path)
load_game_request.emit(save_data, slot)
@ -116,9 +115,9 @@ func _on_new_game_pressed() -> void:
var slot_index: int = get_unique_save_slot_index()
load_game_request.emit(save_data, slot_index)
var config: ConfigFile = Utils.load_config(USER_SETTINGS_PATH)
var config: ConfigFile = Utils.load_config(Game.USER_SETTINGS_PATH)
config.set_value("save", "last_slot", slot_index)
config.save(USER_SETTINGS_PATH)
config.save(Game.USER_SETTINGS_PATH)
func _on_options_pressed() -> void:
@ -130,9 +129,9 @@ func _on_quit_pressed() -> void:
func _on_save_entry_pressed(save_slot: int) -> void:
var config: ConfigFile = Utils.load_config(USER_SETTINGS_PATH)
var config: ConfigFile = Utils.load_config(Game.USER_SETTINGS_PATH)
config.set_value("save", "last_slot", save_slot)
config.save(USER_SETTINGS_PATH)
config.save(Game.USER_SETTINGS_PATH)
var save_path: String = get_save_path(save_slot)

View File

@ -60,7 +60,11 @@ func _ready() -> void:
controller_setup_menu.confirmed.connect(_on_vibration_config_confirmed)
controller_vibrations.toggled.connect(_on_controller_vibrations_toggled)
visibility_changed.connect(func() -> void: if is_visible_in_tree(): update_controls_from_settings())
visibility_changed.connect(
func() -> void:
if is_visible_in_tree():
update_controls_from_settings()
)
set_process(false)
@ -82,8 +86,10 @@ func close() -> void:
func update_controls_from_settings() -> void:
# Gameplay
headbobbing.set_pressed_no_signal(SettingsHandler.get_setting("gameplay", "headbobbing", true))
headbobbing_slider.set_value_no_signal(SettingsHandler.get_setting("gameplay", "headbobbing_multiplier", 1.0))
var enabled: bool = SettingsHandler.get_setting("gameplay", "headbobbing", true)
var multiplier: float = SettingsHandler.get_setting("gameplay", "headbobbing_multiplier", 1.0)
headbobbing.set_pressed_no_signal(enabled)
headbobbing_slider.set_value_no_signal(multiplier)
# Localization
match SettingsHandler.get_setting("localization", "language", "en_US"):

View File

@ -41,7 +41,8 @@ func set_slider(new_slider: Slider) -> void:
func _on_value_changed(new_value: float) -> void:
var value: float = new_value
if do_remap:
value = remap(value, remap_initial_min, remap_initial_max, remap_output_min, remap_output_max)
value = remap(value, remap_initial_min, remap_initial_max,
remap_output_min, remap_output_max)
var new_text: String = str(value).pad_zeros(pad_zeros).pad_decimals(pad_decimals)
set_text(str(prefix, positive_prefix if value >= 0.0 else negative_prefix, new_text, suffix))

View File

@ -10,7 +10,7 @@ var is_testing_weak: bool = false
var is_testing_strong: bool = false
var _duration_idx: int = 0
@onready var vibration_component: VibrationComponent = %VibrationComponent
@onready var rumble_component: RumbleComponent = %RumbleComponent
@onready var repeat_vibration_timer: Timer = %RepeatVibrationTimer
@onready var min_duration_slider: HSlider = %MinDurationSlider
@ -22,9 +22,6 @@ var _duration_idx: int = 0
func _ready() -> void:
_on_visibility_changed()
visibility_changed.connect(_on_visibility_changed)
repeat_vibration_timer.timeout.connect(_test_vibration)
min_weak_magnitude.focus_entered.connect(_on_weak_slider_focused)
@ -32,25 +29,25 @@ func _ready() -> void:
min_strong_magnitude.focus_entered.connect(_on_strong_slider_focused)
min_strong_magnitude.focus_exited.connect(_on_strong_slider_unfocused)
min_weak_magnitude.grab_focus()
_on_weak_slider_focused()
min_weak_magnitude.value_changed.connect(_on_min_weak_magnitude_value_changed)
min_strong_magnitude.value_changed.connect(_on_min_strong_magnitude_value_changed)
confirm_button.pressed.connect(confirm)
visibility_changed.connect(_on_visibility_changed)
_on_visibility_changed()
func confirm() -> void:
SettingsHandler.set_setting(
"controls",
"vibration_min_weak_threshold",
VibrationComponent.min_weak_magnitude_threshold,
RumbleConductor.min_weak_magnitude_threshold,
false
)
SettingsHandler.set_setting(
"controls",
"vibration_min_strong_threshold",
VibrationComponent.min_strong_magnitude_threshold,
RumbleConductor.min_strong_magnitude_threshold,
true
)
@ -58,27 +55,30 @@ func confirm() -> void:
func _test_vibration() -> void:
vibration_component.weak_magnitude = MIN_WEAK_MAGNITUDE * float(is_testing_weak)
vibration_component.strong_magnitude = MIN_STRONG_MAGNITUDE * float(is_testing_strong)
# If is_testing_weak and is_testing_strong are both false, vibrate both together.
var weak_enabled: bool = is_testing_weak or (not is_testing_weak and not is_testing_strong)
var strong_enabled: bool = is_testing_strong or (not is_testing_weak and not is_testing_strong)
rumble_component.data.weak_intensity = MIN_WEAK_MAGNITUDE * float(weak_enabled)
rumble_component.data.strong_intensity = MIN_STRONG_MAGNITUDE * float(strong_enabled)
match _duration_idx:
5:
vibration_component.duration = 0.75
rumble_component.data.duration = 0.75
_:
vibration_component.duration = 0.15
rumble_component.data.duration = 0.15
#1:
#vibration_component.duration = 0.35
#rumble_component.duration = 0.35
#2:
#vibration_component.duration = 0.75
#rumble_component.duration = 0.75
_duration_idx = posmod(_duration_idx + 1, 6)
vibration_component.vibrate()
rumble_component.vibrate()
_vibrate_texture()
func _vibrate_texture() -> void:
var tween: Tween = create_tween().set_loops(maxi(int(vibration_component.duration / 0.1), 1))
var tween: Tween = create_tween().set_loops(maxi(int(rumble_component.data.duration / 0.1), 1))
tween.tween_property(vibrate_texture, ^"rotation_degrees", -5.0, 0.05)
tween.tween_property(vibrate_texture, ^"rotation_degrees", 5.0, 0.05)
await tween.finished
@ -91,17 +91,20 @@ func _on_visibility_changed() -> void:
repeat_vibration_timer.start()
process_mode = Node.PROCESS_MODE_INHERIT
min_weak_magnitude.grab_focus()
min_weak_magnitude.set_value_no_signal(RumbleConductor.min_weak_magnitude_threshold)
min_strong_magnitude.set_value_no_signal(RumbleConductor.min_strong_magnitude_threshold)
else:
repeat_vibration_timer.stop()
process_mode = Node.PROCESS_MODE_DISABLED
func _on_min_weak_magnitude_value_changed(value: float) -> void:
VibrationComponent.min_weak_magnitude_threshold = value
RumbleConductor.min_weak_magnitude_threshold = value
func _on_min_strong_magnitude_value_changed(value: float) -> void:
VibrationComponent.min_strong_magnitude_threshold = value
RumbleConductor.min_strong_magnitude_threshold = value
func _on_weak_slider_focused() -> void:

View File

@ -1,8 +1,12 @@
[gd_scene format=3 uid="uid://dak6f2xw3mgjj"]
[ext_resource type="Script" uid="uid://cs2yn6o8vsp4a" path="res://src/ui/setup/controller/controller_setup_menu.gd" id="1_ee61x"]
[ext_resource type="Script" uid="uid://bbwtct3hoxwws" path="res://src/core/vibration_component.gd" id="2_6beo4"]
[ext_resource type="Script" uid="uid://bbwtct3hoxwws" path="res://src/core/controller_rumble/rumble_component.gd" id="2_6beo4"]
[ext_resource type="Texture2D" uid="uid://g85advbc1vrw" path="res://addons/controller_icons/assets/xboxseries/diagram_simple.png" id="3_6beo4"]
[ext_resource type="Script" uid="uid://dwwingj0dsxdg" path="res://src/core/controller_rumble/rumble_config.gd" id="3_sa2mc"]
[sub_resource type="Resource" id="Resource_gtqq5"]
script = ExtResource("3_sa2mc")
[node name="ControllerSetupMenu" type="Control" unique_id=1563422179]
layout_mode = 3
@ -14,9 +18,10 @@ grow_vertical = 2
script = ExtResource("1_ee61x")
metadata/_custom_type_script = "uid://cs2yn6o8vsp4a"
[node name="VibrationComponent" type="Node" parent="." unique_id=193091150]
[node name="RumbleComponent" type="Node" parent="." unique_id=193091150]
unique_name_in_owner = true
script = ExtResource("2_6beo4")
data = SubResource("Resource_gtqq5")
weak_magnitude = 0.05
strong_magnitude = 0.05
metadata/_custom_type_script = "uid://bbwtct3hoxwws"
@ -25,10 +30,13 @@ metadata/_custom_type_script = "uid://bbwtct3hoxwws"
unique_name_in_owner = true
[node name="Label" type="Label" parent="." unique_id=684594410]
layout_mode = 0
offset_right = 384.0
offset_bottom = 49.0
layout_mode = 1
anchors_preset = 10
anchor_right = 1.0
offset_bottom = 23.0
grow_horizontal = 2
text = "Adjust the sliders, until you can bearly feel the vibrations."
horizontal_alignment = 1
[node name="RichTextLabel" type="RichTextLabel" parent="." unique_id=1446444531]
visible = false

View File

@ -7,12 +7,25 @@ signal setup_finished
@onready var controller_recommended: Control = %ControllerRecommended
@onready var rhythm_setup_menu: RhythmSetupMenu = %RhythmSetupMenu
@onready var controller_setup_menu: ControllerSetupMenu = %ControllerSetupMenu
@onready var configurable_notice: Label = %ConfigurableNotice
@onready var fade_control: Control = %FadeControl
func _ready() -> void:
rhythm_setup_menu.confirmed.connect(_on_rythm_setup_confirmed)
controller_setup_menu.confirmed.connect(_on_controller_setup_confirmed)
visibility_changed.connect(_on_visibility_changed)
_on_visibility_changed()
InputManager.input_method_changed.connect(_on_input_method_changed)
func _on_visibility_changed() -> void:
print("On Visibility Changed. Is Visible: ", is_visible_in_tree())
if not is_visible_in_tree():
return
await get_tree().create_timer(0.5).timeout
controller_recommended.show()
fade_out()
@ -21,23 +34,24 @@ func _ready() -> void:
controller_recommended.hide()
controller_setup_menu.show()
configurable_notice.show()
fade_out()
InputManager.input_method_changed.connect(_on_input_method_changed)
func fade_in() -> void:
get_viewport().gui_release_focus()
foreground_color.mouse_filter = Control.MOUSE_FILTER_STOP
var tween: Tween = create_tween()
tween.tween_property(foreground_color, ^"color:a", 1.0, 3.0)
#tween.tween_property(foreground_color, ^"color:a", 1.0, 3.0)
tween.tween_property(fade_control, ^"modulate:a", 0.0, 3.0)
await tween.finished
func fade_out() -> void:
foreground_color.mouse_filter = Control.MOUSE_FILTER_IGNORE
var tween: Tween = create_tween()
tween.tween_property(foreground_color, ^"color:a", 0.0, 3.0)
#tween.tween_property(foreground_color, ^"color:a", 0.0, 3.0)
tween.tween_property(fade_control, ^"modulate:a", 1.0, 3.0)
func _on_rythm_setup_confirmed() -> void:

View File

@ -24,7 +24,17 @@ grow_horizontal = 2
grow_vertical = 2
color = Color(0, 0, 0, 1)
[node name="ControllerRecommended" type="Control" parent="." unique_id=167704832]
[node name="FadeControl" type="Control" parent="." unique_id=2135836694]
unique_name_in_owner = true
modulate = Color(1, 1, 1, 0)
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="ControllerRecommended" type="Control" parent="FadeControl" unique_id=167704832]
unique_name_in_owner = true
visible = false
layout_mode = 1
@ -34,7 +44,7 @@ anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VBoxContainer" type="VBoxContainer" parent="ControllerRecommended" unique_id=684870312]
[node name="VBoxContainer" type="VBoxContainer" parent="FadeControl/ControllerRecommended" unique_id=684870312]
layout_mode = 1
anchors_preset = -1
anchor_left = 0.15
@ -44,17 +54,17 @@ anchor_bottom = 0.97
grow_horizontal = 2
grow_vertical = 2
[node name="Label" type="Label" parent="ControllerRecommended/VBoxContainer" unique_id=1590844875]
[node name="Label" type="Label" parent="FadeControl/ControllerRecommended/VBoxContainer" unique_id=1590844875]
layout_mode = 2
theme_override_font_sizes/font_size = 42
text = "Use of a controller recommended"
horizontal_alignment = 1
[node name="Control" type="Control" parent="ControllerRecommended/VBoxContainer" unique_id=595986704]
[node name="Control" type="Control" parent="FadeControl/ControllerRecommended/VBoxContainer" unique_id=595986704]
layout_mode = 2
size_flags_vertical = 3
[node name="TextureRect" type="TextureRect" parent="ControllerRecommended/VBoxContainer/Control" unique_id=1190977067]
[node name="TextureRect" type="TextureRect" parent="FadeControl/ControllerRecommended/VBoxContainer/Control" unique_id=1190977067]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
@ -68,20 +78,35 @@ texture = ExtResource("4_sr5uw")
expand_mode = 1
stretch_mode = 5
[node name="RhythmSetupMenu" parent="." unique_id=552044082 instance=ExtResource("2_2gigy")]
[node name="RhythmSetupMenu" parent="FadeControl" unique_id=552044082 instance=ExtResource("2_2gigy")]
unique_name_in_owner = true
process_mode = 4
visible = false
layout_mode = 1
[node name="ControllerSetupMenu" parent="." unique_id=1563422179 instance=ExtResource("3_sr5uw")]
[node name="ControllerSetupMenu" parent="FadeControl" unique_id=1563422179 instance=ExtResource("3_sr5uw")]
unique_name_in_owner = true
process_mode = 4
visible = false
layout_mode = 1
[node name="ConfigurableNotice" type="Label" parent="FadeControl" unique_id=2047433102]
unique_name_in_owner = true
visible = false
layout_mode = 1
anchors_preset = 12
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_top = -23.0
grow_horizontal = 2
grow_vertical = 0
text = "You can change this later in the settings."
horizontal_alignment = 1
[node name="ForegroundColor" type="ColorRect" parent="." unique_id=1692094271]
unique_name_in_owner = true
visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0

View File

@ -32,6 +32,13 @@ func close() -> void:
confirmed.emit()
func fade_out_and_stop_setup(duration: float) -> void:
var tween: Tween = create_tween()
tween.tween_property(rhythm_beat, ^"volume_linear", 0.0, duration)
tween.tween_callback(stop_setup)
await tween.finished
func stop_setup() -> void:
rhythm_player.stop()
_restore_song_playback_data()
@ -55,7 +62,8 @@ func _on_visibility_changed() -> void:
if not rhythm_beat.playing:
_store_song_playback_data()
user_offset_slider.set_value_no_signal(SettingsHandler.get_setting("audio", "user_offset_ms", 0.0))
var user_offset: float = SettingsHandler.get_setting("audio", "user_offset_ms", 0.0)
user_offset_slider.set_value_no_signal(user_offset)
user_offset_slider.grab_focus()
rhythm_player.play()

View File

@ -4,13 +4,24 @@
[ext_resource type="Script" uid="uid://bfpr421kg4s" path="res://src/ui/settings_menu/slider_label.gd" id="2_0yond"]
[ext_resource type="Script" uid="uid://bdi06itcm6wfp" path="res://src/core/rhythm/rhythm_player.gd" id="2_jsobq"]
[ext_resource type="AudioStream" uid="uid://cwpx80o5yaauf" path="res://src/ui/setup/rhythm/120bpm_beat.ogg" id="2_uupbh"]
[ext_resource type="Script" uid="uid://bbwtct3hoxwws" path="res://src/core/vibration_component.gd" id="2_yr7ls"]
[ext_resource type="Script" uid="uid://bbwtct3hoxwws" path="res://src/core/controller_rumble/rumble_component.gd" id="2_yr7ls"]
[ext_resource type="Script" uid="uid://co7j2qtqpud6b" path="res://src/core/rhythm/rhythm_listener.gd" id="3_o47te"]
[ext_resource type="Script" uid="uid://dwwingj0dsxdg" path="res://src/core/controller_rumble/rumble_config.gd" id="3_xnyx0"]
[ext_resource type="Script" uid="uid://c5mqtmsvgt4e8" path="res://src/core/rhythm/song_info.gd" id="4_7a0hf"]
[ext_resource type="Script" uid="uid://cx1nws4t8hs2u" path="res://src/core/rhythm/tempo_section_info.gd" id="5_cribi"]
[ext_resource type="Texture2D" uid="uid://t6ydwif1bo1c" path="res://godot_icon.svg" id="6_cribi"]
[ext_resource type="Script" uid="uid://bvmfdeypbeqsn" path="res://src/core/rhythm/rhythm_property_setter.gd" id="7_0yond"]
[sub_resource type="Resource" id="Resource_ej02t"]
script = ExtResource("3_xnyx0")
weak_intensity = 0.5
strong_intensity = 0.0
[sub_resource type="Resource" id="Resource_sp7no"]
script = ExtResource("3_xnyx0")
weak_intensity = 0.9
strong_intensity = 0.5
[sub_resource type="Resource" id="Resource_0yond"]
script = ExtResource("4_7a0hf")
audio_stream = ExtResource("2_uupbh")
@ -27,14 +38,16 @@ mouse_filter = 2
script = ExtResource("1_la56f")
metadata/_custom_type_script = "uid://bvs4uvpewolwc"
[node name="BeatVibration" type="Node" parent="." unique_id=1560105761]
[node name="BeatRumble" type="Node" parent="." unique_id=1560105761]
script = ExtResource("2_yr7ls")
data = SubResource("Resource_ej02t")
weak_magnitude = 0.5
strong_magnitude = 0.0
metadata/_custom_type_script = "uid://bbwtct3hoxwws"
[node name="BarVibration" type="Node" parent="." unique_id=1199048244]
[node name="BarRumble" type="Node" parent="." unique_id=1199048244]
script = ExtResource("2_yr7ls")
data = SubResource("Resource_sp7no")
weak_magnitude = 0.9
strong_magnitude = 0.5
metadata/_custom_type_script = "uid://bbwtct3hoxwws"
@ -155,5 +168,14 @@ texture = ExtResource("6_cribi")
layout_mode = 2
texture = ExtResource("6_cribi")
[connection signal="bar_tick" from="RhythmListener" to="BarVibration" method="vibrate" flags=3 unbinds=1]
[connection signal="beat_tick" from="RhythmListener" to="BeatVibration" method="vibrate" unbinds=1]
[node name="Label" type="Label" parent="." unique_id=1207688688]
layout_mode = 1
anchors_preset = 10
anchor_right = 1.0
offset_bottom = 23.0
grow_horizontal = 2
text = "Adjust the slider so that everything syncs up with the beat."
horizontal_alignment = 1
[connection signal="bar_ticked" from="RhythmListener" to="BarRumble" method="vibrate" flags=3 unbinds=1]
[connection signal="beat_ticked" from="RhythmListener" to="BeatRumble" method="vibrate" unbinds=1]

View File

@ -0,0 +1,30 @@
shader_type canvas_item;
uniform sampler2D color_ramp;
uniform float fog_amount = 1.0;
uniform sampler2D fog_texture : repeat_enable;
uniform sampler2D fog_overlay_texture : repeat_enable;
global uniform float time;
void vertex() {
// Called for every vertex the material is visible on.
}
void fragment() {
// Called for every pixel the material is visible on.
if (UV.y > 0.5)
{
vec4 fog = texture(fog_texture, vec2(UV.x + time * 0.02, UV.y));
vec4 fog_overlay = texture(fog_overlay_texture, vec2(UV.x + time * -0.015, UV.y + time * 0.0025));
fog = mix(fog, fog_overlay, 0.5);
vec3 sampled_color = texture(color_ramp, vec2(fog.r, 0.0)).rgb;
fog = mix(fog, vec4(sampled_color, 0.0), 1.0);
COLOR += fog * ((abs(0.5 - UV.x) * 2.0) * (abs(0.5 - UV.y) * 2.0)) * fog_amount;
}
}
//void light() {
// // Called for every pixel for every light affecting the CanvasItem.
// // Uncomment to replace the default light processing function with this one.
//}

View File

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

View File

@ -0,0 +1,52 @@
class_name StartupScene
extends Control
signal startup_finished
@onready var menu_animations: AnimationPlayer = %MenuAnimations
@onready var initial_setup_menu: InitialSetupMenu = %InitialSetupMenu
@onready var splash_screen_button: Button = %SplashScreenButton
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
splash_screen_button.pressed.connect(_on_splash_confirmed)
menu_animations.play(&"fade_splash_in")
func needs_game_setup() -> bool:
var config := ConfigFile.new()
if config.load(Game.USER_SETTINGS_PATH) != OK:
return true
return config.get_value("save", "needs_initial_setup", true)
func show_initial_setup_menu() -> void:
initial_setup_menu.setup_finished.connect(_on_initial_setup_menu_setup_finished)
initial_setup_menu.show()
func _on_splash_confirmed() -> void:
splash_screen_button.disabled = true
if needs_game_setup():
menu_animations.play(&"minimize_splash")
await menu_animations.animation_finished
show_initial_setup_menu()
else:
menu_animations.play(&"fade_out")
await menu_animations.animation_finished
startup_finished.emit()
func _on_initial_setup_menu_setup_finished() -> void:
var config: ConfigFile = Utils.load_config(Game.USER_SETTINGS_PATH)
config.set_value("save", "needs_initial_setup", false)
config.save(Game.USER_SETTINGS_PATH)
menu_animations.play(&"fade_out")
await menu_animations.animation_finished
startup_finished.emit()

View File

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

Some files were not shown because too many files have changed in this diff Show More