fix: polish player menu presentation

This commit is contained in:
Alexander Sellite 2026-08-19 00:07:33 -04:00
parent 487688c145
commit 132f3ef288
8 changed files with 316 additions and 24 deletions

View file

@ -10,7 +10,6 @@ const CHAT_SURFACE_COLOR := Color(0.025, 0.13, 0.19, 0.94)
const PANEL_WIDTH: float = 290.0
const COMPACT_HEIGHT: float = 250.0
const BOTTOM_MARGIN: float = 12.0
const EXPANDED_TOP_MARGIN: float = 94.0
const MIN_TOP_MARGIN: float = 24.0
const MIN_HISTORY_HEIGHT: float = 92.0
const HISTORY_FONT_SIZE: int = 20
@ -45,6 +44,14 @@ const CALENDAR_SIZE := Vector2(
)
const CALENDAR_FONT_SIZE: int = 16
const CALENDAR_TOP_GAP: float = 4.0
const EXPANDED_CHAT_TOP_GAP: float = 12.0
const EXPANDED_TOP_MARGIN: float = (
CLOCK_EDGE_MARGIN
+ CLOCK_SIZE.y
+ CALENDAR_TOP_GAP
+ CALENDAR_SIZE.y
+ EXPANDED_CHAT_TOP_GAP
)
const STATUS_EFFECT_ICON_SIZE := Vector2(40.0, 40.0)
const STATUS_EFFECT_TOP_GAP: float = 6.0
const STATUS_EFFECT_ICON_GAP: int = 4
@ -116,6 +123,7 @@ var _height_tween: Tween
var _opened: bool = false
var _available: bool = false
var _hud_hidden: bool = false
var _world_speech_visible: bool = true
var _presentation_state := PresentationState.COMPACT
var _visible_state_before_collapse := PresentationState.COMPACT
var _panel_hovered: bool = false
@ -1200,6 +1208,16 @@ func is_hud_hidden() -> bool:
return _hud_hidden
func set_world_speech_visible(should_be_visible: bool) -> void:
_world_speech_visible = should_be_visible
if _speech_layer != null:
_speech_layer.visible = should_be_visible
func is_world_speech_visible() -> bool:
return _world_speech_visible
func _refresh_handle_labels(state: PresentationState) -> void:
var collapsed := state == PresentationState.COLLAPSED
var height_state := _visible_state_before_collapse if collapsed else state

View file

