Refine TAB menu presentation and standardize UI fonts

This commit is contained in:
Alexander Sellite 2026-07-31 13:14:55 -04:00
parent 78b91c350b
commit 59bdb07fc5
19 changed files with 393 additions and 435 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://d0o3ym81t1sxs"
path="res://.godot/imported/pattern_bluedot.png-2880ee070284314ed1e7b46e1dbc0570.ctex"
uid="uid://f8a0cs0s7ler"
path="res://.godot/imported/pattern_tealdot.png-ea096873729758aad8d393553ab96b2d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/patterns/pattern_bluedot.png"
dest_files=["res://.godot/imported/pattern_bluedot.png-2880ee070284314ed1e7b46e1dbc0570.ctex"]
source_file="res://art/patterns/pattern_tealdot.png"
dest_files=["res://.godot/imported/pattern_tealdot.png-ea096873729758aad8d393553ab96b2d.ctex"]
[params]

View file

@ -180,9 +180,7 @@ func _ready() -> void:
):
_settings_manager.settings_changed.connect(_apply_runtime_settings)
_settings_manager.load_settings()
_interface_fonts.set_readable_font_enabled(
_settings_manager.current_settings.use_readable_interface_font
)
_interface_fonts.enforce_standard_font()
if _data_root.resolve():
_configure_portable_stores()
_initialize_after_data_root()
@ -856,9 +854,6 @@ func _process(_delta: float) -> void:
func _apply_runtime_settings(settings: PlayerSettingsType) -> void:
if settings == null:
return
_interface_fonts.set_readable_font_enabled(
settings.use_readable_interface_font
)
_apply_world_pixelation(settings.world_pixel_size)
_ui_pixelation.set_pixel_size(settings.ui_pixel_size)
_game_ui.get_title_screen().set_world_pixelation(
@ -935,7 +930,7 @@ func _set_player_menu_backdrop_visible(is_visible: bool) -> void:
_player_menu_backdrop,
"modulate:a",
1.0,
UIMotion.UTILITY_ENTER_DURATION,
UIMotion.PLAYER_MENU_ENTER_DURATION,
).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
return
if not _player_menu_backdrop.visible:
@ -945,7 +940,7 @@ func _set_player_menu_backdrop_visible(is_visible: bool) -> void:
_player_menu_backdrop,
"modulate:a",
0.0,
UIMotion.UTILITY_EXIT_DURATION,
UIMotion.PLAYER_MENU_EXIT_DURATION,
).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN)
_player_menu_backdrop_tween.finished.connect(
func() -> void:

View file

@ -40,7 +40,7 @@
[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"]
[ext_resource type="Texture2D" path="res://art/patterns/pattern_bluedot.png" id="41_menu_pattern"]
[ext_resource type="Texture2D" path="res://art/patterns/pattern_tealdot.png" id="41_menu_pattern"]
[ext_resource type="Shader" path="res://ui/player_menu_pattern.gdshader" id="42_menu_pattern"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_title_water_native"]

View file

@ -21,7 +21,8 @@ const UI_DESKTOP_RENDER_HEIGHTS: Array[int] = [0, 612, 504, 396, 288]
const UI_COMPACT_RENDER_HEIGHTS: Array[int] = [0, 408, 336, 264, 192]
@export var auto_click_enabled: bool = false
@export var use_readable_interface_font: bool = false
# Legacy settings-file field. Tuffy is now always used at runtime.
@export var use_readable_interface_font: bool = true
@export_range(0.10, 0.50, 0.01) var auto_click_interval: float = 0.20
@export_range(0.001, 0.012, 0.0005) var mouse_camera_sensitivity: float = 0.005
@export_range(0.5, 5.0, 0.1) var controller_camera_sensitivity: float = 2.5
@ -54,7 +55,7 @@ func is_valid() -> bool:
func copy() -> PlayerSettings:
var result := PlayerSettings.new()
result.auto_click_enabled = auto_click_enabled
result.use_readable_interface_font = use_readable_interface_font
result.use_readable_interface_font = true
result.auto_click_interval = auto_click_interval
result.mouse_camera_sensitivity = mouse_camera_sensitivity
result.controller_camera_sensitivity = controller_camera_sensitivity

View file

@ -61,9 +61,8 @@ func load_settings() -> bool:
return _use_defaults_after_corruption("Player settings values are invalid.")
var loaded := PlayerSettings.new()
loaded.auto_click_enabled = accessibility["auto_click_enabled"]
loaded.use_readable_interface_font = bool(
accessibility.get("use_readable_interface_font", false)
)
# Accept the legacy field, but normalize runtime and future saved state.
loaded.use_readable_interface_font = true
loaded.auto_click_interval = _read_float(
accessibility.get("auto_click_interval"),
-1.0
@ -159,9 +158,7 @@ func save_now() -> bool:
"accessibility": {
"auto_click_enabled": current_settings.auto_click_enabled,
"auto_click_interval": current_settings.auto_click_interval,
"use_readable_interface_font": (
current_settings.use_readable_interface_font
),
"use_readable_interface_font": true,
},
"camera": {
"mouse_sensitivity": current_settings.mouse_camera_sensitivity,

View file

@ -10,6 +10,7 @@ const CONTENT_MARGIN_LEFT := 18.0
const CONTENT_MARGIN_TOP := 98.0
const CONTENT_MARGIN_RIGHT := 18.0
const CONTENT_MARGIN_BOTTOM := 16.0
const HANDWRITTEN_FONT: Font = preload("res://ui/fonts/seattle_avenue.otf")
@export var title_text := "notes"
@export var inset_content := true
@ -17,14 +18,25 @@ const CONTENT_MARGIN_BOTTOM := 16.0
func _ready() -> void:
mouse_filter = Control.MOUSE_FILTER_PASS
add_theme_font_override("font", UtilityPageStyle.TuffyFont)
apply_handwritten_to(self)
add_theme_stylebox_override("panel", make_paper_style(inset_content))
resized.connect(queue_redraw)
queue_redraw()
static func apply_handwritten_to(root: Control) -> void:
root.add_theme_font_override("font", HANDWRITTEN_FONT)
for descendant: Node in root.find_children("*", "Control", true, false):
var control := descendant as Control
control.add_theme_font_override(
"font", HANDWRITTEN_FONT
)
if control is Label:
control.add_theme_color_override("font_color", INK_COLOR)
func _draw() -> void:
var font: Font = UtilityPageStyle.TuffyFont
var font: Font = HANDWRITTEN_FONT
draw_string(
font,
Vector2(28.0, 25.0),

View file

@ -1,27 +1,37 @@
class_name OrganizerTab
extends Button
const INACTIVE_COLOR := Color("d6b875")
const SELECTED_COLOR := Color("f0d995")
const BORDER_COLOR := Color("4c3a25")
const TEXT_COLOR := Color("251b10")
const DISABLED_COLOR := Color("aa9a76")
const PALETTE: Array[Color] = [
Color("b9deea"),
Color("3d9ca0"),
Color("4f9b72"),
]
const TEXT_COLOR := Color("102b35")
const RISE_DURATION: float = UIMotion.UTILITY_ENTER_DURATION
const INACTIVE_SETTLE_Y: float = 8.0
const SELECTED_SETTLE_Y: float = 0.0
const HOVER_SETTLE_Y: float = 4.0
const INACTIVE_SETTLE_Y: float = 7.0
const SELECTED_SETTLE_Y: float = 1.0
const HOVER_SETTLE_Y: float = 5.0
const HIDDEN_SETTLE_Y: float = 30.0
const CAP_HEIGHT: float = 22.0
const FONT_SIZE: int = 15
@export_range(0, 2, 1) var palette_index: int = 0:
set(value):
palette_index = clampi(value, 0, PALETTE.size() - 1)
queue_redraw()
var _motion_tween: Tween
var _hovered: bool = false
var _motion_ready: bool = false
var _visual_y: float = INACTIVE_SETTLE_Y
var _selected: bool = false
func _ready() -> void:
toggle_mode = true
_selected = button_pressed
add_theme_font_override("font", UtilityPageStyle.TuffyFont)
add_theme_font_size_override("font_size", 18)
add_theme_font_size_override("font_size", FONT_SIZE)
for color_name: StringName in [
&"font_color",
&"font_hover_color",
@ -45,6 +55,12 @@ func refresh_state(animate: bool = true) -> void:
_move_to_target(animate)
func set_selected(value: bool, animate: bool = true) -> void:
_selected = value
set_pressed_no_signal(value)
refresh_state(animate)
func animate_entrance(delay: float = 0.0) -> void:
_cancel_motion()
_motion_ready = true
@ -77,7 +93,14 @@ func _initialize_motion() -> void:
_set_visual_y(_target_y())
func _on_toggled(_pressed: bool) -> void:
func _on_toggled(pressed: bool) -> void:
if _selected and not pressed:
# A selected organizer tab is a page marker, not a collapsible toggle.
# Restore without another signal before any lower-state frame is drawn.
set_pressed_no_signal(true)
refresh_state(false)
return
_selected = pressed
refresh_state()
@ -107,35 +130,43 @@ func _move_to_target(animate: bool) -> void:
func _draw() -> void:
var base_color: Color = SELECTED_COLOR if button_pressed else INACTIVE_COLOR
var border_width: int = 2
var shadow_alpha: float = 0.28
if disabled:
base_color = DISABLED_COLOR
border_width = 1
shadow_alpha = 0.12
elif has_focus():
base_color = base_color.lightened(0.09)
border_width = 4
shadow_alpha = 0.40
elif _hovered:
base_color = base_color.lightened(0.07)
border_width = 3
shadow_alpha = 0.34
var visual_rect := Rect2(Vector2(0.0, _visual_y), size)
draw_style_box(
_make_style(base_color, border_width, shadow_alpha),
visual_rect,
var base_color: Color = PALETTE[palette_index]
base_color = (
base_color.lightened(0.06)
if button_pressed
else base_color.darkened(0.07)
)
if disabled:
base_color = base_color.lerp(Color("8a978f"), 0.62)
elif has_focus():
base_color = base_color.lightened(0.12)
elif _hovered:
base_color = base_color.lightened(0.08)
var width: float = size.x
var height: float = size.y
var points := PackedVector2Array([
Vector2(10.0, _visual_y),
Vector2(width - 10.0, _visual_y),
Vector2(width - 5.0, _visual_y + 5.0),
Vector2(width - 5.0, _visual_y + 17.0),
Vector2(width, _visual_y + 26.0),
Vector2(width, _visual_y + height),
Vector2(0.0, _visual_y + height),
Vector2(0.0, _visual_y + 26.0),
Vector2(5.0, _visual_y + 17.0),
Vector2(5.0, _visual_y + 5.0),
])
draw_colored_polygon(points, base_color)
var font: Font = UtilityPageStyle.TuffyFont
var ink: Color = Color(TEXT_COLOR, 0.52) if disabled else TEXT_COLOR
var baseline: float = _visual_y + CAP_HEIGHT * 0.5 + FONT_SIZE * 0.35
draw_string(
font,
Vector2(0.0, _visual_y + 32.0),
Vector2(0.0, baseline),
text,
HORIZONTAL_ALIGNMENT_CENTER,
size.x,
18,
FONT_SIZE,
ink,
)
@ -156,28 +187,6 @@ func _set_visual_y(value: float) -> void:
queue_redraw()
func _make_style(fill: Color, border_width: int, shadow_alpha: float) -> StyleBoxFlat:
var style := StyleBoxFlat.new()
style.bg_color = fill
style.border_color = BORDER_COLOR
style.border_width_left = border_width
style.border_width_top = border_width
style.border_width_right = border_width
style.border_width_bottom = 1
style.corner_radius_top_left = 13
style.corner_radius_top_right = 13
style.corner_radius_bottom_left = 2
style.corner_radius_bottom_right = 2
style.shadow_color = Color(0.12, 0.08, 0.04, shadow_alpha)
style.shadow_size = 4
style.shadow_offset = Vector2(0.0, 3.0)
style.content_margin_left = 14.0
style.content_margin_right = 14.0
style.content_margin_top = 8.0
style.content_margin_bottom = 12.0
return style
func _cancel_motion() -> void:
if _motion_tween != null:
_motion_tween.kill()

View file

@ -1,6 +1,6 @@
[gd_resource type="Theme" load_steps=13 format=3]
[ext_resource type="FontFile" uid="uid://ddbejmxpa3kw6" path="res://ui/fonts/seattle_avenue.otf" id="1_font"]
[ext_resource type="FontFile" path="res://ui/fonts/Tuffy_Bold.otf" id="1_font"]
[sub_resource type="StyleBoxFlat" id="Panel"]
bg_color = Color(0.075, 0.145, 0.17, 0.96)

View file

@ -78,6 +78,9 @@ var _item_effects: PlayerItemEffectsType
func _ready() -> void:
_hotbar_ui.presentation_transition_finished.connect(
_on_hotbar_presentation_transition_finished
)
_title_settings_panel.panel_visibility_changed.connect(
_on_settings_visibility_changed
)
@ -284,6 +287,7 @@ func set_system_menu_open(is_open: bool) -> void:
)
_hotbar_ui.set_drag_enabled(_player_menu_open and not is_open)
if is_open:
_hotbar_ui.set_drag_enabled(false)
_shop_prompt.hide()
_emit_interactive_pointer_ui_changed()
@ -502,21 +506,27 @@ func _on_player_menu_visibility_changed(is_open: bool) -> void:
_player_menu_open = is_open
_gameplay_transient_hud.visible = _gameplay_ui_enabled and not is_open
if is_open:
_hotbar_ui.set_drag_enabled(false)
_hotbar_ui.set_presentation_visible(false, false)
if _player_menu_hotbar_visible:
_hotbar_ui.set_player_menu_context(true)
_hotbar_ui.set_presentation_visible(true, true)
_hotbar_ui.set_presentation_visible(
true,
true,
UIMotion.PLAYER_MENU_ENTER_DURATION,
)
player_menu_backdrop_visibility_changed.emit(true)
else:
_player_menu_hotbar_visible = false
_hotbar_ui.set_presentation_visible(false, false)
_hotbar_ui.set_player_menu_context(false)
player_menu_backdrop_visibility_changed.emit(is_open)
_refresh_chat_availability()
_hotbar_ui.set_gameplay_input_enabled(
_gameplay_ui_enabled and not is_open
)
_hotbar_ui.set_drag_enabled(is_open)
_refresh_hotbar_visibility()
if not is_open:
_hotbar_ui.set_drag_enabled(false)
_refresh_hotbar_visibility()
_refresh_fishing_panel_visibility()
_emit_interactive_pointer_ui_changed()
if is_open:
@ -529,7 +539,12 @@ func _on_player_menu_exit_started() -> void:
if not _player_menu_open:
return
_hotbar_ui.set_drag_enabled(false)
_hotbar_ui.set_presentation_visible(false, true)
_hotbar_ui.set_presentation_visible(
false,
true,
UIMotion.PLAYER_MENU_EXIT_DURATION,
)
player_menu_backdrop_visibility_changed.emit(false)
func _on_shop_visibility_changed(is_open: bool) -> void:
@ -550,13 +565,39 @@ func _on_shop_visibility_changed(is_open: bool) -> void:
func _on_inventory_hotbar_context_changed(show_hotbar: bool) -> void:
var context_changed: bool = _player_menu_hotbar_visible != show_hotbar
_player_menu_hotbar_visible = show_hotbar
if _player_menu_open and show_hotbar and context_changed:
_hotbar_ui.set_presentation_visible(false, false)
_hotbar_ui.set_player_menu_context(true)
_hotbar_ui.set_drag_enabled(_player_menu_open and show_hotbar)
if _player_menu_open and context_changed:
_hotbar_ui.set_drag_enabled(false)
if show_hotbar:
_hotbar_ui.set_presentation_visible(false, false)
_hotbar_ui.set_player_menu_context(true)
_hotbar_ui.set_presentation_visible(
true,
true,
UIMotion.PLAYER_MENU_INVENTORY_DURATION,
)
else:
_hotbar_ui.set_presentation_visible(
false,
true,
UIMotion.PLAYER_MENU_INVENTORY_DURATION,
)
elif _player_menu_open and show_hotbar:
_hotbar_ui.set_drag_enabled(true)
if not context_changed:
return
_refresh_hotbar_visibility()
if not _player_menu_open:
_refresh_hotbar_visibility()
func _on_hotbar_presentation_transition_finished(
is_visible: bool,
) -> void:
_hotbar_ui.set_drag_enabled(
is_visible
and _player_menu_open
and _player_menu_hotbar_visible
and not _system_menu_open
)
func _refresh_hotbar_visibility() -> void:

View file

@ -1,6 +1,8 @@
class_name HotbarUI
extends Control
signal presentation_transition_finished(is_visible: bool)
const ItemCatalogType = preload("res://items/item_catalog.gd")
const PlayerBagType = preload("res://inventory/player_bag.gd")
const PlayerHotbarType = preload("res://inventory/player_hotbar.gd")
@ -14,6 +16,9 @@ const COMPACT_REFERENCE_SIZE := Vector2(640.0, 480.0)
const HOTBAR_PRESENTATION_SCALE: float = 0.60
const HOTBAR_CANONICAL_POSITION := Vector2(256.0, 288.0)
const HOTBAR_MENU_POSITION := Vector2(80.0, 198.0)
const HOTBAR_GAMEPLAY_Z_INDEX: int = 35
# PlayerMenu is z=30 and its authored inventory panels are relative z=50.
const HOTBAR_MENU_Z_INDEX: int = 90
@onready var _presentation_scale_root: Control = %HotbarPresentationScaleRoot
@onready var _bubble_field: Control = %BubbleField
@ -90,28 +95,49 @@ func set_player_menu_context(enabled: bool) -> void:
if _player_menu_context == enabled:
return
_player_menu_context = enabled
z_index = HOTBAR_MENU_Z_INDEX if enabled else HOTBAR_GAMEPLAY_Z_INDEX
_presentation_scale_root.position = (
HOTBAR_MENU_POSITION if enabled else HOTBAR_CANONICAL_POSITION
)
func set_presentation_visible(should_show: bool, animate: bool = true) -> void:
func set_presentation_visible(
should_show: bool,
animate: bool = true,
transition_duration: float = -1.0,
) -> void:
_visibility_generation += 1
var generation: int = _visibility_generation
if _visibility_tween != null:
_visibility_tween.kill()
_visibility_tween = null
if should_show:
var was_visible: bool = visible
visible = true
if not animate:
modulate.a = 1.0
presentation_transition_finished.emit(true)
return
if not was_visible:
modulate.a = 0.0
var duration: float = (
transition_duration
if transition_duration >= 0.0
else UIMotion.UTILITY_ENTER_DURATION
)
_visibility_tween = create_tween()
_visibility_tween.tween_property(
self,
"modulate:a",
1.0,
UIMotion.UTILITY_ENTER_DURATION,
duration,
)
_visibility_tween.finished.connect(
func() -> void:
if generation != _visibility_generation:
return
_visibility_tween = null
presentation_transition_finished.emit(true)
)
else:
if not visible:
@ -119,13 +145,19 @@ func set_presentation_visible(should_show: bool, animate: bool = true) -> void:
if not animate:
visible = false
modulate.a = 1.0
presentation_transition_finished.emit(false)
return
var duration: float = (
transition_duration
if transition_duration >= 0.0
else UIMotion.UTILITY_EXIT_DURATION
)
_visibility_tween = create_tween()
_visibility_tween.tween_property(
self,
"modulate:a",
0.0,
UIMotion.UTILITY_EXIT_DURATION,
duration,
)
_visibility_tween.finished.connect(
func() -> void:
@ -134,6 +166,7 @@ func set_presentation_visible(should_show: bool, animate: bool = true) -> void:
visible = false
modulate.a = 1.0
_visibility_tween = null
presentation_transition_finished.emit(false)
)

View file

@ -1,40 +1,31 @@
class_name InterfaceFontController
extends Node
signal font_mode_changed(use_readable_font: bool)
const READABLE_FONT_PATH: String = "res://ui/fonts/Tuffy_Bold.otf"
const STANDARD_FONT: Font = preload("res://ui/fonts/Tuffy_Bold.otf")
var _game_theme: Theme = preload("res://ui/game_theme.tres")
var _game_font: Font = preload("res://ui/fonts/seattle_avenue.otf")
var _readable_font: Font
var _utility_theme: Theme
var _use_readable_font: bool = false
func _ready() -> void:
if ResourceLoader.exists(READABLE_FONT_PATH):
_readable_font = load(READABLE_FONT_PATH) as Font
if _readable_font == null:
push_error("Readable interface font resource is unavailable.")
else:
_readable_font.fallbacks = [_game_font]
enforce_standard_font()
_utility_theme = _game_theme.duplicate(true)
_utility_theme.default_font = readable_font()
_utility_theme.default_font = STANDARD_FONT
func set_readable_font_enabled(enabled: bool) -> void:
_use_readable_font = enabled
_game_theme.default_font = (
_readable_font
if enabled and _readable_font != null
else _game_font
)
font_mode_changed.emit(_use_readable_font)
func enforce_standard_font() -> void:
_game_theme.default_font = STANDARD_FONT
if _utility_theme != null:
_utility_theme.default_font = STANDARD_FONT
func set_readable_font_enabled(_enabled: bool) -> void:
# Compatibility seam for callers compiled against the old setting.
enforce_standard_font()
func is_readable_font_enabled() -> bool:
return _use_readable_font
return true
func apply_utility_theme(themed_node: Node) -> void:
@ -42,9 +33,7 @@ func apply_utility_theme(themed_node: Node) -> void:
return
if _utility_theme == null:
_utility_theme = _game_theme.duplicate(true)
_utility_theme.default_font = (
_readable_font if _readable_font != null else _game_font
)
_utility_theme.default_font = STANDARD_FONT
if themed_node is Control:
(themed_node as Control).theme = _utility_theme
elif themed_node is Window:
@ -52,4 +41,4 @@ func apply_utility_theme(themed_node: Node) -> void:
func readable_font() -> Font:
return _readable_font if _readable_font != null else _game_font
return STANDARD_FONT

View file

@ -16,6 +16,7 @@ const INK := Color("251b10")
const MUTED_INK := Color("6d5b45")
const PAPER := Color("f2e6c9")
const PAPER_DARK := Color("e8d7b4")
const LOGBOOK_TAB_LEFT_INSET: float = 34.0
var _collection_log: CollectionLogType
var _inventory: FishInventoryType
@ -97,7 +98,7 @@ func set_interactive(value: bool) -> void:
)
tab.mouse_filter = (
Control.MOUSE_FILTER_STOP
if _interactive
if _interactive and not tab.button_pressed
else Control.MOUSE_FILTER_IGNORE
)
for entry: Button in _entry_buttons.values():
@ -139,11 +140,13 @@ func _build_interface() -> void:
outer.add_child(stack)
var tabs := HBoxContainer.new()
tabs.position = Vector2(0.0, 10.0)
tabs.size = Vector2(520.0, 58.0)
# The 26 px page corner plus 8 px clearance keeps the flange behind
# the straight portion of the spread.
tabs.position = Vector2(LOGBOOK_TAB_LEFT_INSET, 20.0)
tabs.size = Vector2(384.0, 38.0)
tabs.z_index = 10
tabs.mouse_filter = Control.MOUSE_FILTER_PASS
tabs.add_theme_constant_override("separation", 8)
tabs.add_theme_constant_override("separation", 6)
stack.add_child(tabs)
for category: LogbookCatalog.Category in [
LogbookCatalog.Category.FRESH_WATER,
@ -151,10 +154,11 @@ func _build_interface() -> void:
LogbookCatalog.Category.OTHER,
]:
var tab := OrganizerTabType.new()
tab.custom_minimum_size = Vector2(168, 58)
tab.custom_minimum_size = Vector2(124, 38)
tab.toggle_mode = true
tab.text = LogbookCatalog.category_label(category)
tab.button_pressed = category == _category
tab.palette_index = int(category)
tab.set_selected(category == _category, false)
tab.pressed.connect(_select_category.bind(category))
tabs.add_child(tab)
_category_tabs.append(tab)
@ -365,8 +369,9 @@ func _select_category(category: LogbookCatalog.Category) -> void:
_selected_id = StringName()
_selected_entry_key = StringName()
for index: int in _category_tabs.size():
_category_tabs[index].button_pressed = index == int(_category)
(_category_tabs[index] as OrganizerTabType).refresh_state()
(_category_tabs[index] as OrganizerTabType).set_selected(
index == int(_category)
)
_begin_category_transition()

View file

@ -66,16 +66,14 @@ const LogbookEntryScene = preload(
"res://ui/components/bubble_menu/logbook_entry.tscn"
)
const PAGE_OUT_DURATION: float = 0.34
const PAGE_IN_DURATION: float = 0.42
const LOGBOOK_PAGE_DURATION: float = 0.18
const TRANSITION_SAFE_MARGIN: float = 28.0
const DESKTOP_REFERENCE_SIZE := Vector2(1280.0, 720.0)
const COMPACT_REFERENCE_SIZE := Vector2(640.0, 480.0)
const COMPACT_HEIGHT_THRESHOLD: float = 560.0
const NAVIGATION_PRESENTATION_SCALE: float = 0.60
const NAVIGATION_CANONICAL_POSITION := Vector2(424.0, 44.0)
const NAVIGATION_SELECTED_SCALE: float = 1.02
const INVENTORY_TAB_LEFT_INSET: float = 96.0
const COOLER_RARITY_COMMON := Color("e8eef0")
const COOLER_RARITY_UNCOMMON := Color("64c87c")
const COOLER_RARITY_RARE := Color("6098dd")
@ -131,6 +129,8 @@ const INVENTORY_NOTEPAD_POSITION := Vector2(
const INVENTORY_NOTEPAD_SIZE := Vector2(278.0, 484.0)
const INVENTORY_HEADER_INSET := Vector2(24.0, 20.0)
const INVENTORY_HEADER_HEIGHT := 40.0
const INVENTORY_MAIN_CORNER_RADIUS: int = 58
const INVENTORY_INNER_CORNER_RADIUS: int = 45
@onready var _navigation_cluster: BubbleClusterType = %NavigationCluster
@onready var _presentation_scale_root: Control = %PlayerMenuPresentationScaleRoot
@ -318,7 +318,8 @@ var _mail_rest_position: Vector2 = Vector2.ZERO
var _profile_rest_position: Vector2 = Vector2.ZERO
var _page_outgoing_root: Control
var _page_incoming_root: Control
var _page_hosts_shared: bool = false
var _page_outgoing_content_root: Control
var _inventory_transition_group: Control
var _fish_nodes: Dictionary[StringName, CoolerFishSpriteType] = {}
var _sorted_catches: Array[FishCatchType] = []
var _bag_item_nodes: Dictionary[StringName, BagItemSpriteType] = {}
@ -334,6 +335,9 @@ var _logbook_page_tween: Tween
func _ready() -> void:
_configure_inventory_transition_group()
_inventory_sub_tabs.move_child(_tackle_sub_tab, 1)
_inventory_sub_tabs.move_child(_bag_sub_tab, 2)
_inventory_tab.pressed.connect(_show_last_inventory_section)
_cooler_sub_tab.pressed.connect(_show_section.bind(Section.COOLER))
_bag_sub_tab.pressed.connect(_show_section.bind(Section.BAG))
@ -401,6 +405,39 @@ func _ready() -> void:
set_process(false)
func _configure_inventory_transition_group() -> void:
# Keep the organizer row and the panel that masks its lower flange under one
# alpha owner. Top-level page crossfades can then never expose a complete tab.
var original_layer_index: int = mini(
_inventory_sub_tabs.get_index(),
mini(
_cooler_page.get_index(),
mini(_bag_page.get_index(), _tackle_box_page.get_index()),
),
)
_inventory_transition_group = Control.new()
_inventory_transition_group.name = "InventoryTransitionGroup"
_inventory_transition_group.set_anchors_and_offsets_preset(
Control.PRESET_FULL_RECT
)
_inventory_transition_group.mouse_filter = Control.MOUSE_FILTER_IGNORE
_presentation_scale_root.add_child(_inventory_transition_group)
# Adding a runtime container normally places it after NavigationCluster in
# GUI picking order. Retain the pages' authored layer so their full-screen
# PASS roots cannot cover the top-level navigation hitboxes.
_presentation_scale_root.move_child(
_inventory_transition_group,
original_layer_index,
)
for control: Control in [
_inventory_sub_tabs,
_cooler_page,
_bag_page,
_tackle_box_page,
]:
control.reparent(_inventory_transition_group, true)
func _apply_mail_notification_style() -> void:
var background := StyleBoxFlat.new()
background.bg_color = Color(0.95, 0.88, 0.63, 0.98)
@ -795,9 +832,9 @@ func _show_section_immediate(section: Section) -> void:
else:
_players_page.deactivate()
_inventory_tab.button_pressed = _is_inventory_section(section)
_cooler_sub_tab.button_pressed = section == Section.COOLER
_bag_sub_tab.button_pressed = section == Section.BAG
_tackle_sub_tab.button_pressed = section == Section.TACKLE_BOX
_cooler_sub_tab.set_selected(section == Section.COOLER)
_bag_sub_tab.set_selected(section == Section.BAG)
_tackle_sub_tab.set_selected(section == Section.TACKLE_BOX)
_refresh_inventory_organizer_tabs()
_logbook_tab.button_pressed = section == Section.LOGBOOK
_mail_tab.button_pressed = section == Section.MAIL
@ -817,8 +854,8 @@ func _is_inventory_section(section: Section) -> bool:
func _refresh_inventory_organizer_tabs() -> void:
for tab: OrganizerTabType in [
_cooler_sub_tab,
_bag_sub_tab,
_tackle_sub_tab,
_bag_sub_tab,
]:
tab.refresh_state()
@ -828,8 +865,8 @@ func _animate_inventory_tab_entry() -> void:
return
var tabs: Array[OrganizerTabType] = [
_cooler_sub_tab,
_bag_sub_tab,
_tackle_sub_tab,
_bag_sub_tab,
]
for index: int in tabs.size():
tabs[index].animate_entrance(float(index) * 0.025)
@ -838,8 +875,8 @@ func _animate_inventory_tab_entry() -> void:
func _settle_inventory_tabs_for_close() -> void:
for tab: OrganizerTabType in [
_cooler_sub_tab,
_bag_sub_tab,
_tackle_sub_tab,
_bag_sub_tab,
]:
tab.settle_for_close()
@ -905,8 +942,8 @@ func _configure_navigation_focus() -> void:
bubble.focus_neighbor_bottom = bubble.focus_neighbor_right
var inventory_tabs: Array[Button] = [
_cooler_sub_tab,
_bag_sub_tab,
_tackle_sub_tab,
_bag_sub_tab,
]
for index: int in inventory_tabs.size():
var tab: Button = inventory_tabs[index]
@ -918,13 +955,23 @@ func _configure_navigation_focus() -> void:
)
tab.focus_neighbor_top = tab.get_path_to(_inventory_tab)
_inventory_tab.focus_neighbor_bottom = _inventory_tab.get_path_to(
inventory_tabs[int(_last_inventory_section)]
_inventory_tab_for_section(_last_inventory_section)
)
_tackle_sub_tab.focus_neighbor_bottom = _tackle_sub_tab.get_path_to(
_bait_filter
)
func _inventory_tab_for_section(section: Section) -> Button:
match section:
Section.COOLER:
return _cooler_sub_tab
Section.BAG:
return _bag_sub_tab
_:
return _tackle_sub_tab
func _configure_sale_confirmation_focus() -> void:
_confirm_sale_button.focus_neighbor_left = (
_confirm_sale_button.get_path_to(_cancel_sale_button)
@ -981,11 +1028,13 @@ func _apply_inventory_styles() -> void:
]:
UtilityPageStyle.apply_button(button)
for panel: PanelContainer in [_tackle_main_panel]:
var panel_style := UtilityPageStyle.panel_style()
panel_style.set_corner_radius_all(INVENTORY_MAIN_CORNER_RADIUS)
panel.add_theme_stylebox_override(
"panel",
UtilityPageStyle.panel_style(),
panel_style,
)
for label: Label in [_tackle_empty, _tackle_detail_text]:
for label: Label in [_tackle_empty]:
label.add_theme_font_override("font", UtilityPageStyle.TuffyFont)
label.add_theme_color_override(
"font_color",
@ -1129,13 +1178,13 @@ func _apply_cooler_wall_styles() -> void:
outer.bg_color = Color(0.76, 0.9, 0.96, 1.0)
outer.border_color = Color(0.91, 0.98, 1.0, 1.0)
outer.set_border_width_all(7)
outer.set_corner_radius_all(58)
outer.set_corner_radius_all(INVENTORY_MAIN_CORNER_RADIUS)
_cooler_outer_wall.add_theme_stylebox_override("panel", outer)
var inner := StyleBoxFlat.new()
inner.bg_color = Color(0.018, 0.16, 0.25, 1.0)
inner.border_color = Color(0.56, 0.78, 0.86, 1.0)
inner.set_border_width_all(5)
inner.set_corner_radius_all(45)
inner.set_corner_radius_all(INVENTORY_INNER_CORNER_RADIUS)
_cooler_inner_liner.add_theme_stylebox_override("panel", inner)
var scroll_bar := _cooler_scroll.get_v_scroll_bar()
var scroll_grabber := StyleBoxFlat.new()
@ -1155,6 +1204,7 @@ func _apply_cooler_notepad_style() -> void:
"panel",
InventoryNotepadType.make_paper_style(false),
)
InventoryNotepadType.apply_handwritten_to(_detail_constellation)
func _apply_navigation_styles() -> void:
@ -1221,19 +1271,13 @@ func _apply_bag_styles() -> void:
outer.bg_color = Color(0.39, 0.31, 0.2, 1.0)
outer.border_color = Color(0.67, 0.54, 0.33, 1.0)
outer.set_border_width_all(7)
outer.corner_radius_top_left = 88
outer.corner_radius_top_right = 64
outer.corner_radius_bottom_right = 94
outer.corner_radius_bottom_left = 70
outer.set_corner_radius_all(INVENTORY_MAIN_CORNER_RADIUS)
_bag_outer_wall.add_theme_stylebox_override("panel", outer)
var inner := StyleBoxFlat.new()
inner.bg_color = Color(0.92, 0.85, 0.68, 1.0)
inner.border_color = Color(0.75, 0.62, 0.38, 1.0)
inner.set_border_width_all(4)
inner.corner_radius_top_left = 68
inner.corner_radius_top_right = 48
inner.corner_radius_bottom_right = 72
inner.corner_radius_bottom_left = 52
inner.set_corner_radius_all(INVENTORY_INNER_CORNER_RADIUS)
_bag_inner_liner.add_theme_stylebox_override("panel", inner)
func _apply_logbook_styles() -> void:
var backing := StyleBoxFlat.new()
@ -1312,8 +1356,10 @@ func _update_shell_layout() -> void:
_compact_layout = compact
var reference_size := DESKTOP_REFERENCE_SIZE
_presentation_scale_root.size = reference_size
_presentation_scale_root.scale = Vector2.ONE
if not _transitioning:
_presentation_scale_root.scale = Vector2.ONE
_presentation_scale_root.position = Vector2.ZERO
_presentation_scale_root.pivot_offset = reference_size * 0.5
_content_shell.position = Vector2(14.0, 92.0) if compact else Vector2(42.0, 104.0)
_content_shell.size = Vector2(612.0, 286.0) if compact else Vector2(1196.0, 478.0)
_presentation_rest_position = _content_shell.position
@ -1329,6 +1375,12 @@ func _update_shell_layout() -> void:
_cooler_page.size = reference_size
_cooler_page.position = Vector2.ZERO
_cooler_rest_position = Vector2.ZERO
# The Bag shell has the widest 88 px upper-left curve. Eight more pixels
# place every tab flange behind a straight section of the shared panel.
_inventory_sub_tabs.position = (
INVENTORY_MAIN_POSITION
+ Vector2(INVENTORY_TAB_LEFT_INSET, -30.0)
)
_layout_cooler_fish(false)
_cooler_outer_wall.position = INVENTORY_MAIN_POSITION
_cooler_outer_wall.size = INVENTORY_MAIN_SIZE
@ -1447,7 +1499,7 @@ func _update_shell_layout() -> void:
)
_bag_filter_tabs.size = Vector2(320.0, INVENTORY_HEADER_HEIGHT)
_bag_host.custom_minimum_size = (
Vector2(520.0, 152.0) if compact else Vector2(796.0, 358.0)
Vector2(520.0, 152.0) if compact else Vector2(788.0, 358.0)
)
_bag_scroll.vertical_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
_bag_detail_constellation.position = INVENTORY_NOTEPAD_POSITION
@ -1585,80 +1637,30 @@ func _layout_cooler_selection_text(compact: bool) -> void:
func _begin_menu_entry() -> void:
_transitioning = true
_set_shell_interactive(false)
_reset_page_transition_visuals()
_animate_inventory_tab_entry()
set_process(true)
var generation: int = _transition_generation
var start_offset: float = (
_presentation_scale_root.size.y + TRANSITION_SAFE_MARGIN
_presentation_scale_root.pivot_offset = (
_presentation_scale_root.size * 0.5
)
_content_shell.position = _presentation_rest_position + Vector2.DOWN * start_offset
_cooler_page.position = _cooler_rest_position + Vector2.DOWN * start_offset
_bag_page.position = _bag_rest_position + Vector2.DOWN * start_offset
_tackle_box_page.position = (
_tackle_rest_position + Vector2.DOWN * start_offset
_presentation_scale_root.modulate.a = 0.0
_presentation_scale_root.scale = (
Vector2.ONE * UIMotion.PLAYER_MENU_ENTER_SCALE
)
_logbook_page.position = _logbook_rest_position + Vector2.DOWN * start_offset
_mail_page.position = _mail_rest_position + Vector2.DOWN * start_offset
_profile_page.position = _profile_rest_position + Vector2.DOWN * start_offset
_players_page.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,
transition_duration
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_presentation_scale_root,
"modulate:a",
1.0,
UIMotion.PLAYER_MENU_ENTER_DURATION,
).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
_presentation_tween.tween_property(
_cooler_page,
"position",
_cooler_rest_position,
transition_duration
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_presentation_tween.tween_property(
_bag_page,
"position",
_bag_rest_position,
transition_duration
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_presentation_tween.tween_property(
_tackle_box_page,
"position",
_tackle_rest_position,
transition_duration
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_presentation_tween.tween_property(
_logbook_page,
"position",
_logbook_rest_position,
transition_duration
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_presentation_tween.tween_property(
_mail_page,
"position",
_mail_rest_position,
transition_duration
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_presentation_tween.tween_property(
_profile_page,
"position",
_profile_rest_position,
transition_duration
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_presentation_tween.tween_property(
_players_page,
"position",
Vector2.ZERO,
transition_duration
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_presentation_tween.tween_property(
_navigation_cluster,
"position",
navigation_rest,
transition_duration
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_presentation_scale_root,
"scale",
Vector2.ONE,
UIMotion.PLAYER_MENU_ENTER_DURATION,
).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
_presentation_tween.chain().tween_callback(
_finish_menu_entry.bind(generation)
)
@ -1682,71 +1684,24 @@ func _begin_menu_exit(reason: CloseReason, restore_controls: bool) -> void:
_transitioning = true
_set_shell_interactive(false)
_settle_inventory_tabs_for_close()
if _current_section == Section.LOGBOOK:
_catalog_logbook.deactivate()
get_viewport().gui_release_focus()
var generation: int = _transition_generation
var closing_generation: int = _menu_generation
var end_y: float = -maxf(
_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,
transition_duration
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_presentation_scale_root,
"modulate:a",
0.0,
UIMotion.PLAYER_MENU_EXIT_DURATION,
).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN)
_presentation_tween.tween_property(
_cooler_page,
"position:y",
-_cooler_page.size.y - TRANSITION_SAFE_MARGIN,
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,
transition_duration
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_presentation_tween.tween_property(
_tackle_box_page,
"position:y",
-_tackle_box_page.size.y - TRANSITION_SAFE_MARGIN,
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,
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,
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,
transition_duration
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_presentation_tween.tween_property(
_players_page,
"position:y",
-_players_page.size.y - TRANSITION_SAFE_MARGIN,
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,
transition_duration
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_presentation_scale_root,
"scale",
Vector2.ONE * UIMotion.PLAYER_MENU_EXIT_SCALE,
UIMotion.PLAYER_MENU_EXIT_DURATION,
).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN)
_presentation_tween.chain().tween_callback(
_finish_menu_exit.bind(
generation,
@ -1781,6 +1736,8 @@ func _finish_close(
_page_transitioning = false
_bag_drag_active = false
_reset_page_transition_visuals()
_presentation_scale_root.modulate.a = 1.0
_presentation_scale_root.scale = Vector2.ONE
visible = false
set_process(false)
get_viewport().gui_release_focus()
@ -1838,74 +1795,59 @@ func _begin_page_transition(section: Section) -> void:
_cancel_page_tween()
_page_transitioning = true
_set_content_interactive(false)
if _is_inventory_section(_current_section) and not _is_inventory_section(section):
get_viewport().gui_release_focus()
var outgoing_section: Section = _current_section
var outgoing_inventory: bool = _is_inventory_section(outgoing_section)
var incoming_inventory: bool = _is_inventory_section(section)
if outgoing_inventory and not incoming_inventory:
_settle_inventory_tabs_for_close()
_set_navigation_target(section)
var generation: int = _page_transition_generation
_page_outgoing_root = _get_section_root(_current_section)
_page_incoming_root = _get_section_root(section)
_page_hosts_shared = _page_outgoing_root == _page_incoming_root
var outgoing_rest: Vector2 = _get_section_rest_position(_current_section)
_page_outgoing_content_root = _get_section_root(outgoing_section)
_page_outgoing_root = (
_inventory_transition_group
if outgoing_inventory and not incoming_inventory
else _page_outgoing_content_root
)
_page_incoming_root = (
_inventory_transition_group
if incoming_inventory and not outgoing_inventory
else _get_section_root(section)
)
var outgoing_rest: Vector2 = _get_section_rest_position(outgoing_section)
var incoming_rest: Vector2 = _get_section_rest_position(section)
if (
_is_inventory_section(_current_section)
and _is_inventory_section(section)
):
_show_section_immediate(section)
_page_outgoing_root.visible = true
_page_incoming_root.visible = true
_page_outgoing_root.position = outgoing_rest
_page_incoming_root.position = incoming_rest
_page_outgoing_root.modulate.a = 1.0
_page_incoming_root.modulate.a = 0.0
_page_tween = create_tween()
_page_tween.tween_property(
_page_outgoing_root,
"modulate:a",
0.0,
UIMotion.UTILITY_ENTER_DURATION,
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_page_tween.parallel().tween_property(
_page_incoming_root,
"modulate:a",
1.0,
UIMotion.UTILITY_ENTER_DURATION,
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_page_tween.finished.connect(
_finish_page_transition.bind(generation),
CONNECT_ONE_SHOT,
)
return
if not _page_hosts_shared:
_page_incoming_root.position = incoming_rest + Vector2.DOWN * 18.0
_page_incoming_root.modulate.a = 0.0
_page_tween = create_tween()
_show_section_immediate(section)
if outgoing_inventory and not incoming_inventory:
# Immediate page selection hides Inventory. Restore the outgoing content
# beneath its still-opaque masking group for the coordinated fade-out.
_page_outgoing_content_root.visible = true
_inventory_sub_tabs.visible = true
_inventory_transition_group.visible = true
_page_outgoing_root.visible = true
_page_incoming_root.visible = true
_page_outgoing_root.position = outgoing_rest
_page_incoming_root.position = incoming_rest
_page_outgoing_root.modulate.a = 1.0
_page_incoming_root.modulate.a = 0.0
if incoming_inventory and not outgoing_inventory:
_animate_inventory_tab_entry()
var duration: float = (
UIMotion.PLAYER_MENU_INVENTORY_DURATION
if outgoing_inventory and incoming_inventory
else UIMotion.PLAYER_MENU_PAGE_DURATION
)
_page_tween = create_tween().set_parallel(true)
_page_tween.tween_property(
_page_outgoing_root,
"modulate:a",
0.0,
PAGE_OUT_DURATION
duration,
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_page_tween.parallel().tween_property(
_page_outgoing_root,
"position:y",
outgoing_rest.y - 18.0,
PAGE_OUT_DURATION
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_page_tween.tween_callback(
_swap_page.bind(section, generation)
)
_page_tween.tween_property(
_page_incoming_root,
"modulate:a",
1.0,
PAGE_IN_DURATION
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_page_tween.parallel().tween_property(
_page_incoming_root,
"position",
incoming_rest,
PAGE_IN_DURATION
duration,
).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
_page_tween.finished.connect(
_finish_page_transition.bind(generation),
@ -1913,19 +1855,6 @@ func _begin_page_transition(section: Section) -> void:
)
func _swap_page(section: Section, generation: int) -> void:
if generation != _page_transition_generation or not visible:
return
_show_section_immediate(section)
if _is_inventory_section(section):
_animate_inventory_tab_entry()
if _page_hosts_shared:
_page_incoming_root.position = (
_presentation_rest_position + Vector2.DOWN * 18.0
)
_page_incoming_root.modulate.a = 0.0
func _finish_page_transition(generation: int) -> void:
if generation != _page_transition_generation or not visible:
return
@ -1934,8 +1863,16 @@ func _finish_page_transition(generation: int) -> void:
if (
_page_outgoing_root != null
and _page_outgoing_root != _page_incoming_root
and _page_outgoing_root != _inventory_transition_group
):
_page_outgoing_root.visible = false
if (
_page_outgoing_content_root != null
and not _is_inventory_section(_current_section)
):
_page_outgoing_content_root.visible = false
_inventory_sub_tabs.visible = _is_inventory_section(_current_section)
_inventory_sub_tabs.modulate.a = 1.0
_reset_page_transition_visuals()
_set_content_interactive(true)
_focus_current_section()
@ -1991,7 +1928,7 @@ func _set_content_interactive(interactive: bool) -> void:
)
tab.mouse_filter = (
Control.MOUSE_FILTER_STOP
if tab_interactive
if tab_interactive and not tab.button_pressed
else Control.MOUSE_FILTER_IGNORE
)
_logbook_page.mouse_filter = (
@ -2084,8 +2021,13 @@ func _reset_page_transition_visuals() -> void:
var page: Control = _get_section_root(section)
page.position = _get_section_rest_position(section)
page.modulate.a = 1.0
if _inventory_transition_group != null:
_inventory_transition_group.modulate.a = 1.0
_inventory_transition_group.visible = true
_inventory_sub_tabs.modulate.a = 1.0
_page_outgoing_root = null
_page_incoming_root = null
_page_outgoing_content_root = null
func _on_sort_selected(index: int, source: OptionButton) -> void:

View file

@ -68,16 +68,16 @@ unique_name_in_owner = true
visible = false
z_index = 40
layout_mode = 0
offset_left = 54.0
offset_top = 126.0
offset_right = 504.0
offset_bottom = 184.0
offset_left = 150.0
offset_top = 136.0
offset_right = 534.0
offset_bottom = 174.0
mouse_filter = 1
theme_override_constants/separation = 8
theme_override_constants/separation = 6
[node name="CoolerSubTab" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/InventorySubTabs"]
unique_name_in_owner = true
custom_minimum_size = Vector2(132, 58)
custom_minimum_size = Vector2(124, 38)
layout_mode = 2
toggle_mode = true
button_group = null
@ -86,21 +86,23 @@ script = ExtResource("23_organizer_tab")
[node name="BagSubTab" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/InventorySubTabs"]
unique_name_in_owner = true
custom_minimum_size = Vector2(132, 58)
custom_minimum_size = Vector2(124, 38)
layout_mode = 2
toggle_mode = true
button_group = null
text = "Bag"
text = "Equipment"
script = ExtResource("23_organizer_tab")
palette_index = 2
[node name="TackleSubTab" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/InventorySubTabs"]
unique_name_in_owner = true
custom_minimum_size = Vector2(154, 58)
custom_minimum_size = Vector2(124, 38)
layout_mode = 2
toggle_mode = true
button_group = null
text = "Tackle Box"
text = "Tackle"
script = ExtResource("23_organizer_tab")
palette_index = 1
[node name="CoolerPage" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot"]
unique_name_in_owner = true
@ -541,7 +543,7 @@ horizontal_scroll_mode = 0
[node name="BagHost" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/BagPage/BagOuterWall/BagOuterMargin/BagInnerLiner/BagInnerMargin/BagScroll"]
unique_name_in_owner = true
custom_minimum_size = Vector2(796, 358)
custom_minimum_size = Vector2(788, 358)
layout_mode = 2
mouse_filter = 1

View file

@ -47,7 +47,6 @@ enum PresentationMode {
@onready var _invert_y_toggle: BubbleButton = %InvertYToggle
@onready var _auto_click_toggle: BubbleButton = %AutoClickToggle
@onready var _auto_click_interval: BubbleButton = %AutoClickIntervalValue
@onready var _readable_font_toggle: BubbleButton = %ReadableFontToggle
@onready var _world_options: Array[BubbleButton] = [
%WorldLegible,
@ -149,7 +148,6 @@ 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")
@ -157,12 +155,6 @@ func _ready() -> void:
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(
@ -685,9 +677,6 @@ func _load_controls() -> void:
_mouse_sensitivity = settings.mouse_camera_sensitivity
_controller_sensitivity = settings.controller_camera_sensitivity
_invert_camera_y = settings.invert_camera_y
_readable_font_toggle.button_pressed = (
settings.use_readable_interface_font
)
_refresh_value_labels()
@ -715,14 +704,6 @@ func _refresh_value_labels() -> void:
"accessibility\nauto-click\n"
+ ("on" if _auto_click_enabled else "off")
)
_readable_font_toggle.text = (
"alternate\nfont\n"
+ (
"on"
if settings.use_readable_interface_font
else "off"
)
)
_auto_click_interval.text = (
"auto-click\ninterval\n%.2f s" % _auto_click_interval_value
)
@ -734,16 +715,11 @@ func _refresh_value_labels() -> void:
_ui_options[index].button_pressed = index + 1 == settings.ui_pixel_size
func _show_accessibility_helper(kind: StringName) -> void:
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."
)
helper.text = (
"Lower intervals click\nbarriers faster\nwhile held."
)
func _style_data_page() -> void:
@ -775,19 +751,6 @@ func _set_world_pixelation(pixel_size: int) -> void:
_refresh_value_labels()
func _toggle_readable_font() -> void:
if _settings_manager == null:
return
var edited: PlayerSettings = _settings_manager.current_settings.copy()
edited.use_readable_interface_font = (
not edited.use_readable_interface_font
)
if not _settings_manager.apply_settings(edited):
_feedback.text = "failed to save accessibility settings."
return
_load_controls()
func _set_ui_pixelation(pixel_size: int) -> void:
if _settings_manager == null:
return

View file

@ -486,8 +486,8 @@ grow_horizontal = 2
grow_vertical = 2
script = ExtResource("3_page")
page_id = &"accessibility"
bubble_paths = Array[NodePath]([NodePath("BubbleCluster/AutoClickToggle"), NodePath("BubbleCluster/IntervalDecrease"), NodePath("BubbleCluster/AutoClickIntervalValue"), NodePath("BubbleCluster/IntervalIncrease"), NodePath("BubbleCluster/ReadableFontToggle"), NodePath("BubbleCluster/IntervalHelp"), NodePath("BubbleCluster/AccessibilityBackButton")])
focus_paths = Array[NodePath]([NodePath("BubbleCluster/AutoClickToggle"), NodePath("BubbleCluster/IntervalDecrease"), NodePath("BubbleCluster/AutoClickIntervalValue"), NodePath("BubbleCluster/IntervalIncrease"), NodePath("BubbleCluster/ReadableFontToggle"), NodePath("BubbleCluster/AccessibilityBackButton")])
bubble_paths = Array[NodePath]([NodePath("BubbleCluster/AutoClickToggle"), NodePath("BubbleCluster/IntervalDecrease"), NodePath("BubbleCluster/AutoClickIntervalValue"), NodePath("BubbleCluster/IntervalIncrease"), NodePath("BubbleCluster/IntervalHelp"), NodePath("BubbleCluster/AccessibilityBackButton")])
focus_paths = Array[NodePath]([NodePath("BubbleCluster/AutoClickToggle"), NodePath("BubbleCluster/IntervalDecrease"), NodePath("BubbleCluster/AutoClickIntervalValue"), NodePath("BubbleCluster/IntervalIncrease"), NodePath("BubbleCluster/AccessibilityBackButton")])
initial_focus_path = NodePath("BubbleCluster/AutoClickToggle")
back_focus_path = NodePath("BubbleCluster/AccessibilityBackButton")
@ -562,43 +562,6 @@ minimum_font_size = 13
maximum_font_size = 22
motion_phase = 4.1
[node name="ReadableFontToggle" parent="AccessibilityPage/BubbleCluster" instance=ExtResource("4_bubble")]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 0)
toggle_mode = true
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)
minimum_font_size = 13
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
offset_right = 700.0
offset_bottom = 82.0
mouse_filter = 2
text = "The quick brown fox jumps over the lazy dog.\n0123456789"
horizontal_alignment = 1
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
offset_right = 700.0
offset_bottom = 112.0
mouse_filter = 2
text = "Uses a clearer font for menus and interface text."
horizontal_alignment = 1
[node name="AccessibilityBackButton" parent="AccessibilityPage/BubbleCluster" instance=ExtResource("4_bubble")]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 0)

View file

@ -6,6 +6,12 @@ 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
const PLAYER_MENU_ENTER_DURATION: float = 0.16
const PLAYER_MENU_EXIT_DURATION: float = 0.14
const PLAYER_MENU_PAGE_DURATION: float = 0.12
const PLAYER_MENU_INVENTORY_DURATION: float = 0.10
const PLAYER_MENU_ENTER_SCALE: float = 0.985
const PLAYER_MENU_EXIT_SCALE: float = 0.99
static func bubble_duration(distance: float) -> float: