3 Commits

Author SHA1 Message Date
6d27281b98 Merge branch 'main' into improve-ui 2026-06-02 10:32:54 +02:00
1037d1343d improve ui and bug fix 2026-06-02 00:05:37 +02:00
6c4f659fd0 improve ui 2026-06-01 20:17:20 +02:00
16 changed files with 337 additions and 51 deletions

View File

@@ -10,6 +10,14 @@ signal on_photo_highlighted(teture: Texture)
signal on_enable_photo_mode_request
@warning_ignore("unused_signal")
signal on_disable_photo_mode_request
@warning_ignore("unused_signal")
signal on_photo_taken_started
@warning_ignore("unused_signal")
signal on_photo_taken_making
@warning_ignore("unused_signal")
signal on_photo_taken_finished
@warning_ignore("unused_signal")
signal on_photo_taken_prepare
const SAVE_PATH: String = "user://savegame.json"

View File

@@ -2,15 +2,19 @@ extends Control
@onready var settings_menu: Control = $%SettingsMenu
@onready var option_menu: Control = $%OptionMenu
@onready var show_container_tween: ContainerTween = $%ShowContainerTween
@onready var hide_container_tween: ContainerTween = $%HideContainerTween
func _ready() -> void:
option_menu.settings_button.pressed.connect(_on_settings_button_pressed)
func _on_settings_button_pressed() -> void:
if TweenFX.is_playing(settings_menu, TweenFX.Animations.FOLD_IN) or TweenFX.is_playing(settings_menu, TweenFX.Animations.FOLD_OUT):
return
if settings_menu.visible:
hide_container_tween.start_tween()
TweenFX.fold_out(settings_menu)
await TweenFX.fold_out(settings_menu).finished
settings_menu.hide()
else:
show_container_tween.start_tween()
settings_menu.scale = Vector2(1,1)
settings_menu.show()
TweenFX.fold_in(settings_menu)

View File

