diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..d2c0a84 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/contentModel.xml +/modules.xml +/projectSettingsUpdater.xml +/.idea.tgcc.iml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/indexLayout.xml b/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/core/ai/agents/base/ai_base.gd b/core/ai/agents/base/ai_base.gd new file mode 100644 index 0000000..96dcc0d --- /dev/null +++ b/core/ai/agents/base/ai_base.gd @@ -0,0 +1,51 @@ +extends CharacterBody3D + +class_name AIBase + +@export var speed: float = 4.0 +var _enable_state_machine: bool = true +@export var enable_state_machine: bool: + set(value): + _enable_state_machine = value + toggle_enable_state_machine() + get: + return _enable_state_machine + + +@onready var patrol_radius_shape: CollisionShape3D = $%PatrolRadiusShape +@onready var nav_agent: NavigationAgent3D = $%NavigationAgent3D +@onready var state_machine: StateMachine = $%StateMachine + + +func _ready() -> void: + randomize() + toggle_enable_state_machine() + +func toggle_enable_state_machine() -> void: + state_machine.enable = _enable_state_machine + +func _physics_process(delta: float) -> void: + if !_enable_state_machine: + return + + state_machine.physics_process(delta) + + if nav_agent.is_navigation_finished(): + velocity = Vector3.ZERO + move_and_slide() + return + + var next_point = nav_agent.get_next_path_position() + var direction = global_position.direction_to(next_point) + + velocity.x = direction.x * speed + velocity.z = direction.z * speed + + move_and_slide() + +func navigate_to_random_point() -> void: + var nav_map_rid = get_world_3d().get_navigation_map() + var patrol_radius = patrol_radius_shape.shape.radius + var target_point_in_space = global_position + Vector3(randf_range(-1, 1), 0, randf_range(-1, 1)).normalized() * randf_range(0, patrol_radius) + var closest_valid_point = NavigationServer3D.map_get_closest_point(nav_map_rid, target_point_in_space) + nav_agent.target_position = closest_valid_point diff --git a/core/ai/agents/base/ai_base.gd.uid b/core/ai/agents/base/ai_base.gd.uid new file mode 100644 index 0000000..ea72f6d --- /dev/null +++ b/core/ai/agents/base/ai_base.gd.uid @@ -0,0 +1 @@ +uid://b30p1yqojbbbk diff --git a/core/ai/agents/base/ai_base.tscn b/core/ai/agents/base/ai_base.tscn new file mode 100644 index 0000000..2143094 --- /dev/null +++ b/core/ai/agents/base/ai_base.tscn @@ -0,0 +1,44 @@ +[gd_scene format=3 uid="uid://clx701xdwelgx"] + +[ext_resource type="Script" uid="uid://b30p1yqojbbbk" path="res://core/ai/agents/base/ai_base.gd" id="1_4d1nn"] +[ext_resource type="Script" uid="uid://ps3vlu2qvmop" path="res://core/ai/framework/state_machine.gd" id="2_q1hg3"] +[ext_resource type="Script" uid="uid://nga8qx56iwgu" path="res://core/ai/agents/base/idle_state.gd" id="3_26faq"] +[ext_resource type="Script" uid="uid://bngfthvt04ivv" path="res://core/ai/agents/base/patrol_state.gd" id="4_lim44"] + +[sub_resource type="CapsuleMesh" id="CapsuleMesh_mh3lg"] + +[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_mh3lg"] + +[sub_resource type="SphereShape3D" id="SphereShape3D_lim44"] +radius = 20.0 + +[node name="AiBase" type="CharacterBody3D" unique_id=1228675528] +script = ExtResource("1_4d1nn") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=214482161] +mesh = SubResource("CapsuleMesh_mh3lg") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=92811823] +shape = SubResource("CapsuleShape3D_mh3lg") + +[node name="NavigationAgent3D" type="NavigationAgent3D" parent="." unique_id=1370024449] +unique_name_in_owner = true + +[node name="StateMachine" type="Node" parent="." unique_id=1286404264 node_paths=PackedStringArray("initial_state")] +unique_name_in_owner = true +script = ExtResource("2_q1hg3") +initial_state = NodePath("IdleState") + +[node name="IdleState" type="Node" parent="StateMachine" unique_id=763668255] +script = ExtResource("3_26faq") +state_id = &"idle" + +[node name="PatrolState" type="Node" parent="StateMachine" unique_id=2054606629] +script = ExtResource("4_lim44") +state_id = &"patrol" + +[node name="PatrolRadiusShape" type="CollisionShape3D" parent="." unique_id=1379515938] +unique_name_in_owner = true +shape = SubResource("SphereShape3D_lim44") +disabled = true +debug_color = Color(1, 1, 0, 1) diff --git a/core/ai/agents/base/idle_state.gd b/core/ai/agents/base/idle_state.gd new file mode 100644 index 0000000..8e5062b --- /dev/null +++ b/core/ai/agents/base/idle_state.gd @@ -0,0 +1,26 @@ +extends State + +const PATROL_STATE_ID: StringName = &"patrol" + +@export var wait_time: float = 3.0 + +var runtime_timer: Timer + +func enter() -> void: + runtime_timer = Timer.new() + runtime_timer.name = "IdleTimer" + add_child(runtime_timer) + runtime_timer.one_shot = true + runtime_timer.timeout.connect(_on_timer_timeout) + runtime_timer.start(wait_time) + +func exit() -> void: + if runtime_timer: + if runtime_timer.is_connected("timeout", _on_timer_timeout): + runtime_timer.timeout.disconnect(_on_timer_timeout) + + runtime_timer.queue_free() + runtime_timer = null + +func _on_timer_timeout() -> void: + transitioned.emit(self, PATROL_STATE_ID) diff --git a/core/ai/agents/base/idle_state.gd.uid b/core/ai/agents/base/idle_state.gd.uid new file mode 100644 index 0000000..41fe475 --- /dev/null +++ b/core/ai/agents/base/idle_state.gd.uid @@ -0,0 +1 @@ +uid://nga8qx56iwgu diff --git a/core/ai/agents/base/patrol_state.gd b/core/ai/agents/base/patrol_state.gd new file mode 100644 index 0000000..0a1fdd7 --- /dev/null +++ b/core/ai/agents/base/patrol_state.gd @@ -0,0 +1,12 @@ +extends State + +const IDLE_STATE_ID: StringName = &"idle" + +@onready var agent: AIBase = owner + +func enter() -> void: + agent.navigate_to_random_point() + +func physics_update(_delta) -> void: + if agent.nav_agent.is_navigation_finished(): + transitioned.emit(self, IDLE_STATE_ID) diff --git a/core/ai/agents/base/patrol_state.gd.uid b/core/ai/agents/base/patrol_state.gd.uid new file mode 100644 index 0000000..4bdcccd --- /dev/null +++ b/core/ai/agents/base/patrol_state.gd.uid @@ -0,0 +1 @@ +uid://bngfthvt04ivv diff --git a/core/ai/framework/state.gd b/core/ai/framework/state.gd new file mode 100644 index 0000000..b24ae72 --- /dev/null +++ b/core/ai/framework/state.gd @@ -0,0 +1,20 @@ +extends Node + +class_name State + +@export var state_id: StringName = &"" + +@warning_ignore("unused_signal") +signal transitioned(state: State, new_state_id: StringName) + +func enter() -> void: + pass + +func exit() -> void: + pass + +func update(_delta) -> void: + pass + +func physics_update(_delta) -> void: + pass diff --git a/core/ai/framework/state.gd.uid b/core/ai/framework/state.gd.uid new file mode 100644 index 0000000..7f2faac --- /dev/null +++ b/core/ai/framework/state.gd.uid @@ -0,0 +1 @@ +uid://dpso7abi5ftyw diff --git a/core/ai/framework/state_machine.gd b/core/ai/framework/state_machine.gd new file mode 100644 index 0000000..0a91f3d --- /dev/null +++ b/core/ai/framework/state_machine.gd @@ -0,0 +1,61 @@ +extends Node + +class_name StateMachine + +@export var initial_state: State + +var current_state: State +var states: Dictionary[StringName, State] = {} +var is_initialized: bool = false +var _enabled: bool = true +var enable: bool: + set(value): + _enabled = value + _set_enabled(value) + get: + return _enabled + +func _ready() -> void: + _initialize_states() + _set_enabled(enable) + +func _initialize_states() -> void: + if is_initialized: + return + + for state in get_children(): + if state is State: + states[state.state_id] = state + state.transitioned.connect(_on_state_transition) + + is_initialized = true + +func _set_enabled(value: bool) -> void: + _enabled = value + + if not _enabled: + return + + _initialize_states() + + if initial_state and current_state == null: + current_state = initial_state + current_state.enter() + +func physics_process(delta) -> void: + if current_state and _enabled: + current_state.physics_update(delta) + +func _on_state_transition(state: State, new_state_id: StringName) -> void: + if state != current_state: + return + + var new_state = states.get(new_state_id) + if not new_state: + return + + if current_state: + current_state.exit() + + current_state = new_state + current_state.enter() diff --git a/core/ai/framework/state_machine.gd.uid b/core/ai/framework/state_machine.gd.uid new file mode 100644 index 0000000..fc3d12e --- /dev/null +++ b/core/ai/framework/state_machine.gd.uid @@ -0,0 +1 @@ +uid://ps3vlu2qvmop diff --git a/core/audio/audio_manager.gd b/core/audio/audio_manager.gd new file mode 100644 index 0000000..2d0a6f0 --- /dev/null +++ b/core/audio/audio_manager.gd @@ -0,0 +1,31 @@ +extends Node + +const MIN_VOLUME: float = 0.0 +const MAX_VOLUME: float = 1.0 + +func _ready() -> void: + load_save_data() + +func load_save_data() -> void: + for bus_name in GameState.save_data.audio_bus_volumes: + _apply_audio_bus_volume(bus_name, GameState.save_data.audio_bus_volumes[bus_name]) + +func set_audio_bus_volume(bus_name: StringName, linear_value: float) -> void: + var normalized_bus_name := str(bus_name) + var clamped_value := clampf(linear_value, MIN_VOLUME, MAX_VOLUME) + + GameState.save_data.audio_bus_volumes[normalized_bus_name] = clamped_value + _apply_audio_bus_volume(normalized_bus_name, clamped_value) + GameState.save_game() + +func get_audio_bus_volume(bus_name: StringName, default_value: float = 1.0) -> float: + return float(GameState.save_data.audio_bus_volumes.get(str(bus_name), default_value)) + +func _apply_audio_bus_volume(bus_name: String, linear_value: float) -> void: + var bus_index := AudioServer.get_bus_index(bus_name) + if bus_index == -1: + return + + var clamped_value := clampf(linear_value, MIN_VOLUME, MAX_VOLUME) + AudioServer.set_bus_volume_db(bus_index, linear_to_db(clamped_value)) + AudioServer.set_bus_mute(bus_index, is_zero_approx(clamped_value)) diff --git a/core/audio/audio_manager.gd.uid b/core/audio/audio_manager.gd.uid new file mode 100644 index 0000000..5d5a0c2 --- /dev/null +++ b/core/audio/audio_manager.gd.uid @@ -0,0 +1 @@ +uid://dcttbbavtwtsg diff --git a/core/audio/settings/audio_option.gd b/core/audio/settings/audio_option.gd new file mode 100644 index 0000000..1c386ff --- /dev/null +++ b/core/audio/settings/audio_option.gd @@ -0,0 +1,56 @@ +extends VBoxContainer + +class_name AudioOption + +const MIN_VOLUME: float = 0.0 +const MAX_VOLUME: float = 1.0 + +@export var bus_name: StringName = &"Master" +@export var label_text: String = "Master Volume" +@export_range(0.0, 1.0, 0.01) var default_volume: float = 1.0 + +@onready var label: Label = $Label +@onready var slider: HSlider = $HSlider + +func _ready() -> void: + slider.min_value = MIN_VOLUME + slider.max_value = MAX_VOLUME + slider.step = 0.01 + slider.value_changed.connect(_on_slider_value_changed) + refresh() + +func refresh() -> void: + label.text = label_text + + if not has_bus(): + slider.set_value_no_signal(default_volume) + slider.editable = false + label.text = "%s (bus missing)" % label_text + return + + slider.editable = true + var saved_volume := AudioManager.get_audio_bus_volume(bus_name, default_volume) + slider.set_value_no_signal(saved_volume) + apply_current_value() + +func reset_to_default() -> void: + slider.value = default_volume + +func apply_current_value() -> void: + _set_bus_volume(slider.value) + +func has_bus() -> bool: + return get_bus_index() != -1 + +func get_bus_index() -> int: + return AudioServer.get_bus_index(bus_name) + +func _set_bus_volume(linear_value: float) -> void: + if not has_bus(): + return + + var clamped_value := clampf(linear_value, MIN_VOLUME, MAX_VOLUME) + AudioManager.set_audio_bus_volume(bus_name, clamped_value) + +func _on_slider_value_changed(value: float) -> void: + _set_bus_volume(value) diff --git a/core/audio/settings/audio_option.gd.uid b/core/audio/settings/audio_option.gd.uid new file mode 100644 index 0000000..97b1806 --- /dev/null +++ b/core/audio/settings/audio_option.gd.uid @@ -0,0 +1 @@ +uid://bnh1y560h55vc diff --git a/core/audio/settings/audio_option.tscn b/core/audio/settings/audio_option.tscn new file mode 100644 index 0000000..c339962 --- /dev/null +++ b/core/audio/settings/audio_option.tscn @@ -0,0 +1,14 @@ +[gd_scene format=3 uid="uid://cescrovsjlwke"] + +[ext_resource type="Script" uid="uid://bnh1y560h55vc" path="res://core/audio/settings/audio_option.gd" id="1_orafl"] + +[node name="AudioOption" type="VBoxContainer" unique_id=1509773712] +custom_minimum_size = Vector2(300, 0) +script = ExtResource("1_orafl") + +[node name="Label" type="Label" parent="." unique_id=781845786] +layout_mode = 2 +text = "Master Volume" + +[node name="HSlider" type="HSlider" parent="." unique_id=1286896253] +layout_mode = 2 diff --git a/core/audio/settings/settings_menu.gd b/core/audio/settings/settings_menu.gd new file mode 100644 index 0000000..ea9501e --- /dev/null +++ b/core/audio/settings/settings_menu.gd @@ -0,0 +1,36 @@ +extends Control + +class_name SettingsMenu + +@onready var audio_options_container: VBoxContainer = $%AudioOptionsContainer +@onready var reset_button: Button = $%ResetToDefault_Button +@onready var close_button: Button = $%Close_Button + +func _ready() -> void: + reset_button.pressed.connect(_on_reset_to_default_button_pressed) + close_button.pressed.connect(_on_close_button_pressed) + _refresh_audio_options() + +func _get_audio_options() -> Array[AudioOption]: + var audio_options: Array[AudioOption] = [] + + for child in audio_options_container.get_children(): + if child is AudioOption: + audio_options.append(child) + + return audio_options + +func _refresh_audio_options() -> void: + for audio_option in _get_audio_options(): + audio_option.refresh() + +func _apply_current_audio_values() -> void: + for audio_option in _get_audio_options(): + audio_option.apply_current_value() + +func _on_reset_to_default_button_pressed() -> void: + for audio_option in _get_audio_options(): + audio_option.reset_to_default() + +func _on_close_button_pressed() -> void: + visible = false diff --git a/core/audio/settings/settings_menu.gd.uid b/core/audio/settings/settings_menu.gd.uid new file mode 100644 index 0000000..e0d0e1c --- /dev/null +++ b/core/audio/settings/settings_menu.gd.uid @@ -0,0 +1 @@ +uid://cvr25q1blyxg diff --git a/core/audio/settings/settings_menu.tscn b/core/audio/settings/settings_menu.tscn new file mode 100644 index 0000000..8143580 --- /dev/null +++ b/core/audio/settings/settings_menu.tscn @@ -0,0 +1,74 @@ +[gd_scene format=3 uid="uid://caqf471x0kttc"] + +[ext_resource type="Script" uid="uid://cvr25q1blyxg" path="res://core/audio/settings/settings_menu.gd" id="1_4lekq"] +[ext_resource type="PackedScene" uid="uid://cescrovsjlwke" path="res://core/audio/settings/audio_option.tscn" id="1_hwcco"] + +[node name="SettingsMenu" type="Control" unique_id=1639777294] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_4lekq") + +[node name="PanelContainer" type="PanelContainer" parent="." unique_id=315821242] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -79.5 +offset_top = -110.0 +offset_right = 79.5 +offset_bottom = 110.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="MarginContainer" type="MarginContainer" parent="PanelContainer" unique_id=648635784] +layout_mode = 2 +size_flags_vertical = 0 +theme_override_constants/margin_left = 12 +theme_override_constants/margin_top = 12 +theme_override_constants/margin_right = 12 +theme_override_constants/margin_bottom = 12 + +[node name="AudioOptionsContainer" type="VBoxContainer" parent="PanelContainer/MarginContainer" unique_id=824023653] +unique_name_in_owner = true +layout_mode = 2 +theme_override_constants/separation = 12 + +[node name="MasterVolume_AudioOption" parent="PanelContainer/MarginContainer/AudioOptionsContainer" unique_id=1509773712 instance=ExtResource("1_hwcco")] +layout_mode = 2 + +[node name="HSeparator" type="HSeparator" parent="PanelContainer/MarginContainer/AudioOptionsContainer" unique_id=1053430754] +layout_mode = 2 + +[node name="MusicVolume_AudioOption" parent="PanelContainer/MarginContainer/AudioOptionsContainer" unique_id=690924616 instance=ExtResource("1_hwcco")] +layout_mode = 2 +bus_name = &"Music" +label_text = "Music Volume" + +[node name="HSeparator2" type="HSeparator" parent="PanelContainer/MarginContainer/AudioOptionsContainer" unique_id=453716295] +layout_mode = 2 + +[node name="SFXVolume_AudioOption" parent="PanelContainer/MarginContainer/AudioOptionsContainer" unique_id=2096291127 instance=ExtResource("1_hwcco")] +layout_mode = 2 +bus_name = &"SFX" +label_text = "SFX Volume" + +[node name="HSeparator3" type="HSeparator" parent="PanelContainer/MarginContainer/AudioOptionsContainer" unique_id=498553283] +layout_mode = 2 + +[node name="ResetToDefault_Button" type="Button" parent="PanelContainer/MarginContainer/AudioOptionsContainer" unique_id=720420423] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 0 +text = "Reset To Default" + +[node name="Close_Button" type="Button" parent="PanelContainer/MarginContainer/AudioOptionsContainer" unique_id=1137906684] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 0 +text = "Close" diff --git a/core/game_state/game_state.gd b/core/game_state/game_state.gd new file mode 100644 index 0000000..ffe6322 --- /dev/null +++ b/core/game_state/game_state.gd @@ -0,0 +1,32 @@ +extends Node + +const SAVE_PATH: String = "user://savegame.json" + +var save_data: SaveGameData = SaveGameData.new() +var is_loaded: bool = false + +func _ready() -> void: + load_game() + +func save_game() -> void: + var save_file = FileAccess.open(SAVE_PATH, FileAccess.WRITE) + var json_string = JSON.stringify(save_data.to_dictionary()) + save_file.store_line(json_string) + +func load_game() -> void: + if not FileAccess.file_exists(SAVE_PATH): + save_data = SaveGameData.new() + is_loaded = true + return + + var file = FileAccess.open(SAVE_PATH, FileAccess.READ) + var json_string = file.get_as_text() + + var json = JSON.new() + var parse_result = json.parse(json_string) + + save_data = SaveGameData.new() + if parse_result == OK and json.data is Dictionary: + save_data = SaveGameData.from_dictionary(json.data) + + is_loaded = true diff --git a/core/game_state/game_state.gd.uid b/core/game_state/game_state.gd.uid new file mode 100644 index 0000000..8f8015c --- /dev/null +++ b/core/game_state/game_state.gd.uid @@ -0,0 +1 @@ +uid://b17g2w2g101o6 diff --git a/core/game_state/save_game_data.gd b/core/game_state/save_game_data.gd new file mode 100644 index 0000000..8a1cf10 --- /dev/null +++ b/core/game_state/save_game_data.gd @@ -0,0 +1,34 @@ +class_name SaveGameData +extends Resource + +var unlocked_collectibles_ids: Array[StringName] = [] +var saved_photos: Array[String] = [] +var audio_bus_volumes: Dictionary[String, float] = {} + +func to_dictionary() -> Dictionary: + var serialized_collectible_ids: Array[String] = [] + for collectible_id in unlocked_collectibles_ids: + serialized_collectible_ids.append(str(collectible_id)) + + return { + "unlocked_collectibles_ids": serialized_collectible_ids, + "saved_photos": saved_photos, + "audio_bus_volumes": audio_bus_volumes, + } + +static func from_dictionary(data: Dictionary) -> SaveGameData: + var save_game_data := SaveGameData.new() + + if data.has("unlocked_collectibles_ids"): + for collectible_id in data["unlocked_collectibles_ids"]: + save_game_data.unlocked_collectibles_ids.append(StringName(str(collectible_id))) + + if data.has("saved_photos"): + for photo_path in data["saved_photos"]: + save_game_data.saved_photos.append(str(photo_path)) + + if data.has("audio_bus_volumes") and data["audio_bus_volumes"] is Dictionary: + for bus_name in data["audio_bus_volumes"]: + save_game_data.audio_bus_volumes[str(bus_name)] = float(data["audio_bus_volumes"][bus_name]) + + return save_game_data diff --git a/core/game_state/save_game_data.gd.uid b/core/game_state/save_game_data.gd.uid new file mode 100644 index 0000000..b994a29 --- /dev/null +++ b/core/game_state/save_game_data.gd.uid @@ -0,0 +1 @@ +uid://bxmvs842r82vl diff --git a/core/photo_mode/data/collectible_library.gd b/core/photo_mode/data/collectible_library.gd new file mode 100644 index 0000000..7aede1f --- /dev/null +++ b/core/photo_mode/data/collectible_library.gd @@ -0,0 +1,4 @@ +class_name CollectibleLibrary +extends Resource + +@export var collectibles: Array[CollectibleResource] diff --git a/core/photo_mode/data/collectible_library.gd.uid b/core/photo_mode/data/collectible_library.gd.uid new file mode 100644 index 0000000..4a5e341 --- /dev/null +++ b/core/photo_mode/data/collectible_library.gd.uid @@ -0,0 +1 @@ +uid://hhuufh87skq5 diff --git a/core/photo_mode/data/collectible_library.tres b/core/photo_mode/data/collectible_library.tres new file mode 100644 index 0000000..0ee1fe2 --- /dev/null +++ b/core/photo_mode/data/collectible_library.tres @@ -0,0 +1,31 @@ +[gd_resource type="Resource" script_class="CollectibleLibrary" format=3 uid="uid://c6pkpvsvimafb"] + +[ext_resource type="Script" uid="uid://bj34o0org55ei" path="res://core/photo_mode/data/collectible_resource.gd" id="1_3cgvf"] +[ext_resource type="Script" uid="uid://hhuufh87skq5" path="res://core/photo_mode/data/collectible_library.gd" id="2_ggu10"] +[ext_resource type="Texture2D" uid="uid://cx8d233y32kmu" path="res://icon.svg" id="2_pxmdy"] + +[sub_resource type="Resource" id="Resource_3cgvf"] +script = ExtResource("1_3cgvf") +id = &"cane" +title = "Cane" +image = ExtResource("2_pxmdy") +metadata/_custom_type_script = "uid://bj34o0org55ei" + +[sub_resource type="Resource" id="Resource_ggu10"] +script = ExtResource("1_3cgvf") +id = &"gatto" +title = "Gatto" +image = ExtResource("2_pxmdy") +metadata/_custom_type_script = "uid://bj34o0org55ei" + +[sub_resource type="Resource" id="Resource_pxmdy"] +script = ExtResource("1_3cgvf") +id = &"farfalla" +title = "Farfalla" +image = ExtResource("2_pxmdy") +metadata/_custom_type_script = "uid://bj34o0org55ei" + +[resource] +script = ExtResource("2_ggu10") +collectibles = Array[ExtResource("1_3cgvf")]([SubResource("Resource_3cgvf"), SubResource("Resource_ggu10"), SubResource("Resource_pxmdy")]) +metadata/_custom_type_script = "uid://hhuufh87skq5" diff --git a/core/photo_mode/data/collectible_resource.gd b/core/photo_mode/data/collectible_resource.gd new file mode 100644 index 0000000..90e2d4d --- /dev/null +++ b/core/photo_mode/data/collectible_resource.gd @@ -0,0 +1,6 @@ +class_name CollectibleResource +extends Resource + +@export var id: StringName +@export var title: String +@export var image: Texture2D diff --git a/core/photo_mode/data/collectible_resource.gd.uid b/core/photo_mode/data/collectible_resource.gd.uid new file mode 100644 index 0000000..698ed09 --- /dev/null +++ b/core/photo_mode/data/collectible_resource.gd.uid @@ -0,0 +1 @@ +uid://bj34o0org55ei diff --git a/core/photo_mode/managers/collection_manager.gd b/core/photo_mode/managers/collection_manager.gd new file mode 100644 index 0000000..193b28a --- /dev/null +++ b/core/photo_mode/managers/collection_manager.gd @@ -0,0 +1,60 @@ +extends Node + +signal on_collectible_unlocked(collectible_id: StringName) +signal on_photo_saved(filePath: String) + +var collectibles_library: CollectibleLibrary = preload("res://core/photo_mode/data/collectible_library.tres") + +var unlocked_collectibles_ids: Array[StringName] = [] +var saved_photos: Array[String] = [] + +func _ready() -> void: + load_save_data() + +func unlock_collectible(collectible_id: StringName) -> void: + if not collectible_id in unlocked_collectibles_ids: + var new_collectible = get_collectible_by_id(collectible_id) + if new_collectible: + unlocked_collectibles_ids.append(collectible_id) + sync_save_data() + on_collectible_unlocked.emit(collectible_id) + +func get_collectible_by_id(id: StringName) -> CollectibleResource: + for collectible in collectibles_library.collectibles: + if collectible.id == id: + return collectible + return null + +func get_all_collectibles() -> Array[CollectibleResource]: + return collectibles_library.collectibles + +func get_unlocked_collectible_ids() -> Array[StringName]: + return unlocked_collectibles_ids + +func save_photo_to_disk_async() -> void: + await RenderingServer.frame_post_draw + var image = get_viewport().get_texture().get_image() + + if not DirAccess.dir_exists_absolute("user://photos"): + DirAccess.make_dir_absolute("user://photos") + + var timestamp = str(Time.get_unix_time_from_system()) + var file_path = "user://photos/photo_" + timestamp + ".png" + image.save_png(file_path) + + saved_photos.append(file_path) + sync_save_data() + on_photo_saved.emit(file_path) + +func sync_save_data() -> void: + GameState.save_data.unlocked_collectibles_ids = unlocked_collectibles_ids.duplicate() + GameState.save_data.saved_photos = saved_photos.duplicate() + +func load_save_data() -> void: + unlocked_collectibles_ids = GameState.save_data.unlocked_collectibles_ids.duplicate() + saved_photos = GameState.save_data.saved_photos.duplicate() + + if unlocked_collectibles_ids.is_empty() and saved_photos.is_empty(): + unlocked_collectibles_ids.append(&"cane") + + sync_save_data() diff --git a/core/photo_mode/managers/collection_manager.gd.uid b/core/photo_mode/managers/collection_manager.gd.uid new file mode 100644 index 0000000..39979fc --- /dev/null +++ b/core/photo_mode/managers/collection_manager.gd.uid @@ -0,0 +1 @@ +uid://c3kq1qddpm8tf diff --git a/core/photo_mode/runtime/collectible.gd b/core/photo_mode/runtime/collectible.gd new file mode 100644 index 0000000..08772f7 --- /dev/null +++ b/core/photo_mode/runtime/collectible.gd @@ -0,0 +1,6 @@ +extends Area3D + +@export var collectible_data: CollectibleResource + +func _ready() -> void: + add_to_group("collectible") diff --git a/core/photo_mode/runtime/collectible.gd.uid b/core/photo_mode/runtime/collectible.gd.uid new file mode 100644 index 0000000..3f51b53 --- /dev/null +++ b/core/photo_mode/runtime/collectible.gd.uid @@ -0,0 +1 @@ +uid://62d14boivr3g diff --git a/core/photo_mode/runtime/collectible.tscn b/core/photo_mode/runtime/collectible.tscn new file mode 100644 index 0000000..12b1c10 --- /dev/null +++ b/core/photo_mode/runtime/collectible.tscn @@ -0,0 +1,11 @@ +[gd_scene format=3 uid="uid://bmkxt6btcx8qr"] + +[ext_resource type="Script" uid="uid://62d14boivr3g" path="res://core/photo_mode/runtime/collectible.gd" id="1_xse8c"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_xse8c"] + +[node name="Collectible" type="Area3D" unique_id=1229019813] +script = ExtResource("1_xse8c") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=1479480920] +shape = SubResource("BoxShape3D_xse8c") diff --git a/core/photo_mode/runtime/photo_mode_controller.gd b/core/photo_mode/runtime/photo_mode_controller.gd new file mode 100644 index 0000000..d28d40d --- /dev/null +++ b/core/photo_mode/runtime/photo_mode_controller.gd @@ -0,0 +1,94 @@ +extends Node3D + +@export_group("Speed") +@export var pan_speed: float = 5.0 +@export var rotation_speed: float = 0.003 + +@export_group("Bounds") +@export var movement_bounds: AABB + +@export_group("Ref") +@export var rotation_target: Node3D + +@onready var camera: Camera3D = $%Camera3D + +var total_yaw: float = 0.0 +var total_pitch: float = 0.0 +var orbit_distance: float = 0.0 +var current_pan: Vector2 = Vector2.ZERO +var is_active: bool = false + +func _ready() -> void: + total_yaw = global_rotation.y + total_pitch = global_rotation.x + + if rotation_target: + orbit_distance = global_position.distance_to(rotation_target.global_position) + +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed("toggle_photo_mode"): + is_active = !is_active + + get_tree().paused = is_active + + if !is_active: + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + else: + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + + if event is InputEventMouseMotion and is_active: + total_yaw -= event.relative.x * rotation_speed + + if event.is_action_pressed("take_photo"): + take_photo_async() + +func _process(delta: float) -> void: + if not rotation_target: + return + + + var pan_input = Input.get_vector("photo_pan_left", "photo_pan_right", "photo_pan_up", "photo_pan_down") + var rot_basis = Basis.from_euler(Vector3(total_pitch, total_yaw, 0)) + + if pan_input != Vector2.ZERO and is_active: + current_pan.x += pan_input.x * pan_speed * delta + current_pan.y += -pan_input.y * pan_speed * delta + + if movement_bounds.size != Vector3.ZERO: + current_pan.x = clampf(current_pan.x, movement_bounds.position.x, movement_bounds.position.x + movement_bounds.size.x) + current_pan.y = clampf(current_pan.y, movement_bounds.position.y, movement_bounds.position.y + movement_bounds.size.y) + + var right_dir = rot_basis.x.normalized() + var up_dir = rot_basis.y.normalized() + + var final_pan_offset = (right_dir * current_pan.x) + (up_dir * current_pan.y) + + var orbit_pos = rotation_target.global_position + (rot_basis * Vector3(0, 0, orbit_distance)) + + global_position = orbit_pos + final_pan_offset + global_basis = rot_basis + +func take_photo_async() -> void: + if !is_active: + return + + var targets = get_tree().get_nodes_in_group("collectible") + var space_state = get_world_3d().direct_space_state + + await CollectionManager.save_photo_to_disk_async() + + for target in targets: + if not target.collectible_data: + continue + + if camera.is_position_in_frustum(target.global_position): + var query = PhysicsRayQueryParameters3D.create(camera.global_position, target.global_position) + query.collide_with_areas = true + query.collide_with_bodies = true + + var result = space_state.intersect_ray(query) + + if result and result.collider == target: + CollectionManager.unlock_collectible(target.collectible_data.id) + + GameState.save_game() diff --git a/core/photo_mode/runtime/photo_mode_controller.gd.uid b/core/photo_mode/runtime/photo_mode_controller.gd.uid new file mode 100644 index 0000000..aba9819 --- /dev/null +++ b/core/photo_mode/runtime/photo_mode_controller.gd.uid @@ -0,0 +1 @@ +uid://d7ln6iru6mq6 diff --git a/core/photo_mode/runtime/photo_mode_controller.tscn b/core/photo_mode/runtime/photo_mode_controller.tscn new file mode 100644 index 0000000..d048e34 --- /dev/null +++ b/core/photo_mode/runtime/photo_mode_controller.tscn @@ -0,0 +1,10 @@ +[gd_scene format=3 uid="uid://vni5kjalum6d"] + +[ext_resource type="Script" uid="uid://d7ln6iru6mq6" path="res://core/photo_mode/runtime/photo_mode_controller.gd" id="1_uhpya"] + +[node name="PhotoModeController" type="Node3D" unique_id=695158870] +process_mode = 3 +script = ExtResource("1_uhpya") + +[node name="Camera3D" type="Camera3D" parent="." unique_id=1369039645] +unique_name_in_owner = true diff --git a/core/photo_mode/ui/collectible_gallery.gd b/core/photo_mode/ui/collectible_gallery.gd new file mode 100644 index 0000000..ea1a87b --- /dev/null +++ b/core/photo_mode/ui/collectible_gallery.gd @@ -0,0 +1,34 @@ +extends Control + +@export var collectible_ui_scene: PackedScene + +@onready var grid_container: GridContainer = $%CollectibleGrid + +func _ready() -> void: + CollectionManager.on_collectible_unlocked.connect(_unlock_collectible) + setup() + +func setup() -> void: + var unlocked_collectible_ids = CollectionManager.get_unlocked_collectible_ids() + var collectibles = CollectionManager.get_all_collectibles() + + for child in grid_container.get_children(): + child.queue_free() + + for collectible in collectibles: + _add_collectible(collectible) + if unlocked_collectible_ids.has(collectible.id): + _unlock_collectible(collectible.id) + +func on_collectible_unlocked(collectible_id: StringName) -> void: + _unlock_collectible(collectible_id) + +func _add_collectible(collectible: CollectibleResource) -> void: + var collectible_ui: CollectibleUI = collectible_ui_scene.instantiate() + collectible_ui.setup(collectible) + grid_container.add_child(collectible_ui) + +func _unlock_collectible(collectible_id: StringName) -> void: + for collectible_ui in grid_container.get_children(): + if collectible_ui.collectible_resource.id == collectible_id: + collectible_ui.unlock() diff --git a/core/photo_mode/ui/collectible_gallery.gd.uid b/core/photo_mode/ui/collectible_gallery.gd.uid new file mode 100644 index 0000000..2ec65a4 --- /dev/null +++ b/core/photo_mode/ui/collectible_gallery.gd.uid @@ -0,0 +1 @@ +uid://dq3qtcrdnikl7 diff --git a/core/photo_mode/ui/collectible_gallery.tscn b/core/photo_mode/ui/collectible_gallery.tscn new file mode 100644 index 0000000..27851d6 --- /dev/null +++ b/core/photo_mode/ui/collectible_gallery.tscn @@ -0,0 +1,50 @@ +[gd_scene format=3 uid="uid://bvw086glfpcba"] + +[ext_resource type="Script" uid="uid://dq3qtcrdnikl7" path="res://core/photo_mode/ui/collectible_gallery.gd" id="1_67tug"] +[ext_resource type="PackedScene" uid="uid://dp7dvfauh5rpx" path="res://core/photo_mode/ui/collectible_ui.tscn" id="2_or234"] + +[node name="CollectibleGallery" type="Control" unique_id=354419843] +layout_mode = 3 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_67tug") +collectible_ui_scene = ExtResource("2_or234") + +[node name="PanelContainer" type="PanelContainer" parent="." unique_id=640179265] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -350.0 +offset_top = -350.0 +offset_right = 350.0 +offset_bottom = 350.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="MarginContainer" type="MarginContainer" parent="PanelContainer" unique_id=125147979] +layout_mode = 2 +theme_override_constants/margin_left = 12 +theme_override_constants/margin_top = 12 +theme_override_constants/margin_right = 12 +theme_override_constants/margin_bottom = 12 + +[node name="ScrollContainer" type="ScrollContainer" parent="PanelContainer/MarginContainer" unique_id=348576028] +layout_mode = 2 +draw_focus_border = true + +[node name="CollectibleGrid" type="GridContainer" parent="PanelContainer/MarginContainer/ScrollContainer" unique_id=1187865988] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 6 +size_flags_vertical = 2 +theme_override_constants/h_separation = 12 +theme_override_constants/v_separation = 12 +columns = 3 diff --git a/core/photo_mode/ui/collectible_ui.gd b/core/photo_mode/ui/collectible_ui.gd new file mode 100644 index 0000000..453f528 --- /dev/null +++ b/core/photo_mode/ui/collectible_ui.gd @@ -0,0 +1,22 @@ +extends Control + +class_name CollectibleUI + +@onready var label: Label = $%CollectibleName +@onready var texture_rect: TextureRect = $%CollectibleTexture +var collectible_resource: CollectibleResource + +func setup(collectible: CollectibleResource) -> void: + collectible_resource = collectible + if !label: + label = $%CollectibleName + label.text = collectible_resource.title + if collectible.image: + if !texture_rect: + texture_rect = $%CollectibleTexture + texture_rect.texture = collectible_resource.image + +func unlock() -> void: + if !texture_rect: + texture_rect = $%CollectibleTexture + texture_rect.set_modulate(Color(1,1,1,1)) diff --git a/core/photo_mode/ui/collectible_ui.gd.uid b/core/photo_mode/ui/collectible_ui.gd.uid new file mode 100644 index 0000000..d9ba065 --- /dev/null +++ b/core/photo_mode/ui/collectible_ui.gd.uid @@ -0,0 +1 @@ +uid://dxh8e1n16qjpp diff --git a/core/photo_mode/ui/collectible_ui.tscn b/core/photo_mode/ui/collectible_ui.tscn new file mode 100644 index 0000000..8242ea3 --- /dev/null +++ b/core/photo_mode/ui/collectible_ui.tscn @@ -0,0 +1,49 @@ +[gd_scene format=3 uid="uid://dp7dvfauh5rpx"] + +[ext_resource type="Script" uid="uid://dxh8e1n16qjpp" path="res://core/photo_mode/ui/collectible_ui.gd" id="1_tu5nx"] +[ext_resource type="Texture2D" uid="uid://cx8d233y32kmu" path="res://icon.svg" id="1_x3wje"] + +[node name="CollectibleUI" type="Control" unique_id=201865221] +custom_minimum_size = Vector2(200, 200) +layout_mode = 3 +anchors_preset = 0 +offset_right = 200.0 +offset_bottom = 200.0 +script = ExtResource("1_tu5nx") + +[node name="Panel" type="PanelContainer" parent="." unique_id=1372516531] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="MarginContainer" type="MarginContainer" parent="Panel" unique_id=1141643525] +layout_mode = 2 +theme_override_constants/margin_left = 12 +theme_override_constants/margin_top = 12 +theme_override_constants/margin_right = 12 +theme_override_constants/margin_bottom = 12 + +[node name="VBoxContainer" type="VBoxContainer" parent="Panel/MarginContainer" unique_id=1841409877] +layout_mode = 2 +alignment = 1 + +[node name="CollectibleName" type="Label" parent="Panel/MarginContainer/VBoxContainer" unique_id=117774359] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 0 +text = "Collectible" +horizontal_alignment = 1 + +[node name="HSeparator" type="HSeparator" parent="Panel/MarginContainer/VBoxContainer" unique_id=1345822244] +layout_mode = 2 + +[node name="CollectibleTexture" type="TextureRect" parent="Panel/MarginContainer/VBoxContainer" unique_id=506844785] +unique_name_in_owner = true +modulate = Color(0.16206557, 0.1620656, 0.16206557, 1) +layout_mode = 2 +size_flags_vertical = 3 +texture = ExtResource("1_x3wje") +stretch_mode = 3 diff --git a/core/photo_mode/ui/photo.gd b/core/photo_mode/ui/photo.gd new file mode 100644 index 0000000..5740c30 --- /dev/null +++ b/core/photo_mode/ui/photo.gd @@ -0,0 +1,11 @@ +extends Control + +class_name Photo + +@onready var texture_rect: TextureRect = $%PhotoTexture + +func setup(texture: Texture) -> void: + if texture: + if !texture_rect: + texture_rect = $%PhotoTexture + texture_rect.texture = texture diff --git a/core/photo_mode/ui/photo.gd.uid b/core/photo_mode/ui/photo.gd.uid new file mode 100644 index 0000000..37f3929 --- /dev/null +++ b/core/photo_mode/ui/photo.gd.uid @@ -0,0 +1 @@ +uid://dsey5dvc11vpq diff --git a/core/photo_mode/ui/photo.tscn b/core/photo_mode/ui/photo.tscn new file mode 100644 index 0000000..615e857 --- /dev/null +++ b/core/photo_mode/ui/photo.tscn @@ -0,0 +1,38 @@ +[gd_scene format=3 uid="uid://cvus62qkop3qi"] + +[ext_resource type="Script" uid="uid://dsey5dvc11vpq" path="res://core/photo_mode/ui/photo.gd" id="1_u0arp"] + +[node name="Photo" type="Control" unique_id=201865221] +custom_minimum_size = Vector2(200, 200) +layout_mode = 3 +anchors_preset = 0 +offset_right = 200.0 +offset_bottom = 200.0 +script = ExtResource("1_u0arp") + +[node name="ColorRect" type="ColorRect" parent="." unique_id=1208008621] +layout_mode = 0 +offset_right = 200.0 +offset_bottom = 200.0 + +[node name="MarginContainer" type="MarginContainer" parent="ColorRect" unique_id=1141643525] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 12 +theme_override_constants/margin_top = 12 +theme_override_constants/margin_right = 12 +theme_override_constants/margin_bottom = 12 + +[node name="Panel" type="PanelContainer" parent="ColorRect/MarginContainer" unique_id=1372516531] +layout_mode = 2 + +[node name="PhotoTexture" type="TextureRect" parent="ColorRect/MarginContainer/Panel" unique_id=506844785] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 +expand_mode = 1 +stretch_mode = 6 diff --git a/core/photo_mode/ui/photo_gallery.gd b/core/photo_mode/ui/photo_gallery.gd new file mode 100644 index 0000000..9ffd1e4 --- /dev/null +++ b/core/photo_mode/ui/photo_gallery.gd @@ -0,0 +1,27 @@ +extends Control + +@export var photo_scene: PackedScene + +@onready var grid_container: GridContainer = $%PhotoGrid + +func _ready() -> void: + CollectionManager.on_photo_saved.connect(_create_photo_thumbnail) + load_gallery() + +func load_gallery() -> void: + for child in grid_container.get_children(): + child.queue_free() + + var saved_photos = CollectionManager.saved_photos + + for file_path in saved_photos: + if FileAccess.file_exists(file_path): + _create_photo_thumbnail(file_path) + +func _create_photo_thumbnail(file_path: String) -> void: + var image = Image.load_from_file(file_path) + if image: + var photo: Photo = photo_scene.instantiate() + var texture = ImageTexture.create_from_image(image) + photo.setup(texture) + grid_container.add_child(photo) diff --git a/core/photo_mode/ui/photo_gallery.gd.uid b/core/photo_mode/ui/photo_gallery.gd.uid new file mode 100644 index 0000000..74980db --- /dev/null +++ b/core/photo_mode/ui/photo_gallery.gd.uid @@ -0,0 +1 @@ +uid://k4iqrlkbjppl diff --git a/core/photo_mode/ui/photo_gallery.tscn b/core/photo_mode/ui/photo_gallery.tscn new file mode 100644 index 0000000..64c94a7 --- /dev/null +++ b/core/photo_mode/ui/photo_gallery.tscn @@ -0,0 +1,50 @@ +[gd_scene format=3 uid="uid://b6r787sik5yil"] + +[ext_resource type="Script" uid="uid://k4iqrlkbjppl" path="res://core/photo_mode/ui/photo_gallery.gd" id="1_bp5uf"] +[ext_resource type="PackedScene" uid="uid://cvus62qkop3qi" path="res://core/photo_mode/ui/photo.tscn" id="2_45wok"] + +[node name="PhotoGallery" type="Control" unique_id=354419843] +layout_mode = 3 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_bp5uf") +photo_scene = ExtResource("2_45wok") + +[node name="PanelContainer" type="PanelContainer" parent="." unique_id=640179265] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -350.0 +offset_top = -350.0 +offset_right = 350.0 +offset_bottom = 350.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="MarginContainer" type="MarginContainer" parent="PanelContainer" unique_id=125147979] +layout_mode = 2 +theme_override_constants/margin_left = 12 +theme_override_constants/margin_top = 12 +theme_override_constants/margin_right = 12 +theme_override_constants/margin_bottom = 12 + +[node name="ScrollContainer" type="ScrollContainer" parent="PanelContainer/MarginContainer" unique_id=348576028] +layout_mode = 2 +draw_focus_border = true + +[node name="PhotoGrid" type="GridContainer" parent="PanelContainer/MarginContainer/ScrollContainer" unique_id=1187865988] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 6 +size_flags_vertical = 2 +theme_override_constants/h_separation = 12 +theme_override_constants/v_separation = 12 +columns = 3 diff --git a/core/radio/radio.gd b/core/radio/radio.gd new file mode 100644 index 0000000..0cdaf0f --- /dev/null +++ b/core/radio/radio.gd @@ -0,0 +1,31 @@ +extends AudioStreamPlayer + +class_name Radio + +@export var playlist: Array[AudioStream] = [] +var current_track_index: int = 0 + +func _ready(): + finished.connect(next_track) + +func play_track(index: int = current_track_index): + if playlist.is_empty(): + return + + current_track_index = posmod(index, playlist.size()) + stream = playlist[current_track_index] + play() + stream_paused = false + +func next_track(): + play_track(current_track_index + 1) + +func prev_track(): + play_track(current_track_index - 1) + +func toggle_pause(): + stream_paused = !stream_paused + +func stop_radio(): + stop() + stream_paused = false diff --git a/core/radio/radio.gd.uid b/core/radio/radio.gd.uid new file mode 100644 index 0000000..16144af --- /dev/null +++ b/core/radio/radio.gd.uid @@ -0,0 +1 @@ +uid://bwrgh6xlvhqch diff --git a/core/radio/radio.tscn b/core/radio/radio.tscn new file mode 100644 index 0000000..40f7519 --- /dev/null +++ b/core/radio/radio.tscn @@ -0,0 +1,7 @@ +[gd_scene format=3 uid="uid://cpeyt1dgrtglc"] + +[ext_resource type="Script" uid="uid://bwrgh6xlvhqch" path="res://core/radio/radio.gd" id="1_2akjj"] + +[node name="Radio" type="AudioStreamPlayer" unique_id=1234112225] +bus = &"Music" +script = ExtResource("1_2akjj") diff --git a/default_bus_layout.tres b/default_bus_layout.tres new file mode 100644 index 0000000..3003eca --- /dev/null +++ b/default_bus_layout.tres @@ -0,0 +1,15 @@ +[gd_resource type="AudioBusLayout" format=3 uid="uid://cqvx62pwvvboj"] + +[resource] +bus/1/name = &"Music" +bus/1/solo = false +bus/1/mute = false +bus/1/bypass_fx = false +bus/1/volume_db = 0.0 +bus/1/send = &"Master" +bus/2/name = &"SFX" +bus/2/solo = false +bus/2/mute = false +bus/2/bypass_fx = false +bus/2/volume_db = 0.0 +bus/2/send = &"Master" diff --git a/docs/gyms/ai/gym_ai.tscn b/docs/gyms/ai/gym_ai.tscn new file mode 100644 index 0000000..faa1cc8 --- /dev/null +++ b/docs/gyms/ai/gym_ai.tscn @@ -0,0 +1,92 @@ +[gd_scene format=3 uid="uid://dqvrhiqgkd3w1"] + +[ext_resource type="PackedScene" uid="uid://clx701xdwelgx" path="res://core/ai/agents/base/ai_base.tscn" id="1_a2xtd"] + +[sub_resource type="NavigationMesh" id="NavigationMesh_optuv"] +vertices = PackedVector3Array(10.984741, 0.25012434, -1.0140381, 11.234741, 0.25012434, 0.23596191, 19.484741, 0.25012434, 0.23596191, 19.484741, 0.25012434, -19.514038, 9.234741, 0.25012434, -1.0140381, -19.515259, 0.25012434, -19.514038, -19.515259, 0.25012434, -0.014038086, 8.984741, 0.25012434, -0.014038086, 10.984741, 0.25012434, 1.2359619, 19.484741, 0.25012434, 19.235962, 9.234741, 0.25012434, 1.2359619, -19.515259, 0.25012434, 19.235962) +polygons = [PackedInt32Array(1, 0, 2), PackedInt32Array(2, 0, 3), PackedInt32Array(6, 5, 4), PackedInt32Array(4, 5, 3), PackedInt32Array(3, 0, 4), PackedInt32Array(4, 7, 6), PackedInt32Array(1, 2, 8), PackedInt32Array(8, 2, 9), PackedInt32Array(6, 10, 11), PackedInt32Array(11, 10, 9), PackedInt32Array(10, 8, 9), PackedInt32Array(6, 7, 10)] + +[sub_resource type="PlaneMesh" id="PlaneMesh_optuv"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_xtjak"] +size = Vector3(1.9942131, 0.09710693, 1.984024) + +[sub_resource type="BoxMesh" id="BoxMesh_lmjyn"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_lmjyn"] + +[sub_resource type="Environment" id="Environment_lmjyn"] + +[node name="GymAI" type="Node3D" unique_id=868339787] + +[node name="NavigationRegion3D" type="NavigationRegion3D" parent="." unique_id=774907858] +navigation_mesh = SubResource("NavigationMesh_optuv") + +[node name="Floor" type="MeshInstance3D" parent="NavigationRegion3D" unique_id=1976415311] +transform = Transform3D(20, 0, 0, 0, 20, 0, 0, 0, 20, 0, -0.83473957, 0) +mesh = SubResource("PlaneMesh_optuv") + +[node name="StaticBody3D" type="StaticBody3D" parent="NavigationRegion3D/Floor" unique_id=2007477719] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="NavigationRegion3D/Floor/StaticBody3D" unique_id=1446628130] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0036563873, -0.009703338, -0.00868988) +shape = SubResource("BoxShape3D_xtjak") + +[node name="Obstacle" type="MeshInstance3D" parent="NavigationRegion3D" unique_id=710701082] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 10.148018, 0.06508446, 0) +mesh = SubResource("BoxMesh_lmjyn") + +[node name="StaticBody3D" type="StaticBody3D" parent="NavigationRegion3D/Obstacle" unique_id=67152580] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="NavigationRegion3D/Obstacle/StaticBody3D" unique_id=1663742898] +shape = SubResource("BoxShape3D_lmjyn") + +[node name="AIBase" parent="." unique_id=1228675528 instance=ExtResource("1_a2xtd")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.48246834, 0.21202153, 0.11262059) + +[node name="Camera3D" type="Camera3D" parent="." unique_id=1148396057] +transform = Transform3D(-2.0613477e-08, 0.8818225, -0.47158146, 3.854569e-08, 0.47158146, 0.8818225, 1, -3.5527137e-15, -4.371139e-08, -18.21907, 28.71355, 0) + +[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=1772424900] +environment = SubResource("Environment_lmjyn") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="." unique_id=269230449] +transform = Transform3D(1, 0, 0, 0, 0.17952333, 0.98375374, 0, -0.98375374, 0.17952333, 0, 18.920979, 0) + +[node name="Control" type="Control" parent="." unique_id=1072240389] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="PanelContainer" type="PanelContainer" parent="Control" unique_id=1647272132] +layout_mode = 0 +offset_left = 50.0 +offset_top = 50.0 +offset_right = 400.0 +offset_bottom = 827.0 + +[node name="Label" type="Label" parent="Control/PanelContainer" unique_id=272421245] +custom_minimum_size = Vector2(1, 1) +layout_mode = 2 +size_flags_vertical = 1 +text = "System Logic: +- The NPC uses a finite state machine to switch between behaviors. +- State logic runs during physics updates, while movement is handled by the agent through NavigationAgent3D. + +AI States: +- IdleState: The agent waits in place for the duration defined by wait_time. +- PatrolState: The agent selects a valid random destination and moves toward it. + +Core Components: +- NavigationAgent3D: Calculates the path and reports when the destination has been reached. +- PatrolRadiusShape: Defines the random movement area used when choosing the next patrol point. +- StateMachine: Initializes the available states and handles transitions between them. + +Parameters: +- Speed: Movement speed of the agent. +- Wait Time: Delay in seconds on the IdleState node. +- Area Radius: Radius of the SphereShape3D used by PatrolRadiusShape." +autowrap_mode = 2 diff --git a/docs/gyms/photo_mode/gym_photo_mode.gd b/docs/gyms/photo_mode/gym_photo_mode.gd new file mode 100644 index 0000000..e92bfd2 --- /dev/null +++ b/docs/gyms/photo_mode/gym_photo_mode.gd @@ -0,0 +1,7 @@ +extends Node3D + +@onready var gallery: Control = $%Gallery + + +func _on_button_gallery_pressed() -> void: + gallery.visible = !gallery.visible diff --git a/docs/gyms/photo_mode/gym_photo_mode.gd.uid b/docs/gyms/photo_mode/gym_photo_mode.gd.uid new file mode 100644 index 0000000..b17c53f --- /dev/null +++ b/docs/gyms/photo_mode/gym_photo_mode.gd.uid @@ -0,0 +1 @@ +uid://7oglx4br38d5 diff --git a/docs/gyms/photo_mode/gym_photo_mode.tscn b/docs/gyms/photo_mode/gym_photo_mode.tscn new file mode 100644 index 0000000..7549329 --- /dev/null +++ b/docs/gyms/photo_mode/gym_photo_mode.tscn @@ -0,0 +1,138 @@ +[gd_scene format=3 uid="uid://bwc8slnbu7dmn"] + +[ext_resource type="Script" uid="uid://7oglx4br38d5" path="res://docs/gyms/photo_mode/gym_photo_mode.gd" id="1_cl1h5"] +[ext_resource type="PackedScene" uid="uid://vni5kjalum6d" path="res://core/photo_mode/runtime/photo_mode_controller.tscn" id="2_q5kgc"] +[ext_resource type="PackedScene" uid="uid://bmkxt6btcx8qr" path="res://core/photo_mode/runtime/collectible.tscn" id="3_734hf"] +[ext_resource type="Texture2D" uid="uid://c3grftlmap4q5" path="res://tgcc/chunk/prop/tree/leaf1_alpha.png" id="4_00joj"] +[ext_resource type="Script" uid="uid://bj34o0org55ei" path="res://core/photo_mode/data/collectible_resource.gd" id="5_crfij"] +[ext_resource type="PackedScene" uid="uid://bvw086glfpcba" path="res://core/photo_mode/ui/collectible_gallery.tscn" id="6_6aab5"] +[ext_resource type="PackedScene" uid="uid://b6r787sik5yil" path="res://core/photo_mode/ui/photo_gallery.tscn" id="7_tb1ii"] + +[sub_resource type="Environment" id="Environment_48mla"] + +[sub_resource type="PlaneMesh" id="PlaneMesh_hh1ka"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_ynvi2"] +size = Vector3(1.9942131, 0.09710693, 1.984024) + +[sub_resource type="Resource" id="Resource_ynvi2"] +script = ExtResource("5_crfij") +id = &"gatto" +title = "Gatto" +image = ExtResource("4_00joj") +metadata/_custom_type_script = "uid://bj34o0org55ei" + +[sub_resource type="BoxMesh" id="BoxMesh_hh1ka"] + +[node name="GymPhotoMode" type="Node3D" unique_id=1314600330] +script = ExtResource("1_cl1h5") + +[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=213183287] +environment = SubResource("Environment_48mla") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="." unique_id=1274975837] +transform = Transform3D(1, 0, 0, 0, 0.17952333, 0.98375374, 0, -0.98375374, 0.17952333, 0, 18.920979, 0) + +[node name="Floor" type="MeshInstance3D" parent="." unique_id=958865480] +transform = Transform3D(20, 0, 0, 0, 20, 0, 0, 0, 20, 0, -0.83473957, 0) +mesh = SubResource("PlaneMesh_hh1ka") + +[node name="StaticBody3D" type="StaticBody3D" parent="Floor" unique_id=2096983240] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Floor/StaticBody3D" unique_id=188185045] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0036563873, -0.009703338, -0.00868988) +shape = SubResource("BoxShape3D_ynvi2") + +[node name="PhotoModeController" parent="." unique_id=695158870 node_paths=PackedStringArray("rotation_target") instance=ExtResource("2_q5kgc")] +transform = Transform3D(1, 0, 0, 0, 0.49999994, 0.8660254, 0, -0.8660254, 0.49999994, 0, 30, 20) +movement_bounds = AABB(-5, -5, -5, 10, 10, 10) +rotation_target = NodePath("../Node3D") + +[node name="Node3D" type="Node3D" parent="." unique_id=570786250] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 10, 0) + +[node name="Node3D2" type="Node3D" parent="." unique_id=15037296] + +[node name="Collectible" parent="Node3D2" unique_id=1229019813 instance=ExtResource("3_734hf")] +collectible_data = SubResource("Resource_ynvi2") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Node3D2" unique_id=553040412] +mesh = SubResource("BoxMesh_hh1ka") + +[node name="Control" type="Control" parent="." unique_id=1802496396] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 + +[node name="ButtonGallery" type="Button" parent="Control" unique_id=539195532] +layout_mode = 0 +offset_left = 50.0 +offset_top = 50.0 +offset_right = 163.0 +offset_bottom = 81.0 +text = "Menu" + +[node name="Gallery" type="HSplitContainer" parent="Control" unique_id=1388833682] +unique_name_in_owner = true +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 420.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="CollectibleGallery" parent="Control/Gallery" unique_id=354419843 instance=ExtResource("6_6aab5")] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="PhotoGallery" parent="Control/Gallery" unique_id=263414560 instance=ExtResource("7_tb1ii")] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="PanelContainer" type="PanelContainer" parent="Control" unique_id=2015953740] +layout_mode = 0 +offset_left = 50.0 +offset_top = 150.0 +offset_right = 400.0 +offset_bottom = 927.0 + +[node name="ScrollContainer" type="ScrollContainer" parent="Control/PanelContainer" unique_id=1474258594] +layout_mode = 2 + +[node name="Label" type="Label" parent="Control/PanelContainer/ScrollContainer" unique_id=1982569320] +custom_minimum_size = Vector2(1, 1) +layout_mode = 2 +size_flags_horizontal = 3 +text = "System Logic: +- The system allows players to toggle a free camera mode to photograph and collect museum items. +- Game Pause: Activating the mode pauses the SceneTree, freezing the world while allowing the camera to remain functional. +- Taking a photo saves the captured image to disk and checks which collectibles are visible and unobstructed before unlocking them. +- CollectionManager acts as a global singleton that tracks unlocked collectibles, saved photos, and the data used by the UI. + +Photo Mode Actions: +- Toggle Mode(P): Switches between normal gameplay and the photo camera, capturing or releasing the mouse, and toggles the global pause state. +- Rotate(Mouse): The camera orbits around the configured target while photo mode is active. +- Pan(Input Actions): The camera can be moved horizontally and vertically within the configured bounds. +- Capture(F): Saves the current frame and performs frustum and raycast checks against collectibles in view. + +Core Components: +- PhotoModeController: Manages camera inputs, movement logic, and the photo-taking process. +- Collectible: An Area3D node placed on objects to make them identifiable by the camera. +- CollectionManager: Handles the logic for unlocking items and provides data to the UI. +- CollectibleGallery: Displays all collectibles and visually highlights the unlocked ones. +- PhotoGallery: Displays the photos saved by the player during the session. + +Parameters: +- Pan & Rotation Speed: Defines how fast the camera moves and rotates. +- Movement Bounds: An AABB that restricts the camera's panning area. +- Collectible Data: Resource files containing the ID, title, and image for each item. +- Library: A central list of all CollectibleResources registered in the game." +autowrap_mode = 2 + +[connection signal="pressed" from="Control/ButtonGallery" to="." method="_on_button_gallery_pressed"] diff --git a/docs/gyms/radio/gym_radio.gd b/docs/gyms/radio/gym_radio.gd new file mode 100644 index 0000000..d905bf0 --- /dev/null +++ b/docs/gyms/radio/gym_radio.gd @@ -0,0 +1,35 @@ +extends Node3D + +@onready var radio: Radio = $%Radio +@onready var button_pause_resume: Button = $%Button_Pause_Resume +@onready var settings_menu: SettingsMenu = $%SettingsMenu + +func _on_button_play_pressed() -> void: + if !radio.playing: + radio.play_track() + + +func _on_button_pause_pressed() -> void: + radio.toggle_pause() + if !button_pause_resume: + button_pause_resume = $%Button_Pause_Resume + if radio.stream_paused: + button_pause_resume.text = "Resume" + else: + button_pause_resume.text = "Pause" + + +func _on_button_stop_pressed() -> void: + radio.stop_radio() + + +func _on_button_next_pressed() -> void: + radio.next_track() + + +func _on_button_previous_pressed() -> void: + radio.prev_track() + + +func _on_button_settings_menu_pressed() -> void: + settings_menu.visible = !settings_menu.visible diff --git a/docs/gyms/radio/gym_radio.gd.uid b/docs/gyms/radio/gym_radio.gd.uid new file mode 100644 index 0000000..37098fa --- /dev/null +++ b/docs/gyms/radio/gym_radio.gd.uid @@ -0,0 +1 @@ +uid://ew4b78u5tkiu diff --git a/docs/gyms/radio/gym_radio.tscn b/docs/gyms/radio/gym_radio.tscn new file mode 100644 index 0000000..7289baa --- /dev/null +++ b/docs/gyms/radio/gym_radio.tscn @@ -0,0 +1,104 @@ +[gd_scene format=3 uid="uid://bdkdhn1oallke"] + +[ext_resource type="PackedScene" uid="uid://cpeyt1dgrtglc" path="res://core/radio/radio.tscn" id="1_8yomj"] +[ext_resource type="Script" uid="uid://ew4b78u5tkiu" path="res://docs/gyms/radio/gym_radio.gd" id="1_h5r8c"] +[ext_resource type="AudioStream" uid="uid://70cc8she43re" path="res://docs/gyms/radio/lofi_01.ogg" id="3_ltpvc"] +[ext_resource type="PackedScene" uid="uid://caqf471x0kttc" path="res://core/audio/settings/settings_menu.tscn" id="4_8pw2j"] + +[node name="GymRadio" type="Node3D" unique_id=204859062] +script = ExtResource("1_h5r8c") + +[node name="Radio" parent="." unique_id=1234112225 instance=ExtResource("1_8yomj")] +unique_name_in_owner = true +playlist = Array[AudioStream]([ExtResource("3_ltpvc")]) + +[node name="Control" type="Control" parent="." unique_id=1232082176] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="SettingsMenu" parent="Control" unique_id=1639777294 instance=ExtResource("4_8pw2j")] +unique_name_in_owner = true +visible = false +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 + +[node name="VBoxContainer2" type="VBoxContainer" parent="Control" unique_id=2092627240] +layout_mode = 1 +anchors_preset = 9 +anchor_bottom = 1.0 +offset_right = 229.0 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="Control/VBoxContainer2" unique_id=2097365775] +layout_mode = 2 + +[node name="Button_Play" type="Button" parent="Control/VBoxContainer2/VBoxContainer" unique_id=1422696340] +layout_mode = 2 +text = "Play" + +[node name="Button_Pause_Resume" type="Button" parent="Control/VBoxContainer2/VBoxContainer" unique_id=2016690081] +unique_name_in_owner = true +layout_mode = 2 +text = "Pause" + +[node name="Button_Stop" type="Button" parent="Control/VBoxContainer2/VBoxContainer" unique_id=61861870] +layout_mode = 2 +text = "Stop" + +[node name="Button_Next" type="Button" parent="Control/VBoxContainer2/VBoxContainer" unique_id=957606385] +layout_mode = 2 +text = "Next" + +[node name="Button_Previous" type="Button" parent="Control/VBoxContainer2/VBoxContainer" unique_id=929072518] +layout_mode = 2 +text = "Previous" + +[node name="Button_SettingsMenu" type="Button" parent="Control/VBoxContainer2/VBoxContainer" unique_id=431867154] +layout_mode = 2 +text = "SettingsMenu" + +[node name="PanelContainer" type="PanelContainer" parent="Control/VBoxContainer2" unique_id=1558442050] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="ScrollContainer" type="ScrollContainer" parent="Control/VBoxContainer2/PanelContainer" unique_id=7789304] +layout_mode = 2 + +[node name="Label" type="Label" parent="Control/VBoxContainer2/PanelContainer/ScrollContainer" unique_id=2043293564] +custom_minimum_size = Vector2(1, 1) +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 1 +text = "System Logic: +- The system is an extension of AudioStreamPlayer designed to manage sequential audio playback. +- It automatically triggers the next track in the sequence when the current one finishes via the finished signal. + +Core Functionality: +- Playlist Management: Stores a list of AudioStream resources and tracks the current song index. +- Track Navigation: Allows cycling forward and backward through the playlist with index wrapping (loops back to start/end). +- Playback Control: Supports jumping to specific tracks, toggling the pause state, and stopping the stream. +- Audio Settings: If the Music bus exists, the Settings menu can be used to test and adjust playback volume. + +Key Methods: +- play_track: Loads a specific stream from the playlist and begins playback. +- next_track / prev_track: Increments or decrements the index to navigate the playlist. +- toggle_pause: Resumes or pauses the current stream without resetting its position. + +Adjustable Parameters: +- Playlist: An Array in the inspector where you can assign one or more AudioStream resources." +autowrap_mode = 2 + +[connection signal="pressed" from="Control/VBoxContainer2/VBoxContainer/Button_Play" to="." method="_on_button_play_pressed"] +[connection signal="pressed" from="Control/VBoxContainer2/VBoxContainer/Button_Pause_Resume" to="." method="_on_button_pause_pressed"] +[connection signal="pressed" from="Control/VBoxContainer2/VBoxContainer/Button_Stop" to="." method="_on_button_stop_pressed"] +[connection signal="pressed" from="Control/VBoxContainer2/VBoxContainer/Button_Next" to="." method="_on_button_next_pressed"] +[connection signal="pressed" from="Control/VBoxContainer2/VBoxContainer/Button_Previous" to="." method="_on_button_previous_pressed"] +[connection signal="pressed" from="Control/VBoxContainer2/VBoxContainer/Button_SettingsMenu" to="." method="_on_button_settings_menu_pressed"] diff --git a/docs/gyms/radio/lofi_01.ogg b/docs/gyms/radio/lofi_01.ogg new file mode 100644 index 0000000..e465826 Binary files /dev/null and b/docs/gyms/radio/lofi_01.ogg differ diff --git a/docs/gyms/radio/lofi_01.ogg.import b/docs/gyms/radio/lofi_01.ogg.import new file mode 100644 index 0000000..025a2c9 --- /dev/null +++ b/docs/gyms/radio/lofi_01.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://70cc8she43re" +path="res://.godot/imported/lofi_01.ogg-0aacd597266806080412021811923091.oggvorbisstr" + +[deps] + +source_file="res://docs/gyms/radio/lofi_01.ogg" +dest_files=["res://.godot/imported/lofi_01.ogg-0aacd597266806080412021811923091.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/project.godot b/project.godot index 23acade..b1a9573 100644 --- a/project.godot +++ b/project.godot @@ -19,6 +19,9 @@ config/icon="uid://bfar1kk3pgq8f" [autoload] UIEvents="*uid://dehu28iq27mbn" +GameState="*uid://b17g2w2g101o6" +CollectionManager="*uid://c3kq1qddpm8tf" +AudioManager="*uid://dcttbbavtwtsg" [display] @@ -34,6 +37,39 @@ weather_vegetables_node="" wind_node="Materials to apply wind" weather_node="" +[input] + +photo_pan_left={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":65,"location":0,"echo":false,"script":null) +] +} +photo_pan_right={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null) +] +} +photo_pan_up={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null) +] +} +photo_pan_down={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) +] +} +take_photo={ +"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) +] +} +toggle_photo_mode={ +"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":80,"key_label":0,"unicode":112,"location":0,"echo":false,"script":null) +] +} + [physics] 3d/physics_engine="Jolt Physics"