diff --git a/game/_development/ayuroo/maestro/_mo_anim.tres b/game/_development/ayuroo/maestro/_mo_anim.tres index 62cd216..984f2c6 100644 --- a/game/_development/ayuroo/maestro/_mo_anim.tres +++ b/game/_development/ayuroo/maestro/_mo_anim.tres @@ -30,7 +30,7 @@ markers = [{ tracks/0/type = "audio" tracks/0/imported = false tracks/0/enabled = true -tracks/0/path = NodePath("Music") +tracks/0/path = NodePath("RhythmPlayer/Music") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/keys = { diff --git a/game/_development/ayuroo/maestro/_mo_chase_test.tscn b/game/_development/ayuroo/maestro/_mo_chase_test.tscn index 6fd899f..55c17c1 100644 --- a/game/_development/ayuroo/maestro/_mo_chase_test.tscn +++ b/game/_development/ayuroo/maestro/_mo_chase_test.tscn @@ -1,10 +1,20 @@ [gd_scene format=3 uid="uid://lyl5v6s6waw"] +[ext_resource type="Script" uid="uid://bdi06itcm6wfp" path="res://src/core/rhythm/rhythm_player.gd" id="1_018ah"] +[ext_resource type="AudioStream" uid="uid://du3mds6gp7awe" path="res://_development/ayuroo/maestro/Maestro.mp3" id="2_51o3i"] [ext_resource type="Script" uid="uid://byqenxfb1srrp" path="res://tools/time_music_animation_player.gd" id="2_hkcog"] +[ext_resource type="Script" uid="uid://c5mqtmsvgt4e8" path="res://src/core/rhythm/song_info.gd" id="3_7lyik"] [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"] +[sub_resource type="Resource" id="Resource_gvx8b"] +script = ExtResource("3_7lyik") +audio_stream = ExtResource("2_51o3i") +bpm = 160.0 +metadata/_custom_type_script = "uid://c5mqtmsvgt4e8" + [sub_resource type="Curve3D" id="Curve3D_tqtrq"] _data = { "points": PackedVector3Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -897), @@ -25,16 +35,23 @@ size = Vector3(14, 5, 1) [node name="ChaseTest" type="Node3D" unique_id=1255206756] -[node name="Music" type="AudioStreamPlayer" parent="." unique_id=1719638466] +[node name="RhythmPlayer" type="Node" parent="." unique_id=500555265] +script = ExtResource("1_018ah") +song_info = SubResource("Resource_gvx8b") +audio_player = NodePath("Music") +metadata/_custom_type_script = "uid://bdi06itcm6wfp" + +[node name="Music" type="AudioStreamPlayer" parent="RhythmPlayer" unique_id=1719638466] volume_db = -4.5 -[node name="MusicAnimation" type="AnimationPlayer" parent="." unique_id=1841439085] +[node name="MusicAnimation" type="AnimationPlayer" parent="." unique_id=1841439085 node_paths=PackedStringArray("rhythm_player")] audio_max_polyphony = 1 callback_mode_process = 0 callback_mode_method = 1 libraries/ = ExtResource("4_q2x38") script = ExtResource("2_hkcog") -audio_player = NodePath("../Music") +rhythm_player = NodePath("../RhythmPlayer") +audio_player = NodePath("../RhythmPlayer/Music") metadata/_custom_type_script = "uid://byqenxfb1srrp" [node name="CameraRoot" type="Node3D" parent="." unique_id=949164518] @@ -83,8 +100,6 @@ duration = 0.1 sync_to_audio = true weak_magnitude = 0.575 strong_magnitude = 0.75 -weak_controller_magnitude_multiplier = 1.5 -weak_controller_duration_multiplier = 1.25 [node name="LightBeatVibration" type="Node" parent="." unique_id=2006943016] script = ExtResource("9_yut28") @@ -92,7 +107,6 @@ duration = 0.175 sync_to_audio = true weak_magnitude = 0.375 strong_magnitude = 0.0 -weak_controller_magnitude_multiplier = 1.75 [node name="StartChaseArea" type="Area3D" parent="." unique_id=1335887294] collision_layer = 0 diff --git a/game/addons/version_display/version_display.tscn b/game/addons/version_display/version_display.tscn index 7b1a52b..24708d2 100644 --- a/game/addons/version_display/version_display.tscn +++ b/game/addons/version_display/version_display.tscn @@ -27,6 +27,6 @@ layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 theme_override_colors/font_shadow_color = Color(0, 0, 0, 1) -text = "{GameName} - {State} - V - {Version}" +text = "{GameName} - {State} - v{Version}" horizontal_alignment = 2 vertical_alignment = 2 diff --git a/game/assets/models/electrics/spot_light/studio_spot_light.blend b/game/assets/models/electrics/spot_light/studio_spot_light.blend deleted file mode 100644 index 772e7dc..0000000 Binary files a/game/assets/models/electrics/spot_light/studio_spot_light.blend and /dev/null differ diff --git a/game/assets/models/electrics/spot_light/studio_spot_light.blend1 b/game/assets/models/electrics/spot_light/studio_spot_light.blend1 deleted file mode 100644 index 9d952ae..0000000 Binary files a/game/assets/models/electrics/spot_light/studio_spot_light.blend1 and /dev/null differ diff --git a/game/assets/models/electrics/spot_light/studio_light_framing_02.glb b/game/assets/models/electrics/studio_light/studio_light_framing_02.glb similarity index 100% rename from game/assets/models/electrics/spot_light/studio_light_framing_02.glb rename to game/assets/models/electrics/studio_light/studio_light_framing_02.glb diff --git a/game/assets/models/electrics/spot_light/studio_light_framing_02.glb.import b/game/assets/models/electrics/studio_light/studio_light_framing_02.glb.import similarity index 74% rename from game/assets/models/electrics/spot_light/studio_light_framing_02.glb.import rename to game/assets/models/electrics/studio_light/studio_light_framing_02.glb.import index ba32bbc..b0270bb 100644 --- a/game/assets/models/electrics/spot_light/studio_light_framing_02.glb.import +++ b/game/assets/models/electrics/studio_light/studio_light_framing_02.glb.import @@ -4,12 +4,12 @@ importer="scene" importer_version=1 type="PackedScene" uid="uid://boxc0e6to4083" -path="res://.godot/imported/studio_light_framing_02.glb-60b358246079bde473e527e6432e4573.scn" +path="res://.godot/imported/studio_light_framing_02.glb-9f2ff22ec5f0e1faa130c6cf2d30ef80.scn" [deps] -source_file="res://assets/models/electrics/spot_light/studio_light_framing_02.glb" -dest_files=["res://.godot/imported/studio_light_framing_02.glb-60b358246079bde473e527e6432e4573.scn"] +source_file="res://assets/models/electrics/studio_light/studio_light_framing_02.glb" +dest_files=["res://.godot/imported/studio_light_framing_02.glb-9f2ff22ec5f0e1faa130c6cf2d30ef80.scn"] [params] diff --git a/game/assets/models/electrics/studio_light/studio_spot_light.blend b/game/assets/models/electrics/studio_light/studio_spot_light.blend new file mode 100644 index 0000000..3201379 Binary files /dev/null and b/game/assets/models/electrics/studio_light/studio_spot_light.blend differ diff --git a/game/assets/models/electrics/spot_light/studio_spot_light.blend.import b/game/assets/models/electrics/studio_light/studio_spot_light.blend.import similarity index 100% rename from game/assets/models/electrics/spot_light/studio_spot_light.blend.import rename to game/assets/models/electrics/studio_light/studio_spot_light.blend.import diff --git a/game/assets/models/electrics/studio_light/studio_spot_light.blend1 b/game/assets/models/electrics/studio_light/studio_spot_light.blend1 new file mode 100644 index 0000000..d30539a Binary files /dev/null and b/game/assets/models/electrics/studio_light/studio_spot_light.blend1 differ diff --git a/game/assets/models/electrics/spot_light/studio_spot_light.glb b/game/assets/models/electrics/studio_light/studio_spot_light.glb similarity index 100% rename from game/assets/models/electrics/spot_light/studio_spot_light.glb rename to game/assets/models/electrics/studio_light/studio_spot_light.glb diff --git a/game/assets/models/electrics/spot_light/studio_spot_light.glb.import b/game/assets/models/electrics/studio_light/studio_spot_light.glb.import similarity index 75% rename from game/assets/models/electrics/spot_light/studio_spot_light.glb.import rename to game/assets/models/electrics/studio_light/studio_spot_light.glb.import index 01aa265..bc04a04 100644 --- a/game/assets/models/electrics/spot_light/studio_spot_light.glb.import +++ b/game/assets/models/electrics/studio_light/studio_spot_light.glb.import @@ -4,12 +4,12 @@ importer="scene" importer_version=1 type="PackedScene" uid="uid://pvll6bliout1" -path="res://.godot/imported/studio_spot_light.glb-8012087060176854fbc170fa9eeb4e6a.scn" +path="res://.godot/imported/studio_spot_light.glb-8d4c4ec1913c84aa7647ba021a5621de.scn" [deps] -source_file="res://assets/models/electrics/spot_light/studio_spot_light.glb" -dest_files=["res://.godot/imported/studio_spot_light.glb-8012087060176854fbc170fa9eeb4e6a.scn"] +source_file="res://assets/models/electrics/studio_light/studio_spot_light.glb" +dest_files=["res://.godot/imported/studio_spot_light.glb-8d4c4ec1913c84aa7647ba021a5621de.scn"] [params] diff --git a/game/assets/models/electrics/spot_light/studio_spot_light_framing_01.glb b/game/assets/models/electrics/studio_light/studio_spot_light_framing_01.glb similarity index 100% rename from game/assets/models/electrics/spot_light/studio_spot_light_framing_01.glb rename to game/assets/models/electrics/studio_light/studio_spot_light_framing_01.glb diff --git a/game/assets/models/electrics/spot_light/studio_spot_light_framing_01.glb.import b/game/assets/models/electrics/studio_light/studio_spot_light_framing_01.glb.import similarity index 79% rename from game/assets/models/electrics/spot_light/studio_spot_light_framing_01.glb.import rename to game/assets/models/electrics/studio_light/studio_spot_light_framing_01.glb.import index dcf109e..7bb0f6c 100644 --- a/game/assets/models/electrics/spot_light/studio_spot_light_framing_01.glb.import +++ b/game/assets/models/electrics/studio_light/studio_spot_light_framing_01.glb.import @@ -4,12 +4,12 @@ importer="scene" importer_version=1 type="PackedScene" uid="uid://bwejp67rw5erj" -path="res://.godot/imported/studio_spot_light_framing_01.glb-e4cf539b334e9123aa40c25947599f49.scn" +path="res://.godot/imported/studio_spot_light_framing_01.glb-6cf086edc9cacd5b250158910f51fa9e.scn" [deps] -source_file="res://assets/models/electrics/spot_light/studio_spot_light_framing_01.glb" -dest_files=["res://.godot/imported/studio_spot_light_framing_01.glb-e4cf539b334e9123aa40c25947599f49.scn"] +source_file="res://assets/models/electrics/studio_light/studio_spot_light_framing_01.glb" +dest_files=["res://.godot/imported/studio_spot_light_framing_01.glb-6cf086edc9cacd5b250158910f51fa9e.scn"] [params] diff --git a/game/assets/shaders/hologram.gdshader b/game/assets/shaders/hologram.gdshader new file mode 100644 index 0000000..a50b884 --- /dev/null +++ b/game/assets/shaders/hologram.gdshader @@ -0,0 +1,70 @@ +shader_type spatial; +render_mode unshaded, cull_disabled, world_vertex_coords; + +global uniform float time; + +uniform vec4 color : source_color = vec4(0.275, 0.718, 1.0, 0.824); +uniform sampler2D albedo_texture; + +uniform float stripe_falloff = 0.75; + +uniform float strip1_speed = 0.05; +uniform float strip1_scale = 1.0; +uniform float strip1_fract_scale = 50.0; + +uniform float strip2_speed = 0.1; +uniform float strip2_scale = 0.5; +uniform float strip2_fract_scale = 20.0; + +group_uniforms tint_edge; +uniform vec4 tint_color : source_color = vec4(1.0, 0.5, 0.0, 0.5); // #FF8000 +uniform vec4 edge_color : source_color = vec4(1.0, 0.0, 0.0, 1.0); // #FF0000 +uniform float edge_power : hint_range(0.0, 1.0) = 0.5; +uniform float edge_size : hint_range(0.1, 5.0) = 1.0; +uniform float edge_intensity : hint_range(0.0, 2.0) = 0.8; + +varying vec3 vertex_world_position; + +void vertex() { + // Called for every vertex the material is visible on. + vertex_world_position = (PROJECTION_MATRIX * vec4(VERTEX, 1.0)).xyz; +} + +void fragment() { + // Called for every pixel the material is visible on. + + vec2 canvas = UV;//vec2(VIEW.x, VIEW.y); + canvas = vertex_world_position.xy; + //vec3 normal = normalize(NORMAL); + //canvas += normal.xz * 0.1; + + vec2 uv = canvas * strip1_scale; + uv.y += time * strip1_speed; + vec2 uv2 = canvas * strip2_scale; + uv2.y += time * strip2_speed; + //vec2 uv3 = UV * 0.25; + //uv3.y += time * 0.035; + vec4 albedo = texture(albedo_texture, UV); + + ALBEDO = mix(color.rgb, albedo.rgb, 0.5); + + float strip1 = fract(uv.y * strip1_fract_scale); + float strip2 = fract(uv2.y * strip2_fract_scale); + //float strip3 = fract(uv3.y * 20.0); + float stripe = smoothstep(0.0, 1.0, mix(strip1, strip2, 0.5)); + //stripe = 1.0 - smoothstep(0.0, stripe, (1.0 - UV.y) * stripe_falloff); + stripe = 1.0 - smoothstep(0.0, stripe, (1.0 - SCREEN_UV.y) * stripe_falloff); + + float edge = 1.0 - dot(NORMAL, VIEW); + edge = pow(edge, mix(8.0, 2.0, edge_power)); + edge = smoothstep(0.5 - edge_size * 0.1, 0.5 + edge_size * 0.1, edge); + vec4 edge_effect = edge * edge_intensity * edge_color * max(UV.y, 0.0); +// + ALPHA = min(color.a, max(max(edge_effect.a, stripe), 0.0)) * albedo.a; + //ALPHA = min(color.a, max(stripe, 0.0)) * 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. +//} diff --git a/game/assets/shaders/hologram.gdshader.uid b/game/assets/shaders/hologram.gdshader.uid new file mode 100644 index 0000000..8ae5fb9 --- /dev/null +++ b/game/assets/shaders/hologram.gdshader.uid @@ -0,0 +1 @@ +uid://drswvylm4cmsc diff --git a/game/assets/shaders/rhythm/beating_lightbeam.gdshader b/game/assets/shaders/rhythm/beating_lightbeam.gdshader index 7079328..1500ed1 100644 --- a/game/assets/shaders/rhythm/beating_lightbeam.gdshader +++ b/game/assets/shaders/rhythm/beating_lightbeam.gdshader @@ -6,6 +6,7 @@ uniform vec3 color: source_color = vec3(1.0, 1.0, 1.0); uniform float alpha_multiplier: hint_range(0.0, 1.0, 0.001) = 0.25; uniform sampler2D albedo; uniform float flash_exponent = 3.0; +uniform float edge_fade = 0.5; void vertex() { // Called for every vertex the material is visible on. @@ -14,8 +15,12 @@ void vertex() { void fragment() { float phase = get_beat_phase(); vec4 tex = texture(albedo, UV); + + float edge = dot(NORMAL, VIEW); + edge = clamp(pow(edge, mix(8.0, 2.0, edge_fade)), 0.0, 1.0); + ALBEDO = mix(tex.rgb, color.rgb, 0.5); - ALPHA = tex.a * ease(1.0 - phase, flash_exponent) * alpha_multiplier;//mix(tex.a, color.a * (1.0 - phase), 0.5); + ALPHA = max(tex.a * ease(1.0 - phase, flash_exponent) * alpha_multiplier * edge, 0.0); } //void light() { diff --git a/game/project.godot b/game/project.godot index 0de89a2..6da6e04 100644 --- a/game/project.godot +++ b/game/project.godot @@ -14,7 +14,7 @@ config/name="MagicNStuff" config/tags=PackedStringArray("game", "horror", "open_world", "story") run/main_scene="uid://ga0d5817hbc8" config/features=PackedStringArray("4.6", "Forward Plus") -config/icon="res://godot_icon.svg" +config/icon="uid://d1mdvq16ybsto" [audio] @@ -52,6 +52,7 @@ folder_colors={ "res://localization/": "yellow", "res://src/": "green", "res://src/core/": "gray", +"res://src/dialogs/": "yellow", "res://src/gameplay/": "orange", "res://src/ui/": "blue", "res://tools/": "gray" @@ -171,6 +172,7 @@ toggle_mouse={ toggle_flashlight={ "deadzone": 0.2, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":102,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":11,"pressure":0.0,"pressed":true,"script":null) ] } limbo_console_toggle={ @@ -233,3 +235,7 @@ user_offset_ms={ "type": "float", "value": 0.0 } +time={ +"type": "float", +"value": 0.0 +} diff --git a/game/src/core/autoloads/input_manager.gd b/game/src/core/autoloads/input_manager.gd index 1c5dc95..23ef0c9 100644 --- a/game/src/core/autoloads/input_manager.gd +++ b/game/src/core/autoloads/input_manager.gd @@ -1,5 +1,8 @@ extends Node +signal input_method_changed(is_using_controller: bool) + +const JOYPAD_MOTION_DEADZONE: float = 0.5 const TOGGLE_MOUSE_BUTTON: StringName = &"toggle_mouse" var using_controller: bool = false @@ -10,12 +13,7 @@ func _input(event: InputEvent) -> void: get_viewport().set_input_as_handled() return - if event is InputEventMouseButton or event is InputEventKey: - if using_controller: - using_controller = false - elif event is InputEventJoypadButton or event is InputEventJoypadMotion: - if not using_controller: - using_controller = true + _handle_input_method(event) if event.is_action_pressed(TOGGLE_MOUSE_BUTTON): toggle_mouse() @@ -43,3 +41,27 @@ func capture_mouse() -> void: func release_mouse() -> void: Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + + +func is_keyboard_or_mouse_event(event: InputEvent) -> bool: + return ( + event is InputEventMouseButton or event is InputEventMouseMotion or event is InputEventKey + ) + + +func is_controller_event(event: InputEvent) -> bool: + return event is InputEventJoypadButton or event is InputEventJoypadMotion + + +func _handle_input_method(event: InputEvent) -> void: + if is_keyboard_or_mouse_event(event): + if using_controller: + using_controller = false + input_method_changed.emit(using_controller) + elif is_controller_event(event): + if event is InputEventJoypadMotion and absf(event.axis_value) <= JOYPAD_MOTION_DEADZONE: + return + + if not using_controller: + using_controller = true + input_method_changed.emit(using_controller) diff --git a/game/src/core/autoloads/settings_handler.gd b/game/src/core/autoloads/settings_handler.gd index 5b57b99..af6894c 100644 --- a/game/src/core/autoloads/settings_handler.gd +++ b/game/src/core/autoloads/settings_handler.gd @@ -23,7 +23,9 @@ var settings: Dictionary[String, Dictionary] = { "language": "en_US", }, "controls": { - "controller_vibration_min_range": 0.0, + "controller_vibrations": true, + "vibration_min_weak_threshold": 0.0, + "vibration_min_strong_threshold": 0.0, }, } @@ -66,6 +68,9 @@ func apply_settings() -> void: # Video 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) func commit_settings() -> void: diff --git a/game/src/core/autoloads/shader_globals.gd b/game/src/core/autoloads/shader_globals.gd index afba837..423a0f0 100644 --- a/game/src/core/autoloads/shader_globals.gd +++ b/game/src/core/autoloads/shader_globals.gd @@ -1,5 +1,8 @@ +@tool extends Node +var shader_time: float = 0.0 +var time_scale: float = 1.0 var beat: float = 0.0: set = set_beat var bar: float = 0.0: set = set_bar @@ -8,6 +11,21 @@ var total_song_time: float = 0.0: set = set_total_song_time var user_offset_ms: float = 0.0 +func _notification(what: int) -> void: + if what == NOTIFICATION_EDITOR_PRE_SAVE: + # Just in case. + RenderingServer.global_shader_parameter_set(&"time", 0.0) + + +func _process(delta: float) -> void: + shader_time += delta * time_scale + RenderingServer.global_shader_parameter_set(&"time", shader_time) + + +func set_paused(value: bool) -> void: + set_process(not value) + + func set_user_offset_ms(offset: float) -> void: user_offset_ms = offset RenderingServer.global_shader_parameter_set(&"user_offset_ms", beat) diff --git a/game/src/core/camera/camera_effect_target.gd b/game/src/core/camera/camera_effect_target.gd index a06164e..7e064d8 100644 --- a/game/src/core/camera/camera_effect_target.gd +++ b/game/src/core/camera/camera_effect_target.gd @@ -3,7 +3,6 @@ extends Node3D @export var camera: Camera3D - var fov: float = 0.0 var fov_change: float = 0.0 @@ -20,7 +19,7 @@ func _process(_delta: float) -> void: func cleanup_effects() -> void: - if not is_instance_valid(get_tree()): + if not is_instance_valid(get_tree()) or not can_process(): return if not get_tree().paused: diff --git a/game/src/core/dialog/dialog_bank.gd b/game/src/core/dialog/dialog_bank.gd new file mode 100644 index 0000000..a76b333 --- /dev/null +++ b/game/src/core/dialog/dialog_bank.gd @@ -0,0 +1,21 @@ +class_name DialogBank +extends Resource + +# Primarily used for localization purposes, +# so you can easily swap out the bank resource (via the Project Settings -> Localization -> Remaps) +# when changing to another language. +# TODO: Find out a good way for fallback dialogs. + +@export var dialogs: Dictionary[StringName, DialogEntry] = {} +@export var fallback_bank: DialogBank + + +func get_dialog(key: StringName) -> DialogEntry: + if dialogs.has(key): + return dialogs.get(key) + + if is_instance_valid(fallback_bank): + push_warning("No localization exists for key '%s' (%s). Getting fallback dialog." % [key, resource_path]) + return fallback_bank.get_dialog(key) + + return null diff --git a/game/src/core/dialog/dialog_bank.gd.uid b/game/src/core/dialog/dialog_bank.gd.uid new file mode 100644 index 0000000..fcbe496 --- /dev/null +++ b/game/src/core/dialog/dialog_bank.gd.uid @@ -0,0 +1 @@ +uid://w0dwu2x2qhq4 diff --git a/game/src/core/dialog/dialog_player.gd b/game/src/core/dialog/dialog_player.gd index 6d4f32e..4821010 100644 --- a/game/src/core/dialog/dialog_player.gd +++ b/game/src/core/dialog/dialog_player.gd @@ -8,7 +8,7 @@ static var active_dialog_playbacks: Array[DialogEntryPlayback] = [] @export_node_path("AudioStreamPlayer", "AudioStreamPlayer2D", "AudioStreamPlayer3D") var audio_player: NodePath: set = set_audio_player -@export var dialogs: Dictionary[StringName, DialogEntry] = {} +@export var dialogs: DialogBank var _audio_player: Node var _current_dialog_key: StringName @@ -53,18 +53,22 @@ func set_audio_player(audio_player_path: NodePath) -> void: func play(entry_key: StringName, from_position: float = 0.0) -> void: - var dialog_entry: DialogEntry = dialogs.get(entry_key) + var dialog_entry: DialogEntry = dialogs.get_dialog(entry_key) - if is_instance_valid(dialog_entry): - stop_dialog() + if not is_instance_valid(dialog_entry): + push_warning("Could not find dialog entry for key: '%s'. Finishing Dialog." % entry_key) + dialog_finished.emit(entry_key) + return - _audio_player.stream = dialog_entry.get_voiceline_stream() - _current_dialog_key = entry_key - _current_dialog_playback = DialogEntryPlayback.new(dialog_entry) - active_dialog_playbacks.append(_current_dialog_playback) + stop_dialog() - _audio_player.play(from_position) - set_process(true) + _audio_player.stream = dialog_entry.get_voiceline_stream() + _current_dialog_key = entry_key + _current_dialog_playback = DialogEntryPlayback.new(dialog_entry) + active_dialog_playbacks.append(_current_dialog_playback) + + _audio_player.play(from_position) + set_process(true) func get_current_dialog_entry() -> DialogEntry: @@ -83,9 +87,7 @@ func stop_dialog() -> void: func _on_dialog_finished() -> void: - var entry: DialogEntry = dialogs.get(_current_dialog_key) - stop_dialog() set_process(false) - dialog_finished.emit(entry) + dialog_finished.emit(_current_dialog_key) diff --git a/game/src/core/interactive_loader.gd b/game/src/core/interactive_loader.gd index 845e703..f3a1b5d 100644 --- a/game/src/core/interactive_loader.gd +++ b/game/src/core/interactive_loader.gd @@ -6,7 +6,7 @@ extends Node var load_progress: Array = [] -static func create_oneshot(bound_node: Node) -> InteractiveLoader: +static func create_oneshot_and_bind(bound_node: Node) -> InteractiveLoader: var loader := InteractiveLoader.new() loader.auto_free = true bound_node.add_child(loader) diff --git a/game/src/core/rhythm/rhythm_listener.gd b/game/src/core/rhythm/rhythm_listener.gd index c1c4187..119220a 100644 --- a/game/src/core/rhythm/rhythm_listener.gd +++ b/game/src/core/rhythm/rhythm_listener.gd @@ -6,6 +6,7 @@ signal beat_tick(beat_index: int) signal bar_tick(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 var beat: float = 0.0 var bar: float = 0.0 @@ -21,8 +22,8 @@ func _process(_delta: float) -> void: _last_bar_index = 0 return - beat = RhythmPlayer.beat + phase_shift - bar = RhythmPlayer.bar + phase_shift + beat = (RhythmPlayer.beat * phase_multiplier) + phase_shift + bar = (RhythmPlayer.bar * phase_multiplier) + phase_shift var beat_index: int = floori(beat) var bar_index: int = floori(bar) diff --git a/game/src/core/rhythm/rhythm_player.gd b/game/src/core/rhythm/rhythm_player.gd index add72b4..bcfc12d 100644 --- a/game/src/core/rhythm/rhythm_player.gd +++ b/game/src/core/rhythm/rhythm_player.gd @@ -3,10 +3,12 @@ extends Node signal beat_tick(beat_index: int) signal bar_tick(bar_index: int) +signal finished static var user_offset_ms: float = 0.0: set = set_user_offset_ms # Since only one rhythm player should play at any time, these are all static. +static var active_player: RhythmPlayer static var current_song_info: SongInfo static var paused: bool = true static var bpm: float = 120.0 @@ -43,7 +45,7 @@ func _ready() -> void: func _process(_delta: float) -> void: - if not is_instance_valid(_audio_player): + if not is_instance_valid(_audio_player) or active_player != self: return paused = not _audio_player.playing @@ -100,6 +102,10 @@ static func bar_to_signature(bar_index: int, _bar_signature: int) -> int: func set_audio_player(audio_player_path: NodePath) -> void: audio_player = audio_player_path + + if is_instance_valid(_audio_player) and _audio_player.finished.is_connected(_on_audio_player_finished): + _audio_player.finished.disconnect(_on_audio_player_finished) + _audio_player = get_node_or_null(audio_player) if not is_instance_valid(_audio_player): @@ -110,16 +116,20 @@ func set_audio_player(audio_player_path: NodePath) -> void: not _audio_player.has_method(&"play") or not _audio_player.has_method(&"get_playback_position") or not &"playing" in _audio_player + or not _audio_player.has_signal(&"finished") ): _audio_player = null push_error("audio_player is not a valid player.") return + _audio_player.finished.connect(_on_audio_player_finished) #set_process(_audio_player.playing) set_process(true) func play(position: float = 0.0) -> void: + active_player = self + current_song_info = song_info _audio_player.stream = song_info.audio_stream ShaderGlobals.set_total_song_time(song_info.audio_stream.get_length()) @@ -133,6 +143,8 @@ func play(position: float = 0.0) -> void: func stop() -> void: _audio_player.stop() + if active_player == self: + active_player = null func _update_playback() -> void: @@ -166,3 +178,7 @@ func _update_playback() -> void: if _last_bar != bar_index: bar_tick.emit(bar_index) _last_bar = bar_index + + +func _on_audio_player_finished() -> void: + finished.emit() diff --git a/game/src/core/rhythm/rhythm_property_setter.gd b/game/src/core/rhythm/rhythm_property_setter.gd index 66bd9a5..85faf3c 100644 --- a/game/src/core/rhythm/rhythm_property_setter.gd +++ b/game/src/core/rhythm/rhythm_property_setter.gd @@ -14,11 +14,13 @@ extends Node @export_group("Beat Value", "beat_") @export var beat_range_min: float = 0.0 @export var beat_range_max: float = 1.0 +@export var beat_curve: Curve @export_exp_easing("attenuation") var beat_exponent: float = 1.0 @export_group("Bar Value", "bar_") @export var bar_range_min: float = 0.0 @export var bar_range_max: float = 1.0 +@export var bar_curve: Curve @export_exp_easing("attenuation") var bar_exponent: float = 1.0 @@ -26,18 +28,19 @@ func _process(_delta: float) -> void: if RhythmPlayer.paused: return - if not beat_property.is_empty(): + if not beat_property.is_empty() or not nodes.is_empty(): _update_beat_property() - if not bar_property.is_empty(): + if not bar_property.is_empty() or not nodes.is_empty(): _update_bar_property() func _update_beat_property() -> void: var beat: float = RhythmPlayer.beat * phase_multiplier + phase_shift var beat_phase: float = beat - floorf(beat) - var beat_value: float = remap(beat_phase, 0.0, 1.0, beat_range_min, beat_range_max) - beat_value *= ease(1.0 - beat_phase, beat_exponent) + var beat_value: float = beat_curve.sample_baked(beat_phase) if is_instance_valid(beat_curve) else beat_phase + beat_value = remap(beat_value, 0.0, 1.0, beat_range_min, beat_range_max) + #beat_value *= ease(1.0 - beat_phase, beat_exponent) var _nodes: Array[Node] = beat_nodes.duplicate() _nodes.append_array(nodes) @@ -49,7 +52,8 @@ func _update_beat_property() -> void: func _update_bar_property() -> void: var bar: float = RhythmPlayer.bar * phase_multiplier + phase_shift var bar_phase: float = bar - floorf(bar) - var bar_value: float = remap(bar_phase, 0.0, 1.0, bar_range_min, bar_range_max) + var bar_value: float = bar_curve.sample_baked(bar_phase) if is_instance_valid(bar_curve) else bar_phase + bar_value = remap(bar_value, 0.0, 1.0, bar_range_min, bar_range_max) bar_value *= ease(1.0 - bar_phase, bar_exponent) var _nodes: Array[Node] = bar_nodes.duplicate() diff --git a/game/src/core/vibration_component.gd b/game/src/core/vibration_component.gd index 7ded753..62dfb95 100644 --- a/game/src/core/vibration_component.gd +++ b/game/src/core/vibration_component.gd @@ -12,7 +12,7 @@ extends Node #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_duration_threshold: float = 0.0 +#static var min_duration_threshold: float = 0.0 ## If [code]false[/code], calling [method vibrate] will not start a controller vibration. @export var enabled: bool = true: @@ -101,7 +101,8 @@ func vibrate() -> void: _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) + + #duration = maxf(duration, min_duration_threshold) Input.start_joy_vibration(device, _weak_magnitude, _strong_magnitude, duration) @@ -119,7 +120,7 @@ func can_vibrate() -> bool: if not Engine.is_editor_hint(): if ( not InputManager.using_controller - #or not ProjectSettings.get_setting("game/input/controller_vibrations", true) + or not SettingsHandler.get_setting("controls", "controller_vibrations", true) ): return false diff --git a/game/src/core/world/world.gd b/game/src/core/world/world.gd index 3aedba3..0ef80d2 100644 --- a/game/src/core/world/world.gd +++ b/game/src/core/world/world.gd @@ -41,7 +41,9 @@ func _ready() -> void: initialize_level_streamers() initialize_world_proxies() - register_commands() + InputManager.capture_mouse() + + _register_commands() loaded.emit() @@ -112,15 +114,15 @@ func get_level_ids_from_streamers(streamers: Array[LevelStreamer]) -> Array[Stri func get_level_streamers_from_id(level_id: StringName) -> Array[LevelStreamer]: return level_streamers.filter( - func(streamer: LevelStreamer) -> bool: - return streamer.level_id == level_id + func(streamer: LevelStreamer) -> bool: + return streamer.level_id == level_id ) func get_level_streamers_where_point_inside(point: Vector3) -> Array[LevelStreamer]: return level_streamers.filter( - func(streamer: LevelStreamer) -> bool: - return streamer.is_position_in_bounds(point) + func(streamer: LevelStreamer) -> bool: + return streamer.is_position_in_bounds(point) ) @@ -155,32 +157,32 @@ func get_instance_state(key: String, default: Variant) -> Variant: return world_state.instance_data.get(key, default) -func register_commands() -> void: +func _register_commands() -> void: var toggle_streamer_visibility: Callable = func() -> void: - var center_marker_mat := StandardMaterial3D.new() - center_marker_mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED - center_marker_mat.no_depth_test = true - center_marker_mat.depth_draw_mode = BaseMaterial3D.DEPTH_DRAW_DISABLED - center_marker_mat.disable_ambient_light = true - center_marker_mat.disable_fog = true - center_marker_mat.disable_specular_occlusion = true - center_marker_mat.disable_receive_shadows = true + var center_marker_mat := StandardMaterial3D.new() + center_marker_mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + center_marker_mat.no_depth_test = true + center_marker_mat.depth_draw_mode = BaseMaterial3D.DEPTH_DRAW_DISABLED + center_marker_mat.disable_ambient_light = true + center_marker_mat.disable_fog = true + center_marker_mat.disable_specular_occlusion = true + center_marker_mat.disable_receive_shadows = true - for streamer: LevelStreamer in level_streamers: - var children: Array[Node] = streamer.find_children("_DEBUG_VISIBILITY*", "MeshInstance3D", false, false) + for streamer: LevelStreamer in level_streamers: + var children: Array[Node] = streamer.find_children("_DEBUG_VISIBILITY*", "MeshInstance3D", false, false) - if children.is_empty(): - streamer.setup_debug_meshes(load("uid://dag4adrscn4b7")) + if children.is_empty(): + streamer.setup_debug_meshes(load("uid://dag4adrscn4b7")) - var center_marker := MeshInstance3D.new() - center_marker.mesh = SphereMesh.new() - center_marker.scale *= 0.2 - center_marker.name = "_DEBUG_VISIBILITY_CMARKER" + streamer.level_id - center_marker.material_override = center_marker_mat - streamer.add_child(center_marker) - else: - for child: Node in children: - child.queue_free() + var center_marker := MeshInstance3D.new() + center_marker.mesh = SphereMesh.new() + center_marker.scale *= 0.2 + center_marker.name = "_DEBUG_VISIBILITY_CMARKER" + streamer.level_id + center_marker.material_override = center_marker_mat + streamer.add_child(center_marker) + else: + for child: Node in children: + child.queue_free() LimboConsole.register_command(toggle_streamer_visibility, "toggle_level_streamer_visibility") diff --git a/game/src/game.gd b/game/src/game.gd index c44b216..9b1aaa1 100644 --- a/game/src/game.gd +++ b/game/src/game.gd @@ -7,10 +7,11 @@ extends Node const SAVE_DIR: String = "user://saves/%s/" const SAVE_PATH: String = SAVE_DIR + "%s" -const INITIAL_SAVE_DATA: SaveData = preload("res://src/initial_save_data.tres") +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 main_menu_path: String = "uid://7v62dybcabgw" var current_save_slot: int = 0 @@ -33,13 +34,18 @@ static func debug_draw(draw_shape: String, args: Array) -> void: func _ready() -> void: if not Engine.is_editor_hint(): - load_main_menu() + if needs_game_setup(): + load_initial_setup() + else: + load_main_menu() + register_commands() func load_game(save_data: SaveData, save_slot: int) -> void: current_save_data = save_data.duplicate() current_save_slot = save_slot + InputManager.capture_mouse() load_world(current_save_data.current_world, false) @@ -66,12 +72,13 @@ func load_world(world_path: String, save_previous: bool = true, load_from_save: unload_main_menu() unload_world(save_previous) - var loader := InteractiveLoader.create_oneshot(self) + var loader := InteractiveLoader.create_oneshot_and_bind(self) var loaded_scene: PackedScene = await loader.load_threaded(world_path) world = loaded_scene.instantiate() as World if not is_instance_valid(world): loading_screen.fade_out() + push_error("Loaded world is not valid or not of type [World].") return ERR_INVALID_DATA if load_from_save: @@ -123,7 +130,7 @@ func load_world_state(world_path: String) -> WorldState: func load_main_menu() -> void: - var loader := InteractiveLoader.create_oneshot(self) + var loader := InteractiveLoader.create_oneshot_and_bind(self) var loaded_scene: PackedScene = await loader.load_threaded(main_menu_path) var _main_menu: MainMenu = loaded_scene.instantiate() _main_menu.load_game_request.connect(load_game) @@ -132,6 +139,28 @@ func load_main_menu() -> void: world_container.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) + 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) + + func unload_main_menu() -> void: if is_instance_valid(main_menu): main_menu.queue_free() @@ -144,9 +173,9 @@ func quit_game() -> void: func register_commands() -> void: var load_save_func: Callable = func(save_index: int) -> void: - var path: String = MainMenu.get_save_path(save_index) - if ResourceLoader.exists(path): - load_game(load(path), save_index) + var path: String = MainMenu.get_save_path(save_index) + if ResourceLoader.exists(path): + load_game(load(path), save_index) LimboConsole.register_command(load_save_func, "load_save", "Loads the save with the given save slot index.") LimboConsole.register_command(save_game, "save_game", "Saves the game based on the current save slot.") diff --git a/game/src/gameplay/characters/player/player_character.gd b/game/src/gameplay/characters/player/player_character.gd index 5ad181c..289702e 100644 --- a/game/src/gameplay/characters/player/player_character.gd +++ b/game/src/gameplay/characters/player/player_character.gd @@ -47,7 +47,9 @@ func _init() -> void: func _exit_tree() -> void: LimboConsole.unregister_command("player_fly") + LimboConsole.remove_alias("noclip") LimboConsole.unregister_command("player_noclip") + LimboConsole.remove_alias("fly") func _ready() -> void: @@ -190,12 +192,10 @@ func _register_commands() -> void: _flying = false while _flying and is_inside_tree(): - if InputManager.is_window_focused(): + if InputManager.is_window_focused() and not get_tree().paused and can_process(): set_physics_process(false) var input_dir: Vector3 = get_input_direction() - movement_direction = transform.basis * Vector3(input_dir.x, 1.0, input_dir.z) - movement_direction = (movement_direction * Utils.VEC3_HOR).normalized() - movement_direction = movement_direction.rotated(Vector3.UP, head.global_rotation.y) + movement_direction = input_dir.rotated(Vector3.UP, head.global_rotation.y) if Input.is_action_pressed(ACTION_JUMP): movement_direction.y = 1.0 * _NOCLIP_SPEED @@ -219,12 +219,10 @@ func _register_commands() -> void: _noclipping = false while _flying and is_inside_tree(): - if InputManager.is_window_focused(): + if InputManager.is_window_focused() and not get_tree().paused and can_process(): set_physics_process(false) var input_dir: Vector3 = get_input_direction() - movement_direction = transform.basis * Vector3(input_dir.x, 1.0, input_dir.z) - movement_direction = (movement_direction * Utils.VEC3_HOR).normalized() - movement_direction = movement_direction.rotated(Vector3.UP, head.global_rotation.y) + movement_direction = input_dir.rotated(Vector3.UP, head.global_rotation.y) if Input.is_action_pressed(ACTION_JUMP): movement_direction.y = 1.0 * _FLY_SPEED @@ -241,4 +239,6 @@ func _register_commands() -> void: set_physics_process(true) LimboConsole.register_command(noclip_func, "player_noclip") + LimboConsole.add_alias("noclip", "player_noclip") LimboConsole.register_command(fly_func, "player_fly") + LimboConsole.add_alias("fly", "player_fly") diff --git a/game/src/gameplay/characters/player/player_character.tscn b/game/src/gameplay/characters/player/player_character.tscn index 4e009b6..d028b98 100644 --- a/game/src/gameplay/characters/player/player_character.tscn +++ b/game/src/gameplay/characters/player/player_character.tscn @@ -185,11 +185,12 @@ metadata/_custom_type_script = "uid://1i0linakw8mg" [node name="FlashlightSpot" type="SpotLight3D" parent="Head/Flashlight" unique_id=1000286492] light_energy = 1.5 +light_volumetric_fog_energy = 0.0 light_specular = 0.15 light_bake_mode = 0 shadow_enabled = true spot_range = 30.0 -spot_attenuation = 2.0 +spot_attenuation = 1.5 spot_angle_attenuation = 0.5 [node name="InteractionRay" parent="Head" unique_id=941602125 instance=ExtResource("4_de0uv")] diff --git a/game/src/gameplay/objects/stagelight/stagelight.tscn b/game/src/gameplay/objects/stagelight/stagelight.tscn index 21553ca..6e6ab38 100644 --- a/game/src/gameplay/objects/stagelight/stagelight.tscn +++ b/game/src/gameplay/objects/stagelight/stagelight.tscn @@ -1,9 +1,9 @@ [gd_scene format=3 uid="uid://bc84qk6pfgctg"] -[ext_resource type="PackedScene" uid="uid://pvll6bliout1" path="res://assets/models/electrics/spot_light/studio_spot_light.glb" id="1_3cilv"] +[ext_resource type="PackedScene" uid="uid://pvll6bliout1" path="res://assets/models/electrics/studio_light/studio_spot_light.glb" id="1_3cilv"] [ext_resource type="Script" uid="uid://cmh1y78o47f06" path="res://src/gameplay/objects/stagelight/stagelight.gd" id="1_wce40"] [ext_resource type="Shader" uid="uid://b46o5a45g58xb" path="res://assets/shaders/rhythm/beating_surface.gdshader" id="2_wce40"] -[ext_resource type="PackedScene" uid="uid://bwejp67rw5erj" path="res://assets/models/electrics/spot_light/studio_spot_light_framing_01.glb" id="3_otype"] +[ext_resource type="PackedScene" uid="uid://bwejp67rw5erj" path="res://assets/models/electrics/studio_light/studio_spot_light_framing_01.glb" id="3_otype"] [ext_resource type="Shader" uid="uid://c32arbbdbo7m8" path="res://assets/shaders/rhythm/beating_lightbeam.gdshader" id="4_d6ag8"] [ext_resource type="Script" uid="uid://bvmfdeypbeqsn" path="res://src/core/rhythm/rhythm_property_setter.gd" id="5_uce1x"] @@ -26,6 +26,7 @@ shader_parameter/color = Color(1, 1, 1, 1) shader_parameter/alpha_multiplier = 0.25 shader_parameter/albedo = SubResource("GradientTexture2D_du0pf") shader_parameter/flash_exponent = 4.0 +shader_parameter/edge_fade = 0.5 [sub_resource type="Gradient" id="Gradient_vtuqv"] interpolation_mode = 1 @@ -58,12 +59,12 @@ script = ExtResource("1_wce40") lightbeam_material = SubResource("ShaderMaterial_xn83m") light_surface_material = SubResource("ShaderMaterial_nqu5b") -[node name="StudioSpotLight" parent="." unique_id=1407009402 instance=ExtResource("1_3cilv")] +[node name="StudioSpotLight" parent="." unique_id=449918207 instance=ExtResource("1_3cilv")] -[node name="Cylinder" parent="StudioSpotLight" index="0" unique_id=1873656815] +[node name="Cylinder" parent="StudioSpotLight" index="0" unique_id=142845931] surface_material_override/1 = SubResource("ShaderMaterial_nqu5b") -[node name="StudioSpotLightFraming01" parent="." unique_id=166030914 instance=ExtResource("3_otype")] +[node name="StudioSpotLightFraming01" parent="." unique_id=2007355874 instance=ExtResource("3_otype")] [node name="LightbeamRoot" type="Node3D" parent="." unique_id=1922157293] transform = Transform3D(-4.371139e-08, -1, 0, 1, -4.371139e-08, 0, 0, 0, 1, 0.2, 8.742278e-09, 0) @@ -79,15 +80,16 @@ mesh = SubResource("CylinderMesh_787dp") [node name="SpotLight" type="SpotLight3D" parent="LightbeamRoot" unique_id=1841045966] unique_name_in_owner = true transform = Transform3D(1, 0, 0, 0, -4.371139e-08, 1, 0, -1, -4.371139e-08, 0, 0.8, 0) +light_volumetric_fog_energy = 0.0 spot_range = 50.0 spot_attenuation = 1.38 spot_angle = 8.75 spot_angle_attenuation = 0.23325838 -[node name="RhythmPropertySetter" type="Node" parent="LightbeamRoot" unique_id=1355223878 node_paths=PackedStringArray("nodes")] +[node name="RhythmPropertySetter" type="Node" parent="LightbeamRoot" unique_id=1355223878 node_paths=PackedStringArray("beat_nodes")] unique_name_in_owner = true script = ExtResource("5_uce1x") -nodes = [NodePath("../SpotLight")] +beat_nodes = [NodePath("../SpotLight")] beat_property = &"light_energy" phase_multiplier = 0.5 beat_range_min = 10.0 diff --git a/game/src/ui/main_menu/main_menu.gd b/game/src/ui/main_menu/main_menu.gd index cc4fea0..71d7821 100644 --- a/game/src/ui/main_menu/main_menu.gd +++ b/game/src/ui/main_menu/main_menu.gd @@ -59,10 +59,20 @@ func _ready() -> void: settings_menu.close_request.connect(_on_settings_close_request) - continue_button.visible = has_save() + continue_button.visible = has_last_save_slot() + load_button.visible = get_save_slots().size() > 0 + + ( + continue_button if continue_button.visible + else load_button if load_button.visible + else new_game_button + ).grab_focus() + + InputManager.input_method_changed.connect(_on_input_method_changed) + _on_input_method_changed(InputManager.using_controller) -func has_save() -> bool: +func has_last_save_slot() -> bool: var config: ConfigFile = Utils.load_config(USER_SETTINGS_PATH) return config.has_section_key("save", "last_slot") @@ -136,3 +146,10 @@ func _on_save_entry_pressed(save_slot: int) -> void: func _on_settings_close_request() -> void: settings_menu.hide() + + +func _on_input_method_changed(is_using_controller: bool) -> void: + if is_using_controller: + InputManager.capture_mouse() + else: + InputManager.release_mouse() diff --git a/game/src/ui/pause_menu/pause_menu.gd b/game/src/ui/pause_menu/pause_menu.gd index f6396c8..0e275b7 100644 --- a/game/src/ui/pause_menu/pause_menu.gd +++ b/game/src/ui/pause_menu/pause_menu.gd @@ -12,12 +12,14 @@ extends Control func _ready() -> void: - continue_button.pressed.connect(set_paused.bind(false)) + continue_button.pressed.connect(_on_continue_button_pressed) settings_button.pressed.connect(_on_settings_button_pressed) main_menu_button.pressed.connect(_on_main_menu_button_pressed) settings_menu.close_request.connect(_on_settings_menu_close_requested) + InputManager.input_method_changed.connect(_on_input_method_changed) + func _input(event: InputEvent) -> void: if event.is_action_pressed(&"pause"): @@ -28,9 +30,16 @@ func _input(event: InputEvent) -> void: func set_paused(value: bool) -> void: + ShaderGlobals.set_paused(value) world.process_mode = Node.PROCESS_MODE_DISABLED if value else Node.PROCESS_MODE_INHERIT visible = value + if visible: + _on_input_method_changed(InputManager.using_controller) + continue_button.grab_focus() + else: + InputManager.capture_mouse() + func is_paused() -> bool: return world.process_mode == Node.PROCESS_MODE_DISABLED @@ -40,13 +49,30 @@ func toggle_pause() -> void: set_paused(not is_paused()) +func _on_continue_button_pressed() -> void: + set_process_input(true) + set_paused(false) + + func _on_settings_button_pressed() -> void: settings_menu.show() func _on_settings_menu_close_requested() -> void: settings_menu.hide() + settings_button.grab_focus() func _on_main_menu_button_pressed() -> void: + set_process_input(false) world.request_world_unload() + + +func _on_input_method_changed(is_using_controller: bool) -> void: + if not is_paused(): + return + + if is_using_controller: + InputManager.capture_mouse() + else: + InputManager.release_mouse() diff --git a/game/src/ui/settings_menu/settings_menu.gd b/game/src/ui/settings_menu/settings_menu.gd index 3f2bc7f..41e7331 100644 --- a/game/src/ui/settings_menu/settings_menu.gd +++ b/game/src/ui/settings_menu/settings_menu.gd @@ -25,8 +25,12 @@ var _previously_focused_control: Control @onready var sfx_slider: HSlider = %SFXSlider @onready var music_slider: HSlider = %MusicSlider @onready var ambience_slider: HSlider = %AmbienceSlider +# Controls +@onready var vibration_config: Button = %VibrationConfig +@onready var controller_vibrations: CheckButton = %ControllerVibrations -@onready var rhythm_setup_menu: RhythmSetupMenu = $RhythmSetupMenu +@onready var rhythm_setup_menu: RhythmSetupMenu = %RhythmSetupMenu +@onready var controller_setup_menu: ControllerSetupMenu = %ControllerSetupMenu func _ready() -> void: @@ -51,6 +55,10 @@ func _ready() -> void: sfx_slider.value_changed.connect(_on_volume_slider_changed.bind(&"SFX")) music_slider.value_changed.connect(_on_volume_slider_changed.bind(&"Music")) ambience_slider.value_changed.connect(_on_volume_slider_changed.bind(&"Ambient")) + # Controls + vibration_config.pressed.connect(_on_vibration_config_pressed) + 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()) @@ -66,6 +74,8 @@ func _process(_delta: float) -> void: func close() -> void: if rhythm_setup_menu.is_visible_in_tree(): rhythm_setup_menu.close() + elif controller_setup_menu.is_visible_in_tree(): + controller_setup_menu.confirm() else: close_request.emit() @@ -147,8 +157,6 @@ func _on_headbobbing_intensity_value_changed(value: float) -> void: func _on_language_selected(index: int) -> void: var language_string: String = "en_US" match index: - 0: - language_string = "en_US" 1: language_string = "de_DE" 2: @@ -164,8 +172,6 @@ func _on_language_selected(index: int) -> void: func _on_window_mode_item_selected(index: int) -> void: var mode: DisplayServer.WindowMode match index: - 0: - mode = DisplayServer.WindowMode.WINDOW_MODE_FULLSCREEN 1: mode = DisplayServer.WindowMode.WINDOW_MODE_EXCLUSIVE_FULLSCREEN 2: @@ -179,12 +185,32 @@ func _on_window_mode_item_selected(index: int) -> void: func _on_configure_rhythm_delay_pressed() -> void: + _previously_focused_control = get_viewport().gui_get_focus_owner() rhythm_setup_menu.show() func _on_configure_rhythm_confirmed() -> void: rhythm_setup_menu.hide() + if is_instance_valid(_previously_focused_control): + _previously_focused_control.grab_focus() + func _on_volume_slider_changed(value: float, bus: StringName) -> void: SettingsHandler.set_setting("audio", bus, value) + + +func _on_vibration_config_pressed() -> void: + _previously_focused_control = get_viewport().gui_get_focus_owner() + controller_setup_menu.show() + + +func _on_vibration_config_confirmed() -> void: + controller_setup_menu.hide() + + if is_instance_valid(_previously_focused_control): + _previously_focused_control.grab_focus() + + +func _on_controller_vibrations_toggled(toggled_on: bool) -> void: + SettingsHandler.set_setting("controls", "controller_vibrations", toggled_on) diff --git a/game/src/ui/settings_menu/settings_menu.tscn b/game/src/ui/settings_menu/settings_menu.tscn index d66720d..1efc36f 100644 --- a/game/src/ui/settings_menu/settings_menu.tscn +++ b/game/src/ui/settings_menu/settings_menu.tscn @@ -3,6 +3,7 @@ [ext_resource type="Script" uid="uid://cll4odq5p7iuv" path="res://src/ui/settings_menu/settings_menu.gd" id="1_3iv5y"] [ext_resource type="Script" uid="uid://bfpr421kg4s" path="res://src/ui/settings_menu/slider_label.gd" id="2_axtgf"] [ext_resource type="PackedScene" uid="uid://b41bjano4bw6s" path="res://src/ui/setup/rhythm/rhythm_setup_menu.tscn" id="3_kktd5"] +[ext_resource type="PackedScene" uid="uid://dak6f2xw3mgjj" path="res://src/ui/setup/controller/controller_setup_menu.tscn" id="4_wg84k"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_axtgf"] content_margin_left = 0.0 @@ -305,6 +306,12 @@ unique_name_in_owner = true layout_mode = 2 text = "Configure Vibrations" +[node name="ControllerVibrations" type="CheckButton" parent="PanelContainer/VBoxContainer/ScrollContainer/MarginContainer/VBoxContainer" unique_id=143340003] +unique_name_in_owner = true +layout_mode = 2 +button_pressed = true +text = "Controller-Vibrations" + [node name="BackButton" type="Button" parent="PanelContainer/VBoxContainer" unique_id=1438707398] unique_name_in_owner = true layout_mode = 2 @@ -398,6 +405,8 @@ size_flags_horizontal = 3 text = "SETTINGS_REVERT" [node name="RhythmSetupMenu" parent="." unique_id=552044082 instance=ExtResource("3_kktd5")] +unique_name_in_owner = true +process_mode = 4 visible = false layout_mode = 1 mouse_filter = 0 @@ -412,3 +421,20 @@ anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 mouse_filter = 2 + +[node name="ControllerSetupMenu" parent="." unique_id=1563422179 instance=ExtResource("4_wg84k")] +unique_name_in_owner = true +process_mode = 4 +visible = false +layout_mode = 1 + +[node name="ColorRect" type="ColorRect" parent="ControllerSetupMenu" unique_id=1086585111] +modulate = Color(0, 0, 0, 1) +show_behind_parent = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/game/src/ui/setup/controller/controller_setup_menu.gd b/game/src/ui/setup/controller/controller_setup_menu.gd index 510cf84..bb22e4a 100644 --- a/game/src/ui/setup/controller/controller_setup_menu.gd +++ b/game/src/ui/setup/controller/controller_setup_menu.gd @@ -1,10 +1,14 @@ class_name ControllerSetupMenu extends Control -const MIN_MAGNITUDE: float = 0.05 +signal confirmed + +const MIN_WEAK_MAGNITUDE: float = 0.01175 +const MIN_STRONG_MAGNITUDE: float = 0.01175 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 repeat_vibration_timer: Timer = %RepeatVibrationTimer @@ -13,21 +17,83 @@ var is_testing_strong: bool = false @onready var min_weak_magnitude: HSlider = %MinWeakMagnitude @onready var min_strong_magnitude: HSlider = %MinStrongMagnitude +@onready var vibrate_texture: TextureRect = %VibrateTexture +@onready var confirm_button: Button = %ConfirmButton + 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) + min_weak_magnitude.focus_exited.connect(_on_weak_slider_unfocused) 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) + + +func confirm() -> void: + SettingsHandler.set_setting( + "controls", + "vibration_min_weak_threshold", + VibrationComponent.min_weak_magnitude_threshold, + false + ) + SettingsHandler.set_setting( + "controls", + "vibration_min_strong_threshold", + VibrationComponent.min_strong_magnitude_threshold, + true + ) + + confirmed.emit() func _test_vibration() -> void: - vibration_component.weak_magnitude = MIN_MAGNITUDE * float(is_testing_weak) - vibration_component.strong_magnitude = MIN_MAGNITUDE * float(is_testing_strong) + vibration_component.weak_magnitude = MIN_WEAK_MAGNITUDE * float(is_testing_weak) + vibration_component.strong_magnitude = MIN_STRONG_MAGNITUDE * float(is_testing_strong) + + match _duration_idx: + 5: + vibration_component.duration = 0.75 + _: + vibration_component.duration = 0.15 + #1: + #vibration_component.duration = 0.35 + #2: + #vibration_component.duration = 0.75 + + _duration_idx = posmod(_duration_idx + 1, 6) + vibration_component.vibrate() + _vibrate_texture() + + +func _vibrate_texture() -> void: + var tween: Tween = create_tween().set_loops(maxi(int(vibration_component.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 + tween = create_tween() + tween.tween_property(vibrate_texture, ^"rotation_degrees", 0.0, 0.1) + + +func _on_visibility_changed() -> void: + if is_visible_in_tree(): + repeat_vibration_timer.start() + process_mode = Node.PROCESS_MODE_INHERIT + min_weak_magnitude.grab_focus() + else: + repeat_vibration_timer.stop() + process_mode = Node.PROCESS_MODE_DISABLED func _on_min_weak_magnitude_value_changed(value: float) -> void: @@ -40,9 +106,15 @@ func _on_min_strong_magnitude_value_changed(value: float) -> void: func _on_weak_slider_focused() -> void: is_testing_weak = true - is_testing_strong = false + + +func _on_weak_slider_unfocused() -> void: + is_testing_weak = false func _on_strong_slider_focused() -> void: is_testing_strong = true - is_testing_weak = false + + +func _on_strong_slider_unfocused() -> void: + is_testing_strong = false diff --git a/game/src/ui/setup/controller/controller_setup_menu.tscn b/game/src/ui/setup/controller/controller_setup_menu.tscn index e2d8c7e..73c1a37 100644 --- a/game/src/ui/setup/controller/controller_setup_menu.tscn +++ b/game/src/ui/setup/controller/controller_setup_menu.tscn @@ -2,6 +2,7 @@ [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="Texture2D" uid="uid://g85advbc1vrw" path="res://addons/controller_icons/assets/xboxseries/diagram_simple.png" id="3_6beo4"] [node name="ControllerSetupMenu" type="Control" unique_id=1563422179] layout_mode = 3 @@ -22,19 +23,15 @@ metadata/_custom_type_script = "uid://bbwtct3hoxwws" [node name="RepeatVibrationTimer" type="Timer" parent="." unique_id=1579451638] unique_name_in_owner = true -wait_time = 0.5 -autostart = true [node name="Label" type="Label" parent="." unique_id=684594410] layout_mode = 0 offset_right = 384.0 offset_bottom = 49.0 -text = "Adjust the sliders, until you can bearly feel the vibrations. - -Adjust the first slider for the weak magnitude -Adjust the second slider for the strong magnitude" +text = "Adjust the sliders, until you can bearly feel the vibrations." [node name="RichTextLabel" type="RichTextLabel" parent="." unique_id=1446444531] +visible = false layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 @@ -48,6 +45,44 @@ Back [img=32]uid://cjtlrpqb75elt[/img]" horizontal_alignment = 2 vertical_alignment = 2 +[node name="ConfirmButton" type="Button" parent="." unique_id=1463168955] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = -1 +anchor_left = 0.5 +anchor_top = 0.75 +anchor_right = 0.5 +anchor_bottom = 0.75 +offset_left = -35.5 +offset_top = -31.0 +offset_right = 35.5 +grow_horizontal = 2 +grow_vertical = 0 +focus_neighbor_left = NodePath(".") +focus_neighbor_top = NodePath("../VBoxContainer/MinStrongMagnitude") +focus_neighbor_right = NodePath(".") +focus_neighbor_bottom = NodePath(".") +focus_next = NodePath(".") +focus_previous = NodePath("../VBoxContainer/MinStrongMagnitude") +text = "Confirm" + +[node name="VibrateTexture" type="TextureRect" parent="." unique_id=766104981] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = -1 +anchor_left = 0.4 +anchor_top = 0.05 +anchor_right = 0.6 +anchor_bottom = 0.17 +offset_left = -64.0 +offset_right = 64.0 +offset_bottom = 127.99999 +grow_horizontal = 2 +pivot_offset_ratio = Vector2(0.5, 0.6) +texture = ExtResource("3_6beo4") +expand_mode = 1 +stretch_mode = 5 + [node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=239130047] layout_mode = 1 anchors_preset = -1 @@ -68,14 +103,34 @@ unique_name_in_owner = true visible = false layout_mode = 2 +[node name="WeakLabel" type="Label" parent="VBoxContainer" unique_id=464920362] +layout_mode = 2 +text = "Weak-Motor:" + [node name="MinWeakMagnitude" type="HSlider" parent="VBoxContainer" unique_id=1247262766] unique_name_in_owner = true layout_mode = 2 +focus_neighbor_left = NodePath(".") +focus_neighbor_top = NodePath(".") +focus_neighbor_right = NodePath(".") +focus_neighbor_bottom = NodePath("../MinStrongMagnitude") +focus_next = NodePath("../MinStrongMagnitude") +focus_previous = NodePath(".") max_value = 1.0 step = 0.01 +[node name="StrongLabel" type="Label" parent="VBoxContainer" unique_id=1163539352] +layout_mode = 2 +text = "Strong-Motor:" + [node name="MinStrongMagnitude" type="HSlider" parent="VBoxContainer" unique_id=1752017132] unique_name_in_owner = true layout_mode = 2 +focus_neighbor_left = NodePath(".") +focus_neighbor_top = NodePath("../MinWeakMagnitude") +focus_neighbor_right = NodePath(".") +focus_neighbor_bottom = NodePath("../../ConfirmButton") +focus_next = NodePath("../../ConfirmButton") +focus_previous = NodePath("../MinWeakMagnitude") max_value = 1.0 step = 0.01 diff --git a/game/src/ui/setup/initial_setup_menu.gd b/game/src/ui/setup/initial_setup_menu.gd new file mode 100644 index 0000000..33f226d --- /dev/null +++ b/game/src/ui/setup/initial_setup_menu.gd @@ -0,0 +1,60 @@ +class_name InitialSetupMenu +extends Control + +signal setup_finished + +@onready var foreground_color: ColorRect = %ForegroundColor +@onready var controller_recommended: Control = %ControllerRecommended +@onready var rhythm_setup_menu: RhythmSetupMenu = %RhythmSetupMenu +@onready var controller_setup_menu: ControllerSetupMenu = %ControllerSetupMenu + + +func _ready() -> void: + rhythm_setup_menu.confirmed.connect(_on_rythm_setup_confirmed) + controller_setup_menu.confirmed.connect(_on_controller_setup_confirmed) + + await get_tree().create_timer(0.5).timeout + controller_recommended.show() + fade_out() + await get_tree().create_timer(4.5).timeout + await fade_in() + controller_recommended.hide() + + controller_setup_menu.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) + 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) + + +func _on_rythm_setup_confirmed() -> void: + rhythm_setup_menu.stop_setup() + await fade_in() + setup_finished.emit() + + +func _on_controller_setup_confirmed() -> void: + await fade_in() + controller_setup_menu.hide() + rhythm_setup_menu.show() + fade_out() + + +func _on_input_method_changed(is_using_controller: bool) -> void: + if is_using_controller: + InputManager.capture_mouse() + else: + InputManager.release_mouse() diff --git a/game/src/ui/setup/initial_setup_menu.gd.uid b/game/src/ui/setup/initial_setup_menu.gd.uid new file mode 100644 index 0000000..71cac86 --- /dev/null +++ b/game/src/ui/setup/initial_setup_menu.gd.uid @@ -0,0 +1 @@ +uid://bp43pnsww6cf5 diff --git a/game/src/ui/setup/initial_setup_menu.tscn b/game/src/ui/setup/initial_setup_menu.tscn new file mode 100644 index 0000000..eed1f4a --- /dev/null +++ b/game/src/ui/setup/initial_setup_menu.tscn @@ -0,0 +1,91 @@ +[gd_scene format=3 uid="uid://8bxv3c5f8d2j"] + +[ext_resource type="Script" uid="uid://bp43pnsww6cf5" path="res://src/ui/setup/initial_setup_menu.gd" id="1_o4tn8"] +[ext_resource type="PackedScene" uid="uid://b41bjano4bw6s" path="res://src/ui/setup/rhythm/rhythm_setup_menu.tscn" id="2_2gigy"] +[ext_resource type="PackedScene" uid="uid://dak6f2xw3mgjj" path="res://src/ui/setup/controller/controller_setup_menu.tscn" id="3_sr5uw"] +[ext_resource type="Texture2D" uid="uid://g85advbc1vrw" path="res://addons/controller_icons/assets/xboxseries/diagram_simple.png" id="4_sr5uw"] + +[node name="InitialSetupMenu" type="Control" unique_id=1302993740] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_o4tn8") +metadata/_custom_type_script = "uid://bp43pnsww6cf5" + +[node name="ColorRect" type="ColorRect" parent="." unique_id=1648891710] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(0, 0, 0, 1) + +[node name="ControllerRecommended" type="Control" parent="." unique_id=167704832] +unique_name_in_owner = true +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="ControllerRecommended" unique_id=684870312] +layout_mode = 1 +anchors_preset = -1 +anchor_left = 0.15 +anchor_top = 0.03 +anchor_right = 0.85 +anchor_bottom = 0.97 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Label" type="Label" parent="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] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="TextureRect" type="TextureRect" parent="ControllerRecommended/VBoxContainer/Control" unique_id=1190977067] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +scale = Vector2(0.85, 0.85) +pivot_offset_ratio = Vector2(0.5, 0.5) +size_flags_vertical = 3 +texture = ExtResource("4_sr5uw") +expand_mode = 1 +stretch_mode = 5 + +[node name="RhythmSetupMenu" parent="." 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")] +unique_name_in_owner = true +process_mode = 4 +visible = false +layout_mode = 1 + +[node name="ForegroundColor" type="ColorRect" parent="." unique_id=1692094271] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(0, 0, 0, 1) diff --git a/game/src/ui/setup/rhythm/rhythm_setup_menu.gd b/game/src/ui/setup/rhythm/rhythm_setup_menu.gd index aeacaaf..af612e5 100644 --- a/game/src/ui/setup/rhythm/rhythm_setup_menu.gd +++ b/game/src/ui/setup/rhythm/rhythm_setup_menu.gd @@ -4,6 +4,7 @@ extends Control signal confirmed var _previous_song_info: SongInfo +var _previous_player: RhythmPlayer var _previous_paused: bool = true var _previous_bpm: float = 120.0 var _previous_beats_per_bar: int = 4 @@ -31,6 +32,12 @@ func close() -> void: confirmed.emit() +func stop_setup() -> void: + rhythm_player.stop() + _restore_song_playback_data() + process_mode = Node.PROCESS_MODE_DISABLED + + func _on_user_offset_slider_value_changed(value: float) -> void: SettingsHandler.set_setting("audio", "user_offset_ms", value, false) SettingsHandler.commit_settings() @@ -40,18 +47,21 @@ func _on_user_offset_slider_value_changed(value: float) -> void: func _on_visibility_changed() -> void: if not is_visible_in_tree(): - rhythm_player.stop() - _restore_song_playback_data() + stop_setup() return + process_mode = Node.PROCESS_MODE_INHERIT + 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)) + user_offset_slider.grab_focus() rhythm_player.play() func _store_song_playback_data() -> void: + _previous_player = RhythmPlayer.active_player _previous_song_info = RhythmPlayer.current_song_info _previous_paused = RhythmPlayer.paused _previous_bpm = RhythmPlayer.bpm @@ -66,6 +76,7 @@ func _store_song_playback_data() -> void: func _restore_song_playback_data() -> void: + RhythmPlayer.active_player = _previous_player RhythmPlayer.current_song_info = _previous_song_info RhythmPlayer.paused = _previous_paused RhythmPlayer.bpm = _previous_bpm diff --git a/game/src/ui/setup/rhythm/rhythm_setup_menu.tscn b/game/src/ui/setup/rhythm/rhythm_setup_menu.tscn index 40cdb0e..15be745 100644 --- a/game/src/ui/setup/rhythm/rhythm_setup_menu.tscn +++ b/game/src/ui/setup/rhythm/rhythm_setup_menu.tscn @@ -4,6 +4,8 @@ [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://co7j2qtqpud6b" path="res://src/core/rhythm/rhythm_listener.gd" id="3_o47te"] [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"] @@ -25,6 +27,32 @@ mouse_filter = 2 script = ExtResource("1_la56f") metadata/_custom_type_script = "uid://bvs4uvpewolwc" +[node name="BeatVibration" type="Node" parent="." unique_id=1560105761] +script = ExtResource("2_yr7ls") +weak_magnitude = 0.5 +strong_magnitude = 0.0 +metadata/_custom_type_script = "uid://bbwtct3hoxwws" + +[node name="BarVibration" type="Node" parent="." unique_id=1199048244] +script = ExtResource("2_yr7ls") +weak_magnitude = 0.9 +strong_magnitude = 0.5 +metadata/_custom_type_script = "uid://bbwtct3hoxwws" + +[node name="RhythmListener" type="Node" parent="." unique_id=1603246008] +script = ExtResource("3_o47te") +metadata/_custom_type_script = "uid://co7j2qtqpud6b" + +[node name="RhythmPlayer" type="Node" parent="." unique_id=326589779] +script = ExtResource("2_jsobq") +song_info = SubResource("Resource_0yond") +audio_player = NodePath("RhythmBeat") +metadata/_custom_type_script = "uid://bdi06itcm6wfp" + +[node name="RhythmBeat" type="AudioStreamPlayer" parent="RhythmPlayer" unique_id=763640763] +unique_name_in_owner = true +stream = ExtResource("2_uupbh") + [node name="UserOffsetSlider" type="HSlider" parent="." unique_id=1070556103] unique_name_in_owner = true layout_mode = 1 @@ -39,6 +67,12 @@ offset_right = 4.0 offset_bottom = 8.0 grow_horizontal = 2 grow_vertical = 2 +focus_neighbor_left = NodePath(".") +focus_neighbor_top = NodePath(".") +focus_neighbor_right = NodePath(".") +focus_neighbor_bottom = NodePath("../Confirm") +focus_next = NodePath("../Confirm") +focus_previous = NodePath(".") min_value = -1000.0 max_value = 1000.0 step = 50.0 @@ -79,18 +113,14 @@ offset_top = -31.0 offset_right = 35.5 grow_horizontal = 2 grow_vertical = 0 +focus_neighbor_left = NodePath(".") +focus_neighbor_top = NodePath("../UserOffsetSlider") +focus_neighbor_right = NodePath(".") +focus_neighbor_bottom = NodePath(".") +focus_next = NodePath(".") +focus_previous = NodePath("../UserOffsetSlider") text = "Confirm" -[node name="RhythmPlayer" type="Node" parent="." unique_id=326589779] -script = ExtResource("2_jsobq") -song_info = SubResource("Resource_0yond") -audio_player = NodePath("RhythmBeat") -metadata/_custom_type_script = "uid://bdi06itcm6wfp" - -[node name="RhythmBeat" type="AudioStreamPlayer" parent="RhythmPlayer" unique_id=763640763] -unique_name_in_owner = true -stream = ExtResource("2_uupbh") - [node name="HBoxContainer" type="HBoxContainer" parent="." unique_id=1857329940] layout_mode = 1 anchors_preset = -1 @@ -124,3 +154,6 @@ texture = ExtResource("6_cribi") [node name="BarTexture" type="TextureRect" parent="HBoxContainer" unique_id=1873889480] 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] diff --git a/game/src/worlds/exposition/exposition.tscn b/game/src/worlds/exposition/exposition.tscn index 8207cc0..4adcaae 100644 --- a/game/src/worlds/exposition/exposition.tscn +++ b/game/src/worlds/exposition/exposition.tscn @@ -29,8 +29,10 @@ sky_material = SubResource("ProceduralSkyMaterial_glp4g") [sub_resource type="Environment" id="Environment_dy1qy"] background_mode = 2 sky = SubResource("Sky_dy1qy") -tonemap_mode = 2 +tonemap_mode = 1 glow_enabled = true +volumetric_fog_enabled = true +volumetric_fog_density = 0.015 [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_gdn1s"] sun_angle_max = 2.93 diff --git a/game/src/worlds/exposition/levels/entrance_hall.tscn b/game/src/worlds/exposition/levels/entrance_hall.tscn index 46e04d7..5ce6c08 100644 --- a/game/src/worlds/exposition/levels/entrance_hall.tscn +++ b/game/src/worlds/exposition/levels/entrance_hall.tscn @@ -5,6 +5,7 @@ [ext_resource type="Material" uid="uid://bahys2ntbh2ap" path="res://assets/dev/orange/orange_01.tres" id="3_4uqqm"] [ext_resource type="Material" uid="uid://biu40ot7f55no" path="res://assets/dev/dark/dark_04.tres" id="4_3ohxo"] [ext_resource type="PackedScene" uid="uid://qvgrds4w5qlk" path="res://_development/ayuroo/_asset_packs/fc_research_tent/interior_props/SM_PaperPile_03_2.glb" id="5_m5411"] +[ext_resource type="Script" uid="uid://briioihkxilxm" path="res://addons/proto_shape/proto_ramp/proto_ramp.gd" id="5_ndl0p"] [ext_resource type="PackedScene" uid="uid://w5f6qhe2k7nt" path="res://_development/ayuroo/_asset_packs/fc_research_tent/interior_props/SM_PaperPile_03_1.glb" id="6_8s83o"] [ext_resource type="PackedScene" uid="uid://dvypbwty4jpw4" path="res://_development/ayuroo/_asset_packs/fc_research_tent/interior_props/SM_PaperPile_03.glb" id="7_45xuj"] [ext_resource type="PackedScene" uid="uid://brudyosqqlxho" path="res://_development/ayuroo/_asset_packs/fc_research_tent/interior_props/SM_CardboardFileBox_02_closed.glb" id="8_hci5i"] @@ -208,10 +209,461 @@ material = ExtResource("4_3ohxo") transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 20.5, 1, 0) [node name="Box" type="CSGBox3D" parent="Blockout/RightWall" unique_id=1541981230] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 9, 0) -size = Vector3(1, 18, 40) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.25, 9, 10.5) +size = Vector3(0.5, 18, 19) material = ExtResource("4_3ohxo") +[node name="Box2" type="CSGBox3D" parent="Blockout/RightWall" unique_id=2127867271] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.25, 9, -10.5) +size = Vector3(0.5, 18, 19) +material = ExtResource("4_3ohxo") + +[node name="Box3" type="CSGBox3D" parent="Blockout/RightWall" unique_id=106387532] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.25, 10, 0) +size = Vector3(0.5, 16, 2) +material = ExtResource("4_3ohxo") + +[node name="CashierCutout1" type="CSGBox3D" parent="Blockout/RightWall" unique_id=1633457175] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.25, 2, 15.5) +operation = 2 +size = Vector3(0.5, 2, 3) +material = ExtResource("4_3ohxo") + +[node name="CashierCutout2" type="CSGBox3D" parent="Blockout/RightWall" unique_id=1355083669] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.25, 2, 11.5) +operation = 2 +size = Vector3(0.5, 2, 3) +material = ExtResource("4_3ohxo") + +[node name="CashierCutout3" type="CSGBox3D" parent="Blockout/RightWall" unique_id=1274344692] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.25, 2, 7.5) +operation = 2 +size = Vector3(0.5, 2, 3) +material = ExtResource("4_3ohxo") + +[node name="Blockout2" type="CSGCombiner3D" parent="." unique_id=881407991] +use_collision = true + +[node name="Elevator" type="CSGCombiner3D" parent="Blockout2" unique_id=1007301746] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 30, 1, -3) + +[node name="Box" type="CSGBox3D" parent="Blockout2/Elevator" unique_id=904715138] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.75, 1.5, 0.5) +size = Vector3(0.5, 13, 7) +material = ExtResource("4_3ohxo") + +[node name="Box2" type="CSGBox3D" parent="Blockout2/Elevator" unique_id=1690847884] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.75, 1.5, 0.5) +size = Vector3(0.5, 13, 7) +material = ExtResource("4_3ohxo") + +[node name="Box3" type="CSGBox3D" parent="Blockout2/Elevator" unique_id=88862552] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.5, 1.5, 3.75) +size = Vector3(6, 13, 0.5) +material = ExtResource("4_3ohxo") + +[node name="Box4" type="CSGBox3D" parent="Blockout2/Elevator" unique_id=1687753604] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.5, 1.5, -2.75) +size = Vector3(6, 13, 0.5) +material = ExtResource("4_3ohxo") + +[node name="GroundDoor" type="CSGBox3D" parent="Blockout2/Elevator" unique_id=116257150] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.5, 1.5, 3.5) +operation = 2 +size = Vector3(3, 3, 1) +material = ExtResource("4_3ohxo") + +[node name="FirstFloorDoor" type="CSGBox3D" parent="Blockout2/Elevator" unique_id=732050395] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.5, 5.5, 3.5) +operation = 2 +size = Vector3(3, 3, 1) +material = ExtResource("4_3ohxo") + +[node name="BasementDoor" type="CSGBox3D" parent="Blockout2/Elevator" unique_id=1448983350] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.5, -3.5, 0.5) +operation = 2 +size = Vector3(3, 3, 7) +material = ExtResource("4_3ohxo") + +[node name="FirstFloor" type="CSGCombiner3D" parent="Blockout2" unique_id=715021161] + +[node name="Floor" type="CSGBox3D" parent="Blockout2/FirstFloor" unique_id=134284258] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 29.75, 0.625, 11.5) +size = Vector3(18.5, 0.75, 17) +material = ExtResource("2_ro4g0") + +[node name="Floor2" type="CSGBox3D" parent="Blockout2/FirstFloor" unique_id=1681550566] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 36.5, 0.625, -8) +size = Vector3(25, 0.75, 22) +material = ExtResource("2_ro4g0") + +[node name="StairCut" type="CSGBox3D" parent="Blockout2/FirstFloor/Floor2" unique_id=2078556517] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5.9, 0, 8.25) +operation = 2 +size = Vector3(5.2000003, 1, 3) +material = ExtResource("2_ro4g0") + +[node name="ElevatorCutout" type="CSGBox3D" parent="Blockout2/FirstFloor" unique_id=121030117] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 27.5, 0.5, -2.5) +operation = 2 +size = Vector3(6, 1, 6) +material = ExtResource("2_ro4g0") + +[node name="Floor3" type="CSGBox3D" parent="Blockout2/FirstFloor" unique_id=886600087] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 22.25, 0.5, -19) +size = Vector3(3.5, 1, 44) +material = ExtResource("2_ro4g0") + +[node name="Floor4" type="CSGBox3D" parent="Blockout2/FirstFloor" unique_id=1797554578] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 20.5, 0.5, 0) +size = Vector3(1, 1, 2) +material = ExtResource("2_ro4g0") + +[node name="Walls" type="CSGCombiner3D" parent="Blockout2/FirstFloor" unique_id=1613988207] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 44, 1, 3) + +[node name="Box" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=508444177] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.5, 2, 8.5) +size = Vector3(1, 4, 17) +material = ExtResource("4_3ohxo") + +[node name="Box2" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=910747972] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.5, 2, -10.5) +size = Vector3(1, 4, 21) +material = ExtResource("4_3ohxo") + +[node name="Box3" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=1598184416] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -0.5, 2, -0.50000024) +size = Vector3(1, 4, 9) +material = ExtResource("4_3ohxo") + +[node name="Box4" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=547008642] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -14.25, 2, 16.5) +size = Vector3(1, 4, 18.5) +material = ExtResource("4_3ohxo") + +[node name="Box5" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=2059171767] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -8.25, 2, 8.5) +size = Vector3(15, 4, 0.5) +material = ExtResource("4_3ohxo") + +[node name="Box7" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=147534768] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -18.75, 2, 8.75) +size = Vector3(14.5, 4, 0.5) +material = ExtResource("4_3ohxo") + +[node name="Box6" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=1293682810] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -16, 2, 1.2499995) +size = Vector3(0.5, 4, 15) +material = ExtResource("4_3ohxo") + +[node name="Box8" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=493828962] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -4.5, 2, -4.75) +size = Vector3(0.5, 4, 11) +material = ExtResource("4_3ohxo") + +[node name="Box9" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=985245633] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -6.5, 2, -9.25) +size = Vector3(0.5, 4, 15) +material = ExtResource("4_3ohxo") + +[node name="Box10" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=1165526015] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -7.5, 2, -21.5) +size = Vector3(1, 4, 25) +material = ExtResource("4_3ohxo") + +[node name="Box11" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=1789713990] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -0.25, 2, -15.25) +size = Vector3(11.5, 4, 0.5) +material = ExtResource("4_3ohxo") + +[node name="Box12" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=690842495] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -13.75, 2, -12.25) +size = Vector3(5.5, 4, 0.5) +material = ExtResource("4_3ohxo") + +[node name="Box13" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=1633634375] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -16.25, 2, -18) +size = Vector3(6, 4, 0.5) +material = ExtResource("4_3ohxo") + +[node name="Box14" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=896734474] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -12.75, 2, -15.25) +size = Vector3(0.5, 4, 6.5) +material = ExtResource("4_3ohxo") + +[node name="Box15" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=100177393] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -9.25, 2, -15.25) +size = Vector3(11.5, 4, 0.5) +material = ExtResource("4_3ohxo") + +[node name="Box16" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=2069465461] +transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -1.25, 2, -7) +size = Vector3(4, 4, 0.5) +material = ExtResource("4_3ohxo") + +[node name="DoorBackEntrance" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=627941822] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 1, -21.5) +operation = 2 +size = Vector3(2, 2, 1.1) +material = ExtResource("4_3ohxo") + +[node name="DoorBroomcloset" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=2114478674] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.5, 1, -9.25) +operation = 2 +size = Vector3(1, 2, 0.5) +material = ExtResource("4_3ohxo") + +[node name="DoorCashiers" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=1858109886] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -21.5, 1, 1.25) +operation = 2 +size = Vector3(1, 2, 1) +material = ExtResource("4_3ohxo") + +[node name="DoorCashiersStorage" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=1515500690] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -18.75, 1, 14.5) +operation = 2 +size = Vector3(0.5, 2, 1) +material = ExtResource("4_3ohxo") + +[node name="DoorStorage1" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=222997830] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8.25, 1, 14) +operation = 2 +size = Vector3(1, 2, 2) +material = ExtResource("4_3ohxo") + +[node name="DoorStorage2" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=896191973] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.5, 1, 1.25) +operation = 2 +size = Vector3(1, 2, 1) +material = ExtResource("4_3ohxo") + +[node name="DoorWardrobe1" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=433589257] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -7.5, 1, -9.25) +operation = 2 +size = Vector3(1, 2, 0.5) +material = ExtResource("4_3ohxo") + +[node name="DoorWardrobe2" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=1306521499] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.25, 1, -16) +operation = 2 +size = Vector3(1, 2, 2) +material = ExtResource("4_3ohxo") + +[node name="DoorHallway" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=429376472] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.25, 1, -7) +operation = 2 +size = Vector3(1, 2, 2) +material = ExtResource("4_3ohxo") + +[node name="DoorWashroom" type="CSGBox3D" parent="Blockout2/FirstFloor/Walls" unique_id=510313348] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -9.25, 1, -19.5) +operation = 2 +size = Vector3(0.5, 2, 1) +material = ExtResource("4_3ohxo") + +[node name="SecondFloor" type="CSGCombiner3D" parent="Blockout2" unique_id=413979186] + +[node name="Floor" type="CSGBox3D" parent="Blockout2/SecondFloor" unique_id=1785516803] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 29.75, 4.75, 11) +size = Vector3(18.5, 0.5, 18) +material = ExtResource("2_ro4g0") + +[node name="Floor2" type="CSGBox3D" parent="Blockout2/SecondFloor" unique_id=1336369407] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 34.25, 4.75, -8) +size = Vector3(27.5, 0.5, 20) +material = ExtResource("2_ro4g0") + +[node name="ElevatorCutout" type="CSGBox3D" parent="Blockout2/SecondFloor" unique_id=1749127075] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 27.5, 4.5, -2.5) +operation = 2 +size = Vector3(6, 1, 6) +material = ExtResource("2_ro4g0") + +[node name="StairCut" type="CSGBox3D" parent="Blockout2/SecondFloor" unique_id=649199003] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 42.4, 4.625, 0.25) +operation = 2 +size = Vector3(5.2000003, 1, 3) +material = ExtResource("2_ro4g0") + +[node name="Walls" type="CSGCombiner3D" parent="Blockout2/SecondFloor" unique_id=6206139] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 44, 1, 3) + +[node name="Box" type="CSGBox3D" parent="Blockout2/SecondFloor/Walls" unique_id=230533424] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.5, 2, 8.5) +size = Vector3(1, 4, 17) +material = ExtResource("4_3ohxo") + +[node name="Basement" type="CSGCombiner3D" parent="Blockout2" unique_id=492170364] + +[node name="Floor" type="CSGBox3D" parent="Blockout2/Basement" unique_id=1263026494] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 35, -4.5, 3) +size = Vector3(28, 1, 34) +material = ExtResource("2_ro4g0") + +[node name="Walls" type="CSGCombiner3D" parent="Blockout2/Basement" unique_id=1934295321] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 44, 1, 3) + +[node name="Box" type="CSGBox3D" parent="Blockout2/Basement/Walls" unique_id=521645691] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.5, -2.85, 8.5) +size = Vector3(1, 4.3, 17) +material = ExtResource("4_3ohxo") + +[node name="StairsGroundFirst" type="CSGCombiner3D" parent="Blockout2" unique_id=50904445] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 39.5, 1, 0.25) + +[node name="ProtoRamp" type="Node3D" parent="Blockout2/StairsGroundFirst" unique_id=1590845627] +transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 0) +script = ExtResource("5_ndl0p") +type = 1 +collisions_enabled = true +width = 3.001 +height = 4.001 +depth = 5.5036000000000005 +anchor = 0 +anchor_fixed = true +fill = 0.05 +material = ExtResource("1_4sesj") +calculation = 0 +steps = 25 +metadata/_custom_type_script = "uid://briioihkxilxm" + +[node name="CSGBox3D" type="CSGBox3D" parent="Blockout2/StairsGroundFirst" unique_id=406454348] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.09, 0.08, 0) +visible = false +size = Vector3(0.18, 0.16, 3) +material = ExtResource("1_4sesj") + +[node name="CSGBox3D2" type="CSGBox3D" parent="Blockout2/StairsGroundFirst" unique_id=627750334] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.27, 0.08, 0) +visible = false +size = Vector3(0.18, 0.16, 3) +material = ExtResource("1_4sesj") + +[node name="LowerCutoff" type="CSGPolygon3D" parent="Blockout2/StairsGroundFirst" unique_id=546956421] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.29999924, 0, 1.5) +visible = false +operation = 2 +polygon = PackedVector2Array(0, 0, 4.2000003, 2.8, 4.2000003, 0, 0, -0.1) +depth = 3.0 +material = ExtResource("1_4sesj") + +[node name="StairsBasementGround" type="CSGCombiner3D" parent="Blockout2" unique_id=435444009] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 38.5, -4, 0.25) + +[node name="ProtoRamp" type="Node3D" parent="Blockout2/StairsBasementGround" unique_id=1321448414] +transform = Transform3D(-4.371139e-08, 0, 1, 0, 1, 0, -1, 0, -4.371139e-08, 0, 0, 0) +script = ExtResource("5_ndl0p") +type = 1 +collisions_enabled = true +width = 3.001 +height = 5.001 +depth = 6.501 +anchor = 0 +anchor_fixed = true +fill = 0.05 +material = ExtResource("1_4sesj") +calculation = 0 +steps = 30 +metadata/_custom_type_script = "uid://briioihkxilxm" + +[node name="CSGBox3D" type="CSGBox3D" parent="Blockout2/StairsBasementGround" unique_id=1095695383] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.15000153, 0.099999905, -0.25) +visible = false +size = Vector3(0.3, 0.2, 3) +material = ExtResource("1_4sesj") + +[node name="CSGBox3D2" type="CSGBox3D" parent="Blockout2/StairsBasementGround" unique_id=868708169] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.45000076, 0.19999981, -0.25) +visible = false +size = Vector3(0.3, 0.4, 3) +material = ExtResource("1_4sesj") + +[node name="CSGBox3D3" type="CSGBox3D" parent="Blockout2/StairsBasementGround" unique_id=422106355] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.75, 0.29999995, -0.25) +visible = false +size = Vector3(0.3, 0.6, 3) +material = ExtResource("1_4sesj") + +[node name="CSGBox3D4" type="CSGBox3D" parent="Blockout2/StairsBasementGround" unique_id=1548003424] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.0499992, 0.39999986, -0.25) +visible = false +size = Vector3(0.3, 0.8, 3) +material = ExtResource("1_4sesj") + +[node name="CSGBox3D5" type="CSGBox3D" parent="Blockout2/StairsBasementGround" unique_id=2089590460] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.3499985, 0.5, -0.25) +visible = false +size = Vector3(0.3, 1, 3) +material = ExtResource("1_4sesj") + +[node name="CSGBox3D6" type="CSGBox3D" parent="Blockout2/StairsBasementGround" unique_id=1289793030] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.6499977, 0.5999999, -0.25) +visible = false +size = Vector3(0.3, 1.2, 3) +material = ExtResource("1_4sesj") + +[node name="CSGBox3D7" type="CSGBox3D" parent="Blockout2/StairsBasementGround" unique_id=386670767] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.949997, 0.6999998, -0.25) +visible = false +size = Vector3(0.3, 1.4, 3) +material = ExtResource("1_4sesj") + +[node name="CSGBox3D8" type="CSGBox3D" parent="Blockout2/StairsBasementGround" unique_id=1074085011] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.2499962, 0.79999995, -0.25) +visible = false +size = Vector3(0.3, 1.6, 3) +material = ExtResource("1_4sesj") + +[node name="CSGBox3D9" type="CSGBox3D" parent="Blockout2/StairsBasementGround" unique_id=1326025129] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.5499954, 0.89999986, -0.25) +visible = false +size = Vector3(0.3, 1.8000001, 3) +material = ExtResource("1_4sesj") + +[node name="CSGBox3D10" type="CSGBox3D" parent="Blockout2/StairsBasementGround" unique_id=479580568] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.8499947, 1, -0.25) +visible = false +size = Vector3(0.3, 2, 3) +material = ExtResource("1_4sesj") + +[node name="CSGBox3D11" type="CSGBox3D" parent="Blockout2/StairsBasementGround" unique_id=1940381184] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.149994, 1.0999999, -0.25) +visible = false +size = Vector3(0.3, 2.2, 3) +material = ExtResource("1_4sesj") + +[node name="CSGBox3D12" type="CSGBox3D" parent="Blockout2/StairsBasementGround" unique_id=769714104] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.4499931, 1.2, -0.25) +visible = false +size = Vector3(0.3, 2.4, 3) +material = ExtResource("1_4sesj") + +[node name="CSGBox3D13" type="CSGBox3D" parent="Blockout2/StairsBasementGround" unique_id=367197121] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.7499924, 1.3000002, -0.25) +visible = false +size = Vector3(0.3, 2.6000001, 3) +material = ExtResource("1_4sesj") + +[node name="CSGBox3D14" type="CSGBox3D" parent="Blockout2/StairsBasementGround" unique_id=1410997967] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.0499916, 1.4000001, -0.25) +visible = false +size = Vector3(0.3, 2.8, 3) +material = ExtResource("1_4sesj") + +[node name="CSGBox3D15" type="CSGBox3D" parent="Blockout2/StairsBasementGround" unique_id=714328024] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.349991, 1.5, -0.25) +visible = false +size = Vector3(0.3, 3, 3) +material = ExtResource("1_4sesj") + +[node name="LowerCutoff" type="CSGPolygon3D" parent="Blockout2/StairsBasementGround" unique_id=921642134] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.29999924, 0, 1.5) +operation = 2 +polygon = PackedVector2Array(0, 0, 4.2000003, 2.8, 4.2000003, 0, 0, -0.1) +depth = 3.0 +material = ExtResource("1_4sesj") + [node name="Props" type="Node3D" parent="." unique_id=1024337945] [node name="godot_plush V2" parent="Props" unique_id=1730647663 instance=ExtResource("13_ro4g0")] @@ -226,57 +678,57 @@ visible = false [node name="godot_plush_02" parent="Props/godot_plush V2" index="2" unique_id=688355995] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.0025618896, 0) -[node name="SM_PaperPile_03_2" parent="Props" unique_id=1345844095 instance=ExtResource("5_m5411")] +[node name="SM_PaperPile_03_2" parent="Props" unique_id=1695162213 instance=ExtResource("5_m5411")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.718074, 1.0000002, 0.91673136) -[node name="SM_PaperPile_03_1" parent="Props" unique_id=1405386528 instance=ExtResource("6_8s83o")] +[node name="SM_PaperPile_03_1" parent="Props" unique_id=1478905191 instance=ExtResource("6_8s83o")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.15694028, 1.0000007, 0.6348417) -[node name="SM_PaperPile_03" parent="Props" unique_id=1152191568 instance=ExtResource("7_45xuj")] +[node name="SM_PaperPile_03" parent="Props" unique_id=810981200 instance=ExtResource("7_45xuj")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.9146078, 1.0000002, 2.7609625) -[node name="SM_CardboardFileBox_02_closed" parent="Props" unique_id=1652579900 instance=ExtResource("8_hci5i")] +[node name="SM_CardboardFileBox_02_closed" parent="Props" unique_id=373561476 instance=ExtResource("8_hci5i")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.817931, 1.0000015, 1.2458999) -[node name="SM_CardboardFileBox_02_open_01" parent="Props" unique_id=893917537 instance=ExtResource("9_hx1l4")] +[node name="SM_CardboardFileBox_02_open_01" parent="Props" unique_id=982447176 instance=ExtResource("9_hx1l4")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.503678, 1.0000011, 2.1690526) -[node name="SM_CardboardFileBox_01_closed" parent="Props" unique_id=1230475848 instance=ExtResource("10_mgf24")] +[node name="SM_CardboardFileBox_01_closed" parent="Props" unique_id=1680044329 instance=ExtResource("10_mgf24")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.4848406, 1.0000011, 1.309094) -[node name="SM_Closet_b1" parent="Props" unique_id=640104480 instance=ExtResource("11_t7ac6")] +[node name="SM_Closet_b1" parent="Props" unique_id=932645688 instance=ExtResource("11_t7ac6")] transform = Transform3D(0.9396926, 0, -0.34202012, 0, 1, 0, 0.34202012, 0, 0.9396926, 1.4325718, 1.0000005, -5.5614686) -[node name="SM_Chair_01" parent="Props" unique_id=438450022 instance=ExtResource("12_ndl0p")] +[node name="SM_Chair_01" parent="Props" unique_id=585144572 instance=ExtResource("12_ndl0p")] transform = Transform3D(0.9396926, 0, -0.34202012, 0, 1, 0, 0.34202012, 0, 0.9396926, 2.9192212, 1.0028769, 3.78964) -[node name="SM_Chair_02" parent="Props" unique_id=1717374755 instance=ExtResource("12_ndl0p")] +[node name="SM_Chair_02" parent="Props" unique_id=1131745202 instance=ExtResource("12_ndl0p")] transform = Transform3D(1, -1.4950173e-08, -6.7055225e-08, -7.450581e-09, -4.1075268e-08, 0.99999994, -1.4950176e-08, -1.0000001, -4.107527e-08, 3.919, 1.35, 1.79) [node name="_TMP" type="Node3D" parent="Props" unique_id=1432658199] -[node name="SM_PaperPile_01" parent="Props/_TMP" unique_id=52655774 instance=ExtResource("14_hx1l4")] +[node name="SM_PaperPile_01" parent="Props/_TMP" unique_id=232556154 instance=ExtResource("14_hx1l4")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.050662, 1.0000005, 1.0565416) -[node name="SM_PaperFilePen_01" parent="Props/_TMP" unique_id=745932442 instance=ExtResource("15_mgf24")] +[node name="SM_PaperFilePen_01" parent="Props/_TMP" unique_id=1592576096 instance=ExtResource("15_mgf24")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.1075568, 1.0017344, 0.21156907) -[node name="SM_PaperPile_02" parent="Props/_TMP" unique_id=1667321464 instance=ExtResource("16_t7ac6")] +[node name="SM_PaperPile_02" parent="Props/_TMP" unique_id=158940895 instance=ExtResource("16_t7ac6")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.8432698, 1.0000005, 0.67616963) -[node name="SM_RadioTelephone_01" parent="Props/_TMP" unique_id=107255587 instance=ExtResource("17_ndl0p")] +[node name="SM_RadioTelephone_01" parent="Props/_TMP" unique_id=1421810066 instance=ExtResource("17_ndl0p")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.0042534, 1.0000005, -1.0021183) -[node name="SM_RadioTelephone_02" parent="Props/_TMP" unique_id=1337907733 instance=ExtResource("17_ndl0p")] +[node name="SM_RadioTelephone_02" parent="Props/_TMP" unique_id=1853225865 instance=ExtResource("17_ndl0p")] transform = Transform3D(0.76604444, 0, 0.6427876, 0, 1, 0, -0.6427876, 0, 0.76604444, 1.596, 2.55, -5.102) -[node name="SM_ComicBooks_02" parent="Props/_TMP" unique_id=1014914008 instance=ExtResource("18_id567")] +[node name="SM_ComicBooks_02" parent="Props/_TMP" unique_id=1329919060 instance=ExtResource("18_id567")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.3010767, 1.0000005, -1.1365142) -[node name="SM_ComicBooks_01" parent="Props/_TMP" unique_id=827009623 instance=ExtResource("19_ngprr")] +[node name="SM_ComicBooks_01" parent="Props/_TMP" unique_id=316670501 instance=ExtResource("19_ngprr")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.2338903, 1.0000005, -1.7645805) -[node name="SM_CerealBox_01" parent="Props/_TMP" unique_id=1966092815 instance=ExtResource("20_dcj1l")] +[node name="SM_CerealBox_01" parent="Props/_TMP" unique_id=1414154509 instance=ExtResource("20_dcj1l")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.1755064, 1.0000006, -2.2027547) [editable path="Props/godot_plush V2"]