@@ -4,7 +4,6 @@
[ext_resource type="PackedScene" uid="uid://cxf8s80ivwj1p" path="res://core/game_menu/option_menu.tscn" id="1_uvy4f"]
[ext_resource type="Texture2D" uid="uid://buy4x63u237np" path="res://core/main_menu/assets/main_menu_background.png" id="2_mloc8"]
[ext_resource type="PackedScene" uid="uid://caqf471x0kttc" path="res://core/game_menu/settings_menu.tscn" id="3_26agx"]
[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/tween/container_tween.tscn" id="4_mloc8"]
[node name="MainMenu" type="Control" unique_id=889720172]
layout_mode = 3
@@ -61,16 +60,4 @@ offset_right = 552.0
offset_bottom = 256.0
grow_vertical = 2
[node name="ShowContainerTween" parent="." unique_id=160227524 node_paths=PackedStringArray("targets") instance=ExtResource("4_mloc8")]
unique_name_in_owner = true
targets = [NodePath("../SettingsMenu")]
tween_types = Array[String](["fold_in"])
show_on_start = true
[node name="HideContainerTween" parent="." unique_id=570405239 node_paths=PackedStringArray("targets") instance=ExtResource("4_mloc8")]
unique_name_in_owner = true
targets = [NodePath("../SettingsMenu")]
tween_types = Array[String](["fold_out"])
hide_on_finish = true
[editable path="OptionMenu"]

View File

@@ -0,0 +1,19 @@
shader_type canvas_item;
// Dimensione del rettangolo vuoto al centro (in proporzione allo schermo)
// Esempio: vec2(0.6, 0.6) significa che il buco occuperà il 60% dello schermo.
// Puoi modificare questi valori direttamente dall'Inspector di Godot!
uniform vec2 hole_size = vec2(0.6, 0.6);
void fragment() {
// Calcoliamo la distanza dal centro esatto dello schermo (0.5, 0.5)
vec2 center = vec2(0.5, 0.5);
vec2 d = abs(UV - center);
vec2 half_size = hole_size / 2.0;
// Se il pixel si trova all'interno delle dimensioni del buco,
// impostiamo l'Alpha a 0.0 (rendendolo totalmente trasparente).
if (d.x < half_size.x && d.y < half_size.y) {
COLOR.a = 0.0;
}
}

View File

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

View File

@@ -0,0 +1,10 @@
shader_type canvas_item;
uniform sampler2D mask_texture;
void fragment() {
vec4 mask_color = texture(mask_texture, UV);
// Sottrae l'alpha della maschera dall'alpha del pannello.
// Dove la maschera è opaca (alpha = 1), il pannello diventerà trasparente (alpha = 0).
COLOR.a = max(COLOR.a - mask_color.a, 0.0);
}

View File

@@ -0,0 +1 @@
uid://44y4fig1hi4y

View File

@@ -8,21 +8,32 @@ enum Weather {RAIN, SNOW}
@onready var photo_icon_button: Button = $%PhotoIconButton
@onready var collectible_icon_button: Button = $%CollectibleIconButton
@onready var resume_button: Button = $GameMenuPanel/GameMenu/Pages/Page3/OptionMenu/VBoxContainer/ResumeButton
@onready var show_container_tween: ContainerTween = $%ShowContainerTween
@onready var hide_container_tween: ContainerTween = $%HideContainerTween
@onready var weather_row: HBoxContainer = $%WeatherRow
@onready var time_of_day_row: HBoxContainer = $%TimeOfDayRow
@onready var photo_mode_texture_panel: Panel = $%PhotoModeTexturePanel
@onready var photo_mode_texture_mask: TextureRect = $%PhotoModeTextureMask
@onready var photo_mode_black_screen: ColorRect = $%PhotoModeBlackScreen
@onready var collection_options: VBoxContainer = $%CollectionOptions
@onready var audio_player: Control = $%AudioPlayer
var cycle = false
func _ready() -> void:
GameState.on_enable_photo_mode_request.connect(_on_enable_photo_mode)
GameState.on_disable_photo_mode_request.connect(_on_disable_photo_mode)
GameState.on_photo_taken_started.connect(_on_photo_taken_started)
GameState.on_photo_taken_finished.connect(_on_photo_taken_finished)
GameState.on_photo_taken_prepare.connect(_on_photo_capture_prepare)
menu_icon_button.pressed.connect(_on_menu_icon_button_pressed)
photo_icon_button.pressed.connect(_on_photo_icon_button_pressed)
collectible_icon_button.pressed.connect(_on_collectible_icon_button_pressed)
resume_button.pressed.connect(_on_resume_button_pressed)
func _on_menu_icon_button_pressed() -> void:
GameState.pause_game()
game_menu_panel.show()
show_container_tween.start_tween()
game_menu.scale = Vector2(1, 1)
TweenFX.fold_in(game_menu)
func _on_photo_icon_button_pressed() -> void:
GameState.on_enable_photo_mode_request.emit()
@@ -31,11 +42,12 @@ func _on_collectible_icon_button_pressed() -> void:
GameState.pause_game()
game_menu.on_tab_pressed(1, true)
game_menu_panel.show()
show_container_tween.start_tween()
game_menu.scale = Vector2(1, 1)
TweenFX.fold_in(game_menu)
func _on_resume_button_pressed() -> void:
hide_container_tween.start_tween()
await hide_container_tween.finished
var tween = TweenFX.fold_out(game_menu)
await tween.finished
game_menu_panel.hide()
GameState.resume_game()
@@ -45,10 +57,11 @@ func _on_time_of_day_row_on_option_changed(data: String) -> void:
UIEvents.time_option_item_changed.emit(0)
"Day":
UIEvents.time_option_item_changed.emit(1)
"Sunset":
UIEvents.time_option_item_changed.emit(2)
"Night":
UIEvents.time_option_item_changed.emit(3)
"Cycle":
cycle = !cycle
UIEvents.toggle_pause_daytime.emit(cycle)
_:
pass
@@ -76,3 +89,73 @@ func pick_random_weather() -> void:
if valid_buttons.size() > 0:
var random_button = valid_buttons.pick_random()
weather_row.on_icon_pressed_changed(random_button)
func _on_enable_photo_mode() -> void:
hide_ui_for_photo_mode()
photo_mode_texture_mask.scale = Vector2(1,1)
photo_mode_texture_mask.modulate.a = 0.0
photo_mode_texture_panel.show()
var mat = photo_mode_texture_panel.material as ShaderMaterial
if mat:
mat.set_shader_parameter("hole_size", Vector2(0.72, 0.0))
var tween = create_tween()
tween.tween_property(mat, "shader_parameter/hole_size", Vector2(0.72, 0.806), 0.3).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT)
var alpha_tween = create_tween()
alpha_tween.tween_property(photo_mode_texture_mask, "modulate:a", 1.0, 0.3).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
TweenFX.fold_in(photo_mode_texture_mask)
func _on_disable_photo_mode() -> void:
show_ui_for_photo_mode()
var mat = photo_mode_texture_panel.material as ShaderMaterial
if mat:
var mat_tween = create_tween()
mat_tween.tween_property(mat, "shader_parameter/hole_size", Vector2(0.72, 0.0), 0.3).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_IN)
var alpha_tween = create_tween()
alpha_tween.tween_property(photo_mode_texture_mask, "modulate:a", 0.0, 0.3).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN)
var tween = TweenFX.fold_out(photo_mode_texture_mask)
await tween.finished
photo_mode_texture_panel.hide()
func _on_photo_capture_prepare() -> void:
photo_mode_texture_panel.hide()
photo_mode_texture_mask.hide()
func _on_photo_taken_started() -> void:
photo_mode_texture_panel.show()
photo_mode_texture_mask.show()
photo_mode_black_screen.scale = Vector2(1,1)
photo_mode_black_screen.show()
var tween = TweenFX.fade_in(photo_mode_black_screen, 0.06)
await tween.finished
await RenderingServer.frame_post_draw
GameState.on_photo_taken_making.emit()
func _on_photo_taken_finished() -> void:
var tween = TweenFX.fade_out(photo_mode_black_screen, 0.06)
await tween.finished
photo_mode_black_screen.hide()
func hide_ui_for_photo_mode() -> void:
TweenFX.fade_out(weather_row, 0.25)
TweenFX.fade_out(time_of_day_row, 0.25)
TweenFX.fade_out(menu_icon_button, 0.25)
TweenFX.fade_out(collection_options, 0.25)
TweenFX.fade_out(audio_player, 0.25)
func show_ui_for_photo_mode() -> void:
weather_row.show()
time_of_day_row.show()
menu_icon_button.show()
collection_options.show()
audio_player.show()
TweenFX.fade_in(weather_row, 0.25)
TweenFX.fade_in(time_of_day_row, 0.25)
TweenFX.fade_in(menu_icon_button, 0.25)
TweenFX.fade_in(collection_options, 0.25)
TweenFX.fade_in(audio_player, 0.25)