@ -404,6 +404,7 @@ func setup(
wallet,
sale_service,
default_buyer,
main_shop_buyer,
catalog,
fishing_spot,
bag,
@ -2247,6 +2248,7 @@ func _update_experience_bubble_position() -> void:
func _on_player_menu_visibility_changed(is_open: bool) -> void:
_player_menu_open = is_open
_chat_ui.set_world_speech_visible(not is_open)
if is_open:
_end_virtual_mouse()
_refresh_surface_drawing_activation()

View file

@ -88,6 +88,7 @@ const NAVIGATION_CANONICAL_POSITION := Vector2(
)
const NAVIGATION_SELECTED_SCALE: float = 1.02
const MAIN_SHOP_BUYER_ID: StringName = &"main_fishing_shop"
const PELICAN_BUYER_ID: StringName = &"pelicans"
signal menu_visibility_changed(is_open: bool)
signal inventory_hotbar_context_changed(show_hotbar: bool)
@ -274,6 +275,7 @@ var _network_profile_service: NetworkProfileService
var _network_player_list: NetworkPlayerListService
var _controller_mapping_manager: ControllerMappingManagerType
var _default_buyer: FishBuyerProfileType
var _shop_buyer: FishBuyerProfileType
var _sale_buyer_override: FishBuyerProfileType
var _shop_cooler_context_active: bool = false
var _cooler_original_parent: Node
@ -531,6 +533,7 @@ func setup(
wallet: PlayerWalletType,
sale_service: FishSaleServiceType,
default_buyer: FishBuyerProfileType,
shop_buyer: FishBuyerProfileType,
catalog: FishPoolType,
fishing_spot: FishingSpotType,
bag: PlayerBagType,
@ -556,6 +559,7 @@ func setup(
_wallet = wallet
_sale_service = sale_service
_default_buyer = default_buyer
_shop_buyer = shop_buyer
_catalog = catalog
_fishing_spot = fishing_spot
_bag = bag
@ -5086,17 +5090,19 @@ func _begin_sale_confirmation(catch_ids: Array[StringName]) -> void:
_confirmation_buyer = active_buyer
_confirmation_buyer_id = active_buyer.id
_confirmation_generation = _menu_generation
var fish_label: String = "fish"
_confirmation_message.text = (
"[center]sell %d %s to the %s for %s?\n"
+ "combined base value: %s[/center]"
) % [
preview.fish_count,
fish_label,
_get_buyer_display_group(active_buyer),
CurrencyPresentationType.bbcode_amount(preview.payout, 22),
CurrencyPresentationType.bbcode_amount(preview.base_value, 22),
]
var shop_payout: int = preview.base_value
if _shop_buyer != null and _shop_buyer.is_valid():
var shop_preview: FishSaleResultType = _sale_service.preview_batch(
catch_ids,
_shop_buyer,
)
if shop_preview != null and shop_preview.is_success():
shop_payout = shop_preview.payout
_confirmation_message.text = _sale_confirmation_text(
preview,
active_buyer,
shop_payout,
)
_sale_confirmation.visible = true
if _shop_cooler_context_active:
shop_cooler_modal_changed.emit(true)
@ -5108,6 +5114,36 @@ func _begin_sale_confirmation(catch_ids: Array[StringName]) -> void:
_cancel_sale_button.grab_focus()
func _sale_confirmation_text(
preview: FishSaleResultType,
buyer: FishBuyerProfileType,
shop_payout: int,
) -> String:
var catch_label: String = (
"this fish"
if preview.fish_count == 1
else "these %d fish" % preview.fish_count
)
var payout_text: String = CurrencyPresentationType.bbcode_amount(
preview.payout,
22,
)
if buyer != null and buyer.id == PELICAN_BUYER_ID:
return (
"[center]You can sell %s to the pelicans now for %s, "
+ "but the shop is willing to pay %s![/center]"
) % [
catch_label,
payout_text,
CurrencyPresentationType.bbcode_amount(shop_payout, 22),
]
return "[center]Sell %s to the %s now for %s?[/center]" % [
catch_label,
_get_buyer_display_group(buyer),
payout_text,
]
func _on_confirm_sale_pressed() -> void:
if (
_sale_in_progress

View file

@ -914,13 +914,13 @@ alignment = 1
[node name="ConfirmSaleButton" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/SaleConfirmation/ConfirmationMargin/ConfirmationLayout/ConfirmationButtons"]
unique_name_in_owner = true
layout_mode = 2
text = "confirm"
text = "sell now"
custom_minimum_size = Vector2(140, 44)
[node name="CancelSaleButton" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/SaleConfirmation/ConfirmationMargin/ConfirmationLayout/ConfirmationButtons"]
unique_name_in_owner = true
layout_mode = 2
text = "cancel"
text = "nevermind"
custom_minimum_size = Vector2(140, 44)
[node name="NavigationCluster" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot"]

View file

@ -13,6 +13,10 @@ const FUR_PART_TAB_WIDTH: float = 58.0
const FUR_COLOR_PICKER_POPUP_SIZE: Vector2i = Vector2i(720, 560)
const FUR_COLOR_PICKER_SV_SIZE: Vector2i = Vector2i(520, 300)
const VOICE_OPTION_BUTTON_SIZE: Vector2 = Vector2(68.0, 32.0)
const HEADER_ACTION_FONT_SIZE: int = 18
const BODY_COLUMN_SEPARATION: int = 12
const SIZE_ENDPOINT_FONT_SIZE: int = 18
const SIZE_SLIDER_MIN_WIDTH: float = 180.0
const FUR_SECTION_PATTERNS: String = "patterns"
const FUR_SECTION_COLORS: String = "colors"
const FEATURE_DRAWER_ANIMATION_SECONDS: float = 0.16
@ -572,11 +576,14 @@ func has_modal_confirmation() -> bool:
func _build_ui() -> void:
UtilityPageStyle.apply_page(self)
var margin: MarginContainer = UtilityPageStyle.build_laptop_screen(self)
margin.name = "ProfileContentZone"
var layout := VBoxContainer.new()
layout.name = "ProfileLayout"
layout.add_theme_constant_override("separation", 8)
margin.add_child(layout)
var account_row := HBoxContainer.new()
account_row.name = "ProfileAccountRow"
account_row.add_theme_constant_override("separation", 14)
layout.add_child(account_row)
var account_stack := VBoxContainer.new()
@ -668,6 +675,7 @@ func _build_ui() -> void:
experience_row.add_child(_experience_value)
var actions := HBoxContainer.new()
actions.name = "ProfileActionRow"
actions.alignment = BoxContainer.ALIGNMENT_END
actions.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
actions.add_theme_constant_override("separation", 7)
@ -676,28 +684,41 @@ func _build_ui() -> void:
_customize_button.text = "customize"
_customize_button.custom_minimum_size.x = 96.0
UtilityPageStyle.apply_compact_ocean_button(_customize_button)
_customize_button.add_theme_font_size_override(
"font_size", HEADER_ACTION_FONT_SIZE
)
_customize_button.pressed.connect(_enter_controller_customization)
actions.add_child(_customize_button)
_apply_button = Button.new()
_apply_button.text = "apply"
_apply_button.custom_minimum_size.x = 72.0
UtilityPageStyle.apply_compact_ocean_button(_apply_button)
_apply_button.add_theme_font_size_override(
"font_size", HEADER_ACTION_FONT_SIZE
)
_apply_button.pressed.connect(_apply)
actions.add_child(_apply_button)
_revert_button = Button.new()
_revert_button.text = "revert"
_revert_button.custom_minimum_size.x = 76.0
UtilityPageStyle.apply_compact_ocean_button(_revert_button)
_revert_button.add_theme_font_size_override(
"font_size", HEADER_ACTION_FONT_SIZE
)
_revert_button.pressed.connect(_revert)
actions.add_child(_revert_button)
_defaults_button = Button.new()
_defaults_button.text = "defaults"
_defaults_button.custom_minimum_size.x = 82.0
UtilityPageStyle.apply_compact_ocean_button(_defaults_button)
_defaults_button.add_theme_font_size_override(
"font_size", HEADER_ACTION_FONT_SIZE
)
_defaults_button.pressed.connect(_show_confirmation.bind("defaults"))
actions.add_child(_defaults_button)
var body_panel := PanelContainer.new()
body_panel.name = "ProfileBodyPanel"
body_panel.size_flags_vertical = Control.SIZE_EXPAND_FILL
body_panel.add_theme_stylebox_override(
"panel", UtilityPageStyle.row_style(false)
@ -711,7 +732,9 @@ func _build_ui() -> void:
body_panel.add_child(body_margin)
var body := HBoxContainer.new()
body.alignment = BoxContainer.ALIGNMENT_BEGIN
body.add_theme_constant_override("separation", 16)
body.add_theme_constant_override(
"separation", BODY_COLUMN_SEPARATION
)
body_margin.add_child(body)
var category_scroll := ScrollContainer.new()
category_scroll.name = "CategoryScroll"
@ -1134,6 +1157,9 @@ func _build_scale_option() -> void:
var small_label := Label.new()
small_label.text = "small"
small_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
small_label.add_theme_font_size_override(
"font_size", SIZE_ENDPOINT_FONT_SIZE
)
small_label.add_theme_color_override(
"font_color", UtilityPageStyle.OCEAN_TEXT_SECONDARY
)
@ -1144,7 +1170,7 @@ func _build_scale_option() -> void:
slider.min_value = CharacterCustomizationCatalog.MIN_CHARACTER_SCALE
slider.max_value = CharacterCustomizationCatalog.MAX_CHARACTER_SCALE
slider.step = CharacterCustomizationCatalog.CHARACTER_SCALE_STEP
slider.custom_minimum_size = Vector2(220.0, 40.0)
slider.custom_minimum_size = Vector2(SIZE_SLIDER_MIN_WIDTH, 40.0)
slider.size_flags_horizontal = Control.SIZE_EXPAND_FILL
slider.tooltip_text = "character size"
slider.value = CharacterCustomizationCatalog.character_scale(
@ -1159,6 +1185,9 @@ func _build_scale_option() -> void:
var large_label := Label.new()
large_label.text = "large"
large_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
large_label.add_theme_font_size_override(
"font_size", SIZE_ENDPOINT_FONT_SIZE
)
large_label.add_theme_color_override(
"font_color", UtilityPageStyle.OCEAN_TEXT_SECONDARY
)
@ -1581,7 +1610,7 @@ func _build_fur_pattern_options() -> void:
func _build_fur_color_channels(options: Array) -> void:
var color_panel := PanelContainer.new()
color_panel.name = "FurColorOptionsPanel"
color_panel.custom_minimum_size.y = 250.0
color_panel.custom_minimum_size.y = 180.0
color_panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL
color_panel.size_flags_vertical = Control.SIZE_EXPAND_FILL
color_panel.add_theme_stylebox_override(
@ -1595,12 +1624,18 @@ func _build_fur_color_channels(options: Array) -> void:
color_margin.add_theme_constant_override("margin_right", 14)
color_margin.add_theme_constant_override("margin_bottom", 12)
color_panel.add_child(color_margin)
var color_scroll := ScrollContainer.new()
color_scroll.name = "FurColorScroll"
color_scroll.size_flags_horizontal = Control.SIZE_EXPAND_FILL
color_scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL
color_scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
color_scroll.vertical_scroll_mode = ScrollContainer.SCROLL_MODE_AUTO
color_margin.add_child(color_scroll)
var color_stack := VBoxContainer.new()
color_stack.name = "FurColorStack"
color_stack.size_flags_horizontal = Control.SIZE_EXPAND_FILL
color_stack.size_flags_vertical = Control.SIZE_EXPAND_FILL
color_stack.add_theme_constant_override("separation", 10)
color_margin.add_child(color_stack)
color_scroll.add_child(color_stack)
var channel_grid := GridContainer.new()
channel_grid.name = "FurColorChannelGrid"