783 lines
30 KiB
C#
783 lines
30 KiB
C#
using UnityEngine;
|
|
using TMPro;
|
|
using UnityEngine.UI;
|
|
using UnityEngine.EventSystems;
|
|
using System.Collections.Generic;
|
|
using System;
|
|
using System.Linq;
|
|
using System.Collections;
|
|
|
|
namespace Streamingle.Debug
|
|
{
|
|
public class StreamingleDebugWindow : MonoBehaviour
|
|
{
|
|
private static StreamingleDebugWindow instance;
|
|
public static StreamingleDebugWindow Instance
|
|
{
|
|
get
|
|
{
|
|
if (instance == null)
|
|
{
|
|
var go = new GameObject("StreamingleDebugWindow");
|
|
DontDestroyOnLoad(go);
|
|
instance = go.AddComponent<StreamingleDebugWindow>();
|
|
instance.CreateDebugUI();
|
|
}
|
|
return instance;
|
|
}
|
|
}
|
|
|
|
private Dictionary<StreamingleAvatarImport, System.Action> importers = new Dictionary<StreamingleAvatarImport, System.Action>();
|
|
private StreamingleAvatarImport selectedImporter;
|
|
|
|
private Canvas debugCanvas;
|
|
private TextMeshProUGUI debugText;
|
|
private TMP_Dropdown importerDropdown;
|
|
private bool showDebugUI = false; // 기본값을 false로 변경
|
|
private GameObject debugPanel;
|
|
private Vector2 dragStartPosition;
|
|
private bool isDragging = false;
|
|
private RectTransform containerRect;
|
|
|
|
private TMP_FontAsset nanumGothicFont;
|
|
|
|
private Vector2 savedPosition;
|
|
private bool isPositionInitialized = false;
|
|
|
|
public static StreamingleDebugWindow Create(StreamingleAvatarImport importer, System.Action loadCallback)
|
|
{
|
|
if (instance == null)
|
|
{
|
|
var go = new GameObject("StreamingleDebugWindow");
|
|
DontDestroyOnLoad(go);
|
|
instance = go.AddComponent<StreamingleDebugWindow>();
|
|
instance.CreateDebugUI();
|
|
}
|
|
|
|
instance.RegisterImporter(importer, loadCallback);
|
|
return instance;
|
|
}
|
|
|
|
private void CreateDebugUI()
|
|
{
|
|
// 캔버스 생성
|
|
GameObject canvasObj = new GameObject("StreamingleDebugCanvas");
|
|
canvasObj.transform.SetParent(this.transform, false);
|
|
debugCanvas = canvasObj.AddComponent<Canvas>();
|
|
debugCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
|
debugCanvas.sortingOrder = 10000;
|
|
|
|
CanvasScaler scaler = canvasObj.AddComponent<CanvasScaler>();
|
|
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
|
scaler.referenceResolution = new Vector2(1920, 1080);
|
|
canvasObj.AddComponent<GraphicRaycaster>();
|
|
|
|
// UI 컨테이너
|
|
GameObject containerObj = new GameObject("DebugContainer");
|
|
containerObj.transform.SetParent(debugCanvas.transform, false);
|
|
|
|
containerRect = containerObj.AddComponent<RectTransform>();
|
|
containerRect.anchorMin = new Vector2(0.5f, 0.5f);
|
|
containerRect.anchorMax = new Vector2(0.5f, 0.5f);
|
|
containerRect.pivot = new Vector2(0.5f, 0.5f);
|
|
containerRect.anchoredPosition = Vector2.zero;
|
|
|
|
// 디버그 패널
|
|
debugPanel = CreateDebugPanel();
|
|
debugPanel.transform.SetParent(containerRect, false);
|
|
|
|
// UI 요소들 생성
|
|
CreateDragArea();
|
|
CreateImporterSelector();
|
|
CreateDebugText();
|
|
CreateLoadButton();
|
|
|
|
// 초기 상태를 숨김으로 설정
|
|
debugPanel.SetActive(false);
|
|
|
|
// 토글 버튼만 보이도록 설정
|
|
CreateToggleButton();
|
|
|
|
// 초기 위치 설정 (한 번만 설정)
|
|
if (debugPanel != null)
|
|
{
|
|
var rectTransform = debugPanel.GetComponent<RectTransform>();
|
|
rectTransform.anchorMin = new Vector2(0, 1);
|
|
rectTransform.anchorMax = new Vector2(0, 1);
|
|
rectTransform.pivot = new Vector2(0, 1);
|
|
|
|
if (!isPositionInitialized)
|
|
{
|
|
savedPosition = new Vector2(10, -10);
|
|
isPositionInitialized = true;
|
|
}
|
|
|
|
rectTransform.anchoredPosition = savedPosition;
|
|
}
|
|
|
|
UpdateDebugStatus();
|
|
}
|
|
|
|
private GameObject CreateDebugPanel()
|
|
{
|
|
GameObject panel = new GameObject("DebugPanel");
|
|
Image panelImage = panel.AddComponent<Image>();
|
|
panelImage.color = new Color(0, 0, 0, 0.8f);
|
|
|
|
RectTransform panelRect = panel.GetComponent<RectTransform>();
|
|
panelRect.sizeDelta = new Vector2(300, 250); // 크기 증가
|
|
|
|
return panel;
|
|
}
|
|
|
|
private void CreateDebugText()
|
|
{
|
|
GameObject textObj = new GameObject("DebugText");
|
|
textObj.transform.SetParent(debugPanel.transform, false);
|
|
|
|
debugText = textObj.AddComponent<TextMeshProUGUI>();
|
|
debugText.font = nanumGothicFont;
|
|
debugText.fontSize = 12;
|
|
debugText.color = Color.white;
|
|
debugText.alignment = TextAlignmentOptions.Left;
|
|
|
|
RectTransform textRect = textObj.GetComponent<RectTransform>();
|
|
textRect.anchorMin = new Vector2(0, 0);
|
|
textRect.anchorMax = new Vector2(1, 1);
|
|
textRect.offsetMin = new Vector2(10, 40); // 하단 버튼 위 여백
|
|
textRect.offsetMax = new Vector2(-10, -65); // 드롭다운 아래 여백
|
|
}
|
|
|
|
private void CreateImporterSelector()
|
|
{
|
|
GameObject dropdownObj = new GameObject("ImporterSelector");
|
|
dropdownObj.transform.SetParent(debugPanel.transform, false);
|
|
|
|
// 배경 이미지 개선
|
|
var image = dropdownObj.AddComponent<Image>();
|
|
image.color = new Color(0.2f, 0.2f, 0.2f, 0.95f);
|
|
|
|
importerDropdown = dropdownObj.AddComponent<TMP_Dropdown>();
|
|
|
|
// 드롭다운 위치 및 크기 조정
|
|
RectTransform rect = dropdownObj.GetComponent<RectTransform>();
|
|
rect.anchorMin = new Vector2(0, 1);
|
|
rect.anchorMax = new Vector2(1, 1);
|
|
rect.sizeDelta = new Vector2(-20, 35); // 높이 증가
|
|
rect.anchoredPosition = new Vector2(0, -35);
|
|
|
|
// 캡션 텍스트 개선
|
|
GameObject captionObj = new GameObject("Caption");
|
|
captionObj.transform.SetParent(dropdownObj.transform, false);
|
|
|
|
var captionText = captionObj.AddComponent<TextMeshProUGUI>();
|
|
captionText.font = nanumGothicFont;
|
|
captionText.fontSize = 14;
|
|
captionText.color = Color.white;
|
|
captionText.alignment = TextAlignmentOptions.Left;
|
|
|
|
RectTransform captionRect = captionObj.GetComponent<RectTransform>();
|
|
captionRect.anchorMin = Vector2.zero;
|
|
captionRect.anchorMax = Vector2.one;
|
|
captionRect.offsetMin = new Vector2(15, 2);
|
|
captionRect.offsetMax = new Vector2(-35, -2);
|
|
|
|
importerDropdown.captionText = captionText;
|
|
|
|
// 화살표 개선
|
|
GameObject arrowObj = new GameObject("Arrow");
|
|
arrowObj.transform.SetParent(dropdownObj.transform, false);
|
|
|
|
var arrowText = arrowObj.AddComponent<TextMeshProUGUI>();
|
|
arrowText.font = nanumGothicFont;
|
|
arrowText.text = "▼";
|
|
arrowText.fontSize = 12;
|
|
arrowText.color = new Color(1f, 1f, 1f, 0.8f);
|
|
arrowText.alignment = TextAlignmentOptions.Center;
|
|
|
|
RectTransform arrowRect = arrowObj.GetComponent<RectTransform>();
|
|
arrowRect.anchorMin = new Vector2(1, 0);
|
|
arrowRect.anchorMax = new Vector2(1, 1);
|
|
arrowRect.pivot = new Vector2(1, 0.5f);
|
|
arrowRect.sizeDelta = new Vector2(25, 0);
|
|
arrowRect.anchoredPosition = new Vector2(-10, 0);
|
|
|
|
// 드롭다운 템플릿 생성
|
|
CreateDropdownTemplate(importerDropdown);
|
|
importerDropdown.onValueChanged.RemoveAllListeners();
|
|
importerDropdown.onValueChanged.AddListener((index) =>
|
|
{
|
|
// 위치 저장
|
|
if (debugPanel != null)
|
|
{
|
|
savedPosition = debugPanel.GetComponent<RectTransform>().anchoredPosition;
|
|
}
|
|
|
|
if (index >= 0 && index < importers.Count)
|
|
{
|
|
var selectedKey = importers.Keys.ElementAt(index);
|
|
if (selectedKey != selectedImporter)
|
|
{
|
|
selectedImporter = selectedKey;
|
|
UpdateDebugStatus();
|
|
}
|
|
}
|
|
|
|
// 위치 복원
|
|
if (debugPanel != null)
|
|
{
|
|
debugPanel.GetComponent<RectTransform>().anchoredPosition = savedPosition;
|
|
}
|
|
});
|
|
|
|
// 호버 효과 추가
|
|
var trigger = dropdownObj.AddComponent<EventTrigger>();
|
|
|
|
var pointerEnter = new EventTrigger.Entry { eventID = EventTriggerType.PointerEnter };
|
|
pointerEnter.callback.AddListener((data) =>
|
|
{
|
|
image.color = new Color(0.25f, 0.25f, 0.25f, 0.95f);
|
|
arrowText.color = Color.white;
|
|
});
|
|
trigger.triggers.Add(pointerEnter);
|
|
|
|
var pointerExit = new EventTrigger.Entry { eventID = EventTriggerType.PointerExit };
|
|
pointerExit.callback.AddListener((data) =>
|
|
{
|
|
image.color = new Color(0.2f, 0.2f, 0.2f, 0.95f);
|
|
arrowText.color = new Color(1f, 1f, 1f, 0.8f);
|
|
});
|
|
trigger.triggers.Add(pointerExit);
|
|
|
|
// 초기 옵션 설정
|
|
UpdateDropdownOptions();
|
|
}
|
|
|
|
private void CreateDropdownTemplate(TMP_Dropdown dropdown)
|
|
{
|
|
if (dropdown == null) return;
|
|
|
|
// 템플릿 생성
|
|
var template = new GameObject("Template");
|
|
template.SetActive(false);
|
|
template.transform.SetParent(dropdown.transform, false);
|
|
|
|
var templateRect = template.AddComponent<RectTransform>();
|
|
templateRect.anchorMin = new Vector2(0, 0);
|
|
templateRect.anchorMax = new Vector2(1, 0);
|
|
templateRect.pivot = new Vector2(0.5f, 1);
|
|
templateRect.anchoredPosition = new Vector2(0, 0);
|
|
templateRect.sizeDelta = new Vector2(0, 150);
|
|
|
|
// 템플릿 배경
|
|
var templateBg = template.AddComponent<Image>();
|
|
templateBg.color = new Color(0.1f, 0.1f, 0.1f, 0.95f);
|
|
|
|
// 스크롤 뷰 생성
|
|
var scrollView = new GameObject("Scroll View");
|
|
scrollView.transform.SetParent(template.transform, false);
|
|
var scrollRect = scrollView.AddComponent<ScrollRect>();
|
|
var scrollRectTransform = scrollView.GetComponent<RectTransform>();
|
|
scrollRectTransform.anchorMin = Vector2.zero;
|
|
scrollRectTransform.anchorMax = Vector2.one;
|
|
scrollRectTransform.sizeDelta = Vector2.zero;
|
|
|
|
// 뷰포트 생성
|
|
var viewport = new GameObject("Viewport");
|
|
viewport.transform.SetParent(scrollView.transform, false);
|
|
var viewportRect = viewport.AddComponent<RectTransform>();
|
|
viewportRect.anchorMin = Vector2.zero;
|
|
viewportRect.anchorMax = Vector2.one;
|
|
viewportRect.sizeDelta = Vector2.zero;
|
|
viewport.AddComponent<Mask>();
|
|
var viewportImage = viewport.AddComponent<Image>();
|
|
viewportImage.color = new Color(0.15f, 0.15f, 0.15f, 1f);
|
|
|
|
// 컨텐츠 생성
|
|
var content = new GameObject("Content");
|
|
content.transform.SetParent(viewport.transform, false);
|
|
var contentRect = content.AddComponent<RectTransform>();
|
|
contentRect.anchorMin = new Vector2(0, 1);
|
|
contentRect.anchorMax = new Vector2(1, 1);
|
|
contentRect.pivot = new Vector2(0.5f, 1);
|
|
contentRect.sizeDelta = new Vector2(0, 28);
|
|
|
|
// 스크롤렉트 설정
|
|
scrollRect.content = contentRect;
|
|
scrollRect.viewport = viewportRect;
|
|
scrollRect.horizontal = false;
|
|
scrollRect.movementType = ScrollRect.MovementType.Clamped;
|
|
scrollRect.verticalScrollbarVisibility = ScrollRect.ScrollbarVisibility.AutoHide;
|
|
|
|
// 아이템 생성
|
|
var item = new GameObject("Item");
|
|
item.transform.SetParent(content.transform, false);
|
|
|
|
var itemRect = item.AddComponent<RectTransform>();
|
|
itemRect.anchorMin = new Vector2(0, 1);
|
|
itemRect.anchorMax = new Vector2(1, 1);
|
|
itemRect.pivot = new Vector2(0.5f, 1);
|
|
itemRect.sizeDelta = new Vector2(0, 28);
|
|
|
|
// 아이템 토글
|
|
var toggle = item.AddComponent<Toggle>();
|
|
var itemBg = item.AddComponent<Image>();
|
|
itemBg.color = Color.clear;
|
|
toggle.targetGraphic = itemBg;
|
|
toggle.transition = Selectable.Transition.ColorTint;
|
|
var colors = toggle.colors;
|
|
colors.normalColor = Color.clear;
|
|
colors.highlightedColor = new Color(1, 1, 1, 0.1f);
|
|
colors.pressedColor = new Color(1, 1, 1, 0.2f);
|
|
colors.selectedColor = new Color(0.3f, 0.3f, 0.3f, 1f);
|
|
toggle.colors = colors;
|
|
|
|
// 아이템 텍스트
|
|
var itemLabel = new GameObject("Item Label");
|
|
itemLabel.transform.SetParent(item.transform, false);
|
|
var itemLabelRect = itemLabel.AddComponent<RectTransform>();
|
|
itemLabelRect.anchorMin = Vector2.zero;
|
|
itemLabelRect.anchorMax = Vector2.one;
|
|
itemLabelRect.offsetMin = new Vector2(10, 0);
|
|
itemLabelRect.offsetMax = new Vector2(-10, 0);
|
|
|
|
var itemText = itemLabel.AddComponent<TextMeshProUGUI>();
|
|
itemText.font = nanumGothicFont;
|
|
itemText.fontSize = 14;
|
|
itemText.color = Color.white;
|
|
itemText.alignment = TextAlignmentOptions.Left;
|
|
|
|
// 드롭다운 설정
|
|
dropdown.template = templateRect;
|
|
dropdown.itemText = itemText;
|
|
|
|
// 캡션 텍스트 설정
|
|
var captionText = dropdown.captionText;
|
|
if (captionText != null)
|
|
{
|
|
captionText.font = nanumGothicFont;
|
|
captionText.fontSize = 14;
|
|
captionText.color = Color.white;
|
|
}
|
|
}
|
|
|
|
private void UpdateDropdownOptions()
|
|
{
|
|
if (importerDropdown == null) return;
|
|
|
|
// 옵션을 오름차순으로 정렬된 리스트로 생성
|
|
var sortedOptions = importers.Keys
|
|
.Where(importer => importer != null)
|
|
.Select(importer => importer.gameObject.name)
|
|
.OrderBy(name => name)
|
|
.Select(name => new TMP_Dropdown.OptionData(name))
|
|
.ToList();
|
|
|
|
// 드롭다운 이벤트 일시 중지
|
|
importerDropdown.onValueChanged.RemoveAllListeners();
|
|
|
|
// 옵션 업데이트
|
|
importerDropdown.ClearOptions();
|
|
importerDropdown.AddOptions(sortedOptions);
|
|
|
|
// 첫 번째 아이템 선택
|
|
if (sortedOptions.Count > 0)
|
|
{
|
|
importerDropdown.value = 0;
|
|
var firstImporterName = sortedOptions[0].text;
|
|
selectedImporter = importers.Keys.FirstOrDefault(
|
|
importer => importer != null &&
|
|
importer.gameObject.name == firstImporterName
|
|
);
|
|
|
|
if (selectedImporter != null)
|
|
{
|
|
UpdateDebugStatus();
|
|
}
|
|
}
|
|
|
|
// 드롭다운 이벤트 재설정
|
|
importerDropdown.onValueChanged.AddListener((index) =>
|
|
{
|
|
if (index >= 0 && index < sortedOptions.Count)
|
|
{
|
|
var selectedName = sortedOptions[index].text;
|
|
var selectedKey = importers.Keys.FirstOrDefault(
|
|
importer => importer != null &&
|
|
importer.gameObject.name == selectedName
|
|
);
|
|
|
|
if (selectedKey != null && selectedKey != selectedImporter)
|
|
{
|
|
selectedImporter = selectedKey;
|
|
UpdateDebugStatus();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
public void RegisterImporter(StreamingleAvatarImport importer, System.Action loadCallback)
|
|
{
|
|
if (!importers.ContainsKey(importer))
|
|
{
|
|
importers.Add(importer, loadCallback);
|
|
if (selectedImporter == null)
|
|
{
|
|
selectedImporter = importer;
|
|
}
|
|
UpdateDropdownOptions();
|
|
UpdateDebugStatus();
|
|
}
|
|
}
|
|
|
|
public void UnregisterImporter(StreamingleAvatarImport importer)
|
|
{
|
|
if (importers.ContainsKey(importer))
|
|
{
|
|
importers.Remove(importer);
|
|
if (selectedImporter == importer)
|
|
{
|
|
selectedImporter = importers.Keys.FirstOrDefault();
|
|
}
|
|
UpdateDropdownOptions();
|
|
UpdateDebugStatus();
|
|
}
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
// Resources 폴더 기준으로 경로 수정
|
|
nanumGothicFont = Resources.Load<TMP_FontAsset>("Fonts/SDF/NanumGothic SDF");
|
|
if (nanumGothicFont == null)
|
|
{
|
|
UnityEngine.Debug.LogError("나눔고딕 폰트를 찾을 수 없습니다: Resources/Fonts/SDF/NanumGothic SDF");
|
|
}
|
|
}
|
|
|
|
public void UpdateImporterStatus(string status)
|
|
{
|
|
UpdateDebugStatus();
|
|
}
|
|
|
|
public void UpdateDebugStatus()
|
|
{
|
|
if (debugPanel == null) return;
|
|
|
|
// 현재 위치 저장
|
|
savedPosition = debugPanel.GetComponent<RectTransform>().anchoredPosition;
|
|
|
|
if (debugText != null)
|
|
{
|
|
string text = "Streamingle 디버그 정보\n";
|
|
text += "-------------------\n";
|
|
text += $"등록된 임포터: {importers.Count}개\n\n";
|
|
|
|
if (selectedImporter != null)
|
|
{
|
|
text += $"[{selectedImporter.gameObject.name}]\n";
|
|
var avatars = selectedImporter.GetLoadedAvatars();
|
|
if (avatars.Count == 0)
|
|
{
|
|
text += "- 로드된 아바타 없음\n";
|
|
}
|
|
else
|
|
{
|
|
foreach (var avatar in avatars)
|
|
{
|
|
text += $"- {avatar.Key}: {(avatar.Value != null ? "로드됨" : "없음")}\n";
|
|
|
|
if (avatar.Value != null)
|
|
{
|
|
var renderers = avatar.Value.GetComponentsInChildren<SkinnedMeshRenderer>();
|
|
int totalVertices = 0;
|
|
int totalBlendShapes = 0;
|
|
|
|
foreach (var renderer in renderers)
|
|
{
|
|
totalVertices += renderer.sharedMesh.vertexCount;
|
|
totalBlendShapes += renderer.sharedMesh.blendShapeCount;
|
|
}
|
|
|
|
text += $" 메시 수: {renderers.Length}\n";
|
|
text += $" 총 버텍스: {totalVertices:N0}\n";
|
|
text += $" 총 블렌드쉐입: {totalBlendShapes:N0}\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
text += "선택된 임포터 없음\n";
|
|
}
|
|
|
|
debugText.text = text;
|
|
}
|
|
|
|
// 위치 복원
|
|
debugPanel.GetComponent<RectTransform>().anchoredPosition = savedPosition;
|
|
}
|
|
|
|
private void CreateDragArea()
|
|
{
|
|
GameObject dragAreaObj = new GameObject("DragArea");
|
|
dragAreaObj.transform.SetParent(debugPanel.transform, false);
|
|
|
|
Image dragAreaImage = dragAreaObj.AddComponent<Image>();
|
|
dragAreaImage.color = new Color(0.3f, 0.3f, 0.3f, 0.8f);
|
|
|
|
RectTransform dragAreaRect = dragAreaObj.GetComponent<RectTransform>();
|
|
dragAreaRect.anchorMin = new Vector2(0, 1);
|
|
dragAreaRect.anchorMax = new Vector2(1, 1);
|
|
dragAreaRect.sizeDelta = new Vector2(0, 25);
|
|
dragAreaRect.anchoredPosition = new Vector2(0, 25);
|
|
|
|
// 드래그 이벤트
|
|
EventTrigger trigger = dragAreaObj.AddComponent<EventTrigger>();
|
|
|
|
var beginDrag = new EventTrigger.Entry { eventID = EventTriggerType.BeginDrag };
|
|
beginDrag.callback.AddListener((data) => { OnBeginDrag((PointerEventData)data); });
|
|
trigger.triggers.Add(beginDrag);
|
|
|
|
var drag = new EventTrigger.Entry { eventID = EventTriggerType.Drag };
|
|
drag.callback.AddListener((data) => { OnDrag((PointerEventData)data); });
|
|
trigger.triggers.Add(drag);
|
|
|
|
var endDrag = new EventTrigger.Entry { eventID = EventTriggerType.EndDrag };
|
|
endDrag.callback.AddListener((data) => { OnEndDrag((PointerEventData)data); });
|
|
trigger.triggers.Add(endDrag);
|
|
|
|
// 드래그 영역 텍스트
|
|
CreateDragAreaText(dragAreaRect);
|
|
}
|
|
|
|
private void CreateDragAreaText(RectTransform parent)
|
|
{
|
|
GameObject textObj = new GameObject("DragText");
|
|
textObj.transform.SetParent(parent, false);
|
|
|
|
TextMeshProUGUI text = textObj.AddComponent<TextMeshProUGUI>();
|
|
text.font = nanumGothicFont;
|
|
text.fontSize = 12;
|
|
text.text = "● Streamingle Debug";
|
|
text.alignment = TextAlignmentOptions.Left;
|
|
text.color = Color.white;
|
|
|
|
RectTransform textRect = text.GetComponent<RectTransform>();
|
|
textRect.anchorMin = Vector2.zero;
|
|
textRect.anchorMax = Vector2.one;
|
|
textRect.offsetMin = new Vector2(5, 0);
|
|
textRect.offsetMax = new Vector2(-5, 0);
|
|
}
|
|
|
|
private void CreateLoadButton()
|
|
{
|
|
GameObject buttonObj = new GameObject("LoadButton");
|
|
buttonObj.transform.SetParent(debugPanel.transform, false);
|
|
|
|
Button loadButton = buttonObj.AddComponent<Button>();
|
|
Image buttonImage = buttonObj.AddComponent<Image>();
|
|
buttonImage.color = new Color(0.2f, 0.2f, 0.2f, 1f);
|
|
|
|
RectTransform buttonRect = buttonObj.GetComponent<RectTransform>();
|
|
buttonRect.anchorMin = new Vector2(0, 0);
|
|
buttonRect.anchorMax = new Vector2(1, 0);
|
|
buttonRect.pivot = new Vector2(0.5f, 0);
|
|
buttonRect.sizeDelta = new Vector2(-20, 30);
|
|
buttonRect.anchoredPosition = new Vector2(0, 5);
|
|
|
|
// 버튼 텍스트
|
|
GameObject textObj = new GameObject("LoadButtonText");
|
|
textObj.transform.SetParent(buttonRect, false);
|
|
|
|
TextMeshProUGUI buttonText = textObj.AddComponent<TextMeshProUGUI>();
|
|
buttonText.font = nanumGothicFont;
|
|
buttonText.fontSize = 14;
|
|
buttonText.text = "아바타 로드";
|
|
buttonText.alignment = TextAlignmentOptions.Center;
|
|
buttonText.color = Color.white;
|
|
|
|
RectTransform textRect = buttonText.GetComponent<RectTransform>();
|
|
textRect.anchorMin = Vector2.zero;
|
|
textRect.anchorMax = Vector2.one;
|
|
textRect.offsetMin = Vector2.zero;
|
|
textRect.offsetMax = Vector2.zero;
|
|
|
|
loadButton.onClick.AddListener(() =>
|
|
{
|
|
if (selectedImporter != null && importers.TryGetValue(selectedImporter, out var callback))
|
|
{
|
|
callback?.Invoke();
|
|
}
|
|
});
|
|
}
|
|
|
|
private void CreateToggleButton()
|
|
{
|
|
GameObject toggleObj = new GameObject("DebugToggle");
|
|
toggleObj.transform.SetParent(debugCanvas.transform, false);
|
|
|
|
Button toggleButton = toggleObj.AddComponent<Button>();
|
|
Image toggleImage = toggleObj.AddComponent<Image>();
|
|
toggleImage.color = new Color(0, 0, 0, 0.8f);
|
|
|
|
RectTransform toggleRect = toggleObj.GetComponent<RectTransform>();
|
|
toggleRect.sizeDelta = new Vector2(30, 30);
|
|
toggleRect.anchorMin = new Vector2(1, 1);
|
|
toggleRect.anchorMax = new Vector2(1, 1);
|
|
toggleRect.pivot = new Vector2(1, 1);
|
|
toggleRect.anchoredPosition = new Vector2(-10, -10);
|
|
|
|
// 토글 텍스트
|
|
GameObject textObj = new GameObject("ToggleText");
|
|
textObj.transform.SetParent(toggleRect, false);
|
|
|
|
TextMeshProUGUI toggleText = textObj.AddComponent<TextMeshProUGUI>();
|
|
toggleText.font = nanumGothicFont;
|
|
toggleText.fontSize = 16;
|
|
toggleText.text = "D";
|
|
toggleText.alignment = TextAlignmentOptions.Center;
|
|
toggleText.color = Color.white;
|
|
|
|
RectTransform textRect = toggleText.GetComponent<RectTransform>();
|
|
textRect.anchorMin = Vector2.zero;
|
|
textRect.anchorMax = Vector2.one;
|
|
textRect.offsetMin = Vector2.zero;
|
|
textRect.offsetMax = Vector2.zero;
|
|
|
|
// 호버 효과 추가
|
|
var trigger = toggleObj.AddComponent<EventTrigger>();
|
|
|
|
var pointerEnter = new EventTrigger.Entry { eventID = EventTriggerType.PointerEnter };
|
|
pointerEnter.callback.AddListener((data) =>
|
|
{
|
|
toggleImage.color = new Color(0.25f, 0.25f, 0.25f, 0.9f);
|
|
});
|
|
trigger.triggers.Add(pointerEnter);
|
|
|
|
var pointerExit = new EventTrigger.Entry { eventID = EventTriggerType.PointerExit };
|
|
pointerExit.callback.AddListener((data) =>
|
|
{
|
|
toggleImage.color = new Color(0, 0, 0, 0.8f);
|
|
});
|
|
trigger.triggers.Add(pointerExit);
|
|
|
|
toggleButton.onClick.AddListener(ToggleDebugUI);
|
|
}
|
|
|
|
private void ToggleDebugUI()
|
|
{
|
|
if (debugPanel != null)
|
|
{
|
|
showDebugUI = !showDebugUI;
|
|
debugPanel.SetActive(showDebugUI);
|
|
|
|
// UI가 표시될 때 상태 업데이트
|
|
if (showDebugUI)
|
|
{
|
|
UpdateDebugStatus();
|
|
UpdateDropdownOptions();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnBeginDrag(PointerEventData eventData)
|
|
{
|
|
isDragging = true;
|
|
dragStartPosition = containerRect.position - new Vector3(eventData.position.x, eventData.position.y, 0);
|
|
}
|
|
|
|
private void OnDrag(PointerEventData eventData)
|
|
{
|
|
if (isDragging)
|
|
{
|
|
Vector3 mousePosition = new Vector3(eventData.position.x, eventData.position.y, 0);
|
|
Vector3 newPosition = mousePosition + (Vector3)dragStartPosition;
|
|
containerRect.position = newPosition;
|
|
}
|
|
}
|
|
|
|
private void OnEndDrag(PointerEventData eventData)
|
|
{
|
|
isDragging = false;
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (containerRect == null || debugPanel == null) return;
|
|
if (!debugPanel.activeSelf) return;
|
|
|
|
var panelRect = debugPanel.GetComponent<RectTransform>();
|
|
if (panelRect == null) return;
|
|
|
|
var dragArea = debugPanel.transform.Find("DragArea");
|
|
if (dragArea == null) return;
|
|
|
|
var dragAreaRect = dragArea.GetComponent<RectTransform>();
|
|
if (dragAreaRect == null) return;
|
|
|
|
Vector3[] panelCorners = new Vector3[4];
|
|
Vector3[] dragAreaCorners = new Vector3[4];
|
|
panelRect.GetWorldCorners(panelCorners);
|
|
dragAreaRect.GetWorldCorners(dragAreaCorners);
|
|
|
|
float minX = Mathf.Min(panelCorners[0].x, dragAreaCorners[0].x);
|
|
float maxX = Mathf.Max(panelCorners[2].x, dragAreaCorners[2].x);
|
|
float minY = Mathf.Min(panelCorners[0].y, dragAreaCorners[0].y);
|
|
float maxY = Mathf.Max(panelCorners[1].y, dragAreaCorners[1].y);
|
|
|
|
Vector3 newPosition = containerRect.position;
|
|
bool needsAdjustment = false;
|
|
|
|
if (minX < 0)
|
|
{
|
|
newPosition.x += -minX;
|
|
needsAdjustment = true;
|
|
}
|
|
else if (maxX > Screen.width)
|
|
{
|
|
newPosition.x -= (maxX - Screen.width);
|
|
needsAdjustment = true;
|
|
}
|
|
|
|
if (maxY > Screen.height)
|
|
{
|
|
newPosition.y -= (maxY - Screen.height);
|
|
needsAdjustment = true;
|
|
}
|
|
else if (minY < 0)
|
|
{
|
|
newPosition.y += -minY;
|
|
needsAdjustment = true;
|
|
}
|
|
|
|
if (needsAdjustment)
|
|
{
|
|
containerRect.position = newPosition;
|
|
}
|
|
|
|
// 현재 위치 계속 추적
|
|
savedPosition = debugPanel.GetComponent<RectTransform>().anchoredPosition;
|
|
}
|
|
|
|
internal void UpdateStatus(string v, object value)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
internal void Initialize(Action value)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
// 참조 정리만 수행 (GameObject는 자동으로 정리됨)
|
|
importers.Clear();
|
|
selectedImporter = null;
|
|
debugCanvas = null;
|
|
debugText = null;
|
|
debugPanel = null;
|
|
containerRect = null;
|
|
}
|
|
}
|
|
} |