View File

@@ -7,7 +7,13 @@
[ext_resource type="PackedScene" uid="uid://cpeyt1dgrtglc" path="res://core/radio/radio.tscn" id="5_nevjt"]
[ext_resource type="AudioStream" uid="uid://70cc8she43re" path="res://docs/gyms/radio/lofi_01.ogg" id="6_kd244"]
[ext_resource type="PackedScene" uid="uid://dg4f3v0ukpmay" path="res://core/main_scene_ui/audio_player.tscn" id="7_lapqe"]
[ext_resource type="PackedScene" uid="uid://dxun0jk5t0n6" path="res://core/tween/container_tween.tscn" id="8_msh61"]
[ext_resource type="PackedScene" uid="uid://cifadwamy04ko" path="res://core/main_scene_ui/photo_taken.tscn" id="8_t1xop"]
[ext_resource type="Texture2D" uid="uid://dcsy5yawnlxhq" path="res://core/photo_mode/assets/reticolo.png" id="9_4cc8f"]
[ext_resource type="Shader" uid="uid://dudbt51v33tt7" path="res://core/main_scene_ui/center_hole.gdshader" id="10_shader"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_hole"]
shader = ExtResource("10_shader")
shader_parameter/hole_size = Vector2(0.72, 0.806)
[node name="MainSceneUi" type="Control" unique_id=1359391222]
process_mode = 3
@@ -30,6 +36,7 @@ offset_right = 160.0
grow_vertical = 0
[node name="TimeOfDayRow" parent="VBoxContainer" unique_id=1734127019 instance=ExtResource("2_4cc8f")]
unique_name_in_owner = true
layout_mode = 2
[node name="IconButton2" parent="VBoxContainer/TimeOfDayRow" index="1" unique_id=638856991]
@@ -39,10 +46,10 @@ data = "Sunrise"
data = "Day"
[node name="IconButton4" parent="VBoxContainer/TimeOfDayRow" index="3" unique_id=1375190490]
data = "Sunset"
data = "Night"
[node name="IconButton5" parent="VBoxContainer/TimeOfDayRow" index="4" unique_id=315412403]
data = "Night"
data = "Cycle"
[node name="ShowContainerTween" parent="VBoxContainer/TimeOfDayRow" index="5" unique_id=160227524]
tween_types = Array[String](["impact_land", "fade_in"])
@@ -93,6 +100,7 @@ offset_left = -160.0
grow_horizontal = 0
[node name="CollectionOptions" type="VBoxContainer" parent="." unique_id=542153805]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 6
anchor_left = 1.0
@@ -114,6 +122,7 @@ unique_name_in_owner = true
layout_mode = 2
[node name="AudioPlayer" parent="." unique_id=425192018 node_paths=PackedStringArray("radio") instance=ExtResource("7_lapqe")]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
@@ -142,21 +151,56 @@ grow_vertical = 2
unique_name_in_owner = true
layout_mode = 1
[node name="PhotoModeTexturePanel" type="Panel" parent="." unique_id=901556197]
unique_name_in_owner = true
visible = false
material = SubResource("ShaderMaterial_hole")
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="PhotoModeTextureMask" type="TextureRect" parent="PhotoModeTexturePanel" unique_id=1377788813]
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
pivot_offset_ratio = Vector2(0.5, 0.5)
texture = ExtResource("9_4cc8f")
stretch_mode = 3
metadata/_edit_use_anchors_ = true
[node name="PhotoModeBlackScreen" type="ColorRect" parent="." unique_id=1928591477]
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
color = Color(0, 0, 0, 1)
[node name="PhotoTaken" parent="." unique_id=683693112 instance=ExtResource("8_t1xop")]
visible = false
layout_mode = 1
anchor_left = 0.465625
anchor_top = 0.4287037
anchor_right = 0.534375
anchor_bottom = 0.5712963
offset_right = 0.0
offset_bottom = 0.0
grow_horizontal = 2
grow_vertical = 2
[node name="Radio" parent="." unique_id=1234112225 instance=ExtResource("5_nevjt")]
playlist = Array[AudioStream]([ExtResource("6_kd244")])
[node name="ShowContainerTween" parent="." unique_id=902285649 node_paths=PackedStringArray("targets") instance=ExtResource("8_msh61")]
unique_name_in_owner = true
targets = [NodePath("../GameMenuPanel/GameMenu")]
tween_types = Array[String](["fold_in"])
show_on_start = true
[node name="HideContainerTween" parent="." unique_id=1041880010 node_paths=PackedStringArray("targets") instance=ExtResource("8_msh61")]
unique_name_in_owner = true
targets = [NodePath("../GameMenuPanel/GameMenu")]
tween_types = Array[String](["fold_out"])
hide_on_finish = true
[connection signal="on_option_changed" from="VBoxContainer/TimeOfDayRow" to="." method="_on_time_of_day_row_on_option_changed"]
[connection signal="on_option_changed" from="VBoxContainer/WeatherRow" to="." method="_on_weather_row_on_option_changed"]

