Unify menu presentation and fix UI regressions
This commit is contained in:
parent
3734d4a168
commit
b18d9392d8
35 changed files with 588 additions and 361 deletions
|
|
@ -38,8 +38,8 @@ application/icon_interpolation=4
|
|||
application/file_version="0.2.0.2"
|
||||
application/product_version="0.2.0.2"
|
||||
application/company_name=""
|
||||
application/product_name="NETFISHING"
|
||||
application/file_description="NETFISHING Pre-Alpha Playtest 0.2"
|
||||
application/product_name="NETfishing"
|
||||
application/file_description="NETfishing Pre-Alpha Playtest 0.2"
|
||||
application/copyright=""
|
||||
application/trademarks=""
|
||||
application/export_angle=0
|
||||
|
|
|
|||
16
main/main.gd
16
main/main.gd
|
|
@ -132,6 +132,7 @@ const TITLE_MUSIC_SILENCE_DB: float = -80.0
|
|||
%NetworkProfileService
|
||||
)
|
||||
@onready var _players_root: Node3D = $Players
|
||||
@onready var _title_background: ColorRect = %TitleBackground
|
||||
|
||||
var _gameplay_started: bool = false
|
||||
var _shop_interaction: FishingShopInteractionType
|
||||
|
|
@ -154,6 +155,7 @@ var _pending_existing_root_path := ""
|
|||
|
||||
|
||||
func _ready() -> void:
|
||||
DisplayServer.window_set_title("NETfishing")
|
||||
if not _settings_manager.settings_changed.is_connected(
|
||||
_apply_runtime_settings
|
||||
):
|
||||
|
|
@ -486,7 +488,7 @@ func _initialize_after_data_root() -> void:
|
|||
func _show_data_root_setup() -> void:
|
||||
if _data_setup_dialog == null:
|
||||
_data_setup_dialog = ConfirmationDialog.new()
|
||||
_data_setup_dialog.title = "NETFISHING player data"
|
||||
_data_setup_dialog.title = "NETfishing player data"
|
||||
_data_setup_dialog.ok_button_text = "Use This Folder"
|
||||
_data_setup_dialog.cancel_button_text = "Quit"
|
||||
_data_setup_dialog.confirmed.connect(_use_default_data_root)
|
||||
|
|
@ -503,8 +505,8 @@ func _show_data_root_setup() -> void:
|
|||
var default_path: String = _data_root.default_visible_path()
|
||||
var legacy: bool = PortableDataMigration.legacy_files_present()
|
||||
_data_setup_dialog.dialog_text = (
|
||||
("Move your existing NETFISHING data to an easy-to-find folder."
|
||||
if legacy else "Choose where NETFISHING stores your player data.")
|
||||
("Move your existing NETfishing data to an easy-to-find folder."
|
||||
if legacy else "Choose where NETfishing stores your player data.")
|
||||
+ "\n\n%s\n\nYou can choose a Syncthing folder."
|
||||
% (default_path if not default_path.is_empty() else "Choose a folder")
|
||||
)
|
||||
|
|
@ -513,7 +515,7 @@ func _show_data_root_setup() -> void:
|
|||
)
|
||||
if not _data_root.error_message.is_empty():
|
||||
_data_setup_dialog.dialog_text = (
|
||||
"Your NETFISHING data folder is unavailable.\n\n%s"
|
||||
"Your NETfishing data folder is unavailable.\n\n%s"
|
||||
% _data_root.error_message
|
||||
)
|
||||
_data_setup_dialog.popup_centered(Vector2i(640, 360))
|
||||
|
|
@ -621,11 +623,11 @@ func _activate_selected_data_path(path: String, app_data: bool = false) -> void:
|
|||
func _show_existing_root_choice(path: String) -> void:
|
||||
_pending_existing_root_path = path
|
||||
var dialog: ConfirmationDialog = ConfirmationDialog.new()
|
||||
dialog.title = "Existing NETFISHING data"
|
||||
dialog.title = "Existing NETfishing data"
|
||||
dialog.ok_button_text = "Use Data Already in Selected Folder"
|
||||
dialog.cancel_button_text = "Cancel"
|
||||
dialog.dialog_text = (
|
||||
"This folder already contains NETFISHING player data.\n\n"
|
||||
"This folder already contains NETfishing player data.\n\n"
|
||||
+ "Choose which complete data set to use. Data is never merged automatically."
|
||||
)
|
||||
dialog.add_button(
|
||||
|
|
@ -869,12 +871,14 @@ func _reset_pixelation() -> void:
|
|||
|
||||
func _set_gameplay_active(active: bool) -> void:
|
||||
_gameplay_started = active
|
||||
_title_background.visible = not active
|
||||
_world_pixelation.set_gameplay_active(active)
|
||||
_ui_pixelation.set_gameplay_active(active)
|
||||
if not active:
|
||||
_player.item_effects.reset_all()
|
||||
_player.set_movement_enabled(active)
|
||||
_player.set_camera_input_enabled(active)
|
||||
_player.set_camera_active(active)
|
||||
_fishing_spot.set_gameplay_input_enabled(active)
|
||||
_water_recovery.set_recovery_enabled(active)
|
||||
_game_ui.set_gameplay_ui_enabled(active)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
[gd_scene load_steps=40 format=3]
|
||||
[gd_scene load_steps=42 format=3]
|
||||
|
||||
[ext_resource type="PackedScene" path="res://world/test_world.tscn" id="1_world"]
|
||||
[ext_resource type="PackedScene" path="res://player/player.tscn" id="2_player"]
|
||||
|
|
@ -39,6 +39,10 @@
|
|||
[ext_resource type="Script" path="res://network/player_data_root.gd" id="37_data_root"]
|
||||
[ext_resource type="Script" path="res://network/identity_backup_service.gd" id="38_identity_backup"]
|
||||
[ext_resource type="Script" path="res://ui/interface_font_controller.gd" id="39_fonts"]
|
||||
[ext_resource type="Shader" path="res://ui/title_water_background.gdshader" id="40_title_water"]
|
||||
|
||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_title_water_native"]
|
||||
shader = ExtResource("40_title_water")
|
||||
|
||||
[node name="Main" type="Node3D"]
|
||||
script = ExtResource("3_main")
|
||||
|
|
@ -47,6 +51,20 @@ pelican_buyer_profile = ExtResource("7_pelicans")
|
|||
main_shop_buyer_profile = ExtResource("12_main_shop")
|
||||
item_catalog = ExtResource("11_items")
|
||||
|
||||
[node name="TitleBackgroundLayer" type="CanvasLayer" parent="."]
|
||||
unique_name_in_owner = true
|
||||
layer = -1
|
||||
|
||||
[node name="TitleBackground" type="ColorRect" parent="TitleBackgroundLayer"]
|
||||
unique_name_in_owner = true
|
||||
material = SubResource("ShaderMaterial_title_water_native")
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="InterfaceFontController" type="Node" parent="."]
|
||||
unique_name_in_owner = true
|
||||
script = ExtResource("39_fonts")
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ func import_backup(
|
|||
)
|
||||
_finish(
|
||||
bool(result.get("ok", false)),
|
||||
"Identity imported. Restart NETFISHING before multiplayer."
|
||||
"Identity imported. Restart NETfishing before multiplayer."
|
||||
if bool(result.get("ok", false))
|
||||
else "Could not install this identity backup.",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ static func make_server_hello(
|
|||
"protocol_version": PROTOCOL_VERSION,
|
||||
"session_id": session_id,
|
||||
"assigned_peer_id": assigned_peer_id,
|
||||
"server_display_name": "NETFISHING",
|
||||
"server_display_name": "NETfishing",
|
||||
"player_count": player_count,
|
||||
"max_players": max_players,
|
||||
"capability_flags": PackedStringArray([
|
||||
|
|
|
|||
|
|
@ -787,7 +787,7 @@ func resolve_server_trust(accepted: bool) -> void:
|
|||
if not _server_trust.trust(
|
||||
get_current_endpoint(),
|
||||
str(_pending_server_proof["server_fingerprint"]),
|
||||
"NETFISHING",
|
||||
"NETfishing",
|
||||
):
|
||||
_fail_identity("The server identity could not be pinned.")
|
||||
return
|
||||
|
|
|
|||
|
|
@ -86,16 +86,16 @@ func select_new_root(path: String, app_data: bool = false) -> bool:
|
|||
if FileAccess.file_exists(manifest_path):
|
||||
var manifest: Dictionary = _read_json(manifest_path)
|
||||
if not _valid_manifest(manifest):
|
||||
return _fail("The selected folder has a malformed NETFISHING manifest.")
|
||||
return _fail("The selected folder has a malformed NETfishing manifest.")
|
||||
root_id = str(manifest["root_id"])
|
||||
else:
|
||||
if not _directory_is_empty(normalized) and not app_data:
|
||||
return _fail(
|
||||
"Choose an empty folder or an existing NETFISHING data folder."
|
||||
"Choose an empty folder or an existing NETfishing data folder."
|
||||
)
|
||||
root_id = Crypto.new().generate_random_bytes(16).hex_encode()
|
||||
if not _create_layout(normalized, root_id):
|
||||
return _fail("The NETFISHING data folder could not be created.")
|
||||
return _fail("The NETfishing data folder could not be created.")
|
||||
if not _write_bootstrap(normalized, root_id):
|
||||
return _fail("The data-folder pointer could not be saved.")
|
||||
root_path = normalized
|
||||
|
|
@ -207,15 +207,15 @@ func _activate_existing(path: String, expected_id: String, permit_creation: bool
|
|||
return false
|
||||
var manifest_path: String = normalized.path_join(MANIFEST_FILENAME)
|
||||
if not FileAccess.file_exists(manifest_path):
|
||||
return _fail("The selected folder is not a NETFISHING data folder.")
|
||||
return _fail("The selected folder is not a NETfishing data folder.")
|
||||
var manifest: Dictionary = _read_json(manifest_path)
|
||||
if not _valid_manifest(manifest):
|
||||
return _fail("The NETFISHING data-folder manifest is malformed.")
|
||||
return _fail("The NETfishing data-folder manifest is malformed.")
|
||||
var found_id: String = str(manifest["root_id"])
|
||||
if not expected_id.is_empty() and expected_id != found_id:
|
||||
return _fail("The selected data folder does not match this device pointer.")
|
||||
if not _test_writable(normalized):
|
||||
return _fail("The NETFISHING data folder is unavailable or unwritable.")
|
||||
return _fail("The NETfishing data folder is unavailable or unwritable.")
|
||||
root_path = normalized
|
||||
root_id = found_id
|
||||
requires_selection = false
|
||||
|
|
@ -270,7 +270,7 @@ func _create_layout(path: String, id: String) -> bool:
|
|||
):
|
||||
return false
|
||||
var readme: String = (
|
||||
"NETFISHING player data\n\n"
|
||||
"NETfishing player data\n\n"
|
||||
+ "This folder is safe to synchronize with tools such as Syncthing.\n"
|
||||
+ "Active private identity keys remain device-local.\n"
|
||||
+ "Encrypted identity backups require their passphrase.\n"
|
||||
|
|
|
|||
|
|
@ -33,12 +33,12 @@ static func migrate_legacy_to(
|
|||
return {
|
||||
"ok": false,
|
||||
"requires_existing_root_decision": true,
|
||||
"message": "The selected folder already contains NETFISHING data.",
|
||||
"message": "The selected folder already contains NETfishing data.",
|
||||
}
|
||||
if not _directory_empty(normalized):
|
||||
return {
|
||||
"ok": false,
|
||||
"message": "Choose an empty folder or create a NETFISHING subfolder.",
|
||||
"message": "Choose an empty folder or create a NETfishing subfolder.",
|
||||
}
|
||||
var staging: String = "%s.migration-%s" % [
|
||||
normalized, Crypto.new().generate_random_bytes(8).hex_encode()
|
||||
|
|
@ -107,11 +107,11 @@ static func migrate_active_to(
|
|||
"ok": false,
|
||||
"requires_existing_root_decision": true,
|
||||
"message": (
|
||||
"The selected folder already contains NETFISHING data. "
|
||||
"The selected folder already contains NETfishing data. "
|
||||
+ "Choose it through the existing-data recovery flow."
|
||||
),
|
||||
}
|
||||
return {"ok": false, "message": "Choose an empty folder or a NETFISHING subfolder."}
|
||||
return {"ok": false, "message": "Choose an empty folder or a NETfishing subfolder."}
|
||||
var staging: String = "%s.migration-%s" % [
|
||||
normalized, Crypto.new().generate_random_bytes(8).hex_encode()
|
||||
]
|
||||
|
|
@ -188,7 +188,7 @@ static func replace_existing_with_legacy(
|
|||
var normalized: String = destination.simplify_path().trim_suffix("/")
|
||||
var manifest: String = normalized.path_join(PlayerDataRoot.MANIFEST_FILENAME)
|
||||
if not FileAccess.file_exists(manifest):
|
||||
return {"ok": false, "message": "The selected folder is not a NETFISHING data root."}
|
||||
return {"ok": false, "message": "The selected folder is not a NETfishing data root."}
|
||||
var recovery: String = ProjectSettings.globalize_path(
|
||||
"user://migration-recovery"
|
||||
).path_join(
|
||||
|
|
@ -209,7 +209,7 @@ static func replace_existing_with_active(
|
|||
) -> Dictionary:
|
||||
var normalized: String = destination.simplify_path().trim_suffix("/")
|
||||
if not FileAccess.file_exists(normalized.path_join(PlayerDataRoot.MANIFEST_FILENAME)):
|
||||
return {"ok": false, "message": "The selected folder is not a NETFISHING data root."}
|
||||
return {"ok": false, "message": "The selected folder is not a NETfishing data root."}
|
||||
var recovery: String = ProjectSettings.globalize_path(
|
||||
"user://migration-recovery"
|
||||
).path_join(
|
||||
|
|
|
|||
|
|
@ -26,8 +26,7 @@ var appearance_snapshot: Dictionary = (
|
|||
func apply_appearance_snapshot(snapshot: Dictionary) -> void:
|
||||
if CharacterCustomizationCatalog.validate_snapshot(snapshot):
|
||||
appearance_snapshot = snapshot.duplicate(true)
|
||||
# Current gameplay art is monolithic. This seam intentionally stores the
|
||||
# validated state until modular visual parts are available.
|
||||
PlayerVisualPresenter.apply_appearance(_visuals, appearance_snapshot)
|
||||
|
||||
class ShowcaseCameraSnapshot:
|
||||
extends RefCounted
|
||||
|
|
@ -495,6 +494,10 @@ func set_camera_input_enabled(enabled: bool) -> void:
|
|||
_camera_dragging = false
|
||||
|
||||
|
||||
func set_camera_active(active: bool) -> void:
|
||||
_camera.current = active
|
||||
|
||||
|
||||
func apply_camera_settings(
|
||||
new_mouse_sensitivity: float,
|
||||
new_controller_sensitivity: float,
|
||||
|
|
|
|||
28
player/player_visual_presenter.gd
Normal file
28
player/player_visual_presenter.gd
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
class_name PlayerVisualPresenter
|
||||
extends RefCounted
|
||||
|
||||
const PlayerScene: PackedScene = preload("res://player/player.tscn")
|
||||
|
||||
|
||||
static func instantiate_visuals() -> Node3D:
|
||||
var source: Player = PlayerScene.instantiate()
|
||||
var visuals := source.get_node("Visuals") as Node3D
|
||||
var presentation := visuals.duplicate(
|
||||
Node.DUPLICATE_SIGNALS
|
||||
| Node.DUPLICATE_GROUPS
|
||||
| Node.DUPLICATE_SCRIPTS
|
||||
| Node.DUPLICATE_USE_INSTANTIATION
|
||||
) as Node3D
|
||||
source.free()
|
||||
presentation.name = "PlayerVisuals"
|
||||
return presentation
|
||||
|
||||
|
||||
static func apply_appearance(
|
||||
_visuals: Node3D,
|
||||
snapshot: Dictionary,
|
||||
) -> void:
|
||||
# Gameplay and preview deliberately share this presentation seam. Modular
|
||||
# visual parts can be applied here without coupling Profile to Player.
|
||||
if not CharacterCustomizationCatalog.validate_snapshot(snapshot):
|
||||
return
|
||||
1
player/player_visual_presenter.gd.uid
Normal file
1
player/player_visual_presenter.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://b4w23asm85rtu
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
NETFISHING
|
||||
NETfishing
|
||||
Pre-Alpha Playtest 0.2
|
||||
Version 0.2.0-prealpha.2
|
||||
|
||||
Thank you for trying this early private playtest.
|
||||
|
||||
NETFISHING is currently a local gameplay prototype for a future
|
||||
NETfishing is currently a local gameplay prototype for a future
|
||||
multiplayer-first game. Networking and multiplayer are NOT implemented in
|
||||
this build.
|
||||
|
||||
|
|
|
|||
|
|
@ -96,6 +96,9 @@ func _unhandled_input(event: InputEvent) -> void:
|
|||
):
|
||||
open_chat()
|
||||
get_viewport().set_input_as_handled()
|
||||
elif event.keycode == KEY_T and not _opened and _available:
|
||||
open_chat()
|
||||
get_viewport().set_input_as_handled()
|
||||
elif event.keycode == KEY_ESCAPE and _opened:
|
||||
close_chat()
|
||||
get_viewport().set_input_as_handled()
|
||||
|
|
|
|||
|
|
@ -72,9 +72,6 @@ var _item_effects: PlayerItemEffectsType
|
|||
|
||||
|
||||
func _ready() -> void:
|
||||
_pause_menu.chat_requested.connect(
|
||||
func() -> void: call_deferred("_open_chat_from_pause")
|
||||
)
|
||||
_title_settings_panel.panel_visibility_changed.connect(
|
||||
_on_settings_visibility_changed
|
||||
)
|
||||
|
|
@ -89,10 +86,6 @@ func _ready() -> void:
|
|||
)
|
||||
|
||||
|
||||
func _open_chat_from_pause() -> void:
|
||||
_chat_ui.open_chat()
|
||||
|
||||
|
||||
func setup(
|
||||
player: PlayerType,
|
||||
inventory: FishInventoryType,
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ var _current_mail_id := ""
|
|||
|
||||
func _ready() -> void:
|
||||
set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
UtilityPageStyle.apply_page(self)
|
||||
_build_ui()
|
||||
|
||||
|
||||
|
|
@ -75,6 +76,7 @@ func setup(
|
|||
|
||||
func activate() -> void:
|
||||
_show_inbox()
|
||||
UtilityPageStyle.animate_in(self)
|
||||
call_deferred("_focus_first")
|
||||
|
||||
|
||||
|
|
@ -103,14 +105,7 @@ func _build_ui() -> void:
|
|||
var paper := PanelContainer.new()
|
||||
paper.position = Vector2(116, 126)
|
||||
paper.size = Vector2(1048, 470)
|
||||
var style := StyleBoxFlat.new()
|
||||
style.bg_color = Color("f3ecd7")
|
||||
style.border_color = Color("665a46")
|
||||
style.set_border_width_all(4)
|
||||
style.set_corner_radius_all(18)
|
||||
style.shadow_color = Color(0.05, 0.04, 0.03, 0.42)
|
||||
style.shadow_size = 7
|
||||
paper.add_theme_stylebox_override("panel", style)
|
||||
paper.add_theme_stylebox_override("panel", UtilityPageStyle.panel_style())
|
||||
add_child(paper)
|
||||
var margin := MarginContainer.new()
|
||||
margin.add_theme_constant_override("margin_left", 34)
|
||||
|
|
@ -132,13 +127,14 @@ func _build_ui() -> void:
|
|||
_status.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
_status.add_theme_color_override("font_color", Color("4a3f31"))
|
||||
root.add_child(_status)
|
||||
_style_controls(root)
|
||||
_show_inbox()
|
||||
|
||||
|
||||
func _build_inbox() -> Control:
|
||||
var page := Control.new()
|
||||
var title := Label.new()
|
||||
title.text = "session mail"
|
||||
title.text = "Mail"
|
||||
title.position = Vector2(12, 0)
|
||||
title.size = Vector2(500, 42)
|
||||
title.add_theme_font_size_override("font_size", 30)
|
||||
|
|
@ -367,6 +363,7 @@ func _refresh_inbox() -> void:
|
|||
button.custom_minimum_size = Vector2(930, 54)
|
||||
button.alignment = HORIZONTAL_ALIGNMENT_LEFT
|
||||
button.pressed.connect(_open_letter.bind(str(letter["mail_id"])))
|
||||
UtilityPageStyle.apply_button(button)
|
||||
_inbox_list.add_child(button)
|
||||
|
||||
|
||||
|
|
@ -601,3 +598,24 @@ func _focus_first() -> void:
|
|||
var buttons := _inbox_list.find_children("*", "Button", true, false)
|
||||
if not buttons.is_empty():
|
||||
(buttons.front() as Button).grab_focus()
|
||||
|
||||
|
||||
func _style_controls(root: Node) -> void:
|
||||
for node: Node in root.find_children("*", "", true, false):
|
||||
if node is BaseButton:
|
||||
UtilityPageStyle.apply_button(node)
|
||||
elif node is LineEdit:
|
||||
UtilityPageStyle.apply_line_edit(node)
|
||||
elif node is Label:
|
||||
node.add_theme_color_override(
|
||||
"font_color", UtilityPageStyle.INK
|
||||
)
|
||||
elif node is TextEdit:
|
||||
node.add_theme_font_override("font", UtilityPageStyle.TuffyFont)
|
||||
node.add_theme_color_override(
|
||||
"font_color", UtilityPageStyle.LIGHT_TEXT
|
||||
)
|
||||
node.add_theme_color_override(
|
||||
"font_placeholder_color",
|
||||
Color(0.82, 0.80, 0.71, 0.84)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -26,17 +26,17 @@ const DIRECT_WORKFLOW_HELP: String = (
|
|||
@onready var _name_helper: Label = %NameHelper
|
||||
@onready var _server_list: ItemList = %ServerList
|
||||
@onready var _details: Label = %Details
|
||||
@onready var _direct_button: BubbleButton = %DirectButton
|
||||
@onready var _saved_button: BubbleButton = %SavedButton
|
||||
@onready var _recent_button: BubbleButton = %RecentButton
|
||||
@onready var _join_button: BubbleButton = %JoinButton
|
||||
@onready var _save_button: BubbleButton = %SaveButton
|
||||
@onready var _edit_button: BubbleButton = %EditButton
|
||||
@onready var _favorite_button: BubbleButton = %FavoriteButton
|
||||
@onready var _delete_button: BubbleButton = %DeleteButton
|
||||
@onready var _cancel_button: BubbleButton = %CancelButton
|
||||
@onready var _back_button: BubbleButton = %BackButton
|
||||
@onready var _open_close_button: BubbleButton = %OpenCloseButton
|
||||
@onready var _direct_button: Button = %DirectButton
|
||||
@onready var _saved_button: Button = %SavedButton
|
||||
@onready var _recent_button: Button = %RecentButton
|
||||
@onready var _join_button: Button = %JoinButton
|
||||
@onready var _save_button: Button = %SaveButton
|
||||
@onready var _edit_button: Button = %EditButton
|
||||
@onready var _favorite_button: Button = %FavoriteButton
|
||||
@onready var _delete_button: Button = %DeleteButton
|
||||
@onready var _cancel_button: Button = %CancelButton
|
||||
@onready var _back_button: Button = %BackButton
|
||||
@onready var _open_close_button: Button = %OpenCloseButton
|
||||
@onready var _status: Label = %Status
|
||||
@onready var _session_summary: Label = %SessionSummary
|
||||
@onready var _delete_confirmation: BubbleConfirmationPage = (
|
||||
|
|
@ -56,6 +56,19 @@ var _delete_armed: bool = false
|
|||
|
||||
|
||||
func _ready() -> void:
|
||||
UtilityPageStyle.apply_page(self)
|
||||
var paper := get_node("Paper") as PanelContainer
|
||||
paper.add_theme_stylebox_override(
|
||||
"panel", UtilityPageStyle.panel_style()
|
||||
)
|
||||
for button: BaseButton in [
|
||||
_direct_button, _saved_button, _recent_button, _join_button,
|
||||
_save_button, _edit_button, _favorite_button, _delete_button,
|
||||
_cancel_button, _back_button, _open_close_button,
|
||||
]:
|
||||
UtilityPageStyle.apply_button(button)
|
||||
UtilityPageStyle.apply_line_edit(_address)
|
||||
UtilityPageStyle.apply_line_edit(_name_edit)
|
||||
_direct_button.pressed.connect(_set_mode.bind(Mode.DIRECT))
|
||||
_saved_button.pressed.connect(_set_mode.bind(Mode.SAVED))
|
||||
_recent_button.pressed.connect(_set_mode.bind(Mode.RECENT))
|
||||
|
|
@ -126,6 +139,7 @@ func open_page(preserved_endpoint: String = "") -> void:
|
|||
elif _address.text.is_empty():
|
||||
_address.text = "127.0.0.1:7777"
|
||||
show()
|
||||
UtilityPageStyle.animate_in(self)
|
||||
_set_mode(_mode)
|
||||
if _mode == Mode.DIRECT:
|
||||
_address.grab_focus()
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
[gd_scene load_steps=13 format=3]
|
||||
[gd_scene load_steps=12 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://ui/network/join_game_page.gd" id="1_script"]
|
||||
[ext_resource type="Theme" path="res://ui/game_theme.tres" id="2_theme"]
|
||||
[ext_resource type="PackedScene" path="res://ui/components/bubble_menu/bubble_button.tscn" id="3_bubble"]
|
||||
[ext_resource type="PackedScene" path="res://ui/components/bubble_menu/bubble_confirmation_page.tscn" id="4_confirmation"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBox_paper"]
|
||||
|
|
@ -128,41 +127,23 @@ layout_mode = 2
|
|||
theme_override_constants/separation = 14
|
||||
alignment = 1
|
||||
|
||||
[node name="DirectButton" parent="Paper/Margin/Layout/Modes" instance=ExtResource("3_bubble")]
|
||||
[node name="DirectButton" type="Button" parent="Paper/Margin/Layout/Modes"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(100, 72)
|
||||
layout_mode = 2
|
||||
text = "direct"
|
||||
neutral_size = Vector2(100, 72)
|
||||
minimum_font_size = 16
|
||||
maximum_font_size = 19
|
||||
horizontal_amplitude = 0.0
|
||||
vertical_amplitude = 0.0
|
||||
deformation_amplitude = 0.0
|
||||
|
||||
[node name="SavedButton" parent="Paper/Margin/Layout/Modes" instance=ExtResource("3_bubble")]
|
||||
[node name="SavedButton" type="Button" parent="Paper/Margin/Layout/Modes"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(100, 72)
|
||||
layout_mode = 2
|
||||
text = "saved"
|
||||
neutral_size = Vector2(100, 72)
|
||||
minimum_font_size = 16
|
||||
maximum_font_size = 19
|
||||
horizontal_amplitude = 0.0
|
||||
vertical_amplitude = 0.0
|
||||
deformation_amplitude = 0.0
|
||||
|
||||
[node name="RecentButton" parent="Paper/Margin/Layout/Modes" instance=ExtResource("3_bubble")]
|
||||
[node name="RecentButton" type="Button" parent="Paper/Margin/Layout/Modes"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(100, 72)
|
||||
layout_mode = 2
|
||||
text = "recent"
|
||||
neutral_size = Vector2(100, 72)
|
||||
minimum_font_size = 16
|
||||
maximum_font_size = 19
|
||||
horizontal_amplitude = 0.0
|
||||
vertical_amplitude = 0.0
|
||||
deformation_amplitude = 0.0
|
||||
|
||||
[node name="AddressLabel" type="Label" parent="Paper/Margin/Layout"]
|
||||
unique_name_in_owner = true
|
||||
|
|
@ -290,106 +271,58 @@ layout_mode = 2
|
|||
theme_override_constants/separation = 7
|
||||
alignment = 1
|
||||
|
||||
[node name="JoinButton" parent="Paper/Margin/Layout/Actions" instance=ExtResource("3_bubble")]
|
||||
[node name="JoinButton" type="Button" parent="Paper/Margin/Layout/Actions"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(82, 72)
|
||||
layout_mode = 2
|
||||
text = "join"
|
||||
neutral_size = Vector2(82, 72)
|
||||
minimum_font_size = 15
|
||||
maximum_font_size = 18
|
||||
horizontal_amplitude = 0.0
|
||||
vertical_amplitude = 0.0
|
||||
deformation_amplitude = 0.0
|
||||
|
||||
[node name="SaveButton" parent="Paper/Margin/Layout/Actions" instance=ExtResource("3_bubble")]
|
||||
[node name="SaveButton" type="Button" parent="Paper/Margin/Layout/Actions"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(82, 72)
|
||||
layout_mode = 2
|
||||
text = "save\nserver"
|
||||
neutral_size = Vector2(82, 72)
|
||||
minimum_font_size = 14
|
||||
maximum_font_size = 17
|
||||
horizontal_amplitude = 0.0
|
||||
vertical_amplitude = 0.0
|
||||
deformation_amplitude = 0.0
|
||||
|
||||
[node name="EditButton" parent="Paper/Margin/Layout/Actions" instance=ExtResource("3_bubble")]
|
||||
[node name="EditButton" type="Button" parent="Paper/Margin/Layout/Actions"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
custom_minimum_size = Vector2(76, 68)
|
||||
layout_mode = 2
|
||||
text = "edit"
|
||||
neutral_size = Vector2(76, 68)
|
||||
minimum_font_size = 14
|
||||
maximum_font_size = 17
|
||||
horizontal_amplitude = 0.0
|
||||
vertical_amplitude = 0.0
|
||||
deformation_amplitude = 0.0
|
||||
|
||||
[node name="FavoriteButton" parent="Paper/Margin/Layout/Actions" instance=ExtResource("3_bubble")]
|
||||
[node name="FavoriteButton" type="Button" parent="Paper/Margin/Layout/Actions"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
custom_minimum_size = Vector2(88, 68)
|
||||
layout_mode = 2
|
||||
text = "favorite"
|
||||
neutral_size = Vector2(88, 68)
|
||||
minimum_font_size = 13
|
||||
maximum_font_size = 16
|
||||
horizontal_amplitude = 0.0
|
||||
vertical_amplitude = 0.0
|
||||
deformation_amplitude = 0.0
|
||||
|
||||
[node name="DeleteButton" parent="Paper/Margin/Layout/Actions" instance=ExtResource("3_bubble")]
|
||||
[node name="DeleteButton" type="Button" parent="Paper/Margin/Layout/Actions"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
custom_minimum_size = Vector2(82, 68)
|
||||
layout_mode = 2
|
||||
text = "delete"
|
||||
neutral_size = Vector2(82, 68)
|
||||
minimum_font_size = 13
|
||||
maximum_font_size = 16
|
||||
horizontal_amplitude = 0.0
|
||||
vertical_amplitude = 0.0
|
||||
deformation_amplitude = 0.0
|
||||
|
||||
[node name="OpenCloseButton" parent="Paper/Margin/Layout/Actions" instance=ExtResource("3_bubble")]
|
||||
[node name="OpenCloseButton" type="Button" parent="Paper/Margin/Layout/Actions"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
custom_minimum_size = Vector2(88, 72)
|
||||
layout_mode = 2
|
||||
text = "open\ngame"
|
||||
neutral_size = Vector2(88, 72)
|
||||
minimum_font_size = 14
|
||||
maximum_font_size = 17
|
||||
horizontal_amplitude = 0.0
|
||||
vertical_amplitude = 0.0
|
||||
deformation_amplitude = 0.0
|
||||
|
||||
[node name="CancelButton" parent="Paper/Margin/Layout/Actions" instance=ExtResource("3_bubble")]
|
||||
[node name="CancelButton" type="Button" parent="Paper/Margin/Layout/Actions"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
custom_minimum_size = Vector2(76, 68)
|
||||
layout_mode = 2
|
||||
text = "cancel"
|
||||
neutral_size = Vector2(76, 68)
|
||||
minimum_font_size = 14
|
||||
maximum_font_size = 17
|
||||
horizontal_amplitude = 0.0
|
||||
vertical_amplitude = 0.0
|
||||
deformation_amplitude = 0.0
|
||||
|
||||
[node name="BackButton" parent="Paper/Margin/Layout/Actions" instance=ExtResource("3_bubble")]
|
||||
[node name="BackButton" type="Button" parent="Paper/Margin/Layout/Actions"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(76, 68)
|
||||
layout_mode = 2
|
||||
text = "back"
|
||||
neutral_size = Vector2(76, 68)
|
||||
minimum_font_size = 14
|
||||
maximum_font_size = 17
|
||||
horizontal_amplitude = 0.0
|
||||
vertical_amplitude = 0.0
|
||||
deformation_amplitude = 0.0
|
||||
|
||||
[node name="DeleteConfirmation" parent="." instance=ExtResource("4_confirmation")]
|
||||
unique_name_in_owner = true
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ const INPUT_OWNER: StringName = &"game_menu"
|
|||
const PAUSE_DESKTOP_REFERENCE_SIZE: Vector2 = Vector2(1280.0, 720.0)
|
||||
const PAUSE_COMPACT_REFERENCE_SIZE: Vector2 = Vector2(640.0, 480.0)
|
||||
const COMPACT_HEIGHT_THRESHOLD: float = 560.0
|
||||
const PAGE_OUTGOING_DURATION: float = 1.70
|
||||
const PAGE_INCOMING_DURATION: float = 1.85
|
||||
const VISIBILITY_FADE_DURATION: float = 0.55
|
||||
const BACKDROP_TARGET_ALPHA: float = 0.68
|
||||
const PlayerType = preload("res://player/player.gd")
|
||||
|
|
@ -28,7 +26,6 @@ signal reset_progress_requested
|
|||
signal quit_requested
|
||||
signal menu_visibility_changed(is_open: bool)
|
||||
signal join_game_requested(endpoint: String)
|
||||
signal chat_requested
|
||||
|
||||
enum ConfirmationAction {
|
||||
NONE,
|
||||
|
|
@ -88,7 +85,6 @@ func _ready() -> void:
|
|||
_save_button.pressed.connect(_save_now)
|
||||
%SettingsButton.pressed.connect(_open_settings)
|
||||
%JoinGameButton.pressed.connect(_open_join_game)
|
||||
%ChatButton.pressed.connect(_request_chat)
|
||||
%ReturnToTitleButton.pressed.connect(_confirm_return_to_title)
|
||||
%ResetProgressButton.pressed.connect(_confirm_reset_progress)
|
||||
%QuitButton.pressed.connect(_request_quit)
|
||||
|
|
@ -96,6 +92,7 @@ func _ready() -> void:
|
|||
_confirmation_page.cancelled.connect(_close_confirmation)
|
||||
_settings_panel.applied.connect(_on_settings_applied)
|
||||
_settings_panel.closed.connect(_on_settings_closed)
|
||||
_settings_panel.closing.connect(_on_settings_closing)
|
||||
_settings_panel.navigation_transition_started.connect(
|
||||
_emit_transition_flurry
|
||||
)
|
||||
|
|
@ -107,13 +104,6 @@ func _ready() -> void:
|
|||
call_deferred("_update_responsive_pause_stage")
|
||||
|
||||
|
||||
func _request_chat() -> void:
|
||||
if not visible or _action_in_progress or _root_transition_active:
|
||||
return
|
||||
close_menu(CloseReason.USER_RETURN, true)
|
||||
chat_requested.emit()
|
||||
|
||||
|
||||
func setup(
|
||||
player: PlayerType,
|
||||
save_manager: SaveManagerType,
|
||||
|
|
@ -287,12 +277,19 @@ func _on_settings_applied() -> void:
|
|||
if _closing_menu:
|
||||
return
|
||||
_feedback.text = "settings saved."
|
||||
_begin_root_entry(true)
|
||||
|
||||
|
||||
func _on_settings_closed() -> void:
|
||||
pass
|
||||
|
||||
|
||||
func _on_settings_closing() -> void:
|
||||
if _closing_menu:
|
||||
return
|
||||
await get_tree().create_timer(
|
||||
UIMotion.BUBBLE_TRANSITION_OVERLAP_DELAY
|
||||
).timeout
|
||||
if _settings_panel.visible:
|
||||
_begin_root_entry(true)
|
||||
|
||||
|
||||
|
|
@ -364,7 +361,7 @@ func _open_confirmation(
|
|||
|
||||
func _show_confirmation() -> void:
|
||||
_confirmation_page.transition_in(
|
||||
PAGE_INCOMING_DURATION,
|
||||
0.0,
|
||||
_finish_confirmation_open
|
||||
)
|
||||
|
||||
|
|
@ -379,7 +376,7 @@ func _close_confirmation() -> void:
|
|||
_confirmation_action = ConfirmationAction.NONE
|
||||
_emit_transition_flurry()
|
||||
_confirmation_page.transition_out(
|
||||
PAGE_OUTGOING_DURATION,
|
||||
0.0,
|
||||
_finish_confirmation_cancel
|
||||
)
|
||||
|
||||
|
|
@ -448,7 +445,7 @@ func _begin_root_entry(flurry_already_emitted: bool) -> void:
|
|||
_root_page.transition_in(
|
||||
true,
|
||||
_finish_root_entry.bind(generation),
|
||||
PAGE_INCOMING_DURATION
|
||||
0.0
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -466,19 +463,23 @@ func _begin_root_exit(completed: Callable) -> void:
|
|||
_emit_transition_flurry()
|
||||
var generation: int = _root_transition_generation
|
||||
_root_page.transition_out(
|
||||
_finish_root_exit.bind(generation, completed),
|
||||
PAGE_OUTGOING_DURATION
|
||||
_finish_root_exit.bind(generation),
|
||||
0.0
|
||||
)
|
||||
await get_tree().create_timer(
|
||||
UIMotion.BUBBLE_TRANSITION_OVERLAP_DELAY
|
||||
).timeout
|
||||
if generation != _root_transition_generation or not visible:
|
||||
return
|
||||
completed.call()
|
||||
|
||||
|
||||
func _finish_root_exit(
|
||||
generation: int,
|
||||
completed: Callable,
|
||||
) -> void:
|
||||
if generation != _root_transition_generation or not visible:
|
||||
return
|
||||
_root_transition_active = false
|
||||
completed.call()
|
||||
|
||||
|
||||
func _finish_user_close() -> void:
|
||||
|
|
|
|||
|
|
@ -77,16 +77,14 @@ grow_horizontal = 2
|
|||
grow_vertical = 2
|
||||
script = ExtResource("4_page")
|
||||
page_id = &"pause"
|
||||
bubble_paths = Array[NodePath]([NodePath("BubbleCluster/ResumeButton"), NodePath("BubbleCluster/SaveButton"), NodePath("BubbleCluster/JoinGameButton"), NodePath("BubbleCluster/ChatButton"), NodePath("BubbleCluster/SettingsButton"), NodePath("BubbleCluster/ReturnToTitleButton"), NodePath("BubbleCluster/ResetProgressButton"), NodePath("BubbleCluster/QuitButton")])
|
||||
focus_paths = Array[NodePath]([NodePath("BubbleCluster/ResumeButton"), NodePath("BubbleCluster/SaveButton"), NodePath("BubbleCluster/JoinGameButton"), NodePath("BubbleCluster/ChatButton"), NodePath("BubbleCluster/SettingsButton"), NodePath("BubbleCluster/ReturnToTitleButton"), NodePath("BubbleCluster/ResetProgressButton"), NodePath("BubbleCluster/QuitButton")])
|
||||
bubble_paths = Array[NodePath]([NodePath("BubbleCluster/ResumeButton"), NodePath("BubbleCluster/SaveButton"), NodePath("BubbleCluster/JoinGameButton"), NodePath("BubbleCluster/SettingsButton"), NodePath("BubbleCluster/ReturnToTitleButton"), NodePath("BubbleCluster/ResetProgressButton"), NodePath("BubbleCluster/QuitButton")])
|
||||
focus_paths = Array[NodePath]([NodePath("BubbleCluster/ResumeButton"), NodePath("BubbleCluster/SaveButton"), NodePath("BubbleCluster/JoinGameButton"), NodePath("BubbleCluster/SettingsButton"), NodePath("BubbleCluster/ReturnToTitleButton"), NodePath("BubbleCluster/ResetProgressButton"), NodePath("BubbleCluster/QuitButton")])
|
||||
initial_focus_path = NodePath("BubbleCluster/ResumeButton")
|
||||
back_focus_path = NodePath("BubbleCluster/ResumeButton")
|
||||
maximum_layout_size = Vector2(720, 520)
|
||||
compact_maximum_layout_size = Vector2(544, 400)
|
||||
compact_width_threshold = 680.0
|
||||
compact_height_threshold = 500.0
|
||||
outgoing_rise_duration = 1.7
|
||||
incoming_rise_duration = 1.85
|
||||
|
||||
[node name="BubbleCluster" type="Control" parent="ResponsivePauseStage/PausePresentationScaleRoot/RootPage"]
|
||||
layout_mode = 0
|
||||
|
|
@ -135,18 +133,6 @@ minimum_font_size = 16
|
|||
maximum_font_size = 23
|
||||
motion_phase = 2.05
|
||||
|
||||
[node name="ChatButton" parent="ResponsivePauseStage/PausePresentationScaleRoot/RootPage/BubbleCluster" instance=ExtResource("5_bubble")]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 0)
|
||||
text = "chat"
|
||||
neutral_size = Vector2(112, 106)
|
||||
desktop_anchor = Vector2(620, 255)
|
||||
compact_anchor = Vector2(595, 270)
|
||||
compact_minimum_size = Vector2(92, 88)
|
||||
minimum_font_size = 15
|
||||
maximum_font_size = 20
|
||||
motion_phase = 2.3
|
||||
|
||||
[node name="JoinGameButton" parent="ResponsivePauseStage/PausePresentationScaleRoot/RootPage/BubbleCluster" instance=ExtResource("5_bubble")]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 0)
|
||||
|
|
|
|||
|
|
@ -62,8 +62,6 @@ const LogbookEntryScene = preload(
|
|||
"res://ui/components/bubble_menu/logbook_entry.tscn"
|
||||
)
|
||||
|
||||
const MENU_ENTER_DURATION: float = 0.58
|
||||
const MENU_EXIT_DURATION: float = 0.52
|
||||
const PAGE_OUT_DURATION: float = 0.34
|
||||
const PAGE_IN_DURATION: float = 0.42
|
||||
const LOGBOOK_PAGE_DURATION: float = 0.18
|
||||
|
|
@ -150,7 +148,6 @@ enum CloseReason {
|
|||
@onready var _bag_host: Control = %BagHost
|
||||
@onready var _bag_item_field: Control = %BagItemField
|
||||
@onready var _bag_empty_state: Label = %BagEmptyState
|
||||
@onready var _bag_instruction_bubble: PanelContainer = %BagInstructionBubble
|
||||
@onready var _bag_detail_constellation: Control = %BagDetailConstellation
|
||||
@onready var _bag_sprite_detail_bubble: Control = %BagDetailBubble
|
||||
@onready var _bag_sprite_detail_texture: TextureRect = %BagSpriteDetailTexture
|
||||
|
|
@ -913,7 +910,6 @@ func _apply_bag_styles() -> void:
|
|||
bubble.content_margin_top = 9.0
|
||||
bubble.content_margin_right = 12.0
|
||||
bubble.content_margin_bottom = 9.0
|
||||
_bag_instruction_bubble.add_theme_stylebox_override("panel", bubble)
|
||||
_bag_sprite_detail_bubble.add_theme_stylebox_override(
|
||||
"panel",
|
||||
bubble.duplicate(),
|
||||
|
|
@ -1133,7 +1129,7 @@ func _update_shell_layout() -> void:
|
|||
_bag_page.position = Vector2.ZERO
|
||||
_bag_rest_position = Vector2.ZERO
|
||||
_bag_outer_wall.position = (
|
||||
Vector2(14.0, 170.0) if compact else Vector2(72.0, 132.0)
|
||||
Vector2(14.0, 170.0) if compact else Vector2(122.0, 132.0)
|
||||
)
|
||||
_bag_outer_wall.size = (
|
||||
Vector2(612.0, 200.0) if compact else Vector2(896.0, 442.0)
|
||||
|
|
@ -1142,12 +1138,6 @@ func _update_shell_layout() -> void:
|
|||
Vector2(520.0, 140.0) if compact else Vector2(820.0, 350.0)
|
||||
)
|
||||
_bag_scroll.vertical_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
|
||||
_bag_instruction_bubble.position = (
|
||||
Vector2(218.0, 145.0) if compact else Vector2(992.0, 140.0)
|
||||
)
|
||||
_bag_instruction_bubble.size = (
|
||||
Vector2(204.0, 48.0) if compact else Vector2(240.0, 98.0)
|
||||
)
|
||||
_bag_detail_constellation.position = (
|
||||
Vector2.ZERO if compact else Vector2(984.0, 266.0)
|
||||
)
|
||||
|
|
@ -1335,48 +1325,49 @@ func _begin_menu_entry() -> void:
|
|||
_profile_page.position = _profile_rest_position + Vector2.DOWN * start_offset
|
||||
var navigation_rest: Vector2 = _navigation_cluster.position
|
||||
_navigation_cluster.position = navigation_rest + Vector2.DOWN * start_offset
|
||||
var transition_duration := UIMotion.bubble_duration(start_offset)
|
||||
_presentation_tween = create_tween().set_parallel(true)
|
||||
_presentation_tween.tween_property(
|
||||
_content_shell,
|
||||
"position",
|
||||
_presentation_rest_position,
|
||||
MENU_ENTER_DURATION
|
||||
transition_duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_presentation_tween.tween_property(
|
||||
_cooler_page,
|
||||
"position",
|
||||
_cooler_rest_position,
|
||||
MENU_ENTER_DURATION
|
||||
transition_duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_presentation_tween.tween_property(
|
||||
_bag_page,
|
||||
"position",
|
||||
_bag_rest_position,
|
||||
MENU_ENTER_DURATION
|
||||
transition_duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_presentation_tween.tween_property(
|
||||
_logbook_page,
|
||||
"position",
|
||||
_logbook_rest_position,
|
||||
MENU_ENTER_DURATION
|
||||
transition_duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_presentation_tween.tween_property(
|
||||
_mail_page,
|
||||
"position",
|
||||
_mail_rest_position,
|
||||
MENU_ENTER_DURATION
|
||||
transition_duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_presentation_tween.tween_property(
|
||||
_profile_page,
|
||||
"position",
|
||||
_profile_rest_position,
|
||||
MENU_ENTER_DURATION
|
||||
transition_duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_presentation_tween.tween_property(
|
||||
_navigation_cluster,
|
||||
"position",
|
||||
navigation_rest,
|
||||
MENU_ENTER_DURATION
|
||||
transition_duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_presentation_tween.chain().tween_callback(
|
||||
_finish_menu_entry.bind(generation)
|
||||
|
|
@ -1407,48 +1398,51 @@ func _begin_menu_exit(reason: CloseReason, restore_controls: bool) -> void:
|
|||
_content_shell.size.y,
|
||||
_navigation_cluster.size.y
|
||||
) - TRANSITION_SAFE_MARGIN
|
||||
var transition_duration := UIMotion.bubble_duration(
|
||||
end_y - _navigation_cluster.position.y
|
||||
)
|
||||
_presentation_tween = create_tween().set_parallel(true)
|
||||
_presentation_tween.tween_property(
|
||||
_content_shell,
|
||||
"position:y",
|
||||
end_y,
|
||||
MENU_EXIT_DURATION
|
||||
transition_duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_presentation_tween.tween_property(
|
||||
_cooler_page,
|
||||
"position:y",
|
||||
-_cooler_page.size.y - TRANSITION_SAFE_MARGIN,
|
||||
MENU_EXIT_DURATION
|
||||
transition_duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_presentation_tween.tween_property(
|
||||
_bag_page,
|
||||
"position:y",
|
||||
-_bag_page.size.y - TRANSITION_SAFE_MARGIN,
|
||||
MENU_EXIT_DURATION
|
||||
transition_duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_presentation_tween.tween_property(
|
||||
_logbook_page,
|
||||
"position:y",
|
||||
-_logbook_page.size.y - TRANSITION_SAFE_MARGIN,
|
||||
MENU_EXIT_DURATION
|
||||
transition_duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_presentation_tween.tween_property(
|
||||
_mail_page,
|
||||
"position:y",
|
||||
-_mail_page.size.y - TRANSITION_SAFE_MARGIN,
|
||||
MENU_EXIT_DURATION
|
||||
transition_duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_presentation_tween.tween_property(
|
||||
_profile_page,
|
||||
"position:y",
|
||||
-_profile_page.size.y - TRANSITION_SAFE_MARGIN,
|
||||
MENU_EXIT_DURATION
|
||||
transition_duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_presentation_tween.tween_property(
|
||||
_navigation_cluster,
|
||||
"position:y",
|
||||
-_navigation_cluster.size.y - TRANSITION_SAFE_MARGIN,
|
||||
MENU_EXIT_DURATION
|
||||
transition_duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_presentation_tween.chain().tween_callback(
|
||||
_finish_menu_exit.bind(
|
||||
|
|
@ -2009,14 +2003,10 @@ func _update_bag_detail() -> void:
|
|||
_bag_detail_constellation.visible = (
|
||||
item != null and _current_section == Section.BAG
|
||||
)
|
||||
_bag_instruction_bubble.visible = (
|
||||
item == null and _current_section == Section.BAG
|
||||
)
|
||||
|
||||
|
||||
func _close_bag_detail() -> void:
|
||||
_bag_detail_constellation.visible = false
|
||||
_bag_instruction_bubble.visible = _current_section == Section.BAG
|
||||
|
||||
|
||||
func _on_bag_field_gui_input(event: InputEvent) -> void:
|
||||
|
|
|
|||
|
|
@ -448,9 +448,9 @@ mouse_filter = 1
|
|||
[node name="BagOuterWall" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 0
|
||||
offset_left = 72.0
|
||||
offset_left = 122.0
|
||||
offset_top = 132.0
|
||||
offset_right = 968.0
|
||||
offset_right = 1018.0
|
||||
offset_bottom = 574.0
|
||||
|
||||
[node name="BagOuterMargin" type="MarginContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagOuterWall"]
|
||||
|
|
@ -507,25 +507,6 @@ text = "your bag is empty"
|
|||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="BagInstructionBubble" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage" instance=ExtResource("9_info_scene")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 0
|
||||
offset_left = 992.0
|
||||
offset_top = 140.0
|
||||
offset_right = 1232.0
|
||||
offset_bottom = 238.0
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="BagInstructionText" type="Label" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagInstructionBubble"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
mouse_filter = 2
|
||||
theme_override_colors/font_color = Color(0.22, 0.15, 0.08, 1)
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "drag items\nto the hotbar"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="BagDetailConstellation" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ var _current_tab := 0
|
|||
|
||||
func _ready() -> void:
|
||||
set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
UtilityPageStyle.apply_page(self)
|
||||
_build()
|
||||
|
||||
|
||||
|
|
@ -26,6 +27,7 @@ func setup(service: NetworkPlayerListService) -> void:
|
|||
|
||||
func activate() -> void:
|
||||
_refresh()
|
||||
UtilityPageStyle.animate_in(self)
|
||||
_focus_first()
|
||||
|
||||
|
||||
|
|
@ -38,16 +40,7 @@ func _build() -> void:
|
|||
paper.position = Vector2(58, 128)
|
||||
paper.size = Vector2(1164, 476)
|
||||
add_child(paper)
|
||||
var style := StyleBoxFlat.new()
|
||||
style.bg_color = Color("eee2bd")
|
||||
style.border_color = Color("473d2e")
|
||||
style.set_border_width_all(4)
|
||||
style.set_corner_radius_all(16)
|
||||
style.content_margin_left = 26
|
||||
style.content_margin_right = 26
|
||||
style.content_margin_top = 20
|
||||
style.content_margin_bottom = 20
|
||||
paper.add_theme_stylebox_override("panel", style)
|
||||
paper.add_theme_stylebox_override("panel", UtilityPageStyle.panel_style())
|
||||
var root := VBoxContainer.new()
|
||||
root.add_theme_constant_override("separation", 10)
|
||||
paper.add_child(root)
|
||||
|
|
@ -63,6 +56,7 @@ func _build() -> void:
|
|||
button.text = ["players", "relationships", "banned"][index]
|
||||
button.toggle_mode = true
|
||||
button.pressed.connect(_select_tab.bind(index))
|
||||
UtilityPageStyle.apply_button(button)
|
||||
_tabs.add_child(button)
|
||||
var scroll := ScrollContainer.new()
|
||||
scroll.custom_minimum_size = Vector2(0, 330)
|
||||
|
|
@ -88,7 +82,7 @@ func _select_tab(index: int) -> void:
|
|||
func _refresh() -> void:
|
||||
if _service == null or _list == null:
|
||||
return
|
||||
_header.text = "players %d / %d connected" % [
|
||||
_header.text = "Players\n%d / %d connected" % [
|
||||
_service.get_connected_count(), _service.get_max_players(),
|
||||
]
|
||||
for index: int in _tabs.get_child_count():
|
||||
|
|
@ -129,6 +123,9 @@ func _build_active_rows() -> void:
|
|||
identity.tooltip_text = NetworkIdentityCrypto.format_fingerprint(
|
||||
entry.full_fingerprint
|
||||
)
|
||||
identity.add_theme_color_override(
|
||||
"font_color", UtilityPageStyle.INK
|
||||
)
|
||||
row.add_child(identity)
|
||||
var ping := Label.new()
|
||||
ping.custom_minimum_size.x = 80
|
||||
|
|
@ -137,26 +134,31 @@ func _build_active_rows() -> void:
|
|||
else "%d ms" % entry.ping_to_host_ms
|
||||
if entry.ping_to_host_ms >= 0 else "—"
|
||||
)
|
||||
ping.add_theme_color_override("font_color", UtilityPageStyle.INK)
|
||||
row.add_child(ping)
|
||||
var mute := Button.new()
|
||||
mute.text = "unmute" if entry.muted else "mute"
|
||||
mute.disabled = entry.is_local_player
|
||||
mute.pressed.connect(_toggle_mute.bind(entry))
|
||||
UtilityPageStyle.apply_button(mute)
|
||||
row.add_child(mute)
|
||||
var block := Button.new()
|
||||
block.text = "block"
|
||||
block.disabled = entry.is_local_player
|
||||
block.pressed.connect(_confirm_block.bind(entry))
|
||||
UtilityPageStyle.apply_button(block)
|
||||
row.add_child(block)
|
||||
var kick := Button.new()
|
||||
kick.text = "kick"
|
||||
kick.disabled = not entry.can_kick
|
||||
kick.pressed.connect(_confirm_kick.bind(entry))
|
||||
UtilityPageStyle.apply_button(kick)
|
||||
row.add_child(kick)
|
||||
var ban := Button.new()
|
||||
ban.text = "ban"
|
||||
ban.disabled = not entry.can_ban
|
||||
ban.pressed.connect(_confirm_ban.bind(entry))
|
||||
UtilityPageStyle.apply_button(ban)
|
||||
row.add_child(ban)
|
||||
_list.add_child(row)
|
||||
|
||||
|
|
@ -177,6 +179,7 @@ func _build_relationship_rows() -> void:
|
|||
"Blocked" if bool(record.get("blocked", false)) else "Muted",
|
||||
]
|
||||
label.tooltip_text = NetworkIdentityCrypto.format_fingerprint(fingerprint)
|
||||
label.add_theme_color_override("font_color", UtilityPageStyle.INK)
|
||||
row.add_child(label)
|
||||
if bool(record.get("blocked", false)):
|
||||
var unblock := Button.new()
|
||||
|
|
@ -184,6 +187,7 @@ func _build_relationship_rows() -> void:
|
|||
unblock.pressed.connect(func() -> void:
|
||||
_service.set_blocked(fingerprint, str(record["last_known_display_name"]), false)
|
||||
)
|
||||
UtilityPageStyle.apply_button(unblock)
|
||||
row.add_child(unblock)
|
||||
var unmute := Button.new()
|
||||
unmute.text = "unmute"
|
||||
|
|
@ -191,6 +195,7 @@ func _build_relationship_rows() -> void:
|
|||
unmute.pressed.connect(func() -> void:
|
||||
_service.set_muted(fingerprint, str(record["last_known_display_name"]), false)
|
||||
)
|
||||
UtilityPageStyle.apply_button(unmute)
|
||||
row.add_child(unmute)
|
||||
_list.add_child(row)
|
||||
|
||||
|
|
@ -211,10 +216,12 @@ func _build_ban_rows() -> void:
|
|||
Time.get_date_string_from_unix_time(int(record.get("banned_unix", 0))),
|
||||
]
|
||||
label.tooltip_text = NetworkIdentityCrypto.format_fingerprint(fingerprint)
|
||||
label.add_theme_color_override("font_color", UtilityPageStyle.INK)
|
||||
row.add_child(label)
|
||||
var unban := Button.new()
|
||||
unban.text = "unban"
|
||||
unban.pressed.connect(_confirm_unban.bind(fingerprint))
|
||||
UtilityPageStyle.apply_button(unban)
|
||||
row.add_child(unban)
|
||||
_list.add_child(row)
|
||||
|
||||
|
|
@ -223,6 +230,7 @@ func _make_row() -> HBoxContainer:
|
|||
var row := HBoxContainer.new()
|
||||
row.custom_minimum_size.y = 58
|
||||
row.add_theme_constant_override("separation", 8)
|
||||
row.add_theme_constant_override("outline_size", 1)
|
||||
return row
|
||||
|
||||
|
||||
|
|
@ -231,6 +239,7 @@ func _add_empty(text: String) -> void:
|
|||
label.text = text
|
||||
label.custom_minimum_size.y = 100
|
||||
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
label.add_theme_color_override("font_color", UtilityPageStyle.MUTED_INK)
|
||||
_list.add_child(label)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -45,15 +45,18 @@ func setup(service: NetworkProfileService) -> void:
|
|||
_load_persisted()
|
||||
var identity_value := find_child("IdentityFingerprint", true, false) as Label
|
||||
if identity_value != null:
|
||||
identity_value.text = "%s • Stored on this device" % (
|
||||
NetworkIdentityCrypto.format_fingerprint(
|
||||
_service.get_identity_fingerprint()
|
||||
var fingerprint := _service.get_identity_fingerprint()
|
||||
identity_value.text = "Identity • %s • Stored on this device" % (
|
||||
NetworkIdentityCrypto.compact_suffix(fingerprint)
|
||||
)
|
||||
identity_value.tooltip_text = (
|
||||
NetworkIdentityCrypto.format_fingerprint(fingerprint)
|
||||
)
|
||||
|
||||
|
||||
func activate() -> void:
|
||||
visible = true
|
||||
UtilityPageStyle.animate_in(self)
|
||||
if _service != null:
|
||||
_load_persisted()
|
||||
_name_edit.grab_focus()
|
||||
|
|
@ -100,29 +103,27 @@ func request_close_confirmation() -> bool:
|
|||
func _build_ui() -> void:
|
||||
var paper := PanelContainer.new()
|
||||
paper.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
paper.offset_left = 42.0
|
||||
paper.offset_top = 14.0
|
||||
paper.offset_right = -42.0
|
||||
paper.offset_bottom = -14.0
|
||||
var style := StyleBoxFlat.new()
|
||||
style.bg_color = Color("f2ead3")
|
||||
style.border_color = Color("4a4238")
|
||||
style.set_border_width_all(4)
|
||||
style.set_corner_radius_all(18)
|
||||
paper.add_theme_stylebox_override("panel", style)
|
||||
paper.offset_left = 64.0
|
||||
paper.offset_top = 28.0
|
||||
paper.offset_right = -64.0
|
||||
paper.offset_bottom = -28.0
|
||||
paper.add_theme_stylebox_override(
|
||||
"panel", UtilityPageStyle.panel_style()
|
||||
)
|
||||
add_child(paper)
|
||||
UtilityPageStyle.apply_page(self)
|
||||
|
||||
var margin := MarginContainer.new()
|
||||
for side: String in ["left", "right", "top", "bottom"]:
|
||||
margin.add_theme_constant_override("margin_%s" % side, 28)
|
||||
margin.add_theme_constant_override("margin_%s" % side, 18)
|
||||
paper.add_child(margin)
|
||||
var layout := VBoxContainer.new()
|
||||
layout.add_theme_constant_override("separation", 8)
|
||||
layout.add_theme_constant_override("separation", 5)
|
||||
margin.add_child(layout)
|
||||
|
||||
var heading := Label.new()
|
||||
heading.text = "player profile"
|
||||
heading.add_theme_font_size_override("font_size", 28)
|
||||
heading.text = "Player Profile"
|
||||
heading.add_theme_font_size_override("font_size", 25)
|
||||
heading.add_theme_color_override("font_color", Color("302b27"))
|
||||
layout.add_child(heading)
|
||||
|
||||
|
|
@ -139,7 +140,8 @@ func _build_ui() -> void:
|
|||
_name_edit = LineEdit.new()
|
||||
_name_edit.max_length = NetworkProtocol.MAX_DISPLAY_NAME_LENGTH
|
||||
_name_edit.placeholder_text = "Player"
|
||||
_name_edit.custom_minimum_size = Vector2(360, 42)
|
||||
_name_edit.custom_minimum_size = Vector2(300, 40)
|
||||
UtilityPageStyle.apply_line_edit(_name_edit)
|
||||
_name_edit.text_changed.connect(_on_name_changed)
|
||||
name_stack.add_child(_name_edit)
|
||||
var helper := Label.new()
|
||||
|
|
@ -148,17 +150,20 @@ func _build_ui() -> void:
|
|||
name_stack.add_child(helper)
|
||||
_apply_button = Button.new()
|
||||
_apply_button.text = "apply"
|
||||
_apply_button.custom_minimum_size = Vector2(118, 50)
|
||||
_apply_button.custom_minimum_size = Vector2(92, 40)
|
||||
UtilityPageStyle.apply_button(_apply_button)
|
||||
_apply_button.pressed.connect(_apply)
|
||||
name_row.add_child(_apply_button)
|
||||
_revert_button = Button.new()
|
||||
_revert_button.text = "revert"
|
||||
_revert_button.custom_minimum_size = Vector2(108, 50)
|
||||
_revert_button.custom_minimum_size = Vector2(88, 40)
|
||||
UtilityPageStyle.apply_button(_revert_button)
|
||||
_revert_button.pressed.connect(_revert)
|
||||
name_row.add_child(_revert_button)
|
||||
var defaults_button := Button.new()
|
||||
defaults_button.text = "defaults"
|
||||
defaults_button.custom_minimum_size = Vector2(108, 50)
|
||||
defaults_button.custom_minimum_size = Vector2(88, 40)
|
||||
UtilityPageStyle.apply_button(defaults_button)
|
||||
defaults_button.pressed.connect(_show_confirmation.bind("defaults"))
|
||||
name_row.add_child(defaults_button)
|
||||
|
||||
|
|
@ -169,13 +174,9 @@ func _build_ui() -> void:
|
|||
_suggestions.add_theme_constant_override("separation", 8)
|
||||
layout.add_child(_suggestions)
|
||||
|
||||
var identity_label := Label.new()
|
||||
identity_label.text = "identity"
|
||||
identity_label.add_theme_color_override("font_color", Color("302b27"))
|
||||
layout.add_child(identity_label)
|
||||
var identity_value := Label.new()
|
||||
identity_value.name = "IdentityFingerprint"
|
||||
identity_value.text = "Stored on this device"
|
||||
identity_value.text = "Identity • Stored on this device"
|
||||
identity_value.tooltip_text = (
|
||||
"This identity helps other players recognize you between sessions."
|
||||
)
|
||||
|
|
@ -184,13 +185,13 @@ func _build_ui() -> void:
|
|||
|
||||
var body := HBoxContainer.new()
|
||||
body.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
body.add_theme_constant_override("separation", 18)
|
||||
body.add_theme_constant_override("separation", 12)
|
||||
layout.add_child(body)
|
||||
_category_list = VBoxContainer.new()
|
||||
_category_list.custom_minimum_size = Vector2(170, 0)
|
||||
_category_list.custom_minimum_size = Vector2(140, 0)
|
||||
body.add_child(_category_list)
|
||||
_option_list = VBoxContainer.new()
|
||||
_option_list.custom_minimum_size = Vector2(230, 0)
|
||||
_option_list.custom_minimum_size = Vector2(190, 0)
|
||||
body.add_child(_option_list)
|
||||
var preview_stack := VBoxContainer.new()
|
||||
preview_stack.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
|
|
@ -198,15 +199,19 @@ func _build_ui() -> void:
|
|||
body.add_child(preview_stack)
|
||||
_preview = preload("res://ui/profile_preview.tscn").instantiate()
|
||||
preview_stack.add_child(_preview)
|
||||
var preview_actions := HBoxContainer.new()
|
||||
preview_actions.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
preview_actions.add_theme_constant_override("separation", 10)
|
||||
preview_stack.add_child(preview_actions)
|
||||
var preview_note := Label.new()
|
||||
preview_note.text = "capsule preview • drag or use left / right"
|
||||
preview_note.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
preview_note.text = "Current player • drag or use left / right"
|
||||
preview_note.add_theme_color_override("font_color", Color("514a42"))
|
||||
preview_stack.add_child(preview_note)
|
||||
preview_actions.add_child(preview_note)
|
||||
var reset_view := Button.new()
|
||||
reset_view.text = "reset view"
|
||||
reset_view.pressed.connect(_preview.reset_view)
|
||||
preview_stack.add_child(reset_view)
|
||||
UtilityPageStyle.apply_button(reset_view)
|
||||
preview_actions.add_child(reset_view)
|
||||
|
||||
_discard_confirmation = PanelContainer.new()
|
||||
_discard_confirmation.visible = false
|
||||
|
|
@ -249,6 +254,7 @@ func _build_categories() -> void:
|
|||
button.custom_minimum_size = Vector2(0, 34)
|
||||
button.button_pressed = category_id == _category_id
|
||||
button.pressed.connect(_select_category.bind(category_id))
|
||||
UtilityPageStyle.apply_button(button)
|
||||
_category_list.add_child(button)
|
||||
_refresh_options()
|
||||
|
||||
|
|
@ -287,6 +293,7 @@ func _refresh_options() -> void:
|
|||
button.custom_minimum_size = Vector2(0, 34)
|
||||
button.button_pressed = _draft_appearance.get(_category_id) == option_id
|
||||
button.pressed.connect(_select_option.bind(_category_id, option_id))
|
||||
UtilityPageStyle.apply_button(button)
|
||||
_option_list.add_child(button)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -7,16 +7,25 @@ extends SubViewportContainer
|
|||
@onready var _preview_root: Node3D = %PreviewRoot
|
||||
|
||||
var _dragging: bool = false
|
||||
var _visuals: Node3D
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
focus_mode = Control.FOCUS_ALL
|
||||
gui_input.connect(_on_gui_input)
|
||||
_visuals = PlayerVisualPresenter.instantiate_visuals()
|
||||
_preview_root.add_child(_visuals)
|
||||
var rod := _visuals.find_child("FishingRod", true, false) as Node3D
|
||||
if rod != null:
|
||||
rod.visible = false
|
||||
var catch_display := _visuals.find_child("CatchDisplay", true, false) as Node3D
|
||||
if catch_display != null:
|
||||
catch_display.visible = false
|
||||
|
||||
|
||||
func apply_appearance_profile(_profile: Dictionary) -> void:
|
||||
# The capsule is deliberately neutral until modular character assets exist.
|
||||
pass
|
||||
func apply_appearance_profile(profile: Dictionary) -> void:
|
||||
if _visuals != null:
|
||||
PlayerVisualPresenter.apply_appearance(_visuals, profile)
|
||||
|
||||
|
||||
func reset_view() -> void:
|
||||
|
|
|
|||
|
|
@ -1,15 +1,7 @@
|
|||
[gd_scene load_steps=6 format=3]
|
||||
[gd_scene load_steps=4 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://ui/profile_preview.gd" id="1"]
|
||||
|
||||
[sub_resource type="CapsuleMesh" id="Capsule"]
|
||||
radius = 0.62
|
||||
height = 2.25
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="Material"]
|
||||
albedo_color = Color(0.38, 0.67, 0.74, 1)
|
||||
roughness = 0.72
|
||||
|
||||
[sub_resource type="Environment" id="Environment"]
|
||||
background_mode = 1
|
||||
background_color = Color(0.075, 0.13, 0.16, 1)
|
||||
|
|
@ -21,13 +13,13 @@ ambient_light_energy = 0.65
|
|||
environment = SubResource("Environment")
|
||||
|
||||
[node name="ProfilePreview" type="SubViewportContainer"]
|
||||
custom_minimum_size = Vector2(360, 250)
|
||||
custom_minimum_size = Vector2(300, 220)
|
||||
stretch = true
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="Viewport" type="SubViewport" parent="."]
|
||||
transparent_bg = false
|
||||
size = Vector2i(360, 390)
|
||||
size = Vector2i(320, 330)
|
||||
render_target_update_mode = 4
|
||||
world_3d = SubResource("PreviewWorld")
|
||||
|
||||
|
|
@ -48,10 +40,6 @@ light_energy = 1.3
|
|||
[node name="PreviewRoot" type="Node3D" parent="Viewport"]
|
||||
unique_name_in_owner = true
|
||||
|
||||
[node name="Capsule" type="MeshInstance3D" parent="Viewport/PreviewRoot"]
|
||||
mesh = SubResource("Capsule")
|
||||
material_override = SubResource("Material")
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="Viewport"]
|
||||
position = Vector3(0, 0.15, 4.25)
|
||||
position = Vector3(0, 0.95, 1.9)
|
||||
current = true
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ extends Control
|
|||
@export var compact_maximum_layout_size: Vector2 = Vector2.ZERO
|
||||
@export var compact_width_threshold: float = 680.0
|
||||
@export var compact_height_threshold: float = 500.0
|
||||
@export_range(0.1, 2.0, 0.01) var outgoing_rise_duration: float = 1.70
|
||||
@export_range(0.1, 2.0, 0.01) var incoming_rise_duration: float = 1.85
|
||||
@export_range(0.0, 128.0, 1.0) var transition_safe_margin: float = 24.0
|
||||
|
||||
var _cluster: BubbleCluster
|
||||
|
|
@ -49,30 +47,35 @@ func show_page(should_focus: bool = true) -> void:
|
|||
_cluster.position = _resting_cluster_position
|
||||
set_process(true)
|
||||
_set_interactive(true)
|
||||
var paper := get_node_or_null("Paper") as Control
|
||||
if paper != null:
|
||||
UtilityPageStyle.animate_in(paper)
|
||||
if should_focus:
|
||||
focus_initial()
|
||||
|
||||
|
||||
func transition_out(
|
||||
completed: Callable,
|
||||
duration_override: float = -1.0,
|
||||
_duration_override: float = -1.0,
|
||||
) -> void:
|
||||
_transition_generation += 1
|
||||
_cancel_transition()
|
||||
_is_transitioning = true
|
||||
_set_interactive(false)
|
||||
var paper := get_node_or_null("Paper") as Control
|
||||
if paper != null:
|
||||
UtilityPageStyle.animate_out(paper, Callable())
|
||||
set_process(true)
|
||||
var duration: float = (
|
||||
duration_override
|
||||
if duration_override > 0.0
|
||||
else outgoing_rise_duration
|
||||
var target_y: float = -_cluster.size.y - transition_safe_margin
|
||||
var duration := UIMotion.bubble_duration(
|
||||
target_y - _cluster.position.y
|
||||
)
|
||||
var generation: int = _transition_generation
|
||||
_transition = create_tween()
|
||||
_transition.tween_property(
|
||||
_cluster,
|
||||
"position:y",
|
||||
-_cluster.size.y - transition_safe_margin,
|
||||
target_y,
|
||||
duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_transition.finished.connect(
|
||||
|
|
@ -84,7 +87,7 @@ func transition_out(
|
|||
func transition_in(
|
||||
should_focus: bool,
|
||||
completed: Callable,
|
||||
duration_override: float = -1.0,
|
||||
_duration_override: float = -1.0,
|
||||
) -> void:
|
||||
_transition_generation += 1
|
||||
_cancel_transition()
|
||||
|
|
@ -92,15 +95,16 @@ func transition_in(
|
|||
_is_transitioning = true
|
||||
_set_interactive(false)
|
||||
set_process(true)
|
||||
var duration: float = (
|
||||
duration_override
|
||||
if duration_override > 0.0
|
||||
else incoming_rise_duration
|
||||
)
|
||||
_cluster.position = Vector2(
|
||||
_resting_cluster_position.x,
|
||||
size.y + transition_safe_margin
|
||||
)
|
||||
var paper := get_node_or_null("Paper") as Control
|
||||
if paper != null:
|
||||
UtilityPageStyle.animate_in(paper)
|
||||
var duration := UIMotion.bubble_duration(
|
||||
_cluster.position.y - _resting_cluster_position.y
|
||||
)
|
||||
var generation: int = _transition_generation
|
||||
_transition = create_tween()
|
||||
_transition.tween_property(
|
||||
|
|
@ -208,6 +212,7 @@ func _finish_transition_out(generation: int, completed: Callable) -> void:
|
|||
_is_transitioning = false
|
||||
hide()
|
||||
_cluster.position = _resting_cluster_position
|
||||
if completed.is_valid():
|
||||
completed.call()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ const PAGE_DISPLAY: StringName = &"display"
|
|||
const PAGE_CONTROLS: StringName = &"controls"
|
||||
const PAGE_ACCESSIBILITY: StringName = &"accessibility"
|
||||
const PAGE_DATA: StringName = &"data"
|
||||
const TITLE_HOST_OUTGOING_DURATION: float = 1.70
|
||||
const TITLE_HOST_INCOMING_DURATION: float = 1.80
|
||||
const PIXELATION_NAMES: PackedStringArray = [
|
||||
"legible",
|
||||
"cute",
|
||||
|
|
@ -23,6 +21,7 @@ const SettingsManagerType = preload(
|
|||
|
||||
signal applied
|
||||
signal closed
|
||||
signal closing
|
||||
signal opened
|
||||
signal crisp_reset_focus_requested
|
||||
signal panel_visibility_changed(is_visible: bool)
|
||||
|
|
@ -151,6 +150,19 @@ func _ready() -> void:
|
|||
_invert_y_toggle.pressed.connect(_toggle_invert_y)
|
||||
_auto_click_toggle.pressed.connect(_toggle_auto_click)
|
||||
_readable_font_toggle.pressed.connect(_toggle_readable_font)
|
||||
for control: Control in [_auto_click_toggle, _auto_click_interval]:
|
||||
control.mouse_entered.connect(
|
||||
_show_accessibility_helper.bind(&"auto_click")
|
||||
)
|
||||
control.focus_entered.connect(
|
||||
_show_accessibility_helper.bind(&"auto_click")
|
||||
)
|
||||
_readable_font_toggle.mouse_entered.connect(
|
||||
_show_accessibility_helper.bind(&"alternate_font")
|
||||
)
|
||||
_readable_font_toggle.focus_entered.connect(
|
||||
_show_accessibility_helper.bind(&"alternate_font")
|
||||
)
|
||||
%IntervalDecrease.pressed.connect(_adjust_auto_click_interval.bind(-1))
|
||||
%IntervalIncrease.pressed.connect(_adjust_auto_click_interval.bind(1))
|
||||
_auto_click_interval.pressed.connect(
|
||||
|
|
@ -171,6 +183,7 @@ func _ready() -> void:
|
|||
parent_control.resized.connect(_refresh_panel_size)
|
||||
for page: SettingsBubblePage in _pages.values():
|
||||
page.hide_page()
|
||||
_style_data_page()
|
||||
call_deferred("_refresh_panel_size")
|
||||
|
||||
|
||||
|
|
@ -234,7 +247,7 @@ func open_panel(
|
|||
_root_page.transition_in(
|
||||
true,
|
||||
_finish_animated_open.bind(generation),
|
||||
TITLE_HOST_INCOMING_DURATION
|
||||
0.0
|
||||
)
|
||||
else:
|
||||
_show_active_page(true)
|
||||
|
|
@ -304,34 +317,29 @@ func _start_page_transition(page_id: StringName, push_page: bool) -> void:
|
|||
_page_transition_active = true
|
||||
navigation_transition_started.emit()
|
||||
var generation: int = _page_transition_generation
|
||||
outgoing_page.transition_out(
|
||||
_finish_outgoing_page.bind(
|
||||
generation,
|
||||
page_id,
|
||||
push_page,
|
||||
incoming_page
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
func _finish_outgoing_page(
|
||||
generation: int,
|
||||
page_id: StringName,
|
||||
push_page: bool,
|
||||
incoming_page: SettingsBubblePage,
|
||||
) -> void:
|
||||
if generation != _page_transition_generation or not _page_transition_active:
|
||||
return
|
||||
if push_page:
|
||||
_page_stack.append(page_id)
|
||||
else:
|
||||
_page_stack.pop_back()
|
||||
for page: SettingsBubblePage in _pages.values():
|
||||
if page != incoming_page:
|
||||
if page != outgoing_page and page != incoming_page:
|
||||
page.hide_page()
|
||||
outgoing_page.transition_out(
|
||||
Callable()
|
||||
)
|
||||
get_tree().create_timer(
|
||||
UIMotion.BUBBLE_TRANSITION_OVERLAP_DELAY
|
||||
).timeout.connect(
|
||||
func() -> void:
|
||||
if (
|
||||
generation == _page_transition_generation
|
||||
and _page_transition_active
|
||||
):
|
||||
incoming_page.transition_in(
|
||||
true,
|
||||
_finish_incoming_page.bind(generation)
|
||||
),
|
||||
CONNECT_ONE_SHOT
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -355,10 +363,11 @@ func _begin_animated_close(applied_result: bool) -> void:
|
|||
_page_transition_generation += 1
|
||||
_page_transition_active = true
|
||||
navigation_transition_started.emit()
|
||||
closing.emit()
|
||||
var generation: int = _page_transition_generation
|
||||
active_page.transition_out(
|
||||
_finish_animated_close.bind(generation, applied_result),
|
||||
TITLE_HOST_OUTGOING_DURATION
|
||||
0.0
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -393,7 +402,7 @@ func _refresh_data_page() -> void:
|
|||
if not is_node_ready() or _data_root == null:
|
||||
return
|
||||
%DataFolderPath.text = _data_root.root_path
|
||||
%DataStorageMode.text = "storage mode: " + _data_root.storage_mode_text()
|
||||
%DataStorageMode.text = "Storage Mode: " + _data_root.storage_mode_text()
|
||||
%ChangeDataFolder.disabled = (
|
||||
_data_root.override_active
|
||||
or (_network_session != null and _network_session.is_session_active())
|
||||
|
|
@ -432,7 +441,7 @@ func _change_data_folder(path: String) -> void:
|
|||
_show_existing_data_folder_choice(path)
|
||||
return
|
||||
if bool(result.get("ok", false)):
|
||||
_feedback.text = "Data folder changed. NETFISHING will close safely."
|
||||
_feedback.text = "Data folder changed. NETfishing will close safely."
|
||||
_refresh_data_page()
|
||||
get_tree().call_deferred("quit")
|
||||
else:
|
||||
|
|
@ -441,16 +450,16 @@ func _change_data_folder(path: String) -> void:
|
|||
|
||||
func _show_existing_data_folder_choice(path: String) -> void:
|
||||
var dialog: ConfirmationDialog = ConfirmationDialog.new()
|
||||
dialog.title = "Existing NETFISHING data"
|
||||
dialog.title = "Existing NETfishing data"
|
||||
dialog.ok_button_text = "Use Selected Data"
|
||||
dialog.dialog_text = (
|
||||
"The selected folder contains different NETFISHING data.\n\n"
|
||||
"The selected folder contains different NETfishing data.\n\n"
|
||||
+ "Choose one complete data set. Data will not be merged."
|
||||
)
|
||||
dialog.add_button("Replace Selected Data", false, "replace")
|
||||
dialog.confirmed.connect(func() -> void:
|
||||
if _data_root.use_existing_root(path):
|
||||
_feedback.text = "Data folder changed. NETFISHING will close safely."
|
||||
_feedback.text = "Data folder changed. NETfishing will close safely."
|
||||
get_tree().call_deferred("quit")
|
||||
else:
|
||||
_feedback.text = _data_root.error_message
|
||||
|
|
@ -483,7 +492,7 @@ func _choose_identity_export(identity_type: String) -> void:
|
|||
_export_file_dialog.file_mode = FileDialog.FILE_MODE_SAVE_FILE
|
||||
_export_file_dialog.access = FileDialog.ACCESS_FILESYSTEM
|
||||
_export_file_dialog.use_native_dialog = false
|
||||
_export_file_dialog.filters = PackedStringArray(["*.nfidentity ; NETFISHING identity backup"])
|
||||
_export_file_dialog.filters = PackedStringArray(["*.nfidentity ; NETfishing identity backup"])
|
||||
_export_file_dialog.file_selected.connect(_identity_export_file_selected)
|
||||
_interface_fonts.apply_utility_theme(_export_file_dialog)
|
||||
add_child(_export_file_dialog)
|
||||
|
|
@ -509,7 +518,7 @@ func _choose_identity_import(identity_type: String) -> void:
|
|||
_backup_file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILE
|
||||
_backup_file_dialog.access = FileDialog.ACCESS_FILESYSTEM
|
||||
_backup_file_dialog.use_native_dialog = false
|
||||
_backup_file_dialog.filters = PackedStringArray(["*.nfidentity ; NETFISHING identity backup"])
|
||||
_backup_file_dialog.filters = PackedStringArray(["*.nfidentity ; NETfishing identity backup"])
|
||||
_backup_file_dialog.file_selected.connect(_identity_import_file_selected)
|
||||
_interface_fonts.apply_utility_theme(_backup_file_dialog)
|
||||
add_child(_backup_file_dialog)
|
||||
|
|
@ -707,7 +716,7 @@ func _refresh_value_labels() -> void:
|
|||
+ ("on" if _auto_click_enabled else "off")
|
||||
)
|
||||
_readable_font_toggle.text = (
|
||||
"readable\ninterface font\n"
|
||||
"alternate\nfont\n"
|
||||
+ (
|
||||
"on"
|
||||
if settings.use_readable_interface_font
|
||||
|
|
@ -725,6 +734,35 @@ func _refresh_value_labels() -> void:
|
|||
_ui_options[index].button_pressed = index + 1 == settings.ui_pixel_size
|
||||
|
||||
|
||||
func _show_accessibility_helper(kind: StringName) -> void:
|
||||
var helper := %IntervalHelp as BubbleButton
|
||||
if kind == &"alternate_font":
|
||||
helper.text = (
|
||||
"The quick brown fox\njumps over the lazy dog.\n0123456789"
|
||||
)
|
||||
else:
|
||||
helper.text = (
|
||||
"Lower intervals click\nbarriers faster\nwhile held."
|
||||
)
|
||||
|
||||
|
||||
func _style_data_page() -> void:
|
||||
UtilityPageStyle.apply_page(_data_page)
|
||||
var paper := _data_page.get_node("Paper") as PanelContainer
|
||||
paper.add_theme_stylebox_override(
|
||||
"panel", UtilityPageStyle.panel_style()
|
||||
)
|
||||
var content := _data_page.get_node("Paper/Content") as VBoxContainer
|
||||
content.add_theme_constant_override("separation", 12)
|
||||
for node: Node in content.find_children("*", "", true, false):
|
||||
if node is BaseButton:
|
||||
UtilityPageStyle.apply_button(node)
|
||||
elif node is Label:
|
||||
node.add_theme_color_override(
|
||||
"font_color", UtilityPageStyle.INK
|
||||
)
|
||||
|
||||
|
||||
func _set_world_pixelation(pixel_size: int) -> void:
|
||||
if _settings_manager == null:
|
||||
return
|
||||
|
|
|
|||
|
|
@ -553,8 +553,8 @@ unique_name_in_owner = true
|
|||
custom_minimum_size = Vector2(0, 0)
|
||||
mouse_filter = 2
|
||||
focus_mode = 0
|
||||
text = "lower intervals\nclick barriers\nfaster\nwhile held"
|
||||
neutral_size = Vector2(170, 160)
|
||||
text = "Focus a control\nfor a helpful\npreview."
|
||||
neutral_size = Vector2(210, 176)
|
||||
desktop_anchor = Vector2(315, 405)
|
||||
compact_anchor = Vector2(280, 370)
|
||||
compact_minimum_size = Vector2(160, 152)
|
||||
|
|
@ -566,8 +566,8 @@ motion_phase = 4.1
|
|||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 0)
|
||||
toggle_mode = true
|
||||
text = "readable\ninterface font\noff"
|
||||
neutral_size = Vector2(180, 132)
|
||||
text = "alternate\nfont\noff"
|
||||
neutral_size = Vector2(150, 150)
|
||||
desktop_anchor = Vector2(92, 405)
|
||||
compact_anchor = Vector2(102, 374)
|
||||
compact_minimum_size = Vector2(156, 118)
|
||||
|
|
@ -576,6 +576,7 @@ maximum_font_size = 21
|
|||
motion_phase = 4.6
|
||||
|
||||
[node name="ReadableFontSample" type="Label" parent="AccessibilityPage/BubbleCluster"]
|
||||
visible = false
|
||||
layout_mode = 0
|
||||
offset_left = 250.0
|
||||
offset_top = 20.0
|
||||
|
|
@ -588,6 +589,7 @@ vertical_alignment = 1
|
|||
autowrap_mode = 2
|
||||
|
||||
[node name="ReadableFontHelper" type="Label" parent="AccessibilityPage/BubbleCluster"]
|
||||
visible = false
|
||||
layout_mode = 0
|
||||
offset_left = 250.0
|
||||
offset_top = 82.0
|
||||
|
|
@ -647,6 +649,7 @@ offset_right = 330.0
|
|||
offset_bottom = 210.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
z_index = 1
|
||||
|
||||
[node name="Content" type="VBoxContainer" parent="DataPage/Paper"]
|
||||
layout_mode = 2
|
||||
|
|
@ -655,12 +658,12 @@ theme_override_constants/separation = 10
|
|||
[node name="Heading" type="Label" parent="DataPage/Paper/Content"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 28
|
||||
text = "data & identity"
|
||||
text = "Data & Identity"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="DataFolderLabel" type="Label" parent="DataPage/Paper/Content"]
|
||||
layout_mode = 2
|
||||
text = "Data Folder"
|
||||
text = "Data Folder:"
|
||||
|
||||
[node name="DataFolderPath" type="Label" parent="DataPage/Paper/Content"]
|
||||
unique_name_in_owner = true
|
||||
|
|
@ -671,7 +674,7 @@ autowrap_mode = 2
|
|||
[node name="DataStorageMode" type="Label" parent="DataPage/Paper/Content"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "storage mode: unavailable"
|
||||
text = "Storage Mode: unavailable"
|
||||
|
||||
[node name="OpenDataFolder" type="Button" parent="DataPage/Paper/Content"]
|
||||
unique_name_in_owner = true
|
||||
|
|
@ -714,11 +717,12 @@ text = "Import Host Identity"
|
|||
|
||||
[node name="DataBackButton" parent="DataPage/BubbleCluster" instance=ExtResource("4_bubble")]
|
||||
unique_name_in_owner = true
|
||||
z_index = 4
|
||||
layout_mode = 0
|
||||
text = "back"
|
||||
neutral_size = Vector2(96, 90)
|
||||
desktop_anchor = Vector2(135, 470)
|
||||
compact_anchor = Vector2(115, 420)
|
||||
desktop_anchor = Vector2(-25, 470)
|
||||
compact_anchor = Vector2(-20, 420)
|
||||
compact_minimum_size = Vector2(82, 78)
|
||||
minimum_font_size = 13
|
||||
maximum_font_size = 16
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ func set_stage_rect(stage_rect: Rect2) -> void:
|
|||
|
||||
|
||||
func transition_in(
|
||||
duration: float,
|
||||
_duration: float,
|
||||
completed: Callable,
|
||||
) -> void:
|
||||
_transition_generation += 1
|
||||
|
|
@ -115,6 +115,9 @@ func transition_in(
|
|||
_resting_cluster_position.x,
|
||||
size.y + transition_safe_margin
|
||||
)
|
||||
var duration := UIMotion.bubble_duration(
|
||||
_cluster.position.y - _resting_cluster_position.y
|
||||
)
|
||||
var generation: int = _transition_generation
|
||||
_transition = create_tween()
|
||||
_transition.tween_property(
|
||||
|
|
@ -130,7 +133,7 @@ func transition_in(
|
|||
|
||||
|
||||
func transition_out(
|
||||
duration: float,
|
||||
_duration: float,
|
||||
completed: Callable,
|
||||
) -> void:
|
||||
if not visible or _is_transitioning:
|
||||
|
|
@ -139,12 +142,16 @@ func transition_out(
|
|||
_cancel_transition()
|
||||
_is_transitioning = true
|
||||
_set_interactive(false)
|
||||
var target_y: float = -_cluster.size.y - transition_safe_margin
|
||||
var duration := UIMotion.bubble_duration(
|
||||
target_y - _cluster.position.y
|
||||
)
|
||||
var generation: int = _transition_generation
|
||||
_transition = create_tween()
|
||||
_transition.tween_property(
|
||||
_cluster,
|
||||
"position:y",
|
||||
-_cluster.size.y - transition_safe_margin,
|
||||
target_y,
|
||||
duration
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_transition.finished.connect(
|
||||
|
|
|
|||
|
|
@ -83,8 +83,6 @@ const INTRO_PROMPT_FADE_DURATION: float = 0.55
|
|||
const INTRO_BUBBLE_TRAVEL_DURATION: float = 2.40
|
||||
const INTRO_BRANDING_TRAVEL_DURATION: float = 2.0
|
||||
const INTRO_BRANDING_START_DELAY: float = 0.35
|
||||
const HOST_PRESENTATION_OUT_DURATION: float = 1.70
|
||||
const HOST_PRESENTATION_IN_DURATION: float = 1.85
|
||||
const HOST_CLUSTER_SAFE_MARGIN: float = 24.0
|
||||
|
||||
signal new_game_requested
|
||||
|
|
@ -203,6 +201,7 @@ func _ready() -> void:
|
|||
_confirmation_page.cancelled.connect(_request_close_confirmation)
|
||||
_settings_panel.applied.connect(_on_settings_applied)
|
||||
_settings_panel.closed.connect(_on_settings_closed)
|
||||
_settings_panel.closing.connect(_on_settings_closing)
|
||||
_settings_panel.opened.connect(_on_settings_opened)
|
||||
_settings_panel.navigation_transition_started.connect(
|
||||
_emit_navigation_bubble_flurry
|
||||
|
|
@ -1032,7 +1031,7 @@ func _begin_confirmation_open() -> void:
|
|||
_presentation_center,
|
||||
"position:y",
|
||||
_confirmation_title_content_rest_position.y - exit_distance,
|
||||
HOST_PRESENTATION_OUT_DURATION
|
||||
UIMotion.bubble_duration(exit_distance)
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_confirmation_transition.finished.connect(
|
||||
_finish_confirmation_title_exit.bind(generation),
|
||||
|
|
@ -1050,7 +1049,7 @@ func _finish_confirmation_title_exit(generation: int) -> void:
|
|||
_presentation_center.hide()
|
||||
_presentation_center.position = _confirmation_title_content_rest_position
|
||||
_confirmation_page.transition_in(
|
||||
HOST_PRESENTATION_IN_DURATION,
|
||||
0.0,
|
||||
_finish_confirmation_open.bind(generation)
|
||||
)
|
||||
|
||||
|
|
@ -1074,7 +1073,7 @@ func _begin_confirmation_return() -> void:
|
|||
_confirmation_page.lock_interaction()
|
||||
var generation: int = _confirmation_transition_generation
|
||||
_confirmation_page.transition_out(
|
||||
HOST_PRESENTATION_OUT_DURATION,
|
||||
0.0,
|
||||
_finish_confirmation_page_exit.bind(generation)
|
||||
)
|
||||
|
||||
|
|
@ -1092,12 +1091,16 @@ func _finish_confirmation_page_exit(generation: int) -> void:
|
|||
+ HOST_CLUSTER_SAFE_MARGIN
|
||||
)
|
||||
_presentation_center.show()
|
||||
var entry_distance: float = absf(
|
||||
_presentation_center.position.y
|
||||
- _confirmation_title_content_rest_position.y
|
||||
)
|
||||
_confirmation_transition = create_tween()
|
||||
_confirmation_transition.tween_property(
|
||||
_presentation_center,
|
||||
"position",
|
||||
_confirmation_title_content_rest_position,
|
||||
HOST_PRESENTATION_IN_DURATION
|
||||
UIMotion.bubble_duration(entry_distance)
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_confirmation_transition.finished.connect(
|
||||
_finish_confirmation_return.bind(generation),
|
||||
|
|
@ -1177,15 +1180,23 @@ func _close_settings() -> void:
|
|||
|
||||
|
||||
func _on_settings_applied() -> void:
|
||||
_begin_title_cluster_return("settings saved.")
|
||||
_feedback_text_before_settings = "settings saved."
|
||||
|
||||
|
||||
func _on_settings_closed() -> void:
|
||||
pass
|
||||
|
||||
|
||||
func _on_settings_closing() -> void:
|
||||
await get_tree().create_timer(
|
||||
UIMotion.BUBBLE_TRANSITION_OVERLAP_DELAY
|
||||
).timeout
|
||||
if _settings_panel.visible:
|
||||
_begin_title_cluster_return(_feedback_text_before_settings)
|
||||
|
||||
|
||||
func _on_settings_opened() -> void:
|
||||
_title_settings_transition_active = false
|
||||
pass
|
||||
|
||||
|
||||
func _begin_title_cluster_exit() -> void:
|
||||
|
|
@ -1207,12 +1218,23 @@ func _begin_title_cluster_exit() -> void:
|
|||
_presentation_center,
|
||||
"position:y",
|
||||
_title_content_rest_position.y - exit_distance,
|
||||
HOST_PRESENTATION_OUT_DURATION
|
||||
UIMotion.bubble_duration(exit_distance)
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_title_settings_transition.finished.connect(
|
||||
_finish_title_cluster_exit.bind(generation),
|
||||
CONNECT_ONE_SHOT
|
||||
)
|
||||
await get_tree().create_timer(
|
||||
UIMotion.BUBBLE_TRANSITION_OVERLAP_DELAY
|
||||
).timeout
|
||||
if (
|
||||
generation == _title_settings_transition_generation
|
||||
and _title_settings_transition_active
|
||||
):
|
||||
_settings_panel.open_panel(
|
||||
_settings_manager,
|
||||
SettingsPanelType.PresentationMode.TITLE_EMBEDDED
|
||||
)
|
||||
|
||||
|
||||
func _finish_title_cluster_exit(generation: int) -> void:
|
||||
|
|
@ -1222,12 +1244,9 @@ func _finish_title_cluster_exit(generation: int) -> void:
|
|||
):
|
||||
return
|
||||
_title_settings_transition = null
|
||||
_title_settings_transition_active = false
|
||||
_presentation_center.hide()
|
||||
_presentation_center.position = _title_content_rest_position
|
||||
_settings_panel.open_panel(
|
||||
_settings_manager,
|
||||
SettingsPanelType.PresentationMode.TITLE_EMBEDDED
|
||||
)
|
||||
|
||||
|
||||
func _begin_title_cluster_return(feedback_text: String) -> void:
|
||||
|
|
@ -1245,12 +1264,15 @@ func _begin_title_cluster_return(feedback_text: String) -> void:
|
|||
_title_presentation_scale_root.size.y + HOST_CLUSTER_SAFE_MARGIN
|
||||
)
|
||||
_presentation_center.show()
|
||||
var entry_distance: float = absf(
|
||||
_presentation_center.position.y - _title_content_rest_position.y
|
||||
)
|
||||
_title_settings_transition = create_tween()
|
||||
_title_settings_transition.tween_property(
|
||||
_presentation_center,
|
||||
"position",
|
||||
_title_content_rest_position,
|
||||
HOST_PRESENTATION_IN_DURATION
|
||||
UIMotion.bubble_duration(entry_distance)
|
||||
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
_title_settings_transition.finished.connect(
|
||||
_finish_title_cluster_return.bind(generation),
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ script = ExtResource("1_script")
|
|||
|
||||
[node name="Background" type="ColorRect" parent="."]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
material = SubResource("ShaderMaterial_title_water")
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
|
|
|
|||
12
ui/ui_motion.gd
Normal file
12
ui/ui_motion.gd
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
class_name UIMotion
|
||||
extends RefCounted
|
||||
|
||||
const BUBBLE_VERTICAL_SPEED: float = 420.0
|
||||
const BUBBLE_TRANSITION_OVERLAP_DELAY: float = 0.05
|
||||
const UTILITY_ENTER_DURATION: float = 0.19
|
||||
const UTILITY_EXIT_DURATION: float = 0.15
|
||||
const UTILITY_ENTER_SCALE: float = 0.97
|
||||
|
||||
|
||||
static func bubble_duration(distance: float) -> float:
|
||||
return maxf(absf(distance) / BUBBLE_VERTICAL_SPEED, 0.08)
|
||||
1
ui/ui_motion.gd.uid
Normal file
1
ui/ui_motion.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://biwyjd2usqsm6
|
||||
150
ui/utility_page_style.gd
Normal file
150
ui/utility_page_style.gd
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
class_name UtilityPageStyle
|
||||
extends RefCounted
|
||||
|
||||
const TuffyFont: Font = preload("res://ui/fonts/Tuffy_Bold.otf")
|
||||
const PAPER: Color = Color("eee2bd")
|
||||
const PAPER_ALT: Color = Color("f3ecd7")
|
||||
const INK: Color = Color("28251f")
|
||||
const MUTED_INK: Color = Color("5f5547")
|
||||
const NAVY: Color = Color("092b3d")
|
||||
const NAVY_HOVER: Color = Color("12465b")
|
||||
const GREEN: Color = Color("31594d")
|
||||
const BORDER: Color = Color("473d2e")
|
||||
const LIGHT_TEXT: Color = Color("f5eed9")
|
||||
const DISABLED_TEXT: Color = Color(0.33, 0.36, 0.35, 0.72)
|
||||
const MOTION_TWEEN_META: StringName = &"utility_page_motion_tween"
|
||||
|
||||
|
||||
static func apply_page(root: Control) -> void:
|
||||
root.add_theme_font_override("font", TuffyFont)
|
||||
|
||||
|
||||
static func panel_style() -> StyleBoxFlat:
|
||||
var style := StyleBoxFlat.new()
|
||||
style.bg_color = PAPER
|
||||
style.border_color = BORDER
|
||||
style.set_border_width_all(4)
|
||||
style.set_corner_radius_all(16)
|
||||
style.content_margin_left = 26
|
||||
style.content_margin_right = 26
|
||||
style.content_margin_top = 20
|
||||
style.content_margin_bottom = 20
|
||||
style.shadow_color = Color(0.02, 0.075, 0.11, 0.34)
|
||||
style.shadow_size = 7
|
||||
style.shadow_offset = Vector2(5, 6)
|
||||
return style
|
||||
|
||||
|
||||
static func row_style(selected: bool = false) -> StyleBoxFlat:
|
||||
var style := StyleBoxFlat.new()
|
||||
style.bg_color = NAVY if selected else PAPER_ALT
|
||||
style.border_color = Color(BORDER, 0.55)
|
||||
style.set_border_width_all(2)
|
||||
style.set_corner_radius_all(8)
|
||||
style.content_margin_left = 12
|
||||
style.content_margin_right = 12
|
||||
style.content_margin_top = 8
|
||||
style.content_margin_bottom = 8
|
||||
return style
|
||||
|
||||
|
||||
static func button_style(color: Color) -> StyleBoxFlat:
|
||||
var style := StyleBoxFlat.new()
|
||||
style.bg_color = color
|
||||
style.border_color = Color(0.76, 0.86, 0.78, 0.72)
|
||||
style.set_border_width_all(2)
|
||||
style.set_corner_radius_all(7)
|
||||
style.content_margin_left = 14
|
||||
style.content_margin_right = 14
|
||||
style.content_margin_top = 8
|
||||
style.content_margin_bottom = 8
|
||||
return style
|
||||
|
||||
|
||||
static func apply_button(button: BaseButton) -> void:
|
||||
button.add_theme_font_override("font", TuffyFont)
|
||||
button.add_theme_color_override("font_color", LIGHT_TEXT)
|
||||
button.add_theme_color_override("font_hover_color", Color.WHITE)
|
||||
button.add_theme_color_override("font_pressed_color", Color.WHITE)
|
||||
button.add_theme_color_override("font_focus_color", Color.WHITE)
|
||||
button.add_theme_color_override("font_disabled_color", DISABLED_TEXT)
|
||||
button.add_theme_stylebox_override("normal", button_style(NAVY))
|
||||
button.add_theme_stylebox_override("hover", button_style(NAVY_HOVER))
|
||||
button.add_theme_stylebox_override("pressed", button_style(GREEN))
|
||||
button.add_theme_stylebox_override("focus", button_style(NAVY_HOVER))
|
||||
button.add_theme_stylebox_override(
|
||||
"disabled", button_style(Color(0.37, 0.42, 0.40, 0.55))
|
||||
)
|
||||
button.custom_minimum_size.y = maxf(button.custom_minimum_size.y, 40.0)
|
||||
|
||||
|
||||
static func apply_line_edit(edit: LineEdit) -> void:
|
||||
edit.add_theme_font_override("font", TuffyFont)
|
||||
edit.add_theme_color_override("font_color", LIGHT_TEXT)
|
||||
edit.add_theme_color_override(
|
||||
"font_placeholder_color", Color(0.82, 0.80, 0.71, 0.84)
|
||||
)
|
||||
edit.add_theme_color_override("font_selected_color", Color.WHITE)
|
||||
edit.add_theme_color_override("caret_color", Color("fff0b6"))
|
||||
edit.add_theme_color_override("selection_color", Color("2f7186"))
|
||||
edit.add_theme_color_override("font_uneditable_color", Color("c9c2ae"))
|
||||
edit.add_theme_stylebox_override("normal", button_style(NAVY))
|
||||
edit.add_theme_stylebox_override("focus", button_style(NAVY_HOVER))
|
||||
edit.add_theme_stylebox_override(
|
||||
"read_only", button_style(Color(NAVY, 0.82))
|
||||
)
|
||||
|
||||
|
||||
static func animate_in(control: Control) -> void:
|
||||
_cancel_motion(control)
|
||||
control.pivot_offset = control.size * 0.5
|
||||
control.scale = Vector2.ONE * UIMotion.UTILITY_ENTER_SCALE
|
||||
control.modulate.a = 0.0
|
||||
control.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
var tween := control.create_tween()
|
||||
control.set_meta(MOTION_TWEEN_META, tween)
|
||||
tween.set_parallel(true)
|
||||
tween.tween_property(
|
||||
control, "scale", Vector2.ONE, UIMotion.UTILITY_ENTER_DURATION
|
||||
).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
|
||||
tween.tween_property(
|
||||
control, "modulate:a", 1.0, UIMotion.UTILITY_ENTER_DURATION
|
||||
)
|
||||
tween.finished.connect(func() -> void:
|
||||
if is_instance_valid(control):
|
||||
control.mouse_filter = Control.MOUSE_FILTER_PASS
|
||||
control.remove_meta(MOTION_TWEEN_META)
|
||||
)
|
||||
|
||||
|
||||
static func animate_out(control: Control, completed: Callable) -> void:
|
||||
_cancel_motion(control)
|
||||
control.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
control.pivot_offset = control.size * 0.5
|
||||
var tween := control.create_tween()
|
||||
control.set_meta(MOTION_TWEEN_META, tween)
|
||||
tween.set_parallel(true)
|
||||
tween.tween_property(
|
||||
control,
|
||||
"scale",
|
||||
Vector2.ONE * UIMotion.UTILITY_ENTER_SCALE,
|
||||
UIMotion.UTILITY_EXIT_DURATION
|
||||
).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN)
|
||||
tween.tween_property(
|
||||
control, "modulate:a", 0.0, UIMotion.UTILITY_EXIT_DURATION
|
||||
)
|
||||
if completed.is_valid():
|
||||
tween.finished.connect(completed, CONNECT_ONE_SHOT)
|
||||
tween.finished.connect(func() -> void:
|
||||
if is_instance_valid(control):
|
||||
control.remove_meta(MOTION_TWEEN_META)
|
||||
)
|
||||
|
||||
|
||||
static func _cancel_motion(control: Control) -> void:
|
||||
if not control.has_meta(MOTION_TWEEN_META):
|
||||
return
|
||||
var existing := control.get_meta(MOTION_TWEEN_META) as Tween
|
||||
if existing != null and existing.is_valid():
|
||||
existing.kill()
|
||||
control.remove_meta(MOTION_TWEEN_META)
|
||||
1
ui/utility_page_style.gd.uid
Normal file
1
ui/utility_page_style.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://bmfqwan211x0j
|
||||
Loading…
Add table
Add a link
Reference in a new issue