245 lines
5.9 KiB
C#
245 lines
5.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using Logic.Multilingual;
|
|
using TH1_Logic.Net;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
namespace TH1_UI.View.Common
|
|
{
|
|
public class UINetErrorAreaMono : MonoBehaviour
|
|
{
|
|
[Header("Toggle")]
|
|
public Button ToggleButton;
|
|
public GameObject LogArea;
|
|
|
|
[Header("Log List")]
|
|
public RectTransform Content;
|
|
public GameObject LogItemPrefab;
|
|
public ScrollRect ScrollRect;
|
|
|
|
[Header("Config")]
|
|
public int MaxLogCount = 100;
|
|
|
|
private readonly Queue<GameObject> _logItems = new Queue<GameObject>();
|
|
private bool _initialized;
|
|
private bool _logAreaVisible;
|
|
|
|
private void OnDestroy()
|
|
{
|
|
Shutdown();
|
|
}
|
|
|
|
public void Init()
|
|
{
|
|
if (_initialized) return;
|
|
_initialized = true;
|
|
|
|
if (ToggleButton != null)
|
|
{
|
|
ToggleButton.gameObject.SetActive(true);
|
|
ToggleButton.onClick.RemoveListener(ToggleLogArea);
|
|
ToggleButton.onClick.AddListener(ToggleLogArea);
|
|
}
|
|
|
|
ResetLogItemTemplate();
|
|
SetLogAreaVisible(false);
|
|
foreach (var payload in NetworkPlayerTipManager.Instance.GetRecentPayloads())
|
|
AddLog(payload, false);
|
|
ValidateLogContentState("Init");
|
|
RebuildLogLayout();
|
|
|
|
NetworkPlayerTipManager.Instance.OnTipRequested += OnNetworkPlayerTipRequested;
|
|
}
|
|
|
|
public void Shutdown()
|
|
{
|
|
if (!_initialized) return;
|
|
_initialized = false;
|
|
|
|
NetworkPlayerTipManager.Instance.OnTipRequested -= OnNetworkPlayerTipRequested;
|
|
|
|
if (ToggleButton != null)
|
|
ToggleButton.onClick.RemoveListener(ToggleLogArea);
|
|
|
|
ClearLogs();
|
|
}
|
|
|
|
private void OnNetworkPlayerTipRequested(NetworkPlayerTipPayload payload)
|
|
{
|
|
AddLog(payload, true);
|
|
}
|
|
|
|
private void ToggleLogArea()
|
|
{
|
|
SetLogAreaVisible(!_logAreaVisible);
|
|
}
|
|
|
|
private void SetLogAreaVisible(bool visible)
|
|
{
|
|
_logAreaVisible = visible;
|
|
if (LogArea != null)
|
|
LogArea.SetActive(visible);
|
|
}
|
|
|
|
private void AddLog(NetworkPlayerTipPayload payload, bool rebuildLayout)
|
|
{
|
|
if (Content == null || LogItemPrefab == null)
|
|
{
|
|
Debug.LogWarning("[NetErrorArea] Log prefab or content is not assigned.");
|
|
return;
|
|
}
|
|
|
|
while (_logItems.Count >= Mathf.Max(1, MaxLogCount))
|
|
{
|
|
var oldest = _logItems.Dequeue();
|
|
if (oldest != null)
|
|
Destroy(oldest);
|
|
}
|
|
|
|
var logText = BuildLogText(payload);
|
|
var go = Instantiate(LogItemPrefab, Content);
|
|
DisableDynamicLogMultilingual(go);
|
|
|
|
var text = go.GetComponentInChildren<TMP_Text>(true);
|
|
if (text != null)
|
|
text.text = logText;
|
|
else
|
|
Debug.LogWarning("[NetErrorArea] Log item prefab missing TMP_Text.");
|
|
|
|
go.SetActive(true);
|
|
if (text != null && text.text != logText)
|
|
text.text = logText;
|
|
|
|
_logItems.Enqueue(go);
|
|
|
|
if (rebuildLayout)
|
|
RebuildLogLayout();
|
|
|
|
ValidateLogContentState("AddLog");
|
|
}
|
|
|
|
private void RebuildLogLayout()
|
|
{
|
|
if (Content != null)
|
|
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
|
|
|
if (ScrollRect != null)
|
|
{
|
|
Canvas.ForceUpdateCanvases();
|
|
ScrollRect.verticalNormalizedPosition = 0f;
|
|
}
|
|
}
|
|
|
|
private static string BuildLogText(NetworkPlayerTipPayload payload)
|
|
{
|
|
var sb = new StringBuilder();
|
|
sb.Append('[').Append(DateTime.Now.ToString("HH:mm:ss")).Append("] ");
|
|
sb.Append(payload?.TipType.ToString() ?? "NetworkTip");
|
|
|
|
if (!string.IsNullOrEmpty(payload?.Title))
|
|
sb.Append(" | ").Append(payload.Title);
|
|
|
|
if (!string.IsNullOrEmpty(payload?.Message))
|
|
sb.Append('\n').Append(payload.Message);
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
private void ResetLogItemTemplate()
|
|
{
|
|
if (LogItemPrefab == null)
|
|
return;
|
|
|
|
var sentinel = LogItemPrefab.GetComponent<LogItemTemplateActivationSentinel>();
|
|
if (sentinel == null)
|
|
sentinel = LogItemPrefab.AddComponent<LogItemTemplateActivationSentinel>();
|
|
sentinel.Setup(this, LogItemPrefab);
|
|
|
|
DisableDynamicLogMultilingual(LogItemPrefab);
|
|
|
|
var templateText = LogItemPrefab.GetComponentInChildren<TMP_Text>(true);
|
|
if (templateText != null)
|
|
templateText.text = string.Empty;
|
|
|
|
if (Content != null && LogItemPrefab.transform.IsChildOf(Content))
|
|
{
|
|
if (LogItemPrefab.activeSelf)
|
|
{
|
|
Debug.LogWarning("[NetErrorArea] Log item template was active before reset. Check prefab saved state or code that enables Content children before Init.");
|
|
}
|
|
|
|
LogItemPrefab.SetActive(false);
|
|
}
|
|
}
|
|
|
|
private static void DisableDynamicLogMultilingual(GameObject go)
|
|
{
|
|
if (go == null)
|
|
return;
|
|
|
|
var multilingualTexts = go.GetComponentsInChildren<MultilingualTextMono>(true);
|
|
foreach (var multilingualText in multilingualTexts)
|
|
{
|
|
multilingualText.Ban = true;
|
|
multilingualText.NoExport = true;
|
|
multilingualText.ID = 0;
|
|
multilingualText.enabled = false;
|
|
}
|
|
}
|
|
|
|
private void ValidateLogContentState(string context)
|
|
{
|
|
if (Content == null)
|
|
return;
|
|
|
|
if (LogItemPrefab != null && LogItemPrefab.activeSelf)
|
|
{
|
|
Debug.LogWarning($"[NetErrorArea] Log item template is active during {context}. The template must stay hidden.");
|
|
}
|
|
|
|
for (var i = 0; i < Content.childCount; i++)
|
|
{
|
|
var child = Content.GetChild(i).gameObject;
|
|
if (child == LogItemPrefab || !child.activeSelf || _logItems.Contains(child))
|
|
continue;
|
|
|
|
Debug.LogWarning($"[NetErrorArea] Active untracked log item under Content during {context}: {child.name}");
|
|
}
|
|
}
|
|
|
|
private class LogItemTemplateActivationSentinel : MonoBehaviour
|
|
{
|
|
private UINetErrorAreaMono _owner;
|
|
private GameObject _template;
|
|
|
|
public void Setup(UINetErrorAreaMono owner, GameObject template)
|
|
{
|
|
_owner = owner;
|
|
_template = template;
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
if (_owner == null || _template == null || gameObject != _template)
|
|
return;
|
|
|
|
Debug.LogWarning("[NetErrorArea] Log item template was enabled. This object is only a hidden template and should not be shown as a record.");
|
|
}
|
|
}
|
|
|
|
private void ClearLogs()
|
|
{
|
|
while (_logItems.Count > 0)
|
|
{
|
|
var go = _logItems.Dequeue();
|
|
if (go != null)
|
|
Destroy(go);
|
|
}
|
|
RebuildLogLayout();
|
|
}
|
|
}
|
|
}
|