View File

@@ -0,0 +1,26 @@
extends Control
@onready var photo_texture: TextureRect = $%PhotoTexture
func _ready() -> void:
GameState.on_photo_taken_prepare.connect(_hide_photo_taken)
GameState.on_photo_taken_finished.connect(_show_photo_taken)
CollectionManager.on_photo_saved.connect(_set_photo_taken)
func _hide_photo_taken() -> void:
hide()
func _set_photo_taken(file_path) -> void:
var image = Image.load_from_file(file_path)
if image:
var texture = ImageTexture.create_from_image(image)
photo_texture.texture = texture
func _show_photo_taken() -> void:
scale = Vector2(1,1)
modulate.a = 1.0
rotation_degrees = 0.0
show()
var tween = TweenFX.explode(self, 5, 3)
await tween.finished
hide()

View File

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

View File

@@ -0,0 +1,48 @@
[gd_scene format=3 uid="uid://cifadwamy04ko"]
[ext_resource type="Script" uid="uid://dyye4efo503ih" path="res://core/main_scene_ui/photo_taken.gd" id="1_1n86s"]
[node name="PhotoTaken" type="Control" unique_id=683693112]
custom_minimum_size = Vector2(132, 154)
layout_mode = 3
anchor_right = 0.06875
anchor_bottom = 0.1425926
offset_right = -132.0
offset_bottom = -154.0
pivot_offset_ratio = Vector2(0.5, 0.5)
script = ExtResource("1_1n86s")
metadata/_edit_use_anchors_ = true
[node name="ColorRect" type="ColorRect" parent="." unique_id=1876357733]
custom_minimum_size = Vector2(132, 154)
layout_mode = 1
anchors_preset = -1
anchor_left = 0.465625
anchor_top = 0.4287037
anchor_right = 0.534375
anchor_bottom = 0.5712963
grow_horizontal = 2
grow_vertical = 2
pivot_offset_ratio = Vector2(0.5, 0.5)
mouse_filter = 2
metadata/_edit_use_anchors_ = true
[node name="MarginContainer" type="MarginContainer" parent="ColorRect" unique_id=405077013]
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 = 14
theme_override_constants/margin_top = 15
theme_override_constants/margin_right = 14
theme_override_constants/margin_bottom = 50
[node name="PhotoTexture" type="TextureRect" parent="ColorRect/MarginContainer" unique_id=1754898569]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
mouse_filter = 2
expand_mode = 1
stretch_mode = 6

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dcsy5yawnlxhq"
path="res://.godot/imported/reticolo.png-dba8a0c9eb8601e74902df2dc1fc51e5.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://core/photo_mode/assets/reticolo.png"
dest_files=["res://.godot/imported/reticolo.png-dba8a0c9eb8601e74902df2dc1fc51e5.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@@ -31,9 +31,10 @@ func get_all_collectibles() -> Array[CollectibleResource]:
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()
func save_photo_to_disk_async(image: Image) -> void:
if not image:
return
if not DirAccess.dir_exists_absolute("user://photos"):
DirAccess.make_dir_absolute("user://photos")

View File

@@ -21,9 +21,13 @@ var previous_camera: Camera3D
var initial_local_pos: Vector3
var initial_local_basis: Basis
var is_making_photo = false
var captured_image: Image
func _ready() -> void:
GameState.on_enable_photo_mode_request.connect(enable_photo_mode)
GameState.on_disable_photo_mode_request.connect(disable_photo_mode)
GameState.on_photo_taken_making.connect(take_photo_async)
initial_local_pos = position
initial_local_basis = basis
@@ -48,15 +52,25 @@ func disable_photo_mode() -> void:
func _input(event: InputEvent) -> void:
if event.is_action_pressed("toggle_photo_mode"):
if not is_active:
enable_photo_mode()
GameState.on_enable_photo_mode_request.emit()
else:
disable_photo_mode()
if not is_making_photo:
GameState.on_disable_photo_mode_request.emit()
if event is InputEventMouseMotion and is_active:
total_yaw -= event.relative.x * rotation_speed
if event.is_action_pressed("take_photo"):
take_photo_async()
if !is_active or is_making_photo:
return
is_making_photo = true
GameState.on_photo_taken_prepare.emit()
await RenderingServer.frame_post_draw
captured_image = get_viewport().get_texture().get_image()
GameState.on_photo_taken_started.emit()
func _process(delta: float) -> void:
if not is_active:
@@ -81,13 +95,10 @@ func _process(delta: float) -> void:
basis = rotated_basis.orthonormalized()
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()
await CollectionManager.save_photo_to_disk_async(captured_image)
for target in targets:
if not target.collectible_data:
@@ -104,3 +115,5 @@ func take_photo_async() -> void:
CollectionManager.unlock_collectible(target.collectible_data.id)
GameState.save_game()
GameState.on_photo_taken_finished.emit()
is_making_photo = false