Polish title online and save slot interfaces
This commit is contained in:
parent
a3aea98982
commit
867fd431af
8 changed files with 463 additions and 86 deletions
|
|
@ -30,8 +30,8 @@ enabled=PackedStringArray("res://addons/netfishing_shoreline_baker/plugin.cfg")
|
||||||
|
|
||||||
[gui]
|
[gui]
|
||||||
|
|
||||||
theme/custom="res://ui/game_theme.tres"
|
|
||||||
timers/tooltip_delay_sec=0.0
|
timers/tooltip_delay_sec=0.0
|
||||||
|
theme/custom="res://ui/game_theme.tres"
|
||||||
|
|
||||||
[input]
|
[input]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,28 @@ func _validate_primary_menu_navigation() -> void:
|
||||||
and not (title.get_node("%DeleteSaveButton") as Control).visible,
|
and not (title.get_node("%DeleteSaveButton") as Control).visible,
|
||||||
"Legacy New/Delete title bubbles are still visible.",
|
"Legacy New/Delete title bubbles are still visible.",
|
||||||
)
|
)
|
||||||
_assert_directionally_reachable(title_controls.front(), title_controls)
|
_assert_neighbor(
|
||||||
|
title.get_node("%JoinGameButton") as Control,
|
||||||
|
&"focus_neighbor_right",
|
||||||
|
play_button,
|
||||||
|
)
|
||||||
|
_assert_neighbor(
|
||||||
|
title.get_node("%SettingsButton") as Control,
|
||||||
|
&"focus_neighbor_left",
|
||||||
|
play_button,
|
||||||
|
)
|
||||||
|
_assert_neighbor(
|
||||||
|
title.get_node("%CreditsButton") as Control,
|
||||||
|
&"focus_neighbor_right",
|
||||||
|
play_button,
|
||||||
|
)
|
||||||
|
_assert_neighbor(
|
||||||
|
title.get_node("%QuitButton") as Control,
|
||||||
|
&"focus_neighbor_left",
|
||||||
|
play_button,
|
||||||
|
)
|
||||||
|
for title_control: Control in title_controls:
|
||||||
|
_assert_directionally_reachable(title_control, title_controls)
|
||||||
title.queue_free()
|
title.queue_free()
|
||||||
await process_frame
|
await process_frame
|
||||||
|
|
||||||
|
|
@ -195,6 +216,13 @@ func _validate_save_slots_navigation() -> void:
|
||||||
page.call("_select_page", &"saves", false)
|
page.call("_select_page", &"saves", false)
|
||||||
await process_frame
|
await process_frame
|
||||||
var import_button := page.get_node("%ImportSlotButton") as Button
|
var import_button := page.get_node("%ImportSlotButton") as Button
|
||||||
|
var actions := page.get_node("%Actions") as VBoxContainer
|
||||||
|
var secondary_actions := page.get_node("%SecondaryActions") as GridContainer
|
||||||
|
var play_slot := page.get_node("%PlaySlotButton") as Button
|
||||||
|
var rename_slot := page.get_node("%RenameSlotButton") as Button
|
||||||
|
var duplicate_slot := page.get_node("%DuplicateSlotButton") as Button
|
||||||
|
var export_slot := page.get_node("%ExportSlotButton") as Button
|
||||||
|
var delete_slot := page.get_node("%DeleteSlotButton") as Button
|
||||||
_expect(
|
_expect(
|
||||||
saves_tab.find_valid_focus_neighbor(SIDE_BOTTOM) == import_button,
|
saves_tab.find_valid_focus_neighbor(SIDE_BOTTOM) == import_button,
|
||||||
"An empty Save Slots page does not lead from its tab to Import Save.",
|
"An empty Save Slots page does not lead from its tab to Import Save.",
|
||||||
|
|
@ -204,6 +232,29 @@ func _validate_save_slots_navigation() -> void:
|
||||||
== page.get_node("%BackButton"),
|
== page.get_node("%BackButton"),
|
||||||
"An empty Save Slots page does not lead from Import Save to Back.",
|
"An empty Save Slots page does not lead from Import Save to Back.",
|
||||||
)
|
)
|
||||||
|
_expect(
|
||||||
|
is_equal_approx(play_slot.size.x, actions.size.x),
|
||||||
|
"Save-slot Play does not span the full action width.",
|
||||||
|
)
|
||||||
|
_expect(
|
||||||
|
secondary_actions.columns == 2
|
||||||
|
and is_equal_approx(rename_slot.size.x, duplicate_slot.size.x)
|
||||||
|
and is_equal_approx(export_slot.size.x, delete_slot.size.x)
|
||||||
|
and is_equal_approx(rename_slot.position.y, duplicate_slot.position.y)
|
||||||
|
and is_equal_approx(export_slot.position.y, delete_slot.position.y)
|
||||||
|
and export_slot.position.y > rename_slot.position.y,
|
||||||
|
"Save-slot secondary actions are not arranged as a 2 by 2 grid.",
|
||||||
|
)
|
||||||
|
var play_style := play_slot.get_theme_stylebox("normal") as StyleBoxFlat
|
||||||
|
_expect(
|
||||||
|
play_style != null and play_style.bg_color == UtilityPageStyle.GREEN,
|
||||||
|
"Save-slot Play does not use the green primary-action style.",
|
||||||
|
)
|
||||||
|
_assert_neighbor(play_slot, &"focus_neighbor_bottom", rename_slot)
|
||||||
|
_assert_neighbor(rename_slot, &"focus_neighbor_right", duplicate_slot)
|
||||||
|
_assert_neighbor(rename_slot, &"focus_neighbor_bottom", export_slot)
|
||||||
|
_assert_neighbor(duplicate_slot, &"focus_neighbor_bottom", delete_slot)
|
||||||
|
_assert_neighbor(export_slot, &"focus_neighbor_right", delete_slot)
|
||||||
page.queue_free()
|
page.queue_free()
|
||||||
await process_frame
|
await process_frame
|
||||||
|
|
||||||
|
|
@ -222,6 +273,9 @@ func _validate_join_game_navigation() -> void:
|
||||||
var address := page.get_node("%Address") as LineEdit
|
var address := page.get_node("%Address") as LineEdit
|
||||||
var name_edit := page.get_node("%NameEdit") as LineEdit
|
var name_edit := page.get_node("%NameEdit") as LineEdit
|
||||||
var server_list := page.get_node("%ServerList") as ItemList
|
var server_list := page.get_node("%ServerList") as ItemList
|
||||||
|
var presence := page.get_node("%PresenceButton") as Button
|
||||||
|
var room_open := page.get_node("%RoomOpenButton") as Button
|
||||||
|
var room_listing := page.get_node("%RoomListingButton") as Button
|
||||||
var refresh := page.get_node("%RefreshButton") as Button
|
var refresh := page.get_node("%RefreshButton") as Button
|
||||||
var join := page.get_node("%JoinButton") as Button
|
var join := page.get_node("%JoinButton") as Button
|
||||||
var save := page.get_node("%SaveButton") as Button
|
var save := page.get_node("%SaveButton") as Button
|
||||||
|
|
@ -233,6 +287,7 @@ func _validate_join_game_navigation() -> void:
|
||||||
var direct_content := page.get_node("%DirectContent") as Control
|
var direct_content := page.get_node("%DirectContent") as Control
|
||||||
var list_content := page.get_node("%ListContent") as Control
|
var list_content := page.get_node("%ListContent") as Control
|
||||||
var content_panel := page.get_node("%ContentPanel") as PanelContainer
|
var content_panel := page.get_node("%ContentPanel") as PanelContainer
|
||||||
|
var actions := page.get_node("%Actions") as HBoxContainer
|
||||||
var modes: Array[Control] = [discover, friends, direct, saved, recent]
|
var modes: Array[Control] = [discover, friends, direct, saved, recent]
|
||||||
var tab_overlap: float = (
|
var tab_overlap: float = (
|
||||||
discover.get_global_rect().end.y
|
discover.get_global_rect().end.y
|
||||||
|
|
@ -265,9 +320,36 @@ func _validate_join_game_navigation() -> void:
|
||||||
_assert_neighbor(refresh, &"focus_neighbor_right", join)
|
_assert_neighbor(refresh, &"focus_neighbor_right", join)
|
||||||
_assert_neighbor(join, &"focus_neighbor_bottom", back)
|
_assert_neighbor(join, &"focus_neighbor_bottom", back)
|
||||||
_assert_neighbor(back, &"focus_neighbor_top", join)
|
_assert_neighbor(back, &"focus_neighbor_top", join)
|
||||||
|
_expect(
|
||||||
|
is_equal_approx(
|
||||||
|
join.get_global_rect().end.x,
|
||||||
|
actions.get_global_rect().end.x,
|
||||||
|
),
|
||||||
|
"Discover Refresh and Join are not right-justified.",
|
||||||
|
)
|
||||||
var discover_controls: Array[Control] = modes.duplicate()
|
var discover_controls: Array[Control] = modes.duplicate()
|
||||||
discover_controls.append_array([server_list, refresh, join, back])
|
discover_controls.append_array([server_list, refresh, join, back])
|
||||||
_assert_directionally_reachable(discover, discover_controls)
|
_assert_directionally_reachable(discover, discover_controls)
|
||||||
|
room_open.show()
|
||||||
|
room_listing.show()
|
||||||
|
_set_button_state(room_open, true)
|
||||||
|
_set_button_state(room_listing, true)
|
||||||
|
page.call("_configure_controller_navigation")
|
||||||
|
await process_frame
|
||||||
|
_assert_neighbor(room_open, &"focus_neighbor_right", room_listing)
|
||||||
|
_assert_neighbor(room_open, &"focus_neighbor_left", room_open)
|
||||||
|
_assert_neighbor(room_listing, &"focus_neighbor_left", room_open)
|
||||||
|
_assert_neighbor(room_listing, &"focus_neighbor_bottom", server_list)
|
||||||
|
var hosted_discover_controls: Array[Control] = modes.duplicate()
|
||||||
|
hosted_discover_controls.append_array([
|
||||||
|
room_open,
|
||||||
|
room_listing,
|
||||||
|
server_list,
|
||||||
|
refresh,
|
||||||
|
join,
|
||||||
|
back,
|
||||||
|
])
|
||||||
|
_assert_directionally_reachable(discover, hosted_discover_controls)
|
||||||
var rooms: Array[Dictionary] = [
|
var rooms: Array[Dictionary] = [
|
||||||
{
|
{
|
||||||
"room_id": "controller-default-room",
|
"room_id": "controller-default-room",
|
||||||
|
|
@ -293,16 +375,36 @@ func _validate_join_game_navigation() -> void:
|
||||||
)
|
)
|
||||||
|
|
||||||
page.set("_mode", JoinGamePage.Mode.FRIENDS)
|
page.set("_mode", JoinGamePage.Mode.FRIENDS)
|
||||||
|
(page.get_node("%OnlineControls") as Control).hide()
|
||||||
|
presence.show()
|
||||||
page.call("_configure_controller_navigation")
|
page.call("_configure_controller_navigation")
|
||||||
await process_frame
|
await process_frame
|
||||||
_assert_neighbor(friends, &"focus_neighbor_bottom", server_list)
|
_assert_neighbor(friends, &"focus_neighbor_bottom", server_list)
|
||||||
_assert_neighbor(server_list, &"focus_neighbor_top", friends)
|
_assert_neighbor(server_list, &"focus_neighbor_top", friends)
|
||||||
|
_assert_neighbor(server_list, &"focus_neighbor_bottom", presence)
|
||||||
|
_assert_neighbor(presence, &"focus_neighbor_right", refresh)
|
||||||
|
_assert_neighbor(refresh, &"focus_neighbor_right", join)
|
||||||
|
_expect(
|
||||||
|
is_equal_approx(
|
||||||
|
presence.get_global_rect().position.x,
|
||||||
|
actions.get_global_rect().position.x,
|
||||||
|
),
|
||||||
|
"Friend presence is not left-justified in the action row.",
|
||||||
|
)
|
||||||
|
_expect(
|
||||||
|
is_equal_approx(
|
||||||
|
join.get_global_rect().end.x,
|
||||||
|
actions.get_global_rect().end.x,
|
||||||
|
),
|
||||||
|
"Friends Refresh and Join are not right-justified.",
|
||||||
|
)
|
||||||
var friend_controls: Array[Control] = modes.duplicate()
|
var friend_controls: Array[Control] = modes.duplicate()
|
||||||
friend_controls.append_array([server_list, refresh, join, back])
|
friend_controls.append_array([server_list, presence, refresh, join, back])
|
||||||
_assert_directionally_reachable(friends, friend_controls)
|
_assert_directionally_reachable(friends, friend_controls)
|
||||||
|
|
||||||
list_content.hide()
|
list_content.hide()
|
||||||
direct_content.show()
|
direct_content.show()
|
||||||
|
presence.hide()
|
||||||
address.show()
|
address.show()
|
||||||
address.editable = true
|
address.editable = true
|
||||||
server_list.hide()
|
server_list.hide()
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,10 @@ const DIRECT_WORKFLOW_HELP: String = (
|
||||||
@onready var _direct_content: Control = %DirectContent
|
@onready var _direct_content: Control = %DirectContent
|
||||||
@onready var _list_content: Control = %ListContent
|
@onready var _list_content: Control = %ListContent
|
||||||
@onready var _list_title: Label = %ListTitle
|
@onready var _list_title: Label = %ListTitle
|
||||||
|
@onready var _online_controls: Control = %OnlineControls
|
||||||
|
@onready var _presence_button: Button = %PresenceButton
|
||||||
|
@onready var _room_open_button: Button = %RoomOpenButton
|
||||||
|
@onready var _room_listing_button: Button = %RoomListingButton
|
||||||
@onready var _details_panel: PanelContainer = %DetailsPanel
|
@onready var _details_panel: PanelContainer = %DetailsPanel
|
||||||
@onready var _address: LineEdit = %Address
|
@onready var _address: LineEdit = %Address
|
||||||
@onready var _address_label: Label = %AddressLabel
|
@onready var _address_label: Label = %AddressLabel
|
||||||
|
|
@ -89,6 +93,9 @@ func _ready() -> void:
|
||||||
_direct_button.pressed.connect(_set_mode.bind(Mode.DIRECT))
|
_direct_button.pressed.connect(_set_mode.bind(Mode.DIRECT))
|
||||||
_saved_button.pressed.connect(_set_mode.bind(Mode.SAVED))
|
_saved_button.pressed.connect(_set_mode.bind(Mode.SAVED))
|
||||||
_recent_button.pressed.connect(_set_mode.bind(Mode.RECENT))
|
_recent_button.pressed.connect(_set_mode.bind(Mode.RECENT))
|
||||||
|
_presence_button.pressed.connect(_on_presence_pressed)
|
||||||
|
_room_open_button.pressed.connect(_on_room_open_pressed)
|
||||||
|
_room_listing_button.pressed.connect(_on_room_listing_pressed)
|
||||||
_refresh_button.pressed.connect(_request_discovery_refresh)
|
_refresh_button.pressed.connect(_request_discovery_refresh)
|
||||||
_join_button.pressed.connect(_request_join)
|
_join_button.pressed.connect(_request_join)
|
||||||
_save_button.pressed.connect(_on_save_pressed)
|
_save_button.pressed.connect(_on_save_pressed)
|
||||||
|
|
@ -238,6 +245,10 @@ func setup(
|
||||||
_on_peer_count_changed
|
_on_peer_count_changed
|
||||||
):
|
):
|
||||||
_network_session.peer_count_changed.connect(_on_peer_count_changed)
|
_network_session.peer_count_changed.connect(_on_peer_count_changed)
|
||||||
|
if not _network_session.host_openness_changed.is_connected(
|
||||||
|
_on_host_openness_changed
|
||||||
|
):
|
||||||
|
_network_session.host_openness_changed.connect(_on_host_openness_changed)
|
||||||
if (
|
if (
|
||||||
_saved_servers != null
|
_saved_servers != null
|
||||||
and not _saved_servers.data_changed.is_connected(_on_store_changed)
|
and not _saved_servers.data_changed.is_connected(_on_store_changed)
|
||||||
|
|
@ -278,6 +289,22 @@ func setup(
|
||||||
_discovery.social_status_changed.connect(
|
_discovery.social_status_changed.connect(
|
||||||
_on_social_status_changed
|
_on_social_status_changed
|
||||||
)
|
)
|
||||||
|
if not _discovery.host_settings_changed.is_connected(
|
||||||
|
_on_host_settings_changed
|
||||||
|
):
|
||||||
|
_discovery.host_settings_changed.connect(
|
||||||
|
_on_host_settings_changed
|
||||||
|
)
|
||||||
|
if not _discovery.host_status_changed.is_connected(
|
||||||
|
_on_host_status_changed
|
||||||
|
):
|
||||||
|
_discovery.host_status_changed.connect(_on_host_status_changed)
|
||||||
|
if not _discovery.presence_sharing_changed.is_connected(
|
||||||
|
_on_presence_sharing_changed
|
||||||
|
):
|
||||||
|
_discovery.presence_sharing_changed.connect(
|
||||||
|
_on_presence_sharing_changed
|
||||||
|
)
|
||||||
_friend_entries = _discovery.get_friend_presence()
|
_friend_entries = _discovery.get_friend_presence()
|
||||||
_refresh()
|
_refresh()
|
||||||
|
|
||||||
|
|
@ -792,6 +819,7 @@ func _refresh() -> void:
|
||||||
_direct_content.visible = direct_content_visible
|
_direct_content.visible = direct_content_visible
|
||||||
_list_content.visible = list_content_visible
|
_list_content.visible = list_content_visible
|
||||||
_list_title.text = _current_list_title()
|
_list_title.text = _current_list_title()
|
||||||
|
_refresh_online_controls(discovery_mode, friends_mode, connecting)
|
||||||
_address.visible = direct or _name_entry_active
|
_address.visible = direct or _name_entry_active
|
||||||
_address_label.visible = _address.visible
|
_address_label.visible = _address.visible
|
||||||
_address_helper.visible = _address.visible
|
_address_helper.visible = _address.visible
|
||||||
|
|
@ -916,6 +944,66 @@ func _current_list_title() -> String:
|
||||||
return "public rooms"
|
return "public rooms"
|
||||||
|
|
||||||
|
|
||||||
|
func _refresh_online_controls(
|
||||||
|
discovery_mode: bool,
|
||||||
|
friends_mode: bool,
|
||||||
|
connecting: bool,
|
||||||
|
) -> void:
|
||||||
|
_online_controls.visible = discovery_mode and not _name_entry_active
|
||||||
|
_presence_button.visible = friends_mode and not _name_entry_active
|
||||||
|
var presence_enabled: bool = (
|
||||||
|
_discovery != null and _discovery.is_presence_sharing()
|
||||||
|
)
|
||||||
|
_presence_button.text = (
|
||||||
|
"friends: online" if presence_enabled else "friends: offline"
|
||||||
|
)
|
||||||
|
_presence_button.disabled = (
|
||||||
|
connecting or _discovery == null or not _discovery.is_configured()
|
||||||
|
)
|
||||||
|
_presence_button.tooltip_text = (
|
||||||
|
"Stay visible to friends until you switch this off. "
|
||||||
|
+ "Your current room is shared only while it is publicly joinable."
|
||||||
|
if presence_enabled
|
||||||
|
else "Show as online to friends until you switch this off."
|
||||||
|
)
|
||||||
|
if not _online_controls.visible:
|
||||||
|
return
|
||||||
|
var local_host: bool = _network_session.is_host()
|
||||||
|
_room_open_button.visible = local_host
|
||||||
|
_room_listing_button.visible = local_host
|
||||||
|
if not local_host:
|
||||||
|
return
|
||||||
|
var room_open: bool = _network_session.is_open_host()
|
||||||
|
var room_listed: bool = (
|
||||||
|
_discovery != null and _discovery.is_discoverable()
|
||||||
|
)
|
||||||
|
_room_open_button.text = "room: open" if room_open else "room: closed"
|
||||||
|
_room_open_button.disabled = connecting
|
||||||
|
_room_open_button.tooltip_text = (
|
||||||
|
"Close this room to new connections."
|
||||||
|
if room_open
|
||||||
|
else "Open this room so other players can connect."
|
||||||
|
)
|
||||||
|
_room_listing_button.text = (
|
||||||
|
"listing: on" if room_listed else "listing: off"
|
||||||
|
)
|
||||||
|
_room_listing_button.disabled = (
|
||||||
|
connecting
|
||||||
|
or _discovery == null
|
||||||
|
or not _discovery.is_configured()
|
||||||
|
or not room_open
|
||||||
|
)
|
||||||
|
_room_listing_button.tooltip_text = (
|
||||||
|
"Remove this room from the public room browser."
|
||||||
|
if room_listed
|
||||||
|
else "List this open room in the public room browser."
|
||||||
|
if room_open and _discovery != null and _discovery.is_configured()
|
||||||
|
else "Open the room before enabling its public listing."
|
||||||
|
if _discovery != null and _discovery.is_configured()
|
||||||
|
else "Room discovery is not configured in this build."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
func _configure_controller_navigation() -> void:
|
func _configure_controller_navigation() -> void:
|
||||||
var mode_buttons: Array[Control] = [
|
var mode_buttons: Array[Control] = [
|
||||||
_discover_button,
|
_discover_button,
|
||||||
|
|
@ -924,12 +1012,24 @@ func _configure_controller_navigation() -> void:
|
||||||
_saved_button,
|
_saved_button,
|
||||||
_recent_button,
|
_recent_button,
|
||||||
]
|
]
|
||||||
|
var online_controls: Array[Control] = []
|
||||||
|
for control: Control in [
|
||||||
|
_room_open_button,
|
||||||
|
_room_listing_button,
|
||||||
|
]:
|
||||||
|
if _controller_focus_eligible(control):
|
||||||
|
online_controls.append(control)
|
||||||
var content_controls: Array[Control] = []
|
var content_controls: Array[Control] = []
|
||||||
for control: Control in [_address, _name_edit, _server_list]:
|
for control: Control in [
|
||||||
|
_address,
|
||||||
|
_name_edit,
|
||||||
|
_server_list,
|
||||||
|
]:
|
||||||
if _controller_focus_eligible(control):
|
if _controller_focus_eligible(control):
|
||||||
content_controls.append(control)
|
content_controls.append(control)
|
||||||
var action_controls: Array[Control] = []
|
var action_controls: Array[Control] = []
|
||||||
for control: Control in [
|
for control: Control in [
|
||||||
|
_presence_button,
|
||||||
_refresh_button,
|
_refresh_button,
|
||||||
_join_button,
|
_join_button,
|
||||||
_save_button,
|
_save_button,
|
||||||
|
|
@ -942,12 +1042,16 @@ func _configure_controller_navigation() -> void:
|
||||||
action_controls.append(control)
|
action_controls.append(control)
|
||||||
var all_controls: Array[Control] = []
|
var all_controls: Array[Control] = []
|
||||||
all_controls.append_array(mode_buttons)
|
all_controls.append_array(mode_buttons)
|
||||||
|
all_controls.append_array(online_controls)
|
||||||
all_controls.append_array(content_controls)
|
all_controls.append_array(content_controls)
|
||||||
all_controls.append_array(action_controls)
|
all_controls.append_array(action_controls)
|
||||||
all_controls.append(_back_button)
|
all_controls.append(_back_button)
|
||||||
for control: Control in all_controls:
|
for control: Control in all_controls:
|
||||||
control.focus_mode = Control.FOCUS_ALL
|
control.focus_mode = Control.FOCUS_ALL
|
||||||
for control: Control in [
|
for control: Control in [
|
||||||
|
_presence_button,
|
||||||
|
_room_open_button,
|
||||||
|
_room_listing_button,
|
||||||
_address,
|
_address,
|
||||||
_name_edit,
|
_name_edit,
|
||||||
_server_list,
|
_server_list,
|
||||||
|
|
@ -963,7 +1067,9 @@ func _configure_controller_navigation() -> void:
|
||||||
control.focus_mode = Control.FOCUS_NONE
|
control.focus_mode = Control.FOCUS_NONE
|
||||||
_back_button.focus_mode = Control.FOCUS_ALL
|
_back_button.focus_mode = Control.FOCUS_ALL
|
||||||
var primary_content: Control = (
|
var primary_content: Control = (
|
||||||
content_controls.front()
|
online_controls.front()
|
||||||
|
if not online_controls.is_empty()
|
||||||
|
else content_controls.front()
|
||||||
if not content_controls.is_empty()
|
if not content_controls.is_empty()
|
||||||
else action_controls.front()
|
else action_controls.front()
|
||||||
if not action_controls.is_empty()
|
if not action_controls.is_empty()
|
||||||
|
|
@ -978,11 +1084,29 @@ func _configure_controller_navigation() -> void:
|
||||||
mode_button,
|
mode_button,
|
||||||
primary_content,
|
primary_content,
|
||||||
)
|
)
|
||||||
|
for index: int in online_controls.size():
|
||||||
|
var online_control: Control = online_controls[index]
|
||||||
|
var below: Control = (
|
||||||
|
content_controls.front()
|
||||||
|
if not content_controls.is_empty()
|
||||||
|
else action_controls.front()
|
||||||
|
if not action_controls.is_empty()
|
||||||
|
else _back_button
|
||||||
|
)
|
||||||
|
_set_controller_neighbors(
|
||||||
|
online_control,
|
||||||
|
online_controls[maxi(index - 1, 0)],
|
||||||
|
online_controls[mini(index + 1, online_controls.size() - 1)],
|
||||||
|
mode_buttons[int(_mode)],
|
||||||
|
below,
|
||||||
|
)
|
||||||
for index: int in content_controls.size():
|
for index: int in content_controls.size():
|
||||||
var content: Control = content_controls[index]
|
var content: Control = content_controls[index]
|
||||||
var above: Control = (
|
var above: Control = (
|
||||||
content_controls[index - 1]
|
content_controls[index - 1]
|
||||||
if index > 0
|
if index > 0
|
||||||
|
else online_controls.front()
|
||||||
|
if not online_controls.is_empty()
|
||||||
else mode_buttons[int(_mode)]
|
else mode_buttons[int(_mode)]
|
||||||
)
|
)
|
||||||
var below: Control = (
|
var below: Control = (
|
||||||
|
|
@ -1001,6 +1125,8 @@ func _configure_controller_navigation() -> void:
|
||||||
action_controls[mini(index + 1, action_controls.size() - 1)],
|
action_controls[mini(index + 1, action_controls.size() - 1)],
|
||||||
content_controls.back()
|
content_controls.back()
|
||||||
if not content_controls.is_empty()
|
if not content_controls.is_empty()
|
||||||
|
else online_controls.back()
|
||||||
|
if not online_controls.is_empty()
|
||||||
else mode_buttons[int(_mode)],
|
else mode_buttons[int(_mode)],
|
||||||
_back_button,
|
_back_button,
|
||||||
)
|
)
|
||||||
|
|
@ -1009,6 +1135,8 @@ func _configure_controller_navigation() -> void:
|
||||||
if not action_controls.is_empty()
|
if not action_controls.is_empty()
|
||||||
else content_controls.back()
|
else content_controls.back()
|
||||||
if not content_controls.is_empty()
|
if not content_controls.is_empty()
|
||||||
|
else online_controls.back()
|
||||||
|
if not online_controls.is_empty()
|
||||||
else mode_buttons[int(_mode)]
|
else mode_buttons[int(_mode)]
|
||||||
)
|
)
|
||||||
_set_controller_neighbors(
|
_set_controller_neighbors(
|
||||||
|
|
@ -1270,6 +1398,76 @@ func _on_social_status_changed(message: String, is_error: bool) -> void:
|
||||||
_set_status(message, is_error)
|
_set_status(message, is_error)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_presence_pressed() -> void:
|
||||||
|
if _discovery == null:
|
||||||
|
_set_status("Friend presence is not available.", true)
|
||||||
|
return
|
||||||
|
var enabling: bool = not _discovery.is_presence_sharing()
|
||||||
|
if not _discovery.set_presence_sharing(enabling):
|
||||||
|
return
|
||||||
|
_set_status(
|
||||||
|
"You will remain online to friends until you switch this off."
|
||||||
|
if enabling
|
||||||
|
else "You now appear offline to friends."
|
||||||
|
)
|
||||||
|
_refresh()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_room_open_pressed() -> void:
|
||||||
|
if _network_session == null or not _network_session.is_host():
|
||||||
|
return
|
||||||
|
var opening: bool = not _network_session.is_open_host()
|
||||||
|
if not _network_session.set_host_open(opening):
|
||||||
|
_set_status("The room could not be updated.", true)
|
||||||
|
return
|
||||||
|
_set_status(
|
||||||
|
"The room is open to new connections."
|
||||||
|
if opening
|
||||||
|
else "The room is closed to new connections."
|
||||||
|
)
|
||||||
|
_refresh()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_room_listing_pressed() -> void:
|
||||||
|
if _discovery == null:
|
||||||
|
return
|
||||||
|
var enabling: bool = not _discovery.is_discoverable()
|
||||||
|
if not _discovery.set_discoverable(enabling):
|
||||||
|
return
|
||||||
|
_set_status(
|
||||||
|
"The room is being listed publicly."
|
||||||
|
if enabling
|
||||||
|
else "The room is no longer listed publicly."
|
||||||
|
)
|
||||||
|
_refresh()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_host_openness_changed(_is_open: bool) -> void:
|
||||||
|
_refresh()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_host_settings_changed(
|
||||||
|
_room_name: String,
|
||||||
|
_discoverable: bool,
|
||||||
|
) -> void:
|
||||||
|
_refresh()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_host_status_changed(message: String, is_error: bool) -> void:
|
||||||
|
if (
|
||||||
|
_mode == Mode.DISCOVER
|
||||||
|
and is_visible_in_tree()
|
||||||
|
and _network_session != null
|
||||||
|
and _network_session.is_host()
|
||||||
|
):
|
||||||
|
_set_status(message, is_error)
|
||||||
|
_refresh()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_presence_sharing_changed(_enabled: bool) -> void:
|
||||||
|
_refresh()
|
||||||
|
|
||||||
|
|
||||||
func _format_result_code(result_code: String) -> String:
|
func _format_result_code(result_code: String) -> String:
|
||||||
match result_code.strip_edges().to_upper():
|
match result_code.strip_edges().to_upper():
|
||||||
"SUCCESS":
|
"SUCCESS":
|
||||||
|
|
|
||||||
|
|
@ -138,9 +138,35 @@ layout_mode = 2
|
||||||
theme_override_font_sizes/font_size = 20
|
theme_override_font_sizes/font_size = 20
|
||||||
text = "public rooms"
|
text = "public rooms"
|
||||||
|
|
||||||
|
[node name="OnlineControls" type="HBoxContainer" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/ListContent"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(0, 42)
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 10
|
||||||
|
|
||||||
|
[node name="OnlineControlsSpacer" type="Control" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/ListContent/OnlineControls"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="RoomOpenButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/ListContent/OnlineControls"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
custom_minimum_size = Vector2(160, 42)
|
||||||
|
layout_mode = 2
|
||||||
|
focus_mode = 2
|
||||||
|
text = "room: closed"
|
||||||
|
|
||||||
|
[node name="RoomListingButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/ListContent/OnlineControls"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
custom_minimum_size = Vector2(180, 42)
|
||||||
|
layout_mode = 2
|
||||||
|
focus_mode = 2
|
||||||
|
text = "listing: off"
|
||||||
|
|
||||||
[node name="ServerList" type="ItemList" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/ListContent"]
|
[node name="ServerList" type="ItemList" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/PageStack/ListContent"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(0, 180)
|
custom_minimum_size = Vector2(0, 140)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_vertical = 3
|
size_flags_vertical = 3
|
||||||
theme_override_font_sizes/font_size = 17
|
theme_override_font_sizes/font_size = 17
|
||||||
|
|
@ -235,7 +261,18 @@ unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(0, 46)
|
custom_minimum_size = Vector2(0, 46)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
theme_override_constants/separation = 10
|
theme_override_constants/separation = 10
|
||||||
alignment = 1
|
|
||||||
|
[node name="PresenceButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/Actions"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
custom_minimum_size = Vector2(210, 46)
|
||||||
|
layout_mode = 2
|
||||||
|
focus_mode = 2
|
||||||
|
text = "friends: offline"
|
||||||
|
|
||||||
|
[node name="ActionsSpacer" type="Control" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/Actions"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
[node name="RefreshButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/Actions"]
|
[node name="RefreshButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/ContentLayout/Actions"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ var _online_state_label: Label
|
||||||
var _discoverable_toggle: Button
|
var _discoverable_toggle: Button
|
||||||
var _discoverable_state_label: Label
|
var _discoverable_state_label: Label
|
||||||
var _host_discovery_status: Label
|
var _host_discovery_status: Label
|
||||||
|
var _reset_artwork_button: Button
|
||||||
var _current_tab := 0
|
var _current_tab := 0
|
||||||
var _active: bool = false
|
var _active: bool = false
|
||||||
var _interactive: bool = false
|
var _interactive: bool = false
|
||||||
|
|
@ -295,6 +296,9 @@ func _build_host_settings(root: VBoxContainer) -> void:
|
||||||
"font_color", UtilityPageStyle.OCEAN_TEXT_SECONDARY
|
"font_color", UtilityPageStyle.OCEAN_TEXT_SECONDARY
|
||||||
)
|
)
|
||||||
access_row.add_child(_host_discovery_status)
|
access_row.add_child(_host_discovery_status)
|
||||||
|
_reset_artwork_button = Button.new()
|
||||||
|
_configure_session_artwork_reset_button(_reset_artwork_button)
|
||||||
|
access_row.add_child(_reset_artwork_button)
|
||||||
|
|
||||||
|
|
||||||
func _build_host_toggle(label_text: String, row: HBoxContainer) -> Button:
|
func _build_host_toggle(label_text: String, row: HBoxContainer) -> Button:
|
||||||
|
|
@ -389,7 +393,10 @@ func _refresh_host_settings() -> void:
|
||||||
return
|
return
|
||||||
var host_visible: bool = _service.is_local_host() and _current_tab == 0
|
var host_visible: bool = _service.is_local_host() and _current_tab == 0
|
||||||
_host_settings_panel.visible = host_visible
|
_host_settings_panel.visible = host_visible
|
||||||
if not host_visible or _discovery == null:
|
if not host_visible:
|
||||||
|
return
|
||||||
|
_update_session_artwork_reset_button(_reset_artwork_button)
|
||||||
|
if _discovery == null:
|
||||||
return
|
return
|
||||||
if not _room_name_edit.has_focus():
|
if not _room_name_edit.has_focus():
|
||||||
_room_name_edit.text = _discovery.get_room_name()
|
_room_name_edit.text = _discovery.get_room_name()
|
||||||
|
|
@ -481,7 +488,9 @@ func _on_host_status_changed(message: String, is_error: bool) -> void:
|
||||||
"Open the game before enabling discovery.",
|
"Open the game before enabling discovery.",
|
||||||
]
|
]
|
||||||
_host_discovery_status.text = "" if tooltip_only else message
|
_host_discovery_status.text = "" if tooltip_only else message
|
||||||
_host_discovery_status.visible = not _host_discovery_status.text.is_empty()
|
# Keep this expanding label in the row even when there is no status text so
|
||||||
|
# the session reset action remains pinned to the far-right edge.
|
||||||
|
_host_discovery_status.visible = true
|
||||||
_host_discovery_status.add_theme_color_override(
|
_host_discovery_status.add_theme_color_override(
|
||||||
"font_color",
|
"font_color",
|
||||||
UtilityPageStyle.OCEAN_DANGER
|
UtilityPageStyle.OCEAN_DANGER
|
||||||
|
|
@ -491,7 +500,7 @@ func _on_host_status_changed(message: String, is_error: bool) -> void:
|
||||||
|
|
||||||
|
|
||||||
func _build_active_rows() -> void:
|
func _build_active_rows() -> void:
|
||||||
if _service.is_local_moderator():
|
if _service.is_local_moderator() and not _service.is_local_host():
|
||||||
_build_session_artwork_controls()
|
_build_session_artwork_controls()
|
||||||
var entries := _service.get_entries()
|
var entries := _service.get_entries()
|
||||||
if entries.is_empty():
|
if entries.is_empty():
|
||||||
|
|
@ -502,35 +511,29 @@ func _build_active_rows() -> void:
|
||||||
|
|
||||||
|
|
||||||
func _build_active_player_row(entry: PlayerListEntry) -> void:
|
func _build_active_player_row(entry: PlayerListEntry) -> void:
|
||||||
var row := _make_active_player_row()
|
var row := _make_row()
|
||||||
var identity_row := HBoxContainer.new()
|
|
||||||
identity_row.add_theme_constant_override("separation", 8)
|
|
||||||
row.add_child(identity_row)
|
|
||||||
|
|
||||||
var identity := Label.new()
|
var identity := Label.new()
|
||||||
identity.clip_text = true
|
identity.clip_text = true
|
||||||
identity.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
identity.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
||||||
identity.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
identity.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
var markers: Array[String] = []
|
identity.text = entry.display_name
|
||||||
if entry.is_host:
|
var roles: Array[String] = ["host" if entry.is_host else "player"]
|
||||||
markers.append("host")
|
|
||||||
if entry.is_operator:
|
if entry.is_operator:
|
||||||
markers.append("operator")
|
roles.append("operator")
|
||||||
if entry.is_local_player:
|
if entry.is_local_player:
|
||||||
markers.append("You")
|
roles.append("you")
|
||||||
identity.text = "%s%s · %s\n%s" % [
|
_configure_identity_tooltip(
|
||||||
entry.display_name,
|
identity,
|
||||||
" [%s]" % ", ".join(markers) if not markers.is_empty() else "",
|
"identity fingerprint:\n%s\nrole: %s\nidentity status: %s" % [
|
||||||
entry.compact_fingerprint,
|
NetworkIdentityCrypto.format_fingerprint(entry.full_fingerprint),
|
||||||
|
", ".join(roles),
|
||||||
entry.continuity_state,
|
entry.continuity_state,
|
||||||
]
|
],
|
||||||
identity.tooltip_text = "Full identity fingerprint:\n%s" % (
|
|
||||||
entry.full_fingerprint
|
|
||||||
)
|
)
|
||||||
identity.add_theme_color_override(
|
identity.add_theme_color_override(
|
||||||
"font_color", UtilityPageStyle.OCEAN_TEXT_PRIMARY
|
"font_color", UtilityPageStyle.OCEAN_TEXT_PRIMARY
|
||||||
)
|
)
|
||||||
identity_row.add_child(identity)
|
row.add_child(identity)
|
||||||
var ping := Label.new()
|
var ping := Label.new()
|
||||||
ping.custom_minimum_size.x = 72
|
ping.custom_minimum_size.x = 72
|
||||||
ping.text = (
|
ping.text = (
|
||||||
|
|
@ -542,7 +545,7 @@ func _build_active_player_row(entry: PlayerListEntry) -> void:
|
||||||
"font_color", UtilityPageStyle.OCEAN_TEXT_SECONDARY
|
"font_color", UtilityPageStyle.OCEAN_TEXT_SECONDARY
|
||||||
)
|
)
|
||||||
ping.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
|
ping.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
|
||||||
identity_row.add_child(ping)
|
row.add_child(ping)
|
||||||
|
|
||||||
var actions := HBoxContainer.new()
|
var actions := HBoxContainer.new()
|
||||||
actions.alignment = BoxContainer.ALIGNMENT_END
|
actions.alignment = BoxContainer.ALIGNMENT_END
|
||||||
|
|
@ -634,31 +637,38 @@ func _configure_moderation_button(
|
||||||
|
|
||||||
|
|
||||||
func _build_session_artwork_controls() -> void:
|
func _build_session_artwork_controls() -> void:
|
||||||
var counts: Vector2i = _service.get_session_artwork_counts()
|
|
||||||
var row := _make_row()
|
var row := _make_row()
|
||||||
var label := Label.new()
|
var spacer := Control.new()
|
||||||
label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
label.clip_text = true
|
spacer.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||||
label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
row.add_child(spacer)
|
||||||
label.text = "session artwork · %d layers · %d painted pixels" % [
|
|
||||||
counts.x, counts.y,
|
|
||||||
]
|
|
||||||
label.add_theme_color_override(
|
|
||||||
"font_color", UtilityPageStyle.OCEAN_TEXT_PRIMARY
|
|
||||||
)
|
|
||||||
row.add_child(label)
|
|
||||||
var reset := Button.new()
|
var reset := Button.new()
|
||||||
reset.text = "reset paint"
|
_configure_session_artwork_reset_button(reset)
|
||||||
reset.disabled = counts.x == 0
|
_update_session_artwork_reset_button(reset)
|
||||||
reset.tooltip_text = "Clears all shared artwork from this session."
|
row.add_child(reset)
|
||||||
reset.pressed.connect(func() -> void:
|
|
||||||
|
|
||||||
|
func _configure_session_artwork_reset_button(button: Button) -> void:
|
||||||
|
button.text = "reset paint"
|
||||||
|
button.tooltip_text = "Clears all shared artwork from this session."
|
||||||
|
button.pressed.connect(func() -> void:
|
||||||
_confirm(
|
_confirm(
|
||||||
"Clear all shared paint from this session?\nThis cannot be undone.",
|
"Clear all shared paint from this session?\nThis cannot be undone.",
|
||||||
_service.reset_session_artwork,
|
_service.reset_session_artwork,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
UtilityPageStyle.apply_compact_ocean_button(reset)
|
UtilityPageStyle.apply_compact_ocean_button(button)
|
||||||
row.add_child(reset)
|
|
||||||
|
|
||||||
|
func _update_session_artwork_reset_button(button: Button) -> void:
|
||||||
|
if button == null or _service == null:
|
||||||
|
return
|
||||||
|
button.disabled = _service.get_session_artwork_counts().x == 0
|
||||||
|
|
||||||
|
|
||||||
|
func _configure_identity_tooltip(label: Label, text: String) -> void:
|
||||||
|
label.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||||
|
label.tooltip_text = text
|
||||||
|
|
||||||
|
|
||||||
func _build_relationship_rows() -> void:
|
func _build_relationship_rows() -> void:
|
||||||
|
|
@ -673,12 +683,16 @@ func _build_relationship_rows() -> void:
|
||||||
label.clip_text = true
|
label.clip_text = true
|
||||||
label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
||||||
var fingerprint := str(record["fingerprint"])
|
var fingerprint := str(record["fingerprint"])
|
||||||
label.text = "%s · %s %s" % [
|
label.text = "%s %s" % [
|
||||||
str(record.get("last_known_display_name", "Player")),
|
str(record.get("last_known_display_name", "Player")),
|
||||||
NetworkIdentityCrypto.compact_suffix(fingerprint),
|
|
||||||
"Blocked" if bool(record.get("blocked", false)) else "Muted",
|
"Blocked" if bool(record.get("blocked", false)) else "Muted",
|
||||||
]
|
]
|
||||||
label.tooltip_text = NetworkIdentityCrypto.format_fingerprint(fingerprint)
|
_configure_identity_tooltip(
|
||||||
|
label,
|
||||||
|
"identity fingerprint:\n%s" % (
|
||||||
|
NetworkIdentityCrypto.format_fingerprint(fingerprint)
|
||||||
|
),
|
||||||
|
)
|
||||||
label.add_theme_color_override(
|
label.add_theme_color_override(
|
||||||
"font_color", UtilityPageStyle.OCEAN_TEXT_PRIMARY
|
"font_color", UtilityPageStyle.OCEAN_TEXT_PRIMARY
|
||||||
)
|
)
|
||||||
|
|
@ -724,16 +738,20 @@ func _build_friend_rows() -> void:
|
||||||
label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
label.clip_text = true
|
label.clip_text = true
|
||||||
label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
||||||
label.text = "%s · %s %s" % [
|
label.text = "%s %s" % [
|
||||||
display_name,
|
display_name,
|
||||||
NetworkIdentityCrypto.compact_suffix(fingerprint),
|
|
||||||
"playing in %s" % str(room.get("room_name", "a public room"))
|
"playing in %s" % str(room.get("room_name", "a public room"))
|
||||||
if not room.is_empty()
|
if not room.is_empty()
|
||||||
else "Online"
|
else "Online"
|
||||||
if bool(friend.get("online", false))
|
if bool(friend.get("online", false))
|
||||||
else "Offline",
|
else "Offline",
|
||||||
]
|
]
|
||||||
label.tooltip_text = NetworkIdentityCrypto.format_fingerprint(fingerprint)
|
_configure_identity_tooltip(
|
||||||
|
label,
|
||||||
|
"identity fingerprint:\n%s" % (
|
||||||
|
NetworkIdentityCrypto.format_fingerprint(fingerprint)
|
||||||
|
),
|
||||||
|
)
|
||||||
label.add_theme_color_override(
|
label.add_theme_color_override(
|
||||||
"font_color", UtilityPageStyle.OCEAN_TEXT_PRIMARY
|
"font_color", UtilityPageStyle.OCEAN_TEXT_PRIMARY
|
||||||
)
|
)
|
||||||
|
|
@ -811,12 +829,16 @@ func _build_ban_rows() -> void:
|
||||||
label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
label.clip_text = true
|
label.clip_text = true
|
||||||
label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
label.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
||||||
label.text = "%s · %s banned %s" % [
|
label.text = "%s banned %s" % [
|
||||||
str(record.get("last_known_display_name", "Player")),
|
str(record.get("last_known_display_name", "Player")),
|
||||||
NetworkIdentityCrypto.compact_suffix(fingerprint),
|
|
||||||
Time.get_date_string_from_unix_time(int(record.get("banned_unix", 0))),
|
Time.get_date_string_from_unix_time(int(record.get("banned_unix", 0))),
|
||||||
]
|
]
|
||||||
label.tooltip_text = NetworkIdentityCrypto.format_fingerprint(fingerprint)
|
_configure_identity_tooltip(
|
||||||
|
label,
|
||||||
|
"identity fingerprint:\n%s" % (
|
||||||
|
NetworkIdentityCrypto.format_fingerprint(fingerprint)
|
||||||
|
),
|
||||||
|
)
|
||||||
label.add_theme_color_override(
|
label.add_theme_color_override(
|
||||||
"font_color", UtilityPageStyle.OCEAN_TEXT_PRIMARY
|
"font_color", UtilityPageStyle.OCEAN_TEXT_PRIMARY
|
||||||
)
|
)
|
||||||
|
|
@ -841,20 +863,6 @@ func _make_row() -> HBoxContainer:
|
||||||
return row
|
return row
|
||||||
|
|
||||||
|
|
||||||
func _make_active_player_row() -> VBoxContainer:
|
|
||||||
var panel := PanelContainer.new()
|
|
||||||
panel.clip_contents = true
|
|
||||||
panel.add_theme_stylebox_override(
|
|
||||||
"panel", UtilityPageStyle.row_style(false)
|
|
||||||
)
|
|
||||||
_list.add_child(panel)
|
|
||||||
var row := VBoxContainer.new()
|
|
||||||
row.custom_minimum_size.y = 88
|
|
||||||
row.add_theme_constant_override("separation", 4)
|
|
||||||
panel.add_child(row)
|
|
||||||
return row
|
|
||||||
|
|
||||||
|
|
||||||
func _add_empty(text: String) -> void:
|
func _add_empty(text: String) -> void:
|
||||||
var label := Label.new()
|
var label := Label.new()
|
||||||
label.text = text
|
label.text = text
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,12 @@ func _configure_style() -> void:
|
||||||
if node is OrganizerTab:
|
if node is OrganizerTab:
|
||||||
continue
|
continue
|
||||||
UtilityPageStyle.apply_ocean_button(node as BaseButton)
|
UtilityPageStyle.apply_ocean_button(node as BaseButton)
|
||||||
|
_play_button.add_theme_stylebox_override(
|
||||||
|
"normal",
|
||||||
|
UtilityPageStyle.ocean_button_style(
|
||||||
|
UtilityPageStyle.GREEN,
|
||||||
|
),
|
||||||
|
)
|
||||||
_delete_button.add_theme_stylebox_override(
|
_delete_button.add_theme_stylebox_override(
|
||||||
"normal",
|
"normal",
|
||||||
UtilityPageStyle.ocean_button_style(
|
UtilityPageStyle.ocean_button_style(
|
||||||
|
|
@ -639,11 +645,11 @@ func _configure_controller_focus() -> void:
|
||||||
_set_neighbors(button, button, _slot_name_edit, top, bottom)
|
_set_neighbors(button, button, _slot_name_edit, top, bottom)
|
||||||
_set_neighbors(_import_button, _import_button, _slot_name_edit, last, _back_button)
|
_set_neighbors(_import_button, _import_button, _slot_name_edit, last, _back_button)
|
||||||
_set_neighbors(_slot_name_edit, first, _slot_name_edit, _saves_tab, _play_button)
|
_set_neighbors(_slot_name_edit, first, _slot_name_edit, _saves_tab, _play_button)
|
||||||
_set_neighbors(_play_button, _import_button, _rename_button, _slot_name_edit, _duplicate_button)
|
_set_neighbors(_play_button, _import_button, _play_button, _slot_name_edit, _rename_button)
|
||||||
_set_neighbors(_rename_button, _play_button, _rename_button, _slot_name_edit, _export_button)
|
_set_neighbors(_rename_button, _import_button, _duplicate_button, _play_button, _export_button)
|
||||||
_set_neighbors(_duplicate_button, _import_button, _export_button, _play_button, _delete_button)
|
_set_neighbors(_duplicate_button, _rename_button, _duplicate_button, _play_button, _delete_button)
|
||||||
_set_neighbors(_export_button, _duplicate_button, _export_button, _rename_button, _delete_button)
|
_set_neighbors(_export_button, _import_button, _delete_button, _rename_button, _back_button)
|
||||||
_set_neighbors(_delete_button, _import_button, _delete_button, _duplicate_button, _back_button)
|
_set_neighbors(_delete_button, _export_button, _delete_button, _duplicate_button, _back_button)
|
||||||
_set_neighbors(_back_button, _back_button, _back_button, _import_button, _back_button)
|
_set_neighbors(_back_button, _back_button, _back_button, _import_button, _back_button)
|
||||||
return
|
return
|
||||||
_saves_tab.focus_neighbor_bottom = _saves_tab.get_path_to(_new_slot_name)
|
_saves_tab.focus_neighbor_bottom = _saves_tab.get_path_to(_new_slot_name)
|
||||||
|
|
|
||||||
|
|
@ -165,11 +165,10 @@ scroll_active = false
|
||||||
autowrap_mode = 2
|
autowrap_mode = 2
|
||||||
vertical_alignment = 1
|
vertical_alignment = 1
|
||||||
|
|
||||||
[node name="Actions" type="GridContainer" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/SavesPage/DetailsColumn"]
|
[node name="Actions" type="VBoxContainer" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/SavesPage/DetailsColumn"]
|
||||||
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
theme_override_constants/h_separation = 10
|
theme_override_constants/separation = 10
|
||||||
theme_override_constants/v_separation = 10
|
|
||||||
columns = 2
|
|
||||||
|
|
||||||
[node name="PlaySlotButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/SavesPage/DetailsColumn/Actions"]
|
[node name="PlaySlotButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/SavesPage/DetailsColumn/Actions"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
|
@ -179,7 +178,14 @@ size_flags_horizontal = 3
|
||||||
focus_mode = 2
|
focus_mode = 2
|
||||||
text = "play"
|
text = "play"
|
||||||
|
|
||||||
[node name="RenameSlotButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/SavesPage/DetailsColumn/Actions"]
|
[node name="SecondaryActions" type="GridContainer" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/SavesPage/DetailsColumn/Actions"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/h_separation = 10
|
||||||
|
theme_override_constants/v_separation = 10
|
||||||
|
columns = 2
|
||||||
|
|
||||||
|
[node name="RenameSlotButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/SavesPage/DetailsColumn/Actions/SecondaryActions"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(0, 46)
|
custom_minimum_size = Vector2(0, 46)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
@ -187,7 +193,7 @@ size_flags_horizontal = 3
|
||||||
focus_mode = 2
|
focus_mode = 2
|
||||||
text = "rename"
|
text = "rename"
|
||||||
|
|
||||||
[node name="DuplicateSlotButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/SavesPage/DetailsColumn/Actions"]
|
[node name="DuplicateSlotButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/SavesPage/DetailsColumn/Actions/SecondaryActions"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(0, 46)
|
custom_minimum_size = Vector2(0, 46)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
@ -195,7 +201,7 @@ size_flags_horizontal = 3
|
||||||
focus_mode = 2
|
focus_mode = 2
|
||||||
text = "duplicate"
|
text = "duplicate"
|
||||||
|
|
||||||
[node name="ExportSlotButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/SavesPage/DetailsColumn/Actions"]
|
[node name="ExportSlotButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/SavesPage/DetailsColumn/Actions/SecondaryActions"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(0, 46)
|
custom_minimum_size = Vector2(0, 46)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
@ -203,7 +209,7 @@ size_flags_horizontal = 3
|
||||||
focus_mode = 2
|
focus_mode = 2
|
||||||
text = "export"
|
text = "export"
|
||||||
|
|
||||||
[node name="DeleteSlotButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/SavesPage/DetailsColumn/Actions"]
|
[node name="DeleteSlotButton" type="Button" parent="MainPanel/OuterMargin/Layout/ContentPanel/ContentMargin/PageStack/SavesPage/DetailsColumn/Actions/SecondaryActions"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(0, 46)
|
custom_minimum_size = Vector2(0, 46)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
|
||||||
|
|
@ -464,6 +464,7 @@ func _update_title_layout() -> void:
|
||||||
Vector2(field_width, field_height),
|
Vector2(field_width, field_height),
|
||||||
compact_layout
|
compact_layout
|
||||||
)
|
)
|
||||||
|
_configure_title_controller_navigation()
|
||||||
if not _title_settings_transition_active:
|
if not _title_settings_transition_active:
|
||||||
call_deferred("_capture_title_bubble_rest_position")
|
call_deferred("_capture_title_bubble_rest_position")
|
||||||
if _awaiting_start_input and not _title_entry_transition_active:
|
if _awaiting_start_input and not _title_entry_transition_active:
|
||||||
|
|
@ -1483,9 +1484,28 @@ func _set_title_bubbles_interactive(interactive: bool) -> void:
|
||||||
else Control.MOUSE_FILTER_IGNORE
|
else Control.MOUSE_FILTER_IGNORE
|
||||||
)
|
)
|
||||||
if interactive:
|
if interactive:
|
||||||
ControllerFocusNavigationType.configure_spatial_neighbors(
|
_configure_title_controller_navigation()
|
||||||
_get_title_buttons()
|
|
||||||
)
|
|
||||||
|
func _configure_title_controller_navigation() -> void:
|
||||||
|
ControllerFocusNavigationType.configure_spatial_neighbors(
|
||||||
|
_get_title_buttons()
|
||||||
|
)
|
||||||
|
# The large Play bubble overlaps the inward edge of every surrounding
|
||||||
|
# bubble. Center-only spatial scoring otherwise links the four outside
|
||||||
|
# bubbles into a ring with no route back into Play.
|
||||||
|
_join_game_button.focus_neighbor_right = (
|
||||||
|
_join_game_button.get_path_to(_play_button)
|
||||||
|
)
|
||||||
|
_settings_button.focus_neighbor_left = (
|
||||||
|
_settings_button.get_path_to(_play_button)
|
||||||
|
)
|
||||||
|
_credits_button.focus_neighbor_right = (
|
||||||
|
_credits_button.get_path_to(_play_button)
|
||||||
|
)
|
||||||
|
_quit_button.focus_neighbor_left = (
|
||||||
|
_quit_button.get_path_to(_play_button)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
func _capture_title_bubble_rest_position() -> void:
|
func _capture_title_bubble_rest_position() -> void:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue