MeowmentDebugTool/Packages/com.bywaystudios.meowmentdebugtool/Runtime/RuntimeUIGenerator.cs
2025-12-19 12:14:42 +08:00

813 lines
39 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}
}