Add multiplayer item use and session chat
This commit is contained in:
parent
5e04b70609
commit
5dda74c9e4
27 changed files with 1361 additions and 31 deletions
241
ui/chat_ui.gd
Normal file
241
ui/chat_ui.gd
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
class_name ChatUI
|
||||
extends Control
|
||||
|
||||
const INPUT_OWNER: StringName = &"chat"
|
||||
const COMPACT_SECONDS: float = 8.0
|
||||
const SPEECH_SECONDS: float = 6.0
|
||||
|
||||
var _service: NetworkChatService
|
||||
var _session: NetworkSession
|
||||
var _spawn: PlayerSpawnService
|
||||
var _player: Player
|
||||
var _fishing_spot: FishingSpot
|
||||
var _history: Label
|
||||
var _entry: LineEdit
|
||||
var _chat_button: Button
|
||||
var _panel: PanelContainer
|
||||
var _speech_layer: Control
|
||||
var _speech: Dictionary[int, Dictionary] = {}
|
||||
var _opened: bool = false
|
||||
var _available: bool = false
|
||||
var _last_message_time: float = -INF
|
||||
var _prior_movement: bool = true
|
||||
var _prior_camera: bool = true
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
_build_ui()
|
||||
|
||||
|
||||
func setup(
|
||||
service: NetworkChatService,
|
||||
session: NetworkSession,
|
||||
spawn: PlayerSpawnService,
|
||||
player: Player,
|
||||
fishing_spot: FishingSpot,
|
||||
) -> void:
|
||||
_service = service
|
||||
_session = session
|
||||
_spawn = spawn
|
||||
_player = player
|
||||
_fishing_spot = fishing_spot
|
||||
_service.message_received.connect(_on_message)
|
||||
_service.history_replaced.connect(_on_history)
|
||||
_service.send_rejected.connect(_on_rejected)
|
||||
_session.peer_removed.connect(_on_peer_removed)
|
||||
_refresh_history()
|
||||
|
||||
|
||||
func open_chat() -> void:
|
||||
if (
|
||||
_opened or not _available or _service == null
|
||||
or not _session.is_gameplay_session_active()
|
||||
):
|
||||
return
|
||||
_opened = true
|
||||
_prior_movement = _player.is_movement_enabled()
|
||||
_prior_camera = _player.is_camera_input_enabled()
|
||||
_player.set_movement_enabled(false)
|
||||
_player.set_camera_input_enabled(false)
|
||||
_fishing_spot.set_local_menu_input_suppressed(INPUT_OWNER, true)
|
||||
_panel.show()
|
||||
_entry.show()
|
||||
_entry.grab_focus()
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
|
||||
|
||||
func set_available(value: bool) -> void:
|
||||
_available = value
|
||||
_chat_button.visible = value
|
||||
if not value:
|
||||
close_chat()
|
||||
|
||||
|
||||
func close_chat() -> void:
|
||||
if not _opened:
|
||||
return
|
||||
_opened = false
|
||||
_entry.release_focus()
|
||||
_entry.hide()
|
||||
_player.set_movement_enabled(_prior_movement)
|
||||
_player.set_camera_input_enabled(_prior_camera)
|
||||
_fishing_spot.set_local_menu_input_suppressed(INPUT_OWNER, false)
|
||||
_refresh_visibility()
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event is InputEventKey and event.pressed and not event.echo:
|
||||
if event.keycode in [KEY_ENTER, KEY_KP_ENTER]:
|
||||
if _opened:
|
||||
_send()
|
||||
elif (
|
||||
_available
|
||||
and get_viewport().gui_get_focus_owner() is not LineEdit
|
||||
):
|
||||
open_chat()
|
||||
get_viewport().set_input_as_handled()
|
||||
elif event.keycode == KEY_ESCAPE and _opened:
|
||||
close_chat()
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
_refresh_visibility()
|
||||
var now := Time.get_ticks_msec() / 1000.0
|
||||
for peer_id: int in _speech.keys():
|
||||
var state: Dictionary = _speech[peer_id]
|
||||
var label := state.get("label") as Label
|
||||
if label == null or now >= float(state.get("expires", 0.0)):
|
||||
if label != null:
|
||||
label.queue_free()
|
||||
_speech.erase(peer_id)
|
||||
continue
|
||||
var avatar := _spawn.get_avatar(peer_id)
|
||||
var camera := _player.get_gameplay_camera()
|
||||
if avatar == null or camera == null:
|
||||
label.hide()
|
||||
continue
|
||||
var world_position := avatar.get_body_center_position() + Vector3.UP * 1.2
|
||||
if camera.is_position_behind(world_position):
|
||||
label.hide()
|
||||
continue
|
||||
var screen_position := camera.unproject_position(world_position)
|
||||
label.position = screen_position - Vector2(label.size.x * 0.5, 42.0)
|
||||
label.show()
|
||||
|
||||
|
||||
func _build_ui() -> void:
|
||||
_panel = PanelContainer.new()
|
||||
_panel.position = Vector2(18, 390)
|
||||
_panel.size = Vector2(390, 240)
|
||||
_panel.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
add_child(_panel)
|
||||
var box := VBoxContainer.new()
|
||||
box.add_theme_constant_override("separation", 6)
|
||||
_panel.add_child(box)
|
||||
_history = Label.new()
|
||||
_history.custom_minimum_size = Vector2(360, 150)
|
||||
_history.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
_history.vertical_alignment = VERTICAL_ALIGNMENT_BOTTOM
|
||||
_history.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
box.add_child(_history)
|
||||
_entry = LineEdit.new()
|
||||
_entry.placeholder_text = "type a message…"
|
||||
_entry.max_length = NetworkChatProtocol.MAX_VISIBLE_CHARACTERS
|
||||
_entry.text_submitted.connect(func(_value: String) -> void: _send())
|
||||
_entry.hide()
|
||||
box.add_child(_entry)
|
||||
_chat_button = Button.new()
|
||||
_chat_button.text = "chat"
|
||||
_chat_button.position = Vector2(18, 570)
|
||||
_chat_button.size = Vector2(76, 54)
|
||||
_chat_button.pressed.connect(open_chat)
|
||||
add_child(_chat_button)
|
||||
_speech_layer = Control.new()
|
||||
_speech_layer.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
_speech_layer.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
add_child(_speech_layer)
|
||||
_panel.hide()
|
||||
|
||||
|
||||
func _send() -> void:
|
||||
var body := _entry.text
|
||||
if _service.send_local_message(body):
|
||||
_entry.clear()
|
||||
close_chat()
|
||||
|
||||
|
||||
func _on_message(message: Dictionary) -> void:
|
||||
_last_message_time = Time.get_ticks_msec() / 1000.0
|
||||
_refresh_history()
|
||||
if int(message["kind"]) != NetworkChatProtocol.Kind.PLAYER:
|
||||
return
|
||||
var peer_id: int = message["sender_peer_id"]
|
||||
_on_peer_removed(peer_id)
|
||||
var label := Label.new()
|
||||
label.text = "%s: %s" % [
|
||||
str(message["sender_display_name"]), str(message["body"]).left(120),
|
||||
]
|
||||
label.custom_minimum_size = Vector2(80, 34)
|
||||
label.size = Vector2(280, 70)
|
||||
label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
_speech_layer.add_child(label)
|
||||
_speech[peer_id] = {
|
||||
"label": label,
|
||||
"expires": Time.get_ticks_msec() / 1000.0 + SPEECH_SECONDS,
|
||||
}
|
||||
|
||||
|
||||
func _on_history(_messages: Array[Dictionary]) -> void:
|
||||
if _messages.is_empty():
|
||||
for peer_id: int in _speech.keys():
|
||||
_on_peer_removed(peer_id)
|
||||
_refresh_history()
|
||||
|
||||
|
||||
func _on_rejected(message: String) -> void:
|
||||
_entry.placeholder_text = message
|
||||
if not _opened:
|
||||
open_chat()
|
||||
|
||||
|
||||
func _refresh_history() -> void:
|
||||
if _service == null:
|
||||
return
|
||||
var lines: Array[String] = []
|
||||
var messages := _service.get_history()
|
||||
var start := maxi(0, messages.size() - 8)
|
||||
for message: Dictionary in messages.slice(start):
|
||||
if int(message["kind"]) == NetworkChatProtocol.Kind.SYSTEM:
|
||||
lines.append("• %s" % str(message["body"]))
|
||||
else:
|
||||
lines.append("%s: %s" % [
|
||||
str(message["sender_display_name"]), str(message["body"]),
|
||||
])
|
||||
_history.text = "\n".join(lines)
|
||||
|
||||
|
||||
func _refresh_visibility() -> void:
|
||||
if not _available:
|
||||
_panel.hide()
|
||||
return
|
||||
if _opened:
|
||||
_panel.show()
|
||||
return
|
||||
var recent := (
|
||||
Time.get_ticks_msec() / 1000.0 - _last_message_time
|
||||
< COMPACT_SECONDS
|
||||
)
|
||||
_panel.visible = recent and _service != null and not _service.get_history().is_empty()
|
||||
|
||||
|
||||
func _on_peer_removed(peer_id: int) -> void:
|
||||
var state: Dictionary = _speech.get(peer_id, {})
|
||||
var label := state.get("label") as Label
|
||||
if label != null:
|
||||
label.queue_free()
|
||||
_speech.erase(peer_id)
|
||||
1
ui/chat_ui.gd.uid
Normal file
1
ui/chat_ui.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://canbrvh1cqkie
|
||||
|
|
@ -31,6 +31,7 @@ const PlayerItemEffectsType = preload(
|
|||
const PlayerCoolerCapacityType = preload(
|
||||
"res://progression/player_cooler_capacity.gd"
|
||||
)
|
||||
const ChatUIType = preload("res://ui/chat_ui.gd")
|
||||
|
||||
signal pixelation_settings_visibility_changed(is_visible: bool)
|
||||
signal crisp_reset_focus_requested
|
||||
|
|
@ -53,6 +54,7 @@ signal interactive_pointer_ui_changed(is_open: bool)
|
|||
@onready var _fishing_shop: FishingShopType = %FishingShop
|
||||
@onready var _shop_prompt: PanelContainer = %ShopPrompt
|
||||
@onready var _effect_status: Label = %EffectStatus
|
||||
@onready var _chat_ui: ChatUIType = %ChatUI
|
||||
@onready var _title_settings_panel: SettingsPanelType = (
|
||||
$UIRoot/TitleScreen/ResponsiveTitleStage/TitlePresentationScaleRoot/SettingsPanel
|
||||
)
|
||||
|
|
@ -70,6 +72,9 @@ var _item_effects: PlayerItemEffectsType
|
|||
|
||||
|
||||
func _ready() -> void:
|
||||
_pause_menu.chat_requested.connect(
|
||||
func() -> void: call_deferred("_open_chat_from_pause")
|
||||
)
|
||||
_title_settings_panel.panel_visibility_changed.connect(
|
||||
_on_settings_visibility_changed
|
||||
)
|
||||
|
|
@ -84,6 +89,10 @@ func _ready() -> void:
|
|||
)
|
||||
|
||||
|
||||
func _open_chat_from_pause() -> void:
|
||||
_chat_ui.open_chat()
|
||||
|
||||
|
||||
func setup(
|
||||
player: PlayerType,
|
||||
inventory: FishInventoryType,
|
||||
|
|
@ -104,9 +113,22 @@ func setup(
|
|||
network_session: NetworkSessionType,
|
||||
network_sale_service: NetworkSaleService,
|
||||
network_shop_service: NetworkShopService,
|
||||
network_chat_service: NetworkChatService,
|
||||
network_profile: NetworkProfilePreferences,
|
||||
spawn_service: PlayerSpawnService,
|
||||
) -> void:
|
||||
_fishing_spot = fishing_spot
|
||||
_item_effects = item_effects
|
||||
_chat_ui.setup(
|
||||
network_chat_service, network_session, spawn_service, player,
|
||||
fishing_spot
|
||||
)
|
||||
_title_settings_panel.setup_network_profile(
|
||||
network_profile, network_session
|
||||
)
|
||||
_pause_settings_panel.setup_network_profile(
|
||||
network_profile, network_session
|
||||
)
|
||||
fishing_spot.status_changed.connect(_on_fishing_status_changed)
|
||||
fishing_spot.catch_display_changed.connect(_on_catch_display_changed)
|
||||
fishing_spot.showcase_changed.connect(_on_showcase_changed)
|
||||
|
|
@ -202,6 +224,7 @@ func get_pause_menu() -> PauseMenuType:
|
|||
|
||||
func set_gameplay_ui_enabled(enabled: bool) -> void:
|
||||
_gameplay_ui_enabled = enabled
|
||||
_refresh_chat_availability()
|
||||
if not enabled:
|
||||
close_player_menu_for_session_end()
|
||||
_fishing_shop.close_for_session_end()
|
||||
|
|
@ -217,6 +240,7 @@ func set_gameplay_ui_enabled(enabled: bool) -> void:
|
|||
|
||||
func set_system_menu_open(is_open: bool) -> void:
|
||||
_system_menu_open = is_open
|
||||
_refresh_chat_availability()
|
||||
_hotbar_ui.visible = (
|
||||
_gameplay_ui_enabled and not is_open and not _shop_open
|
||||
)
|
||||
|
|
@ -444,6 +468,7 @@ func _on_showcase_changed(
|
|||
|
||||
func _on_player_menu_visibility_changed(is_open: bool) -> void:
|
||||
_player_menu_open = is_open
|
||||
_refresh_chat_availability()
|
||||
_hotbar_ui.set_gameplay_input_enabled(
|
||||
_gameplay_ui_enabled and not is_open
|
||||
)
|
||||
|
|
@ -456,6 +481,7 @@ func _on_player_menu_visibility_changed(is_open: bool) -> void:
|
|||
|
||||
func _on_shop_visibility_changed(is_open: bool) -> void:
|
||||
_shop_open = is_open
|
||||
_refresh_chat_availability()
|
||||
_hotbar_ui.visible = (
|
||||
_gameplay_ui_enabled and not is_open and not _system_menu_open
|
||||
)
|
||||
|
|
@ -474,3 +500,14 @@ func _emit_interactive_pointer_ui_changed() -> void:
|
|||
interactive_pointer_ui_changed.emit(
|
||||
_system_menu_open or _player_menu_open or _shop_open
|
||||
)
|
||||
|
||||
|
||||
func _refresh_chat_availability() -> void:
|
||||
if _chat_ui == null:
|
||||
return
|
||||
_chat_ui.set_available(
|
||||
_gameplay_ui_enabled
|
||||
and not _system_menu_open
|
||||
and not _player_menu_open
|
||||
and not _shop_open
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
[gd_scene load_steps=13 format=3]
|
||||
[gd_scene load_steps=14 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://ui/game_ui.gd" id="1_ui"]
|
||||
[ext_resource type="PackedScene" path="res://ui/player_menu.tscn" id="2_menu"]
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
[ext_resource type="PackedScene" path="res://ui/pause_menu.tscn" id="6_pause"]
|
||||
[ext_resource type="PackedScene" path="res://ui/hotbar.tscn" id="7_hotbar"]
|
||||
[ext_resource type="PackedScene" path="res://ui/fishing_shop.tscn" id="8_shop"]
|
||||
[ext_resource type="Script" path="res://ui/chat_ui.gd" id="9_chat"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBox_chase_background"]
|
||||
bg_color = Color(0.055, 0.105, 0.125, 1)
|
||||
|
|
@ -185,6 +186,17 @@ theme_override_colors/font_shadow_color = Color(0, 0, 0, 0.9)
|
|||
theme_override_constants/shadow_offset_x = 2
|
||||
theme_override_constants/shadow_offset_y = 2
|
||||
|
||||
[node name="ChatUI" type="Control" parent="UIRoot"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
script = ExtResource("9_chat")
|
||||
|
||||
[node name="ScreenFade" type="ColorRect" parent="UIRoot"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ signal reset_progress_requested
|
|||
signal quit_requested
|
||||
signal menu_visibility_changed(is_open: bool)
|
||||
signal join_game_requested(endpoint: String)
|
||||
signal chat_requested
|
||||
|
||||
enum ConfirmationAction {
|
||||
NONE,
|
||||
|
|
@ -87,6 +88,7 @@ func _ready() -> void:
|
|||
_save_button.pressed.connect(_save_now)
|
||||
%SettingsButton.pressed.connect(_open_settings)
|
||||
%JoinGameButton.pressed.connect(_open_join_game)
|
||||
%ChatButton.pressed.connect(_request_chat)
|
||||
%ReturnToTitleButton.pressed.connect(_confirm_return_to_title)
|
||||
%ResetProgressButton.pressed.connect(_confirm_reset_progress)
|
||||
%QuitButton.pressed.connect(_request_quit)
|
||||
|
|
@ -105,6 +107,13 @@ func _ready() -> void:
|
|||
call_deferred("_update_responsive_pause_stage")
|
||||
|
||||
|
||||
func _request_chat() -> void:
|
||||
if not visible or _action_in_progress or _root_transition_active:
|
||||
return
|
||||
close_menu(CloseReason.USER_RETURN, true)
|
||||
chat_requested.emit()
|
||||
|
||||
|
||||
func setup(
|
||||
player: PlayerType,
|
||||
save_manager: SaveManagerType,
|
||||
|
|
|
|||
|
|
@ -77,8 +77,8 @@ grow_horizontal = 2
|
|||
grow_vertical = 2
|
||||
script = ExtResource("4_page")
|
||||
page_id = &"pause"
|
||||
bubble_paths = Array[NodePath]([NodePath("BubbleCluster/ResumeButton"), NodePath("BubbleCluster/SaveButton"), NodePath("BubbleCluster/JoinGameButton"), NodePath("BubbleCluster/SettingsButton"), NodePath("BubbleCluster/ReturnToTitleButton"), NodePath("BubbleCluster/ResetProgressButton"), NodePath("BubbleCluster/QuitButton")])
|
||||
focus_paths = Array[NodePath]([NodePath("BubbleCluster/ResumeButton"), NodePath("BubbleCluster/SaveButton"), NodePath("BubbleCluster/JoinGameButton"), NodePath("BubbleCluster/SettingsButton"), NodePath("BubbleCluster/ReturnToTitleButton"), NodePath("BubbleCluster/ResetProgressButton"), NodePath("BubbleCluster/QuitButton")])
|
||||
bubble_paths = Array[NodePath]([NodePath("BubbleCluster/ResumeButton"), NodePath("BubbleCluster/SaveButton"), NodePath("BubbleCluster/JoinGameButton"), NodePath("BubbleCluster/ChatButton"), NodePath("BubbleCluster/SettingsButton"), NodePath("BubbleCluster/ReturnToTitleButton"), NodePath("BubbleCluster/ResetProgressButton"), NodePath("BubbleCluster/QuitButton")])
|
||||
focus_paths = Array[NodePath]([NodePath("BubbleCluster/ResumeButton"), NodePath("BubbleCluster/SaveButton"), NodePath("BubbleCluster/JoinGameButton"), NodePath("BubbleCluster/ChatButton"), NodePath("BubbleCluster/SettingsButton"), NodePath("BubbleCluster/ReturnToTitleButton"), NodePath("BubbleCluster/ResetProgressButton"), NodePath("BubbleCluster/QuitButton")])
|
||||
initial_focus_path = NodePath("BubbleCluster/ResumeButton")
|
||||
back_focus_path = NodePath("BubbleCluster/ResumeButton")
|
||||
maximum_layout_size = Vector2(720, 520)
|
||||
|
|
@ -135,6 +135,18 @@ minimum_font_size = 16
|
|||
maximum_font_size = 23
|
||||
motion_phase = 2.05
|
||||
|
||||
[node name="ChatButton" parent="ResponsivePauseStage/PausePresentationScaleRoot/RootPage/BubbleCluster" instance=ExtResource("5_bubble")]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 0)
|
||||
text = "chat"
|
||||
neutral_size = Vector2(112, 106)
|
||||
desktop_anchor = Vector2(620, 255)
|
||||
compact_anchor = Vector2(595, 270)
|
||||
compact_minimum_size = Vector2(92, 88)
|
||||
minimum_font_size = 15
|
||||
maximum_font_size = 20
|
||||
motion_phase = 2.3
|
||||
|
||||
[node name="JoinGameButton" parent="ResponsivePauseStage/PausePresentationScaleRoot/RootPage/BubbleCluster" instance=ExtResource("5_bubble")]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 0)
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ enum PresentationMode {
|
|||
@onready var _controls_page: SettingsBubblePage = %ControlsPage
|
||||
@onready var _accessibility_page: SettingsBubblePage = %AccessibilityPage
|
||||
@onready var _feedback: Label = %SettingsFeedback
|
||||
@onready var _display_name_edit: LineEdit = %DisplayNameEdit
|
||||
|
||||
@onready var _world_value: BubbleButton = %WorldValue
|
||||
@onready var _ui_value: BubbleButton = %UIValue
|
||||
|
|
@ -75,6 +76,8 @@ var _auto_click_interval_value: float = 0.20
|
|||
var _mouse_sensitivity: float = 0.005
|
||||
var _controller_sensitivity: float = 2.5
|
||||
var _invert_camera_y: bool = false
|
||||
var _network_profile: NetworkProfilePreferences
|
||||
var _network_session: NetworkSession
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
|
|
@ -98,6 +101,10 @@ func _ready() -> void:
|
|||
%DisplayBackButton.gui_input.connect(_on_back_bubble_gui_input)
|
||||
%ControlsBackButton.gui_input.connect(_on_back_bubble_gui_input)
|
||||
%AccessibilityBackButton.gui_input.connect(_on_back_bubble_gui_input)
|
||||
_display_name_edit.text_submitted.connect(
|
||||
func(_value: String) -> void: _apply_display_name()
|
||||
)
|
||||
_display_name_edit.focus_exited.connect(_apply_display_name)
|
||||
for index: int in _world_options.size():
|
||||
_world_options[index].pressed.connect(
|
||||
_set_world_pixelation.bind(index + 1)
|
||||
|
|
@ -143,6 +150,33 @@ func _ready() -> void:
|
|||
call_deferred("_refresh_panel_size")
|
||||
|
||||
|
||||
func setup_network_profile(
|
||||
profile: NetworkProfilePreferences,
|
||||
session: NetworkSession,
|
||||
) -> void:
|
||||
_network_profile = profile
|
||||
_network_session = session
|
||||
if _network_profile != null:
|
||||
_display_name_edit.text = _network_profile.display_name
|
||||
|
||||
|
||||
func _apply_display_name() -> void:
|
||||
if _network_profile == null:
|
||||
return
|
||||
var value := _display_name_edit.text.strip_edges()
|
||||
var accepted := (
|
||||
_network_session.update_local_display_name(value)
|
||||
if _network_session != null
|
||||
else _network_profile.set_display_name(value)
|
||||
)
|
||||
if accepted:
|
||||
_display_name_edit.text = _network_profile.display_name
|
||||
_feedback.text = "display name saved."
|
||||
else:
|
||||
_display_name_edit.text = _network_profile.display_name
|
||||
_feedback.text = "display name must be 1–24 plain-text characters."
|
||||
|
||||
|
||||
func open_panel(
|
||||
settings_manager: SettingsManagerType,
|
||||
presentation_mode: PresentationMode = PresentationMode.GAMEPLAY_MODAL,
|
||||
|
|
@ -158,6 +192,8 @@ func open_panel(
|
|||
)
|
||||
_settings_manager = settings_manager
|
||||
_load_controls()
|
||||
if _network_profile != null:
|
||||
_display_name_edit.text = _network_profile.display_name
|
||||
_feedback.text = ""
|
||||
show()
|
||||
_page_stack.clear()
|
||||
|
|
|
|||
|
|
@ -144,6 +144,31 @@ minimum_font_size = 14
|
|||
maximum_font_size = 17
|
||||
motion_phase = 4.8
|
||||
|
||||
[node name="DisplayNamePanel" type="PanelContainer" parent="RootPage"]
|
||||
layout_mode = 0
|
||||
offset_left = 318.0
|
||||
offset_top = 430.0
|
||||
offset_right = 618.0
|
||||
offset_bottom = 510.0
|
||||
|
||||
[node name="VBox" type="VBoxContainer" parent="RootPage/DisplayNamePanel"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="RootPage/DisplayNamePanel/VBox"]
|
||||
layout_mode = 2
|
||||
text = "display name"
|
||||
|
||||
[node name="DisplayNameEdit" type="LineEdit" parent="RootPage/DisplayNamePanel/VBox"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
max_length = 24
|
||||
placeholder_text = "Player"
|
||||
|
||||
[node name="Help" type="Label" parent="RootPage/DisplayNamePanel/VBox"]
|
||||
layout_mode = 2
|
||||
text = "Shown to other players in multiplayer."
|
||||
theme_override_font_sizes/font_size = 12
|
||||
|
||||
[node name="DisplayPage" type="Control" parent="."]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue