using UnityEngine; using UnityEngine.UI; using TMPro; using System.Collections; using System.Collections.Generic; using LLM; // 引用新的 LLM 命名空间 using Core.InputLock; namespace UI { public class TabletController : MonoBehaviour { [SerializeField] private bool debugLogs = true; [Header("UI References")] public GameObject tabletPanel; // 整个平板界面的父物体 public TMP_InputField inputField; // 输入框 public Transform chatContent; // 聊天记录的父物体 (ScrollView Content) public GameObject messagePrefab; // 聊天气泡预设体 [Header("Game Control")] public GameObject hudCanvas; // 游戏原本的 HUD (准星等),打开平板时隐藏 public MonoBehaviour playerController; // 玩家控制器脚本 [Header("LLM Manager")] public LLMChatManager chatManager; // 引用 LLMChatManager 来管理多模型切换 // public GameObject llmServiceObj; // 已废弃,请使用 chatManager private Coroutine rebuildChatLayoutRoutine; public static TabletController Instance { get; private set; } private void Awake() { if (Instance == null) Instance = this; else Destroy(gameObject); if (tabletPanel != null) tabletPanel.SetActive(false); if (playerController == null) { playerController = FindObjectOfType(true); } // 自动查找 LLMChatManager (如果在场景中) if (chatManager == null) { chatManager = FindObjectOfType(); } if (chatManager == null) { Debug.LogError("[TabletController] 未找到 LLMChatManager!请确保场景中存在该管理器。"); } else { // 监听历史记录加载完成(这里简单地在 Start 中延迟一帧加载,因为 SaveManager 加载通常很快) StartCoroutine(InitChatHistory()); } } private IEnumerator InitChatHistory() { // 等待一帧,确保 LLMChatManager 已经完成了 Start 中的 SaveManager.LoadGame() yield return null; if (chatManager.fullChatLog != null && chatManager.fullChatLog.Count > 0) { // 清理可能存在的测试数据(如果有) foreach (Transform child in chatContent) { Destroy(child.gameObject); } // 重建 UI foreach (var msg in chatManager.fullChatLog) { bool isPlayer = (msg.role == "user"); // 只有 user 和 assistant 的消息需要显示 if (msg.role == "user" || msg.role == "assistant") { AddMessageToUI(isPlayer ? "Player" : "AI", msg.content, isPlayer); } } // 滚动到底部 yield return new WaitForEndOfFrame(); ScrollRect scrollRect = chatContent.GetComponentInParent(); if (scrollRect != null) scrollRect.verticalNormalizedPosition = 0f; } } public void ShowTablet() { if (debugLogs) Debug.Log("[TabletController] ShowTablet"); if (tabletPanel != null) tabletPanel.SetActive(true); if (hudCanvas != null) hudCanvas.SetActive(false); TogglePlayerControl(false); Cursor.lockState = CursorLockMode.None; Cursor.visible = true; if (inputField != null) inputField.ActivateInputField(); if (rebuildChatLayoutRoutine != null) StopCoroutine(rebuildChatLayoutRoutine); rebuildChatLayoutRoutine = StartCoroutine(RebuildChatLayoutNextFrame()); if (UI.PanelStack.UIPanelStack.Instance != null && tabletPanel != null) { UI.PanelStack.UIPanelStack.Instance.Push(UI.PanelStack.UIPanelKind.Custom, tabletPanel, HideTablet); } } public void HideTablet() { if (debugLogs) Debug.Log("[TabletController] HideTablet"); if (tabletPanel != null) tabletPanel.SetActive(false); if (hudCanvas != null) hudCanvas.SetActive(true); TogglePlayerControl(true); Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; if (UI.PanelStack.UIPanelStack.Instance != null && tabletPanel != null) { UI.PanelStack.UIPanelStack.Instance.Remove(tabletPanel); } } private void TogglePlayerControl(bool enable) { if (PlayerControlLockService.Instance != null) { if (enable) { PlayerControlLockService.Instance.Unlock(this); } else { PlayerControlLockService.Instance.Lock(this); } } if (playerController != null) playerController.enabled = enable; } public void OnSendClicked() { if (inputField == null || string.IsNullOrWhiteSpace(inputField.text)) return; if (chatManager == null) { AddMessageToUI("System", "LLM 服务管理器未连接。", true); return; } string userMessage = inputField.text; inputField.text = ""; AddMessageToUI("Player", userMessage, true); // 使用 LLMChatManager 发送消息,它会自动选择当前激活的服务 chatManager.SendUserMessage(userMessage, (reply, success) => { AddMessageToUI("AI", reply, false); }); } private void AddMessageToUI(string role, string text, bool isPlayer) { if (messagePrefab == null || chatContent == null) return; GameObject newMsg = Instantiate(messagePrefab, chatContent); TextMeshProUGUI tmp = newMsg.GetComponentInChildren(); if (tmp != null) { tmp.text = text; } var aligner = newMsg.GetComponent(); if (aligner != null) { aligner.SetAlignment(isPlayer); } // 限制 UI 显示数量,防止无限增加导致卡顿 (保留最近的 50 条) int maxUIItems = 50; if (chatContent.childCount > maxUIItems) { Destroy(chatContent.GetChild(0).gameObject); } Canvas.ForceUpdateCanvases(); ScrollRect scrollRect = chatContent.GetComponentInParent(); if (scrollRect != null) scrollRect.verticalNormalizedPosition = 0f; } private IEnumerator RebuildChatLayoutNextFrame() { yield return new WaitForEndOfFrame(); if (chatContent == null) yield break; foreach (Transform child in chatContent) { var aligner = child.GetComponent(); if (aligner != null) aligner.Reapply(); } Canvas.ForceUpdateCanvases(); RectTransform chatContentRect = chatContent as RectTransform; if (chatContentRect != null) LayoutRebuilder.ForceRebuildLayoutImmediate(chatContentRect); ScrollRect scrollRect = chatContent.GetComponentInParent(); if (scrollRect != null) scrollRect.verticalNormalizedPosition = 0f; } } }