模板脚本文件
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
class_name PlayerListUI
|
||||
extends Control
|
||||
|
||||
const PLAYER_ROW_HEIGHT := 28.0
|
||||
const MAX_VISIBLE_ROWS := 8
|
||||
const RESERVED_VERTICAL_SPACE := 190.0
|
||||
const SAFE_AREA_MARGIN := 16.0
|
||||
|
||||
var _player_count := 0
|
||||
|
||||
@onready var panel: PanelContainer = $SafeArea/PositionContainer/Panel
|
||||
@onready var count_label: Label = $SafeArea/PositionContainer/Panel/MarginContainer/Content/Count
|
||||
@onready var player_scroll: ScrollContainer = $SafeArea/PositionContainer/Panel/MarginContainer/Content/PlayerScroll
|
||||
@onready
|
||||
var players_label: RichTextLabel = $SafeArea/PositionContainer/Panel/MarginContainer/Content/PlayerScroll/Players
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
resized.connect(_update_layout)
|
||||
_update_layout()
|
||||
hide()
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if not visible or not (event is InputEventMouseButton):
|
||||
return
|
||||
var mouse_event := event as InputEventMouseButton
|
||||
if not mouse_event.pressed:
|
||||
return
|
||||
if mouse_event.button_index == MOUSE_BUTTON_WHEEL_UP:
|
||||
player_scroll.scroll_vertical -= int(PLAYER_ROW_HEIGHT)
|
||||
elif mouse_event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
|
||||
player_scroll.scroll_vertical += int(PLAYER_ROW_HEIGHT)
|
||||
|
||||
|
||||
func show_players(players: Dictionary, local_peer_id: int) -> void:
|
||||
refresh_players(players, local_peer_id)
|
||||
player_scroll.scroll_vertical = 0
|
||||
show()
|
||||
call_deferred("_apply_panel_scale")
|
||||
|
||||
|
||||
func hide_players() -> void:
|
||||
hide()
|
||||
|
||||
|
||||
func refresh_players(players: Dictionary, local_peer_id: int) -> void:
|
||||
var peer_ids: Array[int] = []
|
||||
for peer_id_value in players:
|
||||
var peer_id := int(peer_id_value)
|
||||
if peer_id > 0:
|
||||
peer_ids.append(peer_id)
|
||||
peer_ids.sort()
|
||||
_player_count = peer_ids.size()
|
||||
|
||||
count_label.text = "%d online" % _player_count
|
||||
players_label.clear()
|
||||
for index in range(peer_ids.size()):
|
||||
var peer_id := peer_ids[index]
|
||||
var player_info: Dictionary = players.get(peer_id, {})
|
||||
var nickname := Network.sanitize_nickname(str(player_info.get("nick", "")), "Player_" + str(peer_id))
|
||||
var local_marker := " [color=#c7ccd4](you)[/color]" if peer_id == local_peer_id else ""
|
||||
players_label.append_text(
|
||||
(
|
||||
"[color=#a8adb5]>[/color] [b]%s[/b]%s [color=#9aa0a8]#%d[/color]"
|
||||
% [_escape_bbcode(nickname), local_marker, peer_id]
|
||||
)
|
||||
)
|
||||
if index < peer_ids.size() - 1:
|
||||
players_label.append_text("\n")
|
||||
_update_layout()
|
||||
|
||||
|
||||
func _update_layout() -> void:
|
||||
if not panel or not player_scroll:
|
||||
return
|
||||
var panel_minimum_size := panel.custom_minimum_size
|
||||
panel_minimum_size.x = maxf(0.0, minf(420.0, size.x - 32.0))
|
||||
panel.custom_minimum_size = panel_minimum_size
|
||||
|
||||
var visible_rows := maxi(1, mini(_player_count, MAX_VISIBLE_ROWS))
|
||||
var desired_height := float(visible_rows) * PLAYER_ROW_HEIGHT
|
||||
var viewport_limit := maxf(30.0, size.y - RESERVED_VERTICAL_SPACE)
|
||||
var scroll_minimum_size := player_scroll.custom_minimum_size
|
||||
scroll_minimum_size.y = minf(desired_height, viewport_limit)
|
||||
player_scroll.custom_minimum_size = scroll_minimum_size
|
||||
|
||||
var players_minimum_size := players_label.custom_minimum_size
|
||||
players_minimum_size.y = float(maxi(1, _player_count)) * PLAYER_ROW_HEIGHT
|
||||
players_label.custom_minimum_size = players_minimum_size
|
||||
call_deferred("_apply_panel_scale")
|
||||
|
||||
|
||||
func _apply_panel_scale() -> void:
|
||||
if not panel:
|
||||
return
|
||||
var available_size := Vector2(
|
||||
maxf(1.0, size.x - SAFE_AREA_MARGIN * 2.0), maxf(1.0, size.y - SAFE_AREA_MARGIN * 2.0)
|
||||
)
|
||||
var panel_size := panel.size
|
||||
if panel_size.x <= 0.0 or panel_size.y <= 0.0:
|
||||
return
|
||||
var scale_factor := minf(1.0, minf(available_size.x / panel_size.x, available_size.y / panel_size.y))
|
||||
panel.pivot_offset = panel_size * 0.5
|
||||
panel.scale = Vector2.ONE * scale_factor
|
||||
|
||||
|
||||
func _escape_bbcode(text: String) -> String:
|
||||
return text.replace("[", "[lb]")
|
||||
Reference in New Issue
Block a user