1724 lines
88 KiB
C#
1724 lines
88 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 customCheckBoxesPage = CreateCustomCheckBoxesPage(contentContainer.transform);
|
||
GameObject customValuesPage = CreateCustomValuesPage(contentContainer.transform);
|
||
GameObject settingsPage = CreateSettingsPage(contentContainer.transform);
|
||
GameObject consolePage = CreateConsolePage(contentContainer.transform);
|
||
|
||
// 创建输入对话框
|
||
GameObject inputDialog = CreateInputDialog(canvasObj.transform);
|
||
|
||
// 设置引用
|
||
SetupReferences(tool, canvas, mainWindow, floatingButton,
|
||
parametersPage, customButtonsPage, customCheckBoxesPage, customValuesPage, settingsPage, consolePage, 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, 1);
|
||
rect.anchorMax = new Vector2(0, 1);
|
||
rect.pivot = new Vector2(0, 1);
|
||
rect.sizeDelta = new Vector2(90, 90);
|
||
// 距离左上角边缘10像素
|
||
rect.anchoredPosition = new Vector2(10, -10);
|
||
|
||
Image img = floatBtn.AddComponent<Image>();
|
||
img.color = new Color(0.2f, 0.6f, 1f, 0.8f);
|
||
img.raycastTarget = true; // 确保可以接收点击事件
|
||
|
||
// 不再添加Button组件,点击事件由DraggableFloatingButton的OnPointerClick处理
|
||
|
||
// 添加文本
|
||
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 = 28;
|
||
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>();
|
||
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 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);
|
||
containerRect.offsetMin = new Vector2(0, containerRect.offsetMin.y);
|
||
containerRect.offsetMax = new Vector2(0, containerRect.offsetMax.y);
|
||
|
||
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 CreateCustomCheckBoxesPage(Transform parent)
|
||
{
|
||
GameObject page = new GameObject("CustomCheckBoxesPage");
|
||
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 checkBoxContainer = new GameObject("CheckBoxContainer");
|
||
checkBoxContainer.transform.SetParent(viewport.transform, false);
|
||
RectTransform containerRect = checkBoxContainer.AddComponent<RectTransform>();
|
||
containerRect.anchorMin = new Vector2(0, 1);
|
||
containerRect.anchorMax = new Vector2(1, 1);
|
||
containerRect.pivot = new Vector2(0.5f, 1);
|
||
containerRect.offsetMin = new Vector2(0, containerRect.offsetMin.y); // left = 0
|
||
containerRect.offsetMax = new Vector2(0, containerRect.offsetMax.y); // right = 0
|
||
|
||
// 使用垂直布局,一行一个复选框
|
||
VerticalLayoutGroup vertLayout = checkBoxContainer.AddComponent<VerticalLayoutGroup>();
|
||
vertLayout.spacing = 15;
|
||
vertLayout.padding = new RectOffset(20, 20, 20, 20);
|
||
vertLayout.childControlWidth = true;
|
||
vertLayout.childControlHeight = false;
|
||
vertLayout.childForceExpandWidth = true;
|
||
|
||
ContentSizeFitter fitter = checkBoxContainer.AddComponent<ContentSizeFitter>();
|
||
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||
|
||
scroll.viewport = vpRect;
|
||
scroll.content = containerRect;
|
||
|
||
return page;
|
||
}
|
||
|
||
private static GameObject CreateCustomValuesPage(Transform parent)
|
||
{
|
||
GameObject page = new GameObject("CustomValuesPage");
|
||
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 valueContainer = new GameObject("ValueContainer");
|
||
valueContainer.transform.SetParent(viewport.transform, false);
|
||
RectTransform containerRect = valueContainer.AddComponent<RectTransform>();
|
||
containerRect.anchorMin = new Vector2(0, 1);
|
||
containerRect.anchorMax = new Vector2(1, 1);
|
||
containerRect.pivot = new Vector2(0.5f, 1);
|
||
containerRect.offsetMin = new Vector2(0, containerRect.offsetMin.y); // left = 0
|
||
containerRect.offsetMax = new Vector2(0, containerRect.offsetMax.y); // right = 0
|
||
|
||
// 使用垂直布局,一行一个数值项
|
||
VerticalLayoutGroup vertLayout = valueContainer.AddComponent<VerticalLayoutGroup>();
|
||
vertLayout.spacing = 20;
|
||
vertLayout.padding = new RectOffset(20, 20, 20, 20);
|
||
vertLayout.childControlWidth = true;
|
||
vertLayout.childControlHeight = false;
|
||
vertLayout.childForceExpandWidth = true;
|
||
|
||
ContentSizeFitter fitter = valueContainer.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秒");
|
||
|
||
// 暂时隐藏按钮
|
||
GameObject hideBtn = CreateButton("HideTemporarilyButton", timePanel.transform, "暂时隐藏 (5秒)");
|
||
hideBtn.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 100);
|
||
hideBtn.GetComponent<Image>().color = new Color(0.5f, 0.3f, 0.1f, 1f); // 橙褐色
|
||
hideBtn.GetComponent<Button>().onClick.AddListener(() => {
|
||
UniversalDebugTool.HideTemporarily(5f);
|
||
});
|
||
|
||
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);
|
||
|
||
// Console Log缓存池设置面板
|
||
GameObject bufferPanel = new GameObject("BufferPanel");
|
||
bufferPanel.transform.SetParent(page.transform, false);
|
||
RectTransform bufferPanelRect = bufferPanel.AddComponent<RectTransform>();
|
||
bufferPanelRect.anchorMin = new Vector2(0, 0);
|
||
bufferPanelRect.anchorMax = new Vector2(1, 0.5f);
|
||
bufferPanelRect.offsetMin = new Vector2(20, 20);
|
||
bufferPanelRect.offsetMax = new Vector2(-20, 0);
|
||
|
||
VerticalLayoutGroup bufferVLayout = bufferPanel.AddComponent<VerticalLayoutGroup>();
|
||
bufferVLayout.spacing = 30;
|
||
bufferVLayout.padding = new RectOffset(40, 40, 40, 40);
|
||
bufferVLayout.childControlWidth = true;
|
||
bufferVLayout.childControlHeight = false;
|
||
bufferVLayout.childForceExpandWidth = true;
|
||
|
||
// 标题
|
||
GameObject bufferTitle = CreateTextObject("BufferTitle", bufferPanel.transform, "Console Log缓存池设置");
|
||
bufferTitle.GetComponent<TextMeshProUGUI>().fontSize = 36;
|
||
bufferTitle.GetComponent<TextMeshProUGUI>().alignment = TextAlignmentOptions.Center;
|
||
bufferTitle.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 60);
|
||
|
||
// Info缓存池输入
|
||
GameObject infoBufferContainer = new GameObject("InfoBufferContainer");
|
||
infoBufferContainer.transform.SetParent(bufferPanel.transform, false);
|
||
RectTransform infoBufferRect = infoBufferContainer.AddComponent<RectTransform>();
|
||
infoBufferRect.sizeDelta = new Vector2(0, 100);
|
||
|
||
HorizontalLayoutGroup infoBufferHLayout = infoBufferContainer.AddComponent<HorizontalLayoutGroup>();
|
||
infoBufferHLayout.spacing = 20;
|
||
infoBufferHLayout.childControlWidth = true;
|
||
infoBufferHLayout.childControlHeight = true;
|
||
infoBufferHLayout.childForceExpandWidth = false;
|
||
infoBufferHLayout.childForceExpandHeight = true;
|
||
|
||
GameObject infoLabel = CreateTextObject("InfoLabel", infoBufferContainer.transform, "Info:");
|
||
infoLabel.GetComponent<TextMeshProUGUI>().fontSize = 28;
|
||
infoLabel.GetComponent<RectTransform>().sizeDelta = new Vector2(200, 100);
|
||
|
||
GameObject infoBufferInput = CreateInputField("InfoBufferInputField", infoBufferContainer.transform, "50");
|
||
infoBufferInput.GetComponent<RectTransform>().sizeDelta = new Vector2(300, 100);
|
||
|
||
// Warning缓存池输入
|
||
GameObject warningBufferContainer = new GameObject("WarningBufferContainer");
|
||
warningBufferContainer.transform.SetParent(bufferPanel.transform, false);
|
||
RectTransform warningBufferRect = warningBufferContainer.AddComponent<RectTransform>();
|
||
warningBufferRect.sizeDelta = new Vector2(0, 100);
|
||
|
||
HorizontalLayoutGroup warningBufferHLayout = warningBufferContainer.AddComponent<HorizontalLayoutGroup>();
|
||
warningBufferHLayout.spacing = 20;
|
||
warningBufferHLayout.childControlWidth = true;
|
||
warningBufferHLayout.childControlHeight = true;
|
||
warningBufferHLayout.childForceExpandWidth = false;
|
||
warningBufferHLayout.childForceExpandHeight = true;
|
||
|
||
GameObject warningLabel = CreateTextObject("WarningLabel", warningBufferContainer.transform, "Warning:");
|
||
warningLabel.GetComponent<TextMeshProUGUI>().fontSize = 28;
|
||
warningLabel.GetComponent<RectTransform>().sizeDelta = new Vector2(200, 100);
|
||
|
||
GameObject warningBufferInput = CreateInputField("WarningBufferInputField", warningBufferContainer.transform, "50");
|
||
warningBufferInput.GetComponent<RectTransform>().sizeDelta = new Vector2(300, 100);
|
||
|
||
// Error缓存池输入
|
||
GameObject errorBufferContainer = new GameObject("ErrorBufferContainer");
|
||
errorBufferContainer.transform.SetParent(bufferPanel.transform, false);
|
||
RectTransform errorBufferRect = errorBufferContainer.AddComponent<RectTransform>();
|
||
errorBufferRect.sizeDelta = new Vector2(0, 100);
|
||
|
||
HorizontalLayoutGroup errorBufferHLayout = errorBufferContainer.AddComponent<HorizontalLayoutGroup>();
|
||
errorBufferHLayout.spacing = 20;
|
||
errorBufferHLayout.childControlWidth = true;
|
||
errorBufferHLayout.childControlHeight = true;
|
||
errorBufferHLayout.childForceExpandWidth = false;
|
||
errorBufferHLayout.childForceExpandHeight = true;
|
||
|
||
GameObject errorLabel = CreateTextObject("ErrorLabel", errorBufferContainer.transform, "Error:");
|
||
errorLabel.GetComponent<TextMeshProUGUI>().fontSize = 28;
|
||
errorLabel.GetComponent<RectTransform>().sizeDelta = new Vector2(200, 100);
|
||
|
||
GameObject errorBufferInput = CreateInputField("ErrorBufferInputField", errorBufferContainer.transform, "50");
|
||
errorBufferInput.GetComponent<RectTransform>().sizeDelta = new Vector2(300, 100);
|
||
|
||
// Fatal缓存池输入
|
||
GameObject fatalBufferContainer = new GameObject("FatalBufferContainer");
|
||
fatalBufferContainer.transform.SetParent(bufferPanel.transform, false);
|
||
RectTransform fatalBufferRect = fatalBufferContainer.AddComponent<RectTransform>();
|
||
fatalBufferRect.sizeDelta = new Vector2(0, 100);
|
||
|
||
HorizontalLayoutGroup fatalBufferHLayout = fatalBufferContainer.AddComponent<HorizontalLayoutGroup>();
|
||
fatalBufferHLayout.spacing = 20;
|
||
fatalBufferHLayout.childControlWidth = true;
|
||
fatalBufferHLayout.childControlHeight = true;
|
||
fatalBufferHLayout.childForceExpandWidth = false;
|
||
fatalBufferHLayout.childForceExpandHeight = true;
|
||
|
||
GameObject fatalLabel = CreateTextObject("FatalLabel", fatalBufferContainer.transform, "Fatal:");
|
||
fatalLabel.GetComponent<TextMeshProUGUI>().fontSize = 28;
|
||
fatalLabel.GetComponent<RectTransform>().sizeDelta = new Vector2(200, 100);
|
||
|
||
GameObject fatalBufferInput = CreateInputField("FatalBufferInputField", fatalBufferContainer.transform, "50");
|
||
fatalBufferInput.GetComponent<RectTransform>().sizeDelta = new Vector2(300, 100);
|
||
|
||
// 缓存池按钮容器
|
||
GameObject bufferBtnContainer = new GameObject("BufferButtonContainer");
|
||
bufferBtnContainer.transform.SetParent(bufferPanel.transform, false);
|
||
RectTransform bufferBtnRect = bufferBtnContainer.AddComponent<RectTransform>();
|
||
bufferBtnRect.sizeDelta = new Vector2(0, 100);
|
||
|
||
HorizontalLayoutGroup bufferBtnLayout = bufferBtnContainer.AddComponent<HorizontalLayoutGroup>();
|
||
bufferBtnLayout.spacing = 20;
|
||
bufferBtnLayout.childControlWidth = true;
|
||
bufferBtnLayout.childControlHeight = true;
|
||
bufferBtnLayout.childForceExpandWidth = true;
|
||
bufferBtnLayout.childForceExpandHeight = true;
|
||
|
||
GameObject applyBufferBtn = CreateButton("ApplyBufferButton", bufferBtnContainer.transform, "应用");
|
||
GameObject resetBufferBtn = CreateButton("ResetBufferButton", bufferBtnContainer.transform, "重置");
|
||
|
||
return page;
|
||
}
|
||
|
||
private static GameObject CreateConsolePage(Transform parent)
|
||
{
|
||
GameObject page = new GameObject("ConsolePage");
|
||
page.transform.SetParent(parent, false);
|
||
RectTransform rect = page.AddComponent<RectTransform>();
|
||
rect.anchorMin = Vector2.zero;
|
||
rect.anchorMax = Vector2.one;
|
||
rect.sizeDelta = Vector2.zero;
|
||
|
||
VerticalLayoutGroup vLayout = page.AddComponent<VerticalLayoutGroup>();
|
||
vLayout.spacing = 10;
|
||
vLayout.padding = new RectOffset(10, 10, 10, 10);
|
||
vLayout.childControlWidth = true;
|
||
vLayout.childControlHeight = false;
|
||
vLayout.childForceExpandWidth = true;
|
||
vLayout.childForceExpandHeight = false;
|
||
|
||
// 控制面板
|
||
GameObject controlPanel = new GameObject("ControlPanel");
|
||
controlPanel.transform.SetParent(page.transform, false);
|
||
RectTransform controlRect = controlPanel.AddComponent<RectTransform>();
|
||
controlRect.sizeDelta = new Vector2(0, 40);
|
||
|
||
// 添加LayoutElement来控制高度
|
||
LayoutElement controlLayout = controlPanel.AddComponent<LayoutElement>();
|
||
controlLayout.preferredHeight = 40;
|
||
controlLayout.flexibleHeight = 0;
|
||
|
||
HorizontalLayoutGroup hLayout = controlPanel.AddComponent<HorizontalLayoutGroup>();
|
||
hLayout.spacing = 10;
|
||
hLayout.padding = new RectOffset(10, 10, 10, 10);
|
||
hLayout.childControlWidth = false;
|
||
hLayout.childControlHeight = true;
|
||
hLayout.childForceExpandHeight = false;
|
||
|
||
// 清空按钮
|
||
GameObject clearBtn = CreateButton("ConsoleClearButton", controlPanel.transform, "清空");
|
||
clearBtn.GetComponent<RectTransform>().sizeDelta = new Vector2(150, 0);
|
||
LayoutElement clearLayout = clearBtn.AddComponent<LayoutElement>();
|
||
clearLayout.preferredHeight = 35;
|
||
|
||
// 锁定滚动Toggle
|
||
GameObject lockToggle = CreateToggle("ConsoleLockScrollToggle", controlPanel.transform, "锁定滚动");
|
||
lockToggle.GetComponent<RectTransform>().sizeDelta = new Vector2(180, 0);
|
||
LayoutElement lockLayout = lockToggle.AddComponent<LayoutElement>();
|
||
lockLayout.preferredHeight = 35;
|
||
|
||
// 过滤器Toggles
|
||
GameObject infoToggle = CreateToggle("ConsoleInfoFilterToggle", controlPanel.transform, "Info (0)");
|
||
infoToggle.GetComponent<RectTransform>().sizeDelta = new Vector2(150, 0);
|
||
infoToggle.GetComponent<Toggle>().isOn = true;
|
||
LayoutElement infoLayout = infoToggle.AddComponent<LayoutElement>();
|
||
infoLayout.preferredHeight = 35;
|
||
|
||
GameObject warningToggle = CreateToggle("ConsoleWarningFilterToggle", controlPanel.transform, "Warning (0)");
|
||
warningToggle.GetComponent<RectTransform>().sizeDelta = new Vector2(180, 0);
|
||
warningToggle.GetComponent<Toggle>().isOn = true;
|
||
LayoutElement warningLayout = warningToggle.AddComponent<LayoutElement>();
|
||
warningLayout.preferredHeight = 35;
|
||
|
||
GameObject errorToggle = CreateToggle("ConsoleErrorFilterToggle", controlPanel.transform, "Error (0)");
|
||
errorToggle.GetComponent<RectTransform>().sizeDelta = new Vector2(150, 0);
|
||
errorToggle.GetComponent<Toggle>().isOn = true;
|
||
LayoutElement errorLayout = errorToggle.AddComponent<LayoutElement>();
|
||
errorLayout.preferredHeight = 35;
|
||
|
||
GameObject fatalToggle = CreateToggle("ConsoleFatalFilterToggle", controlPanel.transform, "Fatal (0)");
|
||
fatalToggle.GetComponent<RectTransform>().sizeDelta = new Vector2(150, 0);
|
||
fatalToggle.GetComponent<Toggle>().isOn = true;
|
||
LayoutElement fatalLayout = fatalToggle.AddComponent<LayoutElement>();
|
||
fatalLayout.preferredHeight = 35;
|
||
|
||
// 文字筛选面板
|
||
GameObject textFilterPanel = new GameObject("TextFilterPanel");
|
||
textFilterPanel.transform.SetParent(page.transform, false);
|
||
RectTransform textFilterRect = textFilterPanel.AddComponent<RectTransform>();
|
||
textFilterRect.sizeDelta = new Vector2(0, 120);
|
||
LayoutElement textFilterLayout = textFilterPanel.AddComponent<LayoutElement>();
|
||
textFilterLayout.preferredHeight = 120;
|
||
textFilterLayout.flexibleHeight = 0;
|
||
|
||
HorizontalLayoutGroup textFilterHLayout = textFilterPanel.AddComponent<HorizontalLayoutGroup>();
|
||
textFilterHLayout.spacing = 20;
|
||
textFilterHLayout.padding = new RectOffset(10, 10, 10, 10);
|
||
textFilterHLayout.childControlWidth = true;
|
||
textFilterHLayout.childControlHeight = true;
|
||
textFilterHLayout.childForceExpandWidth = true;
|
||
textFilterHLayout.childForceExpandHeight = true;
|
||
|
||
// 文字筛选标签
|
||
GameObject textFilterLabel = CreateTextObject("TextFilterLabel", textFilterPanel.transform, "文字筛选:");
|
||
textFilterLabel.GetComponent<TextMeshProUGUI>().fontSize = 28;
|
||
textFilterLabel.GetComponent<TextMeshProUGUI>().alignment = TextAlignmentOptions.Left;
|
||
textFilterLabel.GetComponent<RectTransform>().sizeDelta = new Vector2(200, 0);
|
||
LayoutElement labelLayout = textFilterLabel.AddComponent<LayoutElement>();
|
||
labelLayout.preferredWidth = 200;
|
||
labelLayout.flexibleWidth = 0;
|
||
|
||
// 文字筛选输入框
|
||
GameObject textFilterInput = CreateInputField("ConsoleTextFilterInputField", textFilterPanel.transform, "");
|
||
textFilterInput.GetComponent<RectTransform>().sizeDelta = new Vector2(0, 100);
|
||
TMP_InputField inputField = textFilterInput.GetComponent<TMP_InputField>();
|
||
if (inputField != null && inputField.placeholder is TextMeshProUGUI placeholder)
|
||
{
|
||
placeholder.text = "输入筛选文字...";
|
||
}
|
||
|
||
// 日志区域 (60%)
|
||
GameObject logArea = new GameObject("LogArea");
|
||
logArea.transform.SetParent(page.transform, false);
|
||
RectTransform logAreaRect = logArea.AddComponent<RectTransform>();
|
||
logAreaRect.sizeDelta = new Vector2(0, 1180);
|
||
LayoutElement logAreaLayout = logArea.AddComponent<LayoutElement>();
|
||
logAreaLayout.preferredHeight = 1180;
|
||
logAreaLayout.flexibleHeight = 0;
|
||
|
||
// 日志ScrollView
|
||
GameObject logScrollView = new GameObject("ConsoleLogScrollView");
|
||
logScrollView.transform.SetParent(logArea.transform, false);
|
||
RectTransform logScrollRect = logScrollView.AddComponent<RectTransform>();
|
||
logScrollRect.anchorMin = Vector2.zero;
|
||
logScrollRect.anchorMax = Vector2.one;
|
||
logScrollRect.sizeDelta = Vector2.zero;
|
||
|
||
ScrollRect logScroll = logScrollView.AddComponent<ScrollRect>();
|
||
logScroll.horizontal = false;
|
||
logScroll.vertical = true;
|
||
logScroll.movementType = ScrollRect.MovementType.Elastic;
|
||
|
||
// Viewport
|
||
GameObject logViewport = new GameObject("Viewport");
|
||
logViewport.transform.SetParent(logScrollView.transform, false);
|
||
RectTransform logViewportRect = logViewport.AddComponent<RectTransform>();
|
||
logViewportRect.anchorMin = Vector2.zero;
|
||
logViewportRect.anchorMax = Vector2.one;
|
||
logViewportRect.sizeDelta = Vector2.zero;
|
||
logViewport.AddComponent<Image>().color = new Color(0.05f, 0.05f, 0.05f, 1f);
|
||
logViewport.AddComponent<Mask>().showMaskGraphic = true;
|
||
logScroll.viewport = logViewportRect;
|
||
|
||
// Content
|
||
GameObject logContent = new GameObject("ConsoleLogContent");
|
||
logContent.transform.SetParent(logViewport.transform, false);
|
||
RectTransform logContentRect = logContent.AddComponent<RectTransform>();
|
||
logContentRect.anchorMin = new Vector2(0, 1);
|
||
logContentRect.anchorMax = new Vector2(1, 1);
|
||
logContentRect.pivot = new Vector2(0.5f, 1);
|
||
logContentRect.sizeDelta = new Vector2(0, 0);
|
||
|
||
VerticalLayoutGroup logVLayout = logContent.AddComponent<VerticalLayoutGroup>();
|
||
logVLayout.spacing = 2;
|
||
logVLayout.childAlignment = TextAnchor.UpperCenter;
|
||
logVLayout.childControlWidth = true;
|
||
logVLayout.childControlHeight = true;
|
||
logVLayout.childForceExpandWidth = true;
|
||
logVLayout.childForceExpandHeight = false;
|
||
|
||
ContentSizeFitter logFitter = logContent.AddComponent<ContentSizeFitter>();
|
||
logFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||
|
||
logScroll.content = logContentRect;
|
||
|
||
// 详情区域 (40%)
|
||
GameObject detailArea = new GameObject("DetailArea");
|
||
detailArea.transform.SetParent(page.transform, false);
|
||
RectTransform detailAreaRect = detailArea.AddComponent<RectTransform>();
|
||
detailAreaRect.sizeDelta = new Vector2(0, 800);
|
||
LayoutElement detailAreaLayout = detailArea.AddComponent<LayoutElement>();
|
||
detailAreaLayout.preferredHeight = 800;
|
||
detailAreaLayout.flexibleHeight = 0;
|
||
|
||
// 详情ScrollView
|
||
GameObject detailScrollView = new GameObject("ConsoleDetailScrollView");
|
||
detailScrollView.transform.SetParent(detailArea.transform, false);
|
||
RectTransform detailScrollRect = detailScrollView.AddComponent<RectTransform>();
|
||
detailScrollRect.anchorMin = Vector2.zero;
|
||
detailScrollRect.anchorMax = Vector2.one;
|
||
detailScrollRect.sizeDelta = Vector2.zero;
|
||
|
||
ScrollRect detailScroll = detailScrollView.AddComponent<ScrollRect>();
|
||
detailScroll.horizontal = false;
|
||
detailScroll.vertical = true;
|
||
detailScroll.movementType = ScrollRect.MovementType.Clamped;
|
||
|
||
// Viewport
|
||
GameObject detailViewport = new GameObject("Viewport");
|
||
detailViewport.transform.SetParent(detailScrollView.transform, false);
|
||
RectTransform detailViewportRect = detailViewport.AddComponent<RectTransform>();
|
||
detailViewportRect.anchorMin = Vector2.zero;
|
||
detailViewportRect.anchorMax = Vector2.one;
|
||
detailViewportRect.sizeDelta = Vector2.zero;
|
||
detailViewport.AddComponent<Image>().color = new Color(0.08f, 0.08f, 0.08f, 1f);
|
||
detailViewport.AddComponent<Mask>().showMaskGraphic = true;
|
||
detailScroll.viewport = detailViewportRect;
|
||
|
||
// Content
|
||
GameObject detailContent = new GameObject("Content");
|
||
detailContent.transform.SetParent(detailViewport.transform, false);
|
||
RectTransform detailContentRect = detailContent.AddComponent<RectTransform>();
|
||
detailContentRect.anchorMin = new Vector2(0, 1);
|
||
detailContentRect.anchorMax = new Vector2(1, 1);
|
||
detailContentRect.pivot = new Vector2(0.5f, 1);
|
||
detailContentRect.sizeDelta = new Vector2(0, 100);
|
||
detailContentRect.anchoredPosition = Vector2.zero;
|
||
|
||
// 为 Content 添加 ContentSizeFitter 以自动调整高度
|
||
ContentSizeFitter contentFitter = detailContent.AddComponent<ContentSizeFitter>();
|
||
contentFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||
|
||
// 添加 VerticalLayoutGroup 用于布局
|
||
VerticalLayoutGroup contentLayout = detailContent.AddComponent<VerticalLayoutGroup>();
|
||
contentLayout.childControlHeight = false;
|
||
contentLayout.childControlWidth = true;
|
||
contentLayout.childForceExpandHeight = false;
|
||
contentLayout.childForceExpandWidth = true;
|
||
contentLayout.padding = new RectOffset(10, 10, 10, 10);
|
||
|
||
// 详情文本
|
||
GameObject detailText = CreateTextObject("ConsoleDetailText", detailContent.transform, "点击日志查看详细信息...");
|
||
TextMeshProUGUI detailTMP = detailText.GetComponent<TextMeshProUGUI>();
|
||
detailTMP.fontSize = 24;
|
||
detailTMP.alignment = TextAlignmentOptions.TopLeft;
|
||
detailTMP.enableWordWrapping = true;
|
||
detailTMP.overflowMode = TextOverflowModes.Overflow;
|
||
detailTMP.richText = true;
|
||
detailTMP.color = new Color(0.8f, 0.8f, 0.8f, 1f);
|
||
|
||
RectTransform detailTextRect = detailText.GetComponent<RectTransform>();
|
||
detailTextRect.anchorMin = new Vector2(0, 1);
|
||
detailTextRect.anchorMax = new Vector2(1, 1);
|
||
detailTextRect.pivot = new Vector2(0.5f, 1);
|
||
detailTextRect.sizeDelta = new Vector2(0, 0);
|
||
|
||
// 为文本添加 ContentSizeFitter 使其根据内容自动调整大小
|
||
ContentSizeFitter detailTextFitter = detailText.AddComponent<ContentSizeFitter>();
|
||
detailTextFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||
|
||
// 添加 LayoutElement 使文本在 VerticalLayoutGroup 中正确工作
|
||
LayoutElement detailTextLayout = detailText.AddComponent<LayoutElement>();
|
||
detailTextLayout.flexibleHeight = 0;
|
||
detailTextLayout.preferredHeight = -1;
|
||
|
||
detailScroll.content = detailContentRect;
|
||
|
||
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 CreateToggle(string name, Transform parent, string labelText)
|
||
{
|
||
GameObject toggleObj = new GameObject(name);
|
||
toggleObj.transform.SetParent(parent, false);
|
||
RectTransform rect = toggleObj.AddComponent<RectTransform>();
|
||
rect.sizeDelta = new Vector2(160, 60);
|
||
|
||
// Background
|
||
Image bgImg = toggleObj.AddComponent<Image>();
|
||
bgImg.color = new Color(0.2f, 0.2f, 0.2f, 1f);
|
||
|
||
Toggle toggle = toggleObj.AddComponent<Toggle>();
|
||
toggle.isOn = true;
|
||
toggle.transition = Selectable.Transition.ColorTint;
|
||
|
||
// Checkmark Background
|
||
GameObject checkmarkBg = new GameObject("Background");
|
||
checkmarkBg.transform.SetParent(toggleObj.transform, false);
|
||
RectTransform checkmarkBgRect = checkmarkBg.AddComponent<RectTransform>();
|
||
checkmarkBgRect.anchorMin = new Vector2(0, 0.5f);
|
||
checkmarkBgRect.anchorMax = new Vector2(0, 0.5f);
|
||
checkmarkBgRect.pivot = new Vector2(0, 0.5f);
|
||
checkmarkBgRect.sizeDelta = new Vector2(40, 40);
|
||
checkmarkBgRect.anchoredPosition = new Vector2(10, 0);
|
||
|
||
Image checkmarkBgImg = checkmarkBg.AddComponent<Image>();
|
||
checkmarkBgImg.color = new Color(0.8f, 0.8f, 0.8f, 1f);
|
||
|
||
// Checkmark
|
||
GameObject checkmark = new GameObject("Checkmark");
|
||
checkmark.transform.SetParent(checkmarkBg.transform, false);
|
||
RectTransform checkmarkRect = checkmark.AddComponent<RectTransform>();
|
||
checkmarkRect.anchorMin = Vector2.zero;
|
||
checkmarkRect.anchorMax = Vector2.one;
|
||
checkmarkRect.sizeDelta = new Vector2(-10, -10);
|
||
|
||
Image checkmarkImg = checkmark.AddComponent<Image>();
|
||
checkmarkImg.color = new Color(0.2f, 0.8f, 0.2f, 1f);
|
||
|
||
toggle.targetGraphic = checkmarkBgImg;
|
||
toggle.graphic = checkmarkImg;
|
||
|
||
// Label
|
||
GameObject label = new GameObject("Label");
|
||
label.transform.SetParent(toggleObj.transform, false);
|
||
RectTransform labelRect = label.AddComponent<RectTransform>();
|
||
labelRect.anchorMin = new Vector2(0, 0);
|
||
labelRect.anchorMax = new Vector2(1, 1);
|
||
labelRect.offsetMin = new Vector2(60, 0);
|
||
labelRect.offsetMax = new Vector2(-10, 0);
|
||
|
||
TextMeshProUGUI labelTmp = label.AddComponent<TextMeshProUGUI>();
|
||
labelTmp.text = labelText;
|
||
labelTmp.fontSize = 24;
|
||
labelTmp.alignment = TextAlignmentOptions.MidlineLeft;
|
||
labelTmp.color = Color.white;
|
||
|
||
// 设置默认字体
|
||
TMP_FontAsset defaultFont = GetDefaultFont();
|
||
if (defaultFont != null)
|
||
{
|
||
labelTmp.font = defaultFont;
|
||
}
|
||
|
||
return toggleObj;
|
||
}
|
||
|
||
private static GameObject CreateConsoleLogItemPrefab()
|
||
{
|
||
GameObject logItem = new GameObject("ConsoleLogItem");
|
||
RectTransform rect = logItem.AddComponent<RectTransform>();
|
||
// 设置锚点为水平拉伸,顶部对齐
|
||
rect.anchorMin = new Vector2(0, 1);
|
||
rect.anchorMax = new Vector2(1, 1);
|
||
rect.pivot = new Vector2(0.5f, 1);
|
||
// 设置固定高度50,宽度自动拉伸
|
||
rect.sizeDelta = new Vector2(0, 50);
|
||
|
||
// 添加LayoutElement来确保布局组件正确控制尺寸
|
||
LayoutElement layoutElement = logItem.AddComponent<LayoutElement>();
|
||
layoutElement.minHeight = 50;
|
||
layoutElement.preferredHeight = 50;
|
||
layoutElement.flexibleWidth = 1;
|
||
|
||
// Toggle组件
|
||
Toggle toggle = logItem.AddComponent<Toggle>();
|
||
toggle.isOn = false;
|
||
toggle.transition = Selectable.Transition.ColorTint;
|
||
|
||
// Background
|
||
GameObject background = new GameObject("Background");
|
||
background.transform.SetParent(logItem.transform, false);
|
||
RectTransform bgRect = background.AddComponent<RectTransform>();
|
||
bgRect.anchorMin = Vector2.zero;
|
||
bgRect.anchorMax = Vector2.one;
|
||
bgRect.sizeDelta = Vector2.zero;
|
||
|
||
Image bgImg = background.AddComponent<Image>();
|
||
bgImg.color = new Color(0.12f, 0.12f, 0.12f, 1f);
|
||
|
||
toggle.targetGraphic = bgImg;
|
||
|
||
// Label (日志文本)
|
||
GameObject label = new GameObject("Label");
|
||
label.transform.SetParent(logItem.transform, false);
|
||
RectTransform labelRect = label.AddComponent<RectTransform>();
|
||
labelRect.anchorMin = Vector2.zero;
|
||
labelRect.anchorMax = Vector2.one;
|
||
labelRect.offsetMin = new Vector2(10, 5);
|
||
labelRect.offsetMax = new Vector2(-10, -5);
|
||
|
||
TextMeshProUGUI labelTmp = label.AddComponent<TextMeshProUGUI>();
|
||
labelTmp.fontSize = 28;
|
||
labelTmp.alignment = TextAlignmentOptions.MidlineLeft;
|
||
labelTmp.color = Color.white;
|
||
labelTmp.overflowMode = TextOverflowModes.Truncate;
|
||
labelTmp.richText = true;
|
||
labelTmp.enableWordWrapping = false;
|
||
|
||
// 设置默认字体
|
||
TMP_FontAsset defaultFont = GetDefaultFont();
|
||
if (defaultFont != null)
|
||
{
|
||
labelTmp.font = defaultFont;
|
||
}
|
||
|
||
// 设置ColorBlock以支持选中状态
|
||
ColorBlock colors = toggle.colors;
|
||
colors.normalColor = new Color(0.12f, 0.12f, 0.12f, 1f);
|
||
colors.highlightedColor = new Color(0.2f, 0.2f, 0.2f, 1f);
|
||
colors.selectedColor = new Color(0.25f, 0.35f, 0.45f, 1f);
|
||
colors.pressedColor = new Color(0.15f, 0.15f, 0.15f, 1f);
|
||
toggle.colors = colors;
|
||
|
||
// 不需要设置为不激活,因为Instantiate时会继承这个状态
|
||
// 而且作为模板时不会显示在场景中
|
||
|
||
// 不销毁预制件
|
||
Object.DontDestroyOnLoad(logItem);
|
||
|
||
Debug.Log("[RuntimeUIGenerator] Created ConsoleLogItem prefab");
|
||
|
||
return logItem;
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
private static GameObject CreateCustomCheckBoxPrefab()
|
||
{
|
||
// 使用同一个临时父对象
|
||
GameObject tempParent = GameObject.Find("_TempPrefabHolder");
|
||
if (tempParent == null)
|
||
{
|
||
tempParent = new GameObject("_TempPrefabHolder");
|
||
tempParent.SetActive(false);
|
||
Object.DontDestroyOnLoad(tempParent);
|
||
}
|
||
|
||
GameObject toggleObj = new GameObject("CustomCheckBox", typeof(RectTransform));
|
||
toggleObj.transform.SetParent(tempParent.transform, false);
|
||
RectTransform rect = toggleObj.GetComponent<RectTransform>();
|
||
rect.sizeDelta = new Vector2(800, 80);
|
||
|
||
// 添加背景图片
|
||
Image bg = toggleObj.AddComponent<Image>();
|
||
bg.color = new Color(0.15f, 0.15f, 0.15f, 1f);
|
||
|
||
// 创建复选框背景(左侧)
|
||
GameObject checkboxBg = new GameObject("Background");
|
||
checkboxBg.transform.SetParent(toggleObj.transform, false);
|
||
RectTransform checkboxBgRect = checkboxBg.AddComponent<RectTransform>();
|
||
checkboxBgRect.anchorMin = new Vector2(0, 0.5f);
|
||
checkboxBgRect.anchorMax = new Vector2(0, 0.5f);
|
||
checkboxBgRect.pivot = new Vector2(0, 0.5f);
|
||
checkboxBgRect.anchoredPosition = new Vector2(20, 0);
|
||
checkboxBgRect.sizeDelta = new Vector2(60, 60);
|
||
|
||
Image checkboxBgImage = checkboxBg.AddComponent<Image>();
|
||
checkboxBgImage.color = new Color(0.8f, 0.8f, 0.8f, 1f);
|
||
|
||
// 创建勾选标记
|
||
GameObject checkmark = new GameObject("Checkmark");
|
||
checkmark.transform.SetParent(checkboxBg.transform, false);
|
||
RectTransform checkmarkRect = checkmark.AddComponent<RectTransform>();
|
||
checkmarkRect.anchorMin = Vector2.zero;
|
||
checkmarkRect.anchorMax = Vector2.one;
|
||
checkmarkRect.sizeDelta = Vector2.zero;
|
||
|
||
Image checkmarkImage = checkmark.AddComponent<Image>();
|
||
checkmarkImage.color = new Color(0.2f, 0.8f, 0.2f, 1f);
|
||
|
||
// 创建文本标签(右侧)
|
||
GameObject label = new GameObject("Label");
|
||
label.transform.SetParent(toggleObj.transform, false);
|
||
RectTransform labelRect = label.AddComponent<RectTransform>();
|
||
labelRect.anchorMin = new Vector2(0, 0);
|
||
labelRect.anchorMax = new Vector2(1, 1);
|
||
labelRect.pivot = new Vector2(0, 0.5f);
|
||
labelRect.offsetMin = new Vector2(100, 0);
|
||
labelRect.offsetMax = new Vector2(-20, 0);
|
||
|
||
TextMeshProUGUI labelText = label.AddComponent<TextMeshProUGUI>();
|
||
labelText.text = "复选框";
|
||
labelText.fontSize = 32;
|
||
labelText.alignment = TextAlignmentOptions.Left;
|
||
labelText.color = Color.white;
|
||
|
||
// 设置默认字体
|
||
TMP_FontAsset defaultFont = GetDefaultFont();
|
||
if (defaultFont != null)
|
||
{
|
||
labelText.font = defaultFont;
|
||
}
|
||
|
||
// 添加Toggle组件
|
||
Toggle toggle = toggleObj.AddComponent<Toggle>();
|
||
toggle.targetGraphic = checkboxBgImage;
|
||
toggle.graphic = checkmarkImage;
|
||
toggle.isOn = false;
|
||
|
||
return toggleObj;
|
||
}
|
||
|
||
private static GameObject CreateCustomValuePrefab()
|
||
{
|
||
// 使用同一个临时父对象
|
||
GameObject tempParent = GameObject.Find("_TempPrefabHolder");
|
||
if (tempParent == null)
|
||
{
|
||
tempParent = new GameObject("_TempPrefabHolder");
|
||
tempParent.SetActive(false);
|
||
Object.DontDestroyOnLoad(tempParent);
|
||
}
|
||
|
||
GameObject valueObj = new GameObject("CustomValue", typeof(RectTransform));
|
||
valueObj.transform.SetParent(tempParent.transform, false);
|
||
RectTransform rect = valueObj.GetComponent<RectTransform>();
|
||
rect.sizeDelta = new Vector2(900, 140);
|
||
|
||
// 添加背景图片
|
||
Image bg = valueObj.AddComponent<Image>();
|
||
bg.color = new Color(0.15f, 0.15f, 0.15f, 1f);
|
||
|
||
// 创建标签文本(顶部独占一行)
|
||
GameObject label = new GameObject("Label");
|
||
label.transform.SetParent(valueObj.transform, false);
|
||
RectTransform labelRect = label.AddComponent<RectTransform>();
|
||
labelRect.anchorMin = new Vector2(0, 1);
|
||
labelRect.anchorMax = new Vector2(1, 1);
|
||
labelRect.pivot = new Vector2(0, 1);
|
||
labelRect.anchoredPosition = new Vector2(20, -10);
|
||
labelRect.sizeDelta = new Vector2(-40, 35);
|
||
|
||
TextMeshProUGUI labelText = label.AddComponent<TextMeshProUGUI>();
|
||
labelText.text = "数值名称";
|
||
labelText.fontSize = 28;
|
||
labelText.alignment = TextAlignmentOptions.Left;
|
||
labelText.color = Color.white;
|
||
|
||
// 设置默认字体
|
||
TMP_FontAsset defaultFont = GetDefaultFont();
|
||
if (defaultFont != null)
|
||
{
|
||
labelText.font = defaultFont;
|
||
}
|
||
|
||
// 创建滑动条(标题下方,占据左侧60%)
|
||
GameObject sliderObj = new GameObject("Slider");
|
||
sliderObj.transform.SetParent(valueObj.transform, false);
|
||
RectTransform sliderRect = sliderObj.AddComponent<RectTransform>();
|
||
sliderRect.anchorMin = new Vector2(0, 0);
|
||
sliderRect.anchorMax = new Vector2(0.55f, 0);
|
||
sliderRect.pivot = new Vector2(0, 0);
|
||
sliderRect.anchoredPosition = new Vector2(20, 15);
|
||
sliderRect.sizeDelta = new Vector2(-20, 50);
|
||
|
||
Slider slider = sliderObj.AddComponent<Slider>();
|
||
|
||
// 滑动条背景
|
||
GameObject sliderBg = new GameObject("Background");
|
||
sliderBg.transform.SetParent(sliderObj.transform, false);
|
||
RectTransform sliderBgRect = sliderBg.AddComponent<RectTransform>();
|
||
sliderBgRect.anchorMin = Vector2.zero;
|
||
sliderBgRect.anchorMax = Vector2.one;
|
||
sliderBgRect.sizeDelta = Vector2.zero;
|
||
Image sliderBgImage = sliderBg.AddComponent<Image>();
|
||
sliderBgImage.color = new Color(0.3f, 0.3f, 0.3f, 1f);
|
||
|
||
// 滑动条填充区域
|
||
GameObject fillArea = new GameObject("Fill Area");
|
||
fillArea.transform.SetParent(sliderObj.transform, false);
|
||
RectTransform fillAreaRect = fillArea.AddComponent<RectTransform>();
|
||
fillAreaRect.anchorMin = Vector2.zero;
|
||
fillAreaRect.anchorMax = Vector2.one;
|
||
fillAreaRect.sizeDelta = new Vector2(-10, -10);
|
||
|
||
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;
|
||
Image fillImage = fill.AddComponent<Image>();
|
||
fillImage.color = new Color(0.2f, 0.6f, 1f, 1f);
|
||
|
||
// 滑动条手柄区域
|
||
GameObject handleArea = new GameObject("Handle Slide Area");
|
||
handleArea.transform.SetParent(sliderObj.transform, false);
|
||
RectTransform handleAreaRect = handleArea.AddComponent<RectTransform>();
|
||
handleAreaRect.anchorMin = Vector2.zero;
|
||
handleAreaRect.anchorMax = Vector2.one;
|
||
handleAreaRect.sizeDelta = new Vector2(-10, 0);
|
||
|
||
GameObject handle = new GameObject("Handle");
|
||
handle.transform.SetParent(handleArea.transform, false);
|
||
RectTransform handleRect = handle.AddComponent<RectTransform>();
|
||
handleRect.sizeDelta = new Vector2(30, 30);
|
||
Image handleImage = handle.AddComponent<Image>();
|
||
handleImage.color = Color.white;
|
||
|
||
slider.fillRect = fillRect;
|
||
slider.handleRect = handleRect;
|
||
slider.targetGraphic = handleImage;
|
||
|
||
// 创建输入框(滑动条右侧)
|
||
GameObject inputFieldObj = new GameObject("InputField");
|
||
inputFieldObj.transform.SetParent(valueObj.transform, false);
|
||
RectTransform inputRect = inputFieldObj.AddComponent<RectTransform>();
|
||
inputRect.anchorMin = new Vector2(0.56f, 0);
|
||
inputRect.anchorMax = new Vector2(0.73f, 0);
|
||
inputRect.pivot = new Vector2(0, 0);
|
||
inputRect.anchoredPosition = new Vector2(5, 15);
|
||
inputRect.sizeDelta = new Vector2(0, 50);
|
||
|
||
Image inputBg = inputFieldObj.AddComponent<Image>();
|
||
inputBg.color = new Color(0.25f, 0.25f, 0.25f, 1f);
|
||
|
||
// 创建输入框的文本子对象
|
||
GameObject inputTextObj = new GameObject("Text");
|
||
inputTextObj.transform.SetParent(inputFieldObj.transform, false);
|
||
RectTransform inputTextRect = inputTextObj.AddComponent<RectTransform>();
|
||
inputTextRect.anchorMin = Vector2.zero;
|
||
inputTextRect.anchorMax = Vector2.one;
|
||
inputTextRect.sizeDelta = Vector2.zero;
|
||
|
||
TextMeshProUGUI inputTextComponent = inputTextObj.AddComponent<TextMeshProUGUI>();
|
||
inputTextComponent.fontSize = 28;
|
||
inputTextComponent.alignment = TextAlignmentOptions.Center;
|
||
inputTextComponent.color = Color.white;
|
||
|
||
TMP_InputField inputField = inputFieldObj.AddComponent<TMP_InputField>();
|
||
inputField.textComponent = inputTextComponent;
|
||
|
||
// 创建确认按钮(输入框右侧)- 手动创建而不是使用CreateButton
|
||
GameObject confirmBtn = new GameObject("ConfirmButton", typeof(RectTransform));
|
||
confirmBtn.transform.SetParent(valueObj.transform, false);
|
||
RectTransform confirmRect = confirmBtn.GetComponent<RectTransform>();
|
||
confirmRect.anchorMin = new Vector2(0.74f, 0);
|
||
confirmRect.anchorMax = new Vector2(1, 0);
|
||
confirmRect.pivot = new Vector2(0, 0);
|
||
confirmRect.anchoredPosition = new Vector2(5, 15);
|
||
confirmRect.sizeDelta = new Vector2(-20, 50);
|
||
|
||
Image confirmBtnImage = confirmBtn.AddComponent<Image>();
|
||
confirmBtnImage.color = new Color(0.2f, 0.8f, 0.2f, 1f);
|
||
|
||
Button confirmButton = confirmBtn.AddComponent<Button>();
|
||
confirmButton.targetGraphic = confirmBtnImage;
|
||
|
||
GameObject confirmBtnText = new GameObject("Text");
|
||
confirmBtnText.transform.SetParent(confirmBtn.transform, false);
|
||
RectTransform confirmBtnTextRect = confirmBtnText.AddComponent<RectTransform>();
|
||
confirmBtnTextRect.anchorMin = Vector2.zero;
|
||
confirmBtnTextRect.anchorMax = Vector2.one;
|
||
confirmBtnTextRect.sizeDelta = Vector2.zero;
|
||
|
||
TextMeshProUGUI confirmText = confirmBtnText.AddComponent<TextMeshProUGUI>();
|
||
confirmText.text = "确认";
|
||
confirmText.fontSize = 28;
|
||
confirmText.alignment = TextAlignmentOptions.Center;
|
||
confirmText.color = Color.white;
|
||
|
||
return valueObj;
|
||
}
|
||
|
||
/// <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 customCheckBoxesPage, GameObject customValuesPage, GameObject settingsPage, GameObject consolePage, 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>());
|
||
|
||
// 自定义复选框页面
|
||
type.GetField("customCheckBoxesPage", flags)?.SetValue(tool, customCheckBoxesPage);
|
||
type.GetField("checkBoxContainer", flags)?.SetValue(tool, customCheckBoxesPage.transform.Find("Viewport/CheckBoxContainer").GetComponent<RectTransform>());
|
||
type.GetField("checkBoxesScrollRect", flags)?.SetValue(tool, customCheckBoxesPage.GetComponent<ScrollRect>());
|
||
|
||
// 自定义数值页面
|
||
type.GetField("customValuesPage", flags)?.SetValue(tool, customValuesPage);
|
||
type.GetField("valueContainer", flags)?.SetValue(tool, customValuesPage.transform.Find("Viewport/ValueContainer").GetComponent<RectTransform>());
|
||
type.GetField("valuesScrollRect", flags)?.SetValue(tool, customValuesPage.GetComponent<ScrollRect>());
|
||
|
||
// 创建按钮、复选框和数值预制件
|
||
GameObject buttonPrefab = CreateCustomButtonPrefab();
|
||
GameObject checkBoxPrefab = CreateCustomCheckBoxPrefab();
|
||
GameObject valuePrefab = CreateCustomValuePrefab();
|
||
GameObject tabButtonPrefab = CreateTabButtonPrefab();
|
||
type.GetField("buttonPrefab", flags)?.SetValue(tool, buttonPrefab);
|
||
type.GetField("checkBoxPrefab", flags)?.SetValue(tool, checkBoxPrefab);
|
||
type.GetField("valuePrefab", flags)?.SetValue(tool, valuePrefab);
|
||
type.GetField("tabButtonPrefab", flags)?.SetValue(tool, tabButtonPrefab);
|
||
|
||
// 设置页面
|
||
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>());
|
||
}
|
||
|
||
// 设置缓存池大小输入框
|
||
Transform bufferPanel = settingsPage.transform.Find("BufferPanel");
|
||
if (bufferPanel != null)
|
||
{
|
||
type.GetField("infoBufferInputField", flags)?.SetValue(tool,
|
||
bufferPanel.Find("InfoBufferContainer/InfoBufferInputField")?.GetComponent<TMP_InputField>());
|
||
type.GetField("warningBufferInputField", flags)?.SetValue(tool,
|
||
bufferPanel.Find("WarningBufferContainer/WarningBufferInputField")?.GetComponent<TMP_InputField>());
|
||
type.GetField("errorBufferInputField", flags)?.SetValue(tool,
|
||
bufferPanel.Find("ErrorBufferContainer/ErrorBufferInputField")?.GetComponent<TMP_InputField>());
|
||
type.GetField("fatalBufferInputField", flags)?.SetValue(tool,
|
||
bufferPanel.Find("FatalBufferContainer/FatalBufferInputField")?.GetComponent<TMP_InputField>());
|
||
|
||
Transform bufferBtnContainer = bufferPanel.Find("BufferButtonContainer");
|
||
if (bufferBtnContainer != null)
|
||
{
|
||
type.GetField("applyBufferButton", flags)?.SetValue(tool, bufferBtnContainer.Find("ApplyBufferButton")?.GetComponent<Button>());
|
||
type.GetField("resetBufferButton", flags)?.SetValue(tool, bufferBtnContainer.Find("ResetBufferButton")?.GetComponent<Button>());
|
||
}
|
||
}
|
||
|
||
// 控制台页面
|
||
type.GetField("consolePage", flags)?.SetValue(tool, consolePage);
|
||
type.GetField("consoleLogScrollRect", flags)?.SetValue(tool, consolePage.transform.Find("LogArea/ConsoleLogScrollView")?.GetComponent<ScrollRect>());
|
||
type.GetField("consoleLogContent", flags)?.SetValue(tool, consolePage.transform.Find("LogArea/ConsoleLogScrollView/Viewport/ConsoleLogContent")?.GetComponent<RectTransform>());
|
||
type.GetField("consoleDetailScrollRect", flags)?.SetValue(tool, consolePage.transform.Find("DetailArea/ConsoleDetailScrollView")?.GetComponent<ScrollRect>());
|
||
type.GetField("consoleDetailText", flags)?.SetValue(tool, consolePage.transform.Find("DetailArea/ConsoleDetailScrollView/Viewport/Content/ConsoleDetailText")?.GetComponent<TextMeshProUGUI>());
|
||
Transform controlPanel = consolePage.transform.Find("ControlPanel");
|
||
if (controlPanel != null)
|
||
{
|
||
type.GetField("consoleClearButton", flags)?.SetValue(tool, controlPanel.Find("ConsoleClearButton")?.GetComponent<Button>());
|
||
type.GetField("consoleLockScrollToggle", flags)?.SetValue(tool, controlPanel.Find("ConsoleLockScrollToggle")?.GetComponent<Toggle>());
|
||
type.GetField("consoleInfoFilterToggle", flags)?.SetValue(tool, controlPanel.Find("ConsoleInfoFilterToggle")?.GetComponent<Toggle>());
|
||
type.GetField("consoleWarningFilterToggle", flags)?.SetValue(tool, controlPanel.Find("ConsoleWarningFilterToggle")?.GetComponent<Toggle>());
|
||
type.GetField("consoleErrorFilterToggle", flags)?.SetValue(tool, controlPanel.Find("ConsoleErrorFilterToggle")?.GetComponent<Toggle>());
|
||
type.GetField("consoleFatalFilterToggle", flags)?.SetValue(tool, controlPanel.Find("ConsoleFatalFilterToggle")?.GetComponent<Toggle>());
|
||
}
|
||
|
||
// 设置控制台文字筛选输入框
|
||
Transform textFilterPanel = consolePage.transform.Find("TextFilterPanel");
|
||
if (textFilterPanel != null)
|
||
{
|
||
type.GetField("consoleTextFilterInputField", flags)?.SetValue(tool,
|
||
textFilterPanel.Find("ConsoleTextFilterInputField")?.GetComponent<TMP_InputField>());
|
||
}
|
||
|
||
// 创建日志项预制件
|
||
GameObject consoleLogItemPrefab = CreateConsoleLogItemPrefab();
|
||
type.GetField("consoleLogItemPrefab", flags)?.SetValue(tool, consoleLogItemPrefab);
|
||
|
||
// 输入对话框
|
||
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
|
||
}
|
||
}
|