feat: complete mobile UI implementation

This commit is contained in:
shenlei
2026-09-04 19:54:33 +09:00
parent 9a4a044da5
commit b19d5b5dd3
132 changed files with 6643 additions and 180 deletions
+107 -4
View File
@@ -50,6 +50,8 @@ var _fishing_active := false
var _whisper_dialog: Panel
var _whisper_target: LineEdit
var _whisper_message: LineEdit
var _mobile_mode := false
var _tab_row: HBoxContainer
func setup(m2client: Node, parent: Node, assets_root := "") -> void:
client = m2client
@@ -85,6 +87,29 @@ func focus_input() -> void:
if _input:
_input.grab_focus()
func set_mobile_mode(enabled: bool) -> void:
_mobile_mode = enabled
if _root:
_apply_mobile_layout()
_apply_mobile_whisper_layout()
if enabled and _root:
# Chat is an on-demand full-screen page on mobile; the landscape HUD has
# no permanent bottom chat strip.
_root.visible = false
func close() -> void:
if _root:
_root.visible = false
_close_whisper()
func get_mobile_windows() -> Array[Control]:
var result: Array[Control] = []
if _root:
result.append(_root)
if _whisper_dialog:
result.append(_whisper_dialog)
return result
# 预填 "/w <名> " 并聚焦(好友列表点名字时调)。
func start_whisper(name: String) -> void:
if _whisper_dialog == null or name.strip_edges() == "":
@@ -130,9 +155,9 @@ func _build(parent: Node) -> void:
panel.add_theme_stylebox_override("panel", sb)
_root.add_child(panel)
var tabrow := HBoxContainer.new()
tabrow.position = Vector2(6, 4)
_root.add_child(tabrow)
_tab_row = HBoxContainer.new()
_tab_row.position = Vector2(6, 4)
_root.add_child(_tab_row)
for i in TABS.size():
var b := Button.new()
b.text = TABS[i]
@@ -141,7 +166,7 @@ func _build(parent: Node) -> void:
b.add_theme_font_size_override("font_size", 11)
var idx := i
b.pressed.connect(func(): _select_tab(idx))
tabrow.add_child(b)
_tab_row.add_child(b)
_tab_btns.append(b)
for i in TABS.size():
@@ -165,6 +190,84 @@ func _build(parent: Node) -> void:
_input.text_submitted.connect(_on_submit)
_root.add_child(_input)
_build_whisper_dialog(parent)
_apply_mobile_layout()
_apply_mobile_whisper_layout()
func _apply_mobile_layout() -> void:
if _root == null:
return
if not _mobile_mode:
_root.set_anchors_preset(Control.PRESET_BOTTOM_LEFT)
_root.position = Vector2(12, -232)
_root.size = Vector2(460, 220)
if _tab_row:
_tab_row.position = Vector2(6, 4)
for rt in _log.values():
(rt as RichTextLabel).position = Vector2(6, 30)
(rt as RichTextLabel).size = Vector2(448, 158)
if _input:
_input.position = Vector2(6, 192)
_input.size = Vector2(448, 24)
return
# One landscape page with a large text area and a keyboard-friendly input
# row. The HUD remains clear until the player explicitly opens chat.
_root.set_anchors_preset(Control.PRESET_TOP_LEFT)
_root.position = Vector2.ZERO
_root.size = Vector2(760, 340)
_root.set_meta("mobile_title", "聊天")
if _tab_row:
_tab_row.position = Vector2(14, 48)
_tab_row.size = Vector2(732, 40)
_tab_row.add_theme_constant_override("separation", 6)
for child in _tab_row.get_children():
child.custom_minimum_size = Vector2(112, 38)
child.add_theme_font_size_override("font_size", 12)
for rt in _log.values():
(rt as RichTextLabel).position = Vector2(14, 94)
(rt as RichTextLabel).size = Vector2(732, 190)
(rt as RichTextLabel).add_theme_font_size_override("normal_font_size", 14)
if _input:
_input.position = Vector2(14, 294)
_input.size = Vector2(732, 38)
_input.add_theme_font_size_override("font_size", 13)
func _apply_mobile_whisper_layout() -> void:
if _whisper_dialog == null:
return
if not _mobile_mode:
_whisper_dialog.set_anchors_preset(Control.PRESET_CENTER)
_whisper_dialog.position = Vector2(-170, -82)
_whisper_dialog.size = Vector2(340, 164)
return
_whisper_dialog.set_anchors_preset(Control.PRESET_TOP_LEFT)
_whisper_dialog.position = Vector2.ZERO
_whisper_dialog.size = Vector2(480, 260)
_whisper_dialog.set_meta("mobile_title", "私聊")
var title := _whisper_dialog.get_child(0) as Label
if title:
title.position = Vector2(18, 50)
title.add_theme_font_size_override("font_size", 15)
var target_label := _whisper_dialog.get_child(1) as Label
if target_label:
target_label.position = Vector2(18, 94)
var message_label := _whisper_dialog.get_child(3) as Label
if message_label:
message_label.position = Vector2(18, 148)
if _whisper_target:
_whisper_target.position = Vector2(86, 90)
_whisper_target.size = Vector2(370, 42)
if _whisper_message:
_whisper_message.position = Vector2(86, 144)
_whisper_message.size = Vector2(370, 42)
_whisper_message.virtual_keyboard_type = LineEdit.KEYBOARD_TYPE_DEFAULT
var cancel := _whisper_dialog.get_node_or_null("Button") as Button
var send := _whisper_dialog.get_node_or_null("Button2") as Button
if cancel:
cancel.position = Vector2(174, 202)
cancel.size = Vector2(130, 44)
if send:
send.position = Vector2(316, 202)
send.size = Vector2(130, 44)
func _build_whisper_dialog(parent: Node) -> void:
# root/game.py 的 OpenWhisperDialog 是独立窗口,不应把私聊目标写回公共