813 lines
39 KiB
C#
813 lines
39 KiB
C#
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
using UnityEngine.EventSystems;
|
||
using TMPro;
|
||
|
||
namespace MeowmentDebugTool
|
||
{
|
||
/// <summary>
|
||
/// 运行时UI生成器 - 自动创建调试工具的完整UI
|
||
/// </summary>
|
||
public static class RuntimeUIGenerator
|
||
{
|
||
private const int CANVAS_WIDTH = 1080;
|
||
private const int CANVAS_HEIGHT = 2340;
|
||
|
||
/// <summary>
|
||
/// 创建完整的调试工具UI
|
||
/// </summary>
|
||
public static UniversalDebugTool CreateDebugToolUI()
|
||
{
|
||
// 检查并创建EventSystem
|
||
EnsureEventSystem();
|
||
|
||
// 创建根Canvas
|
||
GameObject canvasObj = new GameObject("UniversalDebugTool_Canvas");
|
||
Canvas canvas = canvasObj.AddComponent<Canvas>();
|
||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||
canvas.sortingOrder = 30000;
|
||
canvas.overrideSorting = true;
|
||
|
||
CanvasScaler scaler = canvasObj.AddComponent<CanvasScaler>();
|
||
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
||
scaler.referenceResolution = new Vector2(CANVAS_WIDTH, CANVAS_HEIGHT);
|
||
scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
|
||
scaler.matchWidthOrHeight = 0.5f;
|
||
|
||
canvasObj.AddComponent<GraphicRaycaster>();
|
||
|
||
// 创建 UniversalDebugTool 组件
|
||
UniversalDebugTool tool = canvasObj.AddComponent<UniversalDebugTool>();
|
||
|
||
// 创建主窗口
|
||
GameObject mainWindow = CreateMainWindow(canvasObj.transform);
|
||
|
||
// 创建悬浮按钮
|
||
GameObject floatingButton = CreateFloatingButton(canvasObj.transform);
|
||
|
||
// 创建标签页
|
||
GameObject tabContainer = mainWindow.transform.Find("TabButtonContainer").gameObject;
|
||
GameObject contentContainer = mainWindow.transform.Find("ContentContainer").gameObject;
|
||
|
||
GameObject parametersPage = CreateParametersPage(contentContainer.transform);
|
||
GameObject customButtonsPage = CreateCustomButtonsPage(contentContainer.transform);
|
||
GameObject toolbarPage = CreateToolbarPage(contentContainer.transform);
|
||
GameObject settingsPage = CreateSettingsPage(contentContainer.transform);
|
||
|
||
// 创建输入对话框
|
||
GameObject inputDialog = CreateInputDialog(canvasObj.transform);
|
||
|
||
// 设置引用
|
||
SetupReferences(tool, canvas, mainWindow, floatingButton,
|
||
parametersPage, customButtonsPage, toolbarPage, settingsPage, inputDialog);
|
||
|
||
return tool;
|
||
}
|
||
|
||
private static GameObject CreateMainWindow(Transform parent)
|
||
{
|
||
GameObject mainWindow = new GameObject("MainWindow");
|
||
mainWindow.transform.SetParent(parent, false);
|
||
RectTransform rect = mainWindow.AddComponent<RectTransform>();
|
||
rect.anchorMin = new Vector2(0, 1);
|
||
rect.anchorMax = new Vector2(0, 1);
|
||
rect.pivot = new Vector2(0, 1);
|
||
rect.sizeDelta = new Vector2(CANVAS_WIDTH, CANVAS_HEIGHT);
|
||
rect.anchoredPosition = Vector2.zero;
|
||
|
||
// 背景
|
||
Image bg = mainWindow.AddComponent<Image>();
|
||
bg.color = new Color(0.1f, 0.1f, 0.1f, 0.95f);
|
||
|
||
// 关闭按钮(左上角)
|
||
GameObject closeBtn = CreateButton("CloseButton", mainWindow.transform, "X");
|
||
RectTransform closeBtnRect = closeBtn.GetComponent<RectTransform>();
|
||
closeBtnRect.anchorMin = new Vector2(0, 1);
|
||
closeBtnRect.anchorMax = new Vector2(0, 1);
|
||
closeBtnRect.pivot = new Vector2(0, 1);
|
||
closeBtnRect.sizeDelta = new Vector2(100, 100);
|
||
closeBtnRect.anchoredPosition = new Vector2(10, -10);
|
||
closeBtn.GetComponent<Image>().color = new Color(0.8f, 0.2f, 0.2f, 1f);
|
||
|
||
// 标签按钮容器(从关闭按钮右侧开始)
|
||
GameObject tabContainer = new GameObject("TabButtonContainer");
|
||
tabContainer.transform.SetParent(mainWindow.transform, false);
|
||
RectTransform tabRect = tabContainer.AddComponent<RectTransform>();
|
||
tabRect.anchorMin = new Vector2(0, 1);
|
||
tabRect.anchorMax = new Vector2(1, 1);
|
||
tabRect.pivot = new Vector2(0, 1);
|
||
tabRect.sizeDelta = new Vector2(-120, 100);
|
||
tabRect.anchoredPosition = new Vector2(120, 0);
|
||
|
||
HorizontalLayoutGroup tabLayout = tabContainer.AddComponent<HorizontalLayoutGroup>();
|
||
tabLayout.childControlWidth = true;
|
||
tabLayout.childControlHeight = true;
|
||
tabLayout.childForceExpandWidth = true;
|
||
tabLayout.childForceExpandHeight = true;
|
||
tabLayout.spacing = 10;
|
||
tabLayout.padding = new RectOffset(10, 20, 10, 10);
|
||
|
||
// 内容容器
|
||
GameObject contentContainer = new GameObject("ContentContainer");
|
||
contentContainer.transform.SetParent(mainWindow.transform, false);
|
||
RectTransform contentRect = contentContainer.AddComponent<RectTransform>();
|
||
contentRect.anchorMin = new Vector2(0, 0);
|
||
contentRect.anchorMax = new Vector2(1, 1);
|
||
contentRect.pivot = new Vector2(0.5f, 0.5f);
|
||
contentRect.offsetMin = new Vector2(20, 20);
|
||
contentRect.offsetMax = new Vector2(-20, -120);
|
||
|
||
return mainWindow;
|
||
}
|
||
|
||
private static GameObject CreateFloatingButton(Transform parent)
|
||
{
|
||
GameObject floatBtn = new GameObject("FloatingButton");
|
||
floatBtn.transform.SetParent(parent, false);
|
||
RectTransform rect = floatBtn.AddComponent<RectTransform>();
|
||
rect.anchorMin = new Vector2(0.5f, 0.5f);
|
||
rect.anchorMax = new Vector2(0.5f, 0.5f);
|
||
rect.pivot = new Vector2(0.5f, 0.5f);
|
||
rect.sizeDelta = new Vector2(120, 120);
|
||
rect.anchoredPosition = new Vector2(400, 0);
|
||
|
||
Image img = floatBtn.AddComponent<Image>();
|
||
img.color = new Color(0.2f, 0.6f, 1f, 0.8f);
|
||
|
||
Button btn = floatBtn.AddComponent<Button>();
|
||
|
||
// 添加文本
|
||
GameObject textObj = new GameObject("Text");
|
||
textObj.transform.SetParent(floatBtn.transform, false);
|
||
RectTransform textRect = textObj.AddComponent<RectTransform>();
|
||
textRect.anchorMin = Vector2.zero;
|
||
textRect.anchorMax = Vector2.one;
|
||
textRect.sizeDelta = Vector2.zero;
|
||
|
||
TextMeshProUGUI text = textObj.AddComponent<TextMeshProUGUI>();
|
||
text.text = "调试";
|
||
text.fontSize = 36;
|
||
text.alignment = TextAlignmentOptions.Center;
|
||
text.color = Color.white;
|
||
|
||
// 添加拖拽组件
|
||
DraggableFloatingButton draggable = floatBtn.AddComponent<DraggableFloatingButton>();
|
||
draggable.clampToScreen = true;
|
||
draggable.snapToEdge = true;
|
||
|
||
return floatBtn;
|
||
}
|
||
|
||
private static GameObject CreateParametersPage(Transform parent)
|
||
{
|
||
GameObject page = new GameObject("ParametersPage");
|
||
page.transform.SetParent(parent, false);
|
||
RectTransform rect = page.AddComponent<RectTransform>();
|
||
rect.anchorMin = Vector2.zero;
|
||
rect.anchorMax = Vector2.one;
|
||
rect.sizeDelta = Vector2.zero;
|
||
|
||
ScrollRect scroll = page.AddComponent<ScrollRect>();
|
||
scroll.horizontal = false;
|
||
scroll.vertical = true;
|
||
|
||
GameObject viewport = new GameObject("Viewport");
|
||
viewport.transform.SetParent(page.transform, false);
|
||
RectTransform vpRect = viewport.AddComponent<RectTransform>();
|
||
vpRect.anchorMin = Vector2.zero;
|
||
vpRect.anchorMax = Vector2.one;
|
||
vpRect.sizeDelta = Vector2.zero;
|
||
viewport.AddComponent<Image>().color = new Color(0, 0, 0, 0.1f);
|
||
viewport.AddComponent<Mask>().showMaskGraphic = false;
|
||
|
||
GameObject content = new GameObject("Content");
|
||
content.transform.SetParent(viewport.transform, false);
|
||
RectTransform 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, 2000);
|
||
|
||
VerticalLayoutGroup layout = content.AddComponent<VerticalLayoutGroup>();
|
||
layout.childControlWidth = true;
|
||
layout.childControlHeight = true;
|
||
layout.childForceExpandWidth = true;
|
||
layout.childForceExpandHeight = false;
|
||
layout.spacing = 20;
|
||
layout.padding = new RectOffset(20, 20, 20, 20);
|
||
|
||
ContentSizeFitter fitter = content.AddComponent<ContentSizeFitter>();
|
||
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||
|
||
scroll.viewport = vpRect;
|
||
scroll.content = contentRect;
|
||
|
||
// 设备信息文本
|
||
GameObject deviceInfo = CreateTextObject("DeviceInfo", content.transform, "设备信息");
|
||
// 系统信息文本
|
||
GameObject systemInfo = CreateTextObject("SystemInfo", content.transform, "系统信息");
|
||
|
||
return page;
|
||
}
|
||
|
||
private static GameObject CreateCustomButtonsPage(Transform parent)
|
||
{
|
||
GameObject page = new GameObject("CustomButtonsPage");
|
||
page.transform.SetParent(parent, false);
|
||
RectTransform rect = page.AddComponent<RectTransform>();
|
||
rect.anchorMin = Vector2.zero;
|
||
rect.anchorMax = Vector2.one;
|
||
rect.sizeDelta = Vector2.zero;
|
||
|
||
ScrollRect scroll = page.AddComponent<ScrollRect>();
|
||
|
||
GameObject viewport = new GameObject("Viewport");
|
||
viewport.transform.SetParent(page.transform, false);
|
||
RectTransform vpRect = viewport.AddComponent<RectTransform>();
|
||
vpRect.anchorMin = Vector2.zero;
|
||
vpRect.anchorMax = Vector2.one;
|
||
vpRect.sizeDelta = Vector2.zero;
|
||
viewport.AddComponent<Mask>().showMaskGraphic = false;
|
||
|
||
GameObject buttonContainer = new GameObject("ButtonContainer");
|
||
buttonContainer.transform.SetParent(viewport.transform, false);
|
||
RectTransform containerRect = buttonContainer.AddComponent<RectTransform>();
|
||
containerRect.anchorMin = new Vector2(0, 1);
|
||
containerRect.anchorMax = new Vector2(1, 1);
|
||
containerRect.pivot = new Vector2(0.5f, 1);
|
||
|
||
GridLayoutGroup grid = buttonContainer.AddComponent<GridLayoutGroup>();
|
||
grid.cellSize = new Vector2(300, 100);
|
||
grid.spacing = new Vector2(20, 20);
|
||
grid.padding = new RectOffset(20, 20, 20, 20);
|
||
grid.constraint = GridLayoutGroup.Constraint.FixedColumnCount;
|
||
grid.constraintCount = 3;
|
||
|
||
ContentSizeFitter fitter = buttonContainer.AddComponent<ContentSizeFitter>();
|
||
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||
|
||
scroll.viewport = vpRect;
|
||
scroll.content = containerRect;
|
||
|
||
return page;
|
||
}
|
||
|
||
private static GameObject CreateToolbarPage(Transform parent)
|
||
{
|
||
GameObject page = new GameObject("ToolbarPage");
|
||
page.transform.SetParent(parent, false);
|
||
RectTransform rect = page.AddComponent<RectTransform>();
|
||
rect.anchorMin = Vector2.zero;
|
||
rect.anchorMax = Vector2.one;
|
||
rect.sizeDelta = Vector2.zero;
|
||
|
||
// 时间调整面板
|
||
GameObject timePanel = new GameObject("TimeAdjustPanel");
|
||
timePanel.transform.SetParent(page.transform, false);
|
||
RectTransform timePanelRect = timePanel.AddComponent<RectTransform>();
|
||
timePanelRect.anchorMin = new Vector2(0, 0.7f);
|
||
timePanelRect.anchorMax = new Vector2(1, 1);
|
||
timePanelRect.offsetMin = new Vector2(20, 0);
|
||
timePanelRect.offsetMax = new Vector2(-20, -20);
|
||
|
||
VerticalLayoutGroup vLayout = timePanel.AddComponent<VerticalLayoutGroup>();
|
||
vLayout.spacing = 20;
|
||
vLayout.padding = new RectOffset(20, 20, 20, 20);
|
||
vLayout.childControlWidth = true;
|
||
vLayout.childControlHeight = false;
|
||
vLayout.childForceExpandWidth = true;
|
||
|
||
// 标题
|
||
GameObject title = CreateTextObject("Title", timePanel.transform, "时间调整");
|
||
title.GetComponent<TextMeshProUGUI>().fontSize = 36;
|
||
title.GetComponent<TextMeshProUGUI>().alignment = TextAlignmentOptions.Center;
|
||
title.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 60);
|
||
|
||
// 滑块
|
||
GameObject slider = CreateSlider("TimeAdjustSlider", timePanel.transform);
|
||
slider.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 60);
|
||
|
||
// 数值显示
|
||
GameObject valueText = CreateTextObject("TimeAdjustValueText", timePanel.transform, "60 秒");
|
||
valueText.GetComponent<TextMeshProUGUI>().fontSize = 32;
|
||
valueText.GetComponent<TextMeshProUGUI>().alignment = TextAlignmentOptions.Center;
|
||
valueText.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 50);
|
||
|
||
// 按钮容器
|
||
GameObject btnContainer = new GameObject("ButtonContainer");
|
||
btnContainer.transform.SetParent(timePanel.transform, false);
|
||
RectTransform btnRect = btnContainer.AddComponent<RectTransform>();
|
||
btnRect.sizeDelta = new Vector2(0, 100);
|
||
|
||
HorizontalLayoutGroup hLayout = btnContainer.AddComponent<HorizontalLayoutGroup>();
|
||
hLayout.spacing = 20;
|
||
hLayout.childControlWidth = true;
|
||
hLayout.childControlHeight = true;
|
||
hLayout.childForceExpandWidth = true;
|
||
hLayout.childForceExpandHeight = true;
|
||
|
||
GameObject increaseBtn = CreateButton("TimeIncreaseButton", btnContainer.transform, "+10秒");
|
||
GameObject decreaseBtn = CreateButton("TimeDecreaseButton", btnContainer.transform, "-10秒");
|
||
|
||
return page;
|
||
}
|
||
|
||
private static GameObject CreateSettingsPage(Transform parent)
|
||
{
|
||
GameObject page = new GameObject("SettingsPage");
|
||
page.transform.SetParent(parent, false);
|
||
RectTransform rect = page.AddComponent<RectTransform>();
|
||
rect.anchorMin = Vector2.zero;
|
||
rect.anchorMax = Vector2.one;
|
||
rect.sizeDelta = Vector2.zero;
|
||
|
||
// 分辨率设置面板
|
||
GameObject resPanel = new GameObject("ResolutionPanel");
|
||
resPanel.transform.SetParent(page.transform, false);
|
||
RectTransform resPanelRect = resPanel.AddComponent<RectTransform>();
|
||
resPanelRect.anchorMin = new Vector2(0, 0.6f);
|
||
resPanelRect.anchorMax = new Vector2(1, 1);
|
||
resPanelRect.offsetMin = new Vector2(20, 0);
|
||
resPanelRect.offsetMax = new Vector2(-20, -20);
|
||
|
||
VerticalLayoutGroup vLayout = resPanel.AddComponent<VerticalLayoutGroup>();
|
||
vLayout.spacing = 30;
|
||
vLayout.padding = new RectOffset(40, 40, 40, 40);
|
||
vLayout.childControlWidth = true;
|
||
vLayout.childControlHeight = false;
|
||
vLayout.childForceExpandWidth = true;
|
||
|
||
// 标题
|
||
GameObject title = CreateTextObject("Title", resPanel.transform, "分辨率设置");
|
||
title.GetComponent<TextMeshProUGUI>().fontSize = 36;
|
||
title.GetComponent<TextMeshProUGUI>().alignment = TextAlignmentOptions.Center;
|
||
title.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 60);
|
||
|
||
// 输入字段容器
|
||
GameObject inputContainer = new GameObject("InputContainer");
|
||
inputContainer.transform.SetParent(resPanel.transform, false);
|
||
RectTransform inputRect = inputContainer.AddComponent<RectTransform>();
|
||
inputRect.sizeDelta = new Vector2(0, 120);
|
||
|
||
HorizontalLayoutGroup hLayout = inputContainer.AddComponent<HorizontalLayoutGroup>();
|
||
hLayout.spacing = 20;
|
||
hLayout.childControlWidth = true;
|
||
hLayout.childControlHeight = true;
|
||
hLayout.childForceExpandWidth = true;
|
||
hLayout.childForceExpandHeight = true;
|
||
|
||
// 宽度输入
|
||
GameObject widthInput = CreateInputField("WidthInputField", inputContainer.transform, "1080");
|
||
widthInput.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 100);
|
||
|
||
// x 分隔符
|
||
GameObject separator = CreateTextObject("X", inputContainer.transform, "×");
|
||
separator.GetComponent<TextMeshProUGUI>().fontSize = 48;
|
||
separator.GetComponent<TextMeshProUGUI>().alignment = TextAlignmentOptions.Center;
|
||
separator.GetComponent<RectTransform>().sizeDelta = new Vector2(80, 100);
|
||
|
||
// 高度输入
|
||
GameObject heightInput = CreateInputField("HeightInputField", inputContainer.transform, "2340");
|
||
heightInput.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 100);
|
||
|
||
// 按钮容器
|
||
GameObject btnContainer = new GameObject("ButtonContainer");
|
||
btnContainer.transform.SetParent(resPanel.transform, false);
|
||
RectTransform btnRect = btnContainer.AddComponent<RectTransform>();
|
||
btnRect.sizeDelta = new Vector2(0, 100);
|
||
|
||
HorizontalLayoutGroup btnLayout = btnContainer.AddComponent<HorizontalLayoutGroup>();
|
||
btnLayout.spacing = 20;
|
||
btnLayout.childControlWidth = true;
|
||
btnLayout.childControlHeight = true;
|
||
btnLayout.childForceExpandWidth = true;
|
||
btnLayout.childForceExpandHeight = true;
|
||
|
||
GameObject applyBtn = CreateButton("ApplyResolutionButton", btnContainer.transform, "应用");
|
||
GameObject resetBtn = CreateButton("ResetResolutionButton", btnContainer.transform, "重置");
|
||
|
||
// 当前分辨率显示
|
||
GameObject currentText = CreateTextObject("CurrentResolutionText", resPanel.transform, "当前: 1080×2340");
|
||
currentText.GetComponent<TextMeshProUGUI>().fontSize = 28;
|
||
currentText.GetComponent<TextMeshProUGUI>().alignment = TextAlignmentOptions.Center;
|
||
currentText.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 60);
|
||
|
||
return page;
|
||
}
|
||
|
||
private static GameObject CreateInputDialog(Transform parent)
|
||
{
|
||
GameObject dialog = new GameObject("InputDialog");
|
||
dialog.transform.SetParent(parent, false);
|
||
RectTransform rect = dialog.AddComponent<RectTransform>();
|
||
rect.anchorMin = Vector2.zero;
|
||
rect.anchorMax = Vector2.one;
|
||
rect.sizeDelta = Vector2.zero;
|
||
|
||
// 半透明背景
|
||
Image bg = dialog.AddComponent<Image>();
|
||
bg.color = new Color(0, 0, 0, 0.8f);
|
||
|
||
// 面板
|
||
GameObject panel = new GameObject("Panel");
|
||
panel.transform.SetParent(dialog.transform, false);
|
||
RectTransform panelRect = panel.AddComponent<RectTransform>();
|
||
panelRect.anchorMin = new Vector2(0.5f, 0.5f);
|
||
panelRect.anchorMax = new Vector2(0.5f, 0.5f);
|
||
panelRect.sizeDelta = new Vector2(900, 500);
|
||
panel.AddComponent<Image>().color = new Color(0.2f, 0.2f, 0.2f, 1f);
|
||
|
||
VerticalLayoutGroup vLayout = panel.AddComponent<VerticalLayoutGroup>();
|
||
vLayout.spacing = 30;
|
||
vLayout.padding = new RectOffset(40, 40, 40, 40);
|
||
vLayout.childControlWidth = true;
|
||
vLayout.childControlHeight = false;
|
||
vLayout.childForceExpandWidth = true;
|
||
|
||
// 标题
|
||
GameObject title = CreateTextObject("Title", panel.transform, "输入");
|
||
title.GetComponent<TextMeshProUGUI>().fontSize = 40;
|
||
title.GetComponent<TextMeshProUGUI>().alignment = TextAlignmentOptions.Center;
|
||
title.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 70);
|
||
|
||
// 输入框
|
||
GameObject inputField = CreateInputField("InputField", panel.transform, "请输入...");
|
||
inputField.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 120);
|
||
|
||
// 按钮容器
|
||
GameObject btnContainer = new GameObject("ButtonContainer");
|
||
btnContainer.transform.SetParent(panel.transform, false);
|
||
RectTransform btnRect = btnContainer.AddComponent<RectTransform>();
|
||
btnRect.sizeDelta = new Vector2(0, 100);
|
||
|
||
HorizontalLayoutGroup hLayout = btnContainer.AddComponent<HorizontalLayoutGroup>();
|
||
hLayout.spacing = 40;
|
||
hLayout.childControlWidth = true;
|
||
hLayout.childControlHeight = true;
|
||
hLayout.childForceExpandWidth = true;
|
||
hLayout.childForceExpandHeight = true;
|
||
|
||
GameObject confirmBtn = CreateButton("ConfirmButton", btnContainer.transform, "确定");
|
||
confirmBtn.GetComponent<Image>().color = new Color(0.2f, 0.6f, 0.2f, 1f);
|
||
|
||
GameObject cancelBtn = CreateButton("CancelButton", btnContainer.transform, "取消");
|
||
cancelBtn.GetComponent<Image>().color = new Color(0.6f, 0.2f, 0.2f, 1f);
|
||
|
||
dialog.SetActive(false);
|
||
|
||
return dialog;
|
||
}
|
||
|
||
#region Helper Methods
|
||
|
||
/// <summary>
|
||
/// 获取TMP默认字体,如果没有则返回null
|
||
/// </summary>
|
||
private static TMP_FontAsset GetDefaultFont()
|
||
{
|
||
// 尝试获取TMP的默认字体
|
||
TMP_FontAsset defaultFont = TMP_Settings.defaultFontAsset;
|
||
|
||
// 如果没有默认字体,尝试加载LiberationSans
|
||
if (defaultFont == null)
|
||
{
|
||
defaultFont = Resources.Load<TMP_FontAsset>("Fonts & Materials/LiberationSans SDF");
|
||
}
|
||
|
||
return defaultFont;
|
||
}
|
||
|
||
private static GameObject CreateButton(string name, Transform parent, string text)
|
||
{
|
||
GameObject btn = new GameObject(name);
|
||
btn.transform.SetParent(parent, false);
|
||
RectTransform rect = btn.AddComponent<RectTransform>();
|
||
rect.sizeDelta = new Vector2(200, 80);
|
||
|
||
Image img = btn.AddComponent<Image>();
|
||
img.color = new Color(0.3f, 0.3f, 0.3f, 1f);
|
||
|
||
Button button = btn.AddComponent<Button>();
|
||
|
||
GameObject textObj = new GameObject("Text");
|
||
textObj.transform.SetParent(btn.transform, false);
|
||
RectTransform textRect = textObj.AddComponent<RectTransform>();
|
||
textRect.anchorMin = Vector2.zero;
|
||
textRect.anchorMax = Vector2.one;
|
||
textRect.sizeDelta = Vector2.zero;
|
||
|
||
TextMeshProUGUI tmp = textObj.AddComponent<TextMeshProUGUI>();
|
||
tmp.text = text;
|
||
tmp.fontSize = 32;
|
||
tmp.alignment = TextAlignmentOptions.Center;
|
||
tmp.color = Color.white;
|
||
|
||
// 设置默认字体
|
||
TMP_FontAsset defaultFont = GetDefaultFont();
|
||
if (defaultFont != null)
|
||
{
|
||
tmp.font = defaultFont;
|
||
}
|
||
|
||
return btn;
|
||
}
|
||
|
||
private static GameObject CreateTextObject(string name, Transform parent, string text)
|
||
{
|
||
GameObject textObj = new GameObject(name);
|
||
textObj.transform.SetParent(parent, false);
|
||
RectTransform rect = textObj.AddComponent<RectTransform>();
|
||
rect.sizeDelta = new Vector2(800, 200);
|
||
|
||
TextMeshProUGUI tmp = textObj.AddComponent<TextMeshProUGUI>();
|
||
tmp.text = text;
|
||
tmp.fontSize = 28;
|
||
tmp.alignment = TextAlignmentOptions.TopLeft;
|
||
tmp.color = Color.white;
|
||
|
||
// 设置默认字体
|
||
TMP_FontAsset defaultFont = GetDefaultFont();
|
||
if (defaultFont != null)
|
||
{
|
||
tmp.font = defaultFont;
|
||
}
|
||
|
||
return textObj;
|
||
}
|
||
|
||
private static GameObject CreateInputField(string name, Transform parent, string placeholder)
|
||
{
|
||
GameObject inputObj = new GameObject(name);
|
||
inputObj.transform.SetParent(parent, false);
|
||
RectTransform rect = inputObj.AddComponent<RectTransform>();
|
||
rect.sizeDelta = new Vector2(600, 80);
|
||
|
||
Image img = inputObj.AddComponent<Image>();
|
||
img.color = new Color(0.15f, 0.15f, 0.15f, 1f);
|
||
|
||
TMP_InputField input = inputObj.AddComponent<TMP_InputField>();
|
||
|
||
GameObject textArea = new GameObject("TextArea");
|
||
textArea.transform.SetParent(inputObj.transform, false);
|
||
RectTransform taRect = textArea.AddComponent<RectTransform>();
|
||
taRect.anchorMin = Vector2.zero;
|
||
taRect.anchorMax = Vector2.one;
|
||
taRect.sizeDelta = Vector2.zero;
|
||
taRect.offsetMin = new Vector2(10, 10);
|
||
taRect.offsetMax = new Vector2(-10, -10);
|
||
|
||
GameObject textObj = new GameObject("Text");
|
||
textObj.transform.SetParent(textArea.transform, false);
|
||
RectTransform textRect = textObj.AddComponent<RectTransform>();
|
||
textRect.anchorMin = Vector2.zero;
|
||
textRect.anchorMax = Vector2.one;
|
||
textRect.sizeDelta = Vector2.zero;
|
||
|
||
TextMeshProUGUI text = textObj.AddComponent<TextMeshProUGUI>();
|
||
text.fontSize = 32;
|
||
text.color = Color.white;
|
||
|
||
// 设置默认字体
|
||
TMP_FontAsset defaultFont = GetDefaultFont();
|
||
if (defaultFont != null)
|
||
{
|
||
text.font = defaultFont;
|
||
}
|
||
|
||
GameObject placeholderObj = new GameObject("Placeholder");
|
||
placeholderObj.transform.SetParent(textArea.transform, false);
|
||
RectTransform phRect = placeholderObj.AddComponent<RectTransform>();
|
||
phRect.anchorMin = Vector2.zero;
|
||
phRect.anchorMax = Vector2.one;
|
||
phRect.sizeDelta = Vector2.zero;
|
||
|
||
TextMeshProUGUI phText = placeholderObj.AddComponent<TextMeshProUGUI>();
|
||
phText.text = placeholder;
|
||
phText.fontSize = 32;
|
||
phText.color = new Color(1, 1, 1, 0.5f);
|
||
|
||
// 设置默认字体
|
||
if (defaultFont != null)
|
||
{
|
||
phText.font = defaultFont;
|
||
}
|
||
|
||
input.textViewport = taRect;
|
||
input.textComponent = text;
|
||
input.placeholder = phText;
|
||
|
||
return inputObj;
|
||
}
|
||
|
||
private static GameObject CreateSlider(string name, Transform parent)
|
||
{
|
||
GameObject sliderObj = new GameObject(name);
|
||
sliderObj.transform.SetParent(parent, false);
|
||
RectTransform rect = sliderObj.AddComponent<RectTransform>();
|
||
rect.sizeDelta = new Vector2(800, 60);
|
||
|
||
Slider slider = sliderObj.AddComponent<Slider>();
|
||
slider.minValue = 0;
|
||
slider.maxValue = 300;
|
||
slider.value = 60;
|
||
|
||
// Background
|
||
GameObject bg = new GameObject("Background");
|
||
bg.transform.SetParent(sliderObj.transform, false);
|
||
RectTransform bgRect = bg.AddComponent<RectTransform>();
|
||
bgRect.anchorMin = Vector2.zero;
|
||
bgRect.anchorMax = Vector2.one;
|
||
bgRect.sizeDelta = Vector2.zero;
|
||
bg.AddComponent<Image>().color = new Color(0.2f, 0.2f, 0.2f, 1f);
|
||
|
||
// Fill Area
|
||
GameObject fillArea = new GameObject("Fill Area");
|
||
fillArea.transform.SetParent(sliderObj.transform, false);
|
||
RectTransform faRect = fillArea.AddComponent<RectTransform>();
|
||
faRect.anchorMin = Vector2.zero;
|
||
faRect.anchorMax = Vector2.one;
|
||
faRect.sizeDelta = Vector2.zero;
|
||
|
||
GameObject fill = new GameObject("Fill");
|
||
fill.transform.SetParent(fillArea.transform, false);
|
||
RectTransform fillRect = fill.AddComponent<RectTransform>();
|
||
fillRect.anchorMin = Vector2.zero;
|
||
fillRect.anchorMax = Vector2.one;
|
||
fillRect.sizeDelta = Vector2.zero;
|
||
fill.AddComponent<Image>().color = new Color(0.2f, 0.6f, 1f, 1f);
|
||
|
||
slider.fillRect = fillRect;
|
||
|
||
// Handle
|
||
GameObject handleArea = new GameObject("Handle Slide Area");
|
||
handleArea.transform.SetParent(sliderObj.transform, false);
|
||
RectTransform haRect = handleArea.AddComponent<RectTransform>();
|
||
haRect.anchorMin = Vector2.zero;
|
||
haRect.anchorMax = Vector2.one;
|
||
haRect.sizeDelta = Vector2.zero;
|
||
|
||
GameObject handle = new GameObject("Handle");
|
||
handle.transform.SetParent(handleArea.transform, false);
|
||
RectTransform handleRect = handle.AddComponent<RectTransform>();
|
||
handleRect.sizeDelta = new Vector2(40, 60);
|
||
handle.AddComponent<Image>().color = Color.white;
|
||
|
||
slider.handleRect = handleRect;
|
||
slider.targetGraphic = handle.GetComponent<Image>();
|
||
|
||
return sliderObj;
|
||
}
|
||
|
||
private static GameObject CreateCustomButtonPrefab()
|
||
{
|
||
// 创建一个隐藏的临时父对象来存放预制件模板
|
||
GameObject tempParent = new GameObject("_TempPrefabHolder");
|
||
tempParent.SetActive(false);
|
||
Object.DontDestroyOnLoad(tempParent);
|
||
|
||
GameObject btn = CreateButton("CustomButton", tempParent.transform, "按钮");
|
||
btn.GetComponent<RectTransform>().sizeDelta = new Vector2(280, 90);
|
||
|
||
// 确保预制件的TextMeshProUGUI也能被SetSDF设置
|
||
// 通过将其标记到特殊层或添加特殊标签
|
||
btn.tag = "Untagged"; // 保持默认,确保能被找到
|
||
|
||
return btn;
|
||
}
|
||
|
||
private static GameObject CreateTabButtonPrefab()
|
||
{
|
||
// 使用同一个临时父对象
|
||
GameObject tempParent = GameObject.Find("_TempPrefabHolder");
|
||
if (tempParent == null)
|
||
{
|
||
tempParent = new GameObject("_TempPrefabHolder");
|
||
tempParent.SetActive(false);
|
||
Object.DontDestroyOnLoad(tempParent);
|
||
}
|
||
|
||
GameObject btn = CreateButton("TabButton", tempParent.transform, "标签");
|
||
btn.GetComponent<RectTransform>().sizeDelta = new Vector2(200, 80);
|
||
|
||
// 确保预制件的TextMeshProUGUI也能被SetSDF设置
|
||
btn.tag = "Untagged"; // 保持默认,确保能被找到
|
||
|
||
return btn;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 确保场景中有EventSystem,如果没有则创建一个
|
||
/// </summary>
|
||
private static void EnsureEventSystem()
|
||
{
|
||
EventSystem eventSystem = Object.FindObjectOfType<EventSystem>();
|
||
if (eventSystem == null)
|
||
{
|
||
GameObject eventSystemObj = new GameObject("EventSystem");
|
||
eventSystem = eventSystemObj.AddComponent<EventSystem>();
|
||
eventSystemObj.AddComponent<StandaloneInputModule>();
|
||
Object.DontDestroyOnLoad(eventSystemObj);
|
||
Debug.Log("[RuntimeUIGenerator] 已自动创建EventSystem");
|
||
}
|
||
else
|
||
{
|
||
Debug.Log("[RuntimeUIGenerator] EventSystem已存在");
|
||
}
|
||
}
|
||
|
||
private static void SetupReferences(UniversalDebugTool tool, Canvas canvas, GameObject mainWindow,
|
||
GameObject floatingButton, GameObject parametersPage, GameObject customButtonsPage,
|
||
GameObject toolbarPage, GameObject settingsPage, GameObject inputDialog)
|
||
{
|
||
// 使用反射设置私有字段
|
||
var type = typeof(UniversalDebugTool);
|
||
var flags = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;
|
||
|
||
// 主窗口
|
||
type.GetField("mainWindow", flags)?.SetValue(tool, mainWindow.GetComponent<RectTransform>());
|
||
type.GetField("canvas", flags)?.SetValue(tool, canvas);
|
||
type.GetField("tabButtonContainer", flags)?.SetValue(tool, mainWindow.transform.Find("TabButtonContainer").GetComponent<RectTransform>());
|
||
type.GetField("contentContainer", flags)?.SetValue(tool, mainWindow.transform.Find("ContentContainer").GetComponent<RectTransform>());
|
||
type.GetField("closeButton", flags)?.SetValue(tool, mainWindow.transform.Find("CloseButton").GetComponent<Button>());
|
||
|
||
// 悬浮按钮
|
||
type.GetField("floatingButton", flags)?.SetValue(tool, floatingButton);
|
||
type.GetField("draggableComponent", flags)?.SetValue(tool, floatingButton.GetComponent<DraggableFloatingButton>());
|
||
|
||
// 参数查看页面
|
||
type.GetField("parametersPage", flags)?.SetValue(tool, parametersPage);
|
||
type.GetField("deviceInfoText", flags)?.SetValue(tool, parametersPage.transform.Find("Viewport/Content/DeviceInfo").GetComponent<TextMeshProUGUI>());
|
||
type.GetField("systemInfoText", flags)?.SetValue(tool, parametersPage.transform.Find("Viewport/Content/SystemInfo").GetComponent<TextMeshProUGUI>());
|
||
type.GetField("parametersScrollRect", flags)?.SetValue(tool, parametersPage.GetComponent<ScrollRect>());
|
||
|
||
// 自定义按钮页面
|
||
type.GetField("customButtonsPage", flags)?.SetValue(tool, customButtonsPage);
|
||
type.GetField("buttonContainer", flags)?.SetValue(tool, customButtonsPage.transform.Find("Viewport/ButtonContainer").GetComponent<RectTransform>());
|
||
type.GetField("buttonsScrollRect", flags)?.SetValue(tool, customButtonsPage.GetComponent<ScrollRect>());
|
||
|
||
// 创建按钮预制件
|
||
GameObject buttonPrefab = CreateCustomButtonPrefab();
|
||
GameObject tabButtonPrefab = CreateTabButtonPrefab();
|
||
type.GetField("buttonPrefab", flags)?.SetValue(tool, buttonPrefab);
|
||
type.GetField("tabButtonPrefab", flags)?.SetValue(tool, tabButtonPrefab);
|
||
|
||
// 工具栏页面
|
||
type.GetField("toolbarPage", flags)?.SetValue(tool, toolbarPage);
|
||
Transform toolbarPanel = toolbarPage.transform.Find("TimeAdjustPanel");
|
||
if (toolbarPanel != null)
|
||
{
|
||
type.GetField("timeAdjustSlider", flags)?.SetValue(tool, toolbarPanel.Find("TimeAdjustSlider")?.GetComponent<Slider>());
|
||
type.GetField("timeAdjustValueText", flags)?.SetValue(tool, toolbarPanel.Find("TimeAdjustValueText")?.GetComponent<TextMeshProUGUI>());
|
||
Transform btnContainer = toolbarPanel.Find("ButtonContainer");
|
||
if (btnContainer != null)
|
||
{
|
||
type.GetField("timeIncreaseButton", flags)?.SetValue(tool, btnContainer.Find("TimeIncreaseButton")?.GetComponent<Button>());
|
||
type.GetField("timeDecreaseButton", flags)?.SetValue(tool, btnContainer.Find("TimeDecreaseButton")?.GetComponent<Button>());
|
||
}
|
||
}
|
||
|
||
// 设置页面
|
||
type.GetField("settingsPage", flags)?.SetValue(tool, settingsPage);
|
||
Transform resPanel = settingsPage.transform.Find("ResolutionPanel");
|
||
if (resPanel != null)
|
||
{
|
||
Transform inputContainer = resPanel.Find("InputContainer");
|
||
if (inputContainer != null)
|
||
{
|
||
type.GetField("widthInputField", flags)?.SetValue(tool, inputContainer.Find("WidthInputField")?.GetComponent<TMP_InputField>());
|
||
type.GetField("heightInputField", flags)?.SetValue(tool, inputContainer.Find("HeightInputField")?.GetComponent<TMP_InputField>());
|
||
}
|
||
|
||
Transform btnContainer = resPanel.Find("ButtonContainer");
|
||
if (btnContainer != null)
|
||
{
|
||
type.GetField("applyResolutionButton", flags)?.SetValue(tool, btnContainer.Find("ApplyResolutionButton")?.GetComponent<Button>());
|
||
type.GetField("resetResolutionButton", flags)?.SetValue(tool, btnContainer.Find("ResetResolutionButton")?.GetComponent<Button>());
|
||
}
|
||
|
||
type.GetField("currentResolutionText", flags)?.SetValue(tool, resPanel.Find("CurrentResolutionText")?.GetComponent<TextMeshProUGUI>());
|
||
}
|
||
|
||
// 输入对话框
|
||
type.GetField("inputDialog", flags)?.SetValue(tool, inputDialog);
|
||
Transform dialogPanel = inputDialog.transform.Find("Panel");
|
||
if (dialogPanel != null)
|
||
{
|
||
type.GetField("inputDialogTitle", flags)?.SetValue(tool, dialogPanel.Find("Title")?.GetComponent<TextMeshProUGUI>());
|
||
type.GetField("inputDialogInputField", flags)?.SetValue(tool, dialogPanel.Find("InputField")?.GetComponent<TMP_InputField>());
|
||
|
||
Transform btnContainer = dialogPanel.Find("ButtonContainer");
|
||
if (btnContainer != null)
|
||
{
|
||
type.GetField("inputDialogConfirmBtn", flags)?.SetValue(tool, btnContainer.Find("ConfirmButton")?.GetComponent<Button>());
|
||
type.GetField("inputDialogCancelBtn", flags)?.SetValue(tool, btnContainer.Find("CancelButton")?.GetComponent<Button>());
|
||
}
|
||
}
|
||
|
||
Debug.Log("[RuntimeUIGenerator] 所有引用已设置完成");
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|