using System; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.UI; using UnityEngine.UIElements; using Button = UnityEngine.UI.Button; using Image = UnityEngine.UI.Image; namespace ADOFAIRenderer.UI { public class DialogButton { public string Text; public Action OnClick; public Color? BackgroundColor; public DialogButton(string text, Action onClick, Color? backgroundColor = null) { Text = text; OnClick = onClick; BackgroundColor = backgroundColor; } } public class CommonWarningDialogUI : MonoBehaviour { public static CommonWarningDialogUI? Instance { get; private set; } private readonly List _disabledElements = new(); private void Awake() { Instance = this; } private void OnDestroy() { foreach (var elem in _disabledElements) { if (elem != null) { elem.SetEnabled(true); } } _disabledElements.Clear(); if (Instance == this) { Instance = null; } } private static TMP_FontAsset GetNanumSquareNeoBdFontAsset() { TMP_FontAsset? font = null; if (RenderMod.FontBundle) { try { font = RenderMod.FontBundle.LoadAsset("NanumSquareNeoOTF-Bd SDF"); } catch { // 로딩 실패 } } // 폴백 처리 if (!font) { try { font = RDString.fontData.fontTMP; } catch { // ignored } } if (!font) { // ReSharper disable once Unity.UnknownResource font = Resources.Load("Fonts & Materials/LiberationSans SDF"); } if (font) return font; var fonts = Resources.FindObjectsOfTypeAll(); if (fonts.Length > 0) font = fonts[0]; return font!; } public static void ShowDialog(string title, string description, params DialogButton[] buttons) { if (buttons.Length == 0) return; var obj = new GameObject("CommonWarningDialogUI"); DontDestroyOnLoad(obj); var dialog = obj.AddComponent(); dialog.Initialize(title, description, buttons); } private void Initialize(string title, string description, DialogButton[] buttons) { if (!UnityEngine.EventSystems.EventSystem.current) { var eventSystemObj = new GameObject("EventSystem"); eventSystemObj.transform.SetParent(transform); eventSystemObj.AddComponent(); eventSystemObj.AddComponent(); } foreach (var doc in FindObjectsByType(FindObjectsSortMode.None)) { if (doc && doc.rootVisualElement != null && doc.rootVisualElement.enabledSelf) { doc.rootVisualElement.SetEnabled(false); _disabledElements.Add(doc.rootVisualElement); } } // UI 레이어(5) 설정 gameObject.layer = 5; // Canvas 설정 var canvas = gameObject.AddComponent(); canvas.renderMode = RenderMode.ScreenSpaceOverlay; canvas.sortingOrder = 32766; // FFmpegDownloadUI(32767) 바로 아래 // 해상도 대응 캔버스 스케일러 설정 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(); // 1. 전체 화면 오버레이 배경 생성 var bgPanelObj = new GameObject("BackgroundPanel"); bgPanelObj.transform.SetParent(transform, false); bgPanelObj.layer = 5; var bgImage = bgPanelObj.AddComponent(); bgImage.color = new Color(0f, 0f, 0f, 0.65f); // 어두운 투명 오버레이 bgImage.raycastTarget = true; var bgRect = bgPanelObj.GetComponent(); bgRect.anchorMin = Vector2.zero; bgRect.anchorMax = Vector2.one; bgRect.offsetMin = Vector2.zero; bgRect.offsetMax = Vector2.zero; var font = GetNanumSquareNeoBdFontAsset(); // 2. 모달 컨테이너 생성 var modalContainerObj = new GameObject("ModalContainer"); modalContainerObj.transform.SetParent(bgPanelObj.transform, false); modalContainerObj.layer = 5; var modalImage = modalContainerObj.AddComponent(); modalImage.color = new Color(0.08f, 0.08f, 0.1f, 0.88f); // 기존 UI의 배경 톤과 동일 var modalOutline = modalContainerObj.AddComponent(); modalOutline.effectColor = Color.white; modalOutline.effectDistance = new Vector2(3.0f, -3.0f); // 기존 UI 외곽선 스타일 일관성 var modalRect = modalContainerObj.GetComponent(); modalRect.anchorMin = new Vector2(0.5f, 0.5f); modalRect.anchorMax = new Vector2(0.5f, 0.5f); modalRect.pivot = new Vector2(0.5f, 0.5f); modalRect.sizeDelta = new Vector2(650, 360); // 3. 타이틀 텍스트 생성 var titleObj = new GameObject("TitleText"); titleObj.transform.SetParent(modalContainerObj.transform, false); titleObj.layer = 5; var titleText = titleObj.AddComponent(); titleText.text = title; titleText.fontSize = 24; titleText.font = font; titleText.color = new Color(1.0f, 0.8f, 0.2f, 1.0f); // 경고 테마에 맞는 주황/황색 계열 titleText.alignment = TextAlignmentOptions.Center; var titleRect = titleObj.GetComponent(); titleRect.anchorMin = new Vector2(0, 1); titleRect.anchorMax = new Vector2(1, 1); titleRect.pivot = new Vector2(0.5f, 1); titleRect.anchoredPosition = new Vector2(0, -35); titleRect.sizeDelta = new Vector2(0, 40); // 4. 본문 설명 텍스트 생성 var descObj = new GameObject("DescriptionText"); descObj.transform.SetParent(modalContainerObj.transform, false); descObj.layer = 5; var descText = descObj.AddComponent(); descText.text = description; descText.fontSize = 15; descText.font = font; descText.color = new Color(0.85f, 0.85f, 0.85f, 1f); descText.alignment = TextAlignmentOptions.Center; descText.lineSpacing = 8; var descRect = descObj.GetComponent(); descRect.anchorMin = new Vector2(0, 0.5f); descRect.anchorMax = new Vector2(1, 1); descRect.pivot = new Vector2(0.5f, 0.5f); descRect.anchoredPosition = new Vector2(0, -65); descRect.sizeDelta = new Vector2(-40, 120); // 5. 버튼 컨테이너 생성 var buttonContainerObj = new GameObject("ButtonContainer", typeof(RectTransform)); buttonContainerObj.transform.SetParent(modalContainerObj.transform, false); buttonContainerObj.layer = 5; var btnContainerRect = buttonContainerObj.GetComponent(); btnContainerRect.anchorMin = new Vector2(0, 0); btnContainerRect.anchorMax = new Vector2(1, 0); btnContainerRect.pivot = new Vector2(0.5f, 0); btnContainerRect.anchoredPosition = new Vector2(0, 35); btnContainerRect.sizeDelta = new Vector2(0, 50); // 6. 가변 버튼 동적 배치 및 스타일링 float totalWidth = 560f; float spacing = 15f; float buttonHeight = 45f; int numButtons = buttons.Length; float buttonWidth = numButtons == 1 ? 200f : (totalWidth - (spacing * (numButtons - 1))) / numButtons; float startX = numButtons == 1 ? 0 : (-totalWidth / 2f) + (buttonWidth / 2f); for (int i = 0; i < numButtons; i++) { var btnData = buttons[i]; var btnObj = new GameObject($"Button_{i}"); btnObj.transform.SetParent(buttonContainerObj.transform, false); btnObj.layer = 5; // 기본 색상 정의 Color baseColor = btnData.BackgroundColor ?? new Color(0.2f, 0.2f, 0.23f, 1f); // 커스텀 색상 또는 회색톤 기본값 Color hoverColor = ApplyColorBrightness(baseColor, 1.2f); Color pressedColor = ApplyColorBrightness(baseColor, 0.8f); var btnImage = btnObj.AddComponent(); btnImage.color = baseColor; btnImage.raycastTarget = true; var btn = btnObj.AddComponent