using System; using System.Text; using System.Threading; using ADOFAIRenderer.Core; using TMPro; using UnityEngine; using UnityEngine.UI; namespace ADOFAIRenderer.UI; internal class DebugMonitorUI : MonoBehaviour { // --- Progress Bar UI Configuration Constants --- private const float BarWidth = 800f; private const float BarHeight = 28f; private const float BarPosX = 0f; private const float BarPosY = -420f; // Y position relative to screen center (Reference: 1920x1080) private const int BarTextFontSize = 16; // Increased font size for visibility private static readonly Color BarBackgroundColor = new(0.08f, 0.08f, 0.1f, 1.0f); private static readonly Color BarFillColor = new(0.0f, 0.8f, 1.0f, 1.0f); // Sleek cyan/blue private static readonly Color BarTextColor = new(1.0f, 1.0f, 1.0f, 1.0f); // --- Progress Bar Outline Configuration Constants --- private static readonly Color BarOutlineColor = Color.white; // Contrasting white outline private static readonly Vector2 BarOutlineDistance = new(3.0f, -3.0f); // Outline thickness private TextMeshProUGUI _text = null!; private GameObject _progressBarObj = null!; private GameObject _progressBarFillObj = null!; private RectTransform _fillRect = null!; private TextMeshProUGUI _progressText = null!; private void Start() { // Set UI layer (5) gameObject.layer = 5; // Canvas setup var canvas = gameObject.AddComponent(); canvas.renderMode = RenderMode.ScreenSpaceOverlay; canvas.sortingOrder = 9999; // Dynamic resolution scaling setup (Reference: 1920x1080) var scaler = gameObject.AddComponent(); scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; scaler.referenceResolution = new Vector2(1920, 1080); scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight; scaler.matchWidthOrHeight = 0.5f; gameObject.AddComponent(); // Create background panel var panelObj = new GameObject("BackgroundPanel"); panelObj.transform.SetParent(transform, false); panelObj.layer = 5; var image = panelObj.AddComponent(); image.color = new Color(0.08f, 0.08f, 0.1f, 0.88f); // Dark tone acrylic style var panelRect = panelObj.GetComponent(); panelRect.anchorMin = new Vector2(1, 1); panelRect.anchorMax = new Vector2(1, 1); panelRect.pivot = new Vector2(1, 1); panelRect.anchoredPosition = new Vector2(-30, -30); panelRect.sizeDelta = new Vector2(360, 220); // Create text var textObj = new GameObject("MonitorText"); textObj.transform.SetParent(panelObj.transform, false); textObj.layer = 5; _text = textObj.AddComponent(); _text.richText = true; _text.fontSize = 16; _text.alignment = TextAlignmentOptions.TopLeft; // Prevent TMPro text clipping _text.textWrappingMode = TextWrappingModes.Normal; _text.overflowMode = TextOverflowModes.Overflow; // Load and apply font _text.font = ModAssets.NanumSquareNeoNormal; var textRect = textObj.GetComponent(); textRect.anchorMin = Vector2.zero; textRect.anchorMax = Vector2.one; textRect.offsetMin = new Vector2(20, 20); // Padding margin textRect.offsetMax = new Vector2(-20, -20); // --- Progress Bar UI Setup --- // 1. Progress Bar Container _progressBarObj = new GameObject("ProgressBar"); _progressBarObj.transform.SetParent(transform, false); _progressBarObj.layer = 5; var bgImage = _progressBarObj.AddComponent(); bgImage.color = BarBackgroundColor; // Add progress bar outline component var bgOutline = _progressBarObj.AddComponent(); bgOutline.effectColor = BarOutlineColor; bgOutline.effectDistance = BarOutlineDistance; var barRect = _progressBarObj.GetComponent(); barRect.anchorMin = new Vector2(0.5f, 0.5f); barRect.anchorMax = new Vector2(0.5f, 0.5f); barRect.pivot = new Vector2(0.5f, 0.5f); barRect.anchoredPosition = new Vector2(BarPosX, BarPosY); barRect.sizeDelta = new Vector2(BarWidth, BarHeight); // 2. Progress Bar Fill _progressBarFillObj = new GameObject("ProgressBarFill"); _progressBarFillObj.transform.SetParent(_progressBarObj.transform, false); _progressBarFillObj.layer = 5; var fillImage = _progressBarFillObj.AddComponent(); fillImage.color = BarFillColor; _fillRect = _progressBarFillObj.GetComponent(); _fillRect.anchorMin = new Vector2(0, 0); _fillRect.anchorMax = new Vector2(0, 1); _fillRect.pivot = new Vector2(0, 0.5f); _fillRect.anchoredPosition = Vector2.zero; _fillRect.sizeDelta = new Vector2(0, 0); // width will be updated dynamically in Update() // 3. Progress Bar Text var progressTextObj = new GameObject("ProgressBarText"); progressTextObj.transform.SetParent(_progressBarObj.transform, false); progressTextObj.layer = 5; _progressText = progressTextObj.AddComponent(); _progressText.richText = true; _progressText.fontSize = BarTextFontSize; _progressText.alignment = TextAlignmentOptions.Center; _progressText.font = ModAssets.NanumSquareNeoNormal; _progressText.color = BarTextColor; // Add progress bar text outline for readability var textOutline = progressTextObj.AddComponent(); textOutline.effectColor = new Color(0f, 0f, 0f, 0.9f); textOutline.effectDistance = new Vector2(1.5f, -1.5f); var textRectBar = progressTextObj.GetComponent(); textRectBar.anchorMin = Vector2.zero; textRectBar.anchorMax = Vector2.one; textRectBar.offsetMin = Vector2.zero; textRectBar.offsetMax = Vector2.zero; } private void Update() { if (!_text) return; var sb = new StringBuilder(); sb.AppendLine("ADOFAI Renderer Realtime Monitor"); sb.AppendLine(); var queueCount = 0; if (RenderManager.Instance) { lock (RenderManager.Instance.ImageQueue) { queueCount = RenderManager.Instance.ImageQueue.Count; } } sb.AppendLine($"• Queue: {queueCount} / {(RenderManager.Instance ? RenderManager.Instance.QueueFrameLimit : RenderManager.MaxQueuedFrames)} frames"); sb.AppendLine($"• Rendered Frames: {(RenderManager.Instance ? RenderManager.Instance.frameCount : 0)}"); sb.AppendLine($"• Frames Sent: {(RenderManager.Instance ? Interlocked.Read(ref RenderManager.Instance.framesSent) : 0)}"); sb.AppendLine(); sb.AppendLine($"• Throttling Controls: {(RenderManager.Instance ? RenderManager.Instance.throttleCount : 0)} times"); sb.AppendLine($"• Readback Hard Failures: {(RenderManager.Instance ? RenderManager.Instance.readbackFailureCount : 0)} times"); var memoryMb = GC.GetTotalMemory(false) / (1024.0 * 1024.0); sb.AppendLine($"• Mono Heap Memory: {memoryMb:F2} MB"); _text.text = sb.ToString(); // Update Progress Bar var progress = 0f; var currentFloor = 0; var totalFloors = 0; if (scrController.instance && ADOBase.lm && ADOBase.lm.listFloors != null) { currentFloor = scrController.instance.currFloor ? scrController.instance.currFloor.seqID : 0; totalFloors = ADOBase.lm.listFloors.Count - 1; if (totalFloors > 0) { progress = Mathf.Clamp01((float)currentFloor / totalFloors); } } if (_fillRect) _fillRect.sizeDelta = new Vector2(BarWidth * progress, 0); if (_progressText) _progressText.text = $"{progress * 100f:F1}% ({currentFloor}/{totalFloors})"; } }