Files
2026-07-08 20:42:51 +08:00

215 lines
7.3 KiB
C#

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<Player.PlayerController>(true);
}
// 自动查找 LLMChatManager (如果在场景中)
if (chatManager == null)
{
chatManager = FindObjectOfType<LLMChatManager>();
}
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<ScrollRect>();
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<TextMeshProUGUI>();
if (tmp != null)
{
tmp.text = text;
}
var aligner = newMsg.GetComponent<MessageAligner>();
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<ScrollRect>();
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<MessageAligner>();
if (aligner != null) aligner.Reapply();
}
Canvas.ForceUpdateCanvases();
RectTransform chatContentRect = chatContent as RectTransform;
if (chatContentRect != null) LayoutRebuilder.ForceRebuildLayoutImmediate(chatContentRect);
ScrollRect scrollRect = chatContent.GetComponentInParent<ScrollRect>();
if (scrollRect != null) scrollRect.verticalNormalizedPosition = 0f;
}
}
}