feat(tools): 添加UI工具脚本及部署文档
新增内容: 1. 创建 06_工具脚本/UI工具/ 目录,包含4个核心工具脚本 - ExternalCommandListener.cs - 外部命令监听器 - RemoteCommand.cs - 远程命令接口 - UIPrefabGenerator.cs - JSON转预制体生成器 - UIPrefabToJson.cs - 预制体转JSON导出器 2. 更新 UI界面拼接设计指南.md - 新增8.9节工具脚本部署说明 - 包含手动部署和自动部署两种方式 - 添加部署规则和验证步骤 3. 更新 README.md - 添加06_工具脚本章节索引 部署方法: - 手动复制:复制工具脚本到项目 Assets/Editor/Command/ 目录 - 自动部署:使用 DeployUITools.bat 脚本
This commit is contained in:
@@ -347,7 +347,71 @@ UIPrefabToJson.ExportPrefabToJson(
|
|||||||
4. **坐标系统**:使用Unity RectTransform的anchorMin/anchorMax/position/sizeDelta四元组
|
4. **坐标系统**:使用Unity RectTransform的anchorMin/anchorMax/position/sizeDelta四元组
|
||||||
5. **文件锁定**:生成前确保目标预制体文件未被其他进程占用
|
5. **文件锁定**:生成前确保目标预制体文件未被其他进程占用
|
||||||
|
|
||||||
|
### 8.9 工具脚本部署
|
||||||
|
|
||||||
|
#### 8.9.1 工具位置
|
||||||
|
|
||||||
|
工具脚本位于UnityAI文档库的以下路径:
|
||||||
|
|
||||||
|
```
|
||||||
|
UnityAI/06_工具脚本/UI工具/
|
||||||
|
├── ExternalCommandListener.cs # 外部命令监听器
|
||||||
|
├── RemoteCommand.cs # 远程命令接口
|
||||||
|
├── UIPrefabGenerator.cs # JSON转预制体生成器
|
||||||
|
└── UIPrefabToJson.cs # 预制体转JSON导出器
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 8.9.2 部署步骤
|
||||||
|
|
||||||
|
**方法一:手动复制**
|
||||||
|
|
||||||
|
1. 复制 `06_工具脚本/UI工具/` 目录下的所有文件
|
||||||
|
2. 粘贴到目标项目的 `Assets/Editor/Command/` 目录中
|
||||||
|
3. 确保目录结构如下:
|
||||||
|
```
|
||||||
|
Assets/Editor/Command/
|
||||||
|
├── ExternalCommandListener.cs
|
||||||
|
├── RemoteCommand.cs
|
||||||
|
├── UIPrefabGenerator.cs
|
||||||
|
└── UIPrefabToJson.cs
|
||||||
|
```
|
||||||
|
|
||||||
|
**方法二:自动部署脚本**
|
||||||
|
|
||||||
|
创建部署脚本 `DeployUITools.bat`:
|
||||||
|
|
||||||
|
```batch
|
||||||
|
@echo off
|
||||||
|
set "SOURCE_DIR=E:\AI\UnityAI\06_工具脚本\UI工具"
|
||||||
|
set "TARGET_DIR=%cd%\Assets\Editor\Command"
|
||||||
|
|
||||||
|
mkdir "%TARGET_DIR%" 2>nul
|
||||||
|
xcopy "%SOURCE_DIR%\*.cs" "%TARGET_DIR%\" /y
|
||||||
|
xcopy "%SOURCE_DIR%\*.cs.meta" "%TARGET_DIR%\" /y
|
||||||
|
|
||||||
|
echo UI工具部署完成
|
||||||
|
pause
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 8.9.3 部署规则
|
||||||
|
|
||||||
|
| 检查项 | 要求 |
|
||||||
|
|-------|------|
|
||||||
|
| **目标路径** | 必须放置在 `Assets/Editor/Command/` 目录下 |
|
||||||
|
| **文件完整性** | 必须包含所有4个cs文件及其meta文件 |
|
||||||
|
| **Unity版本** | 支持Unity 2020及以上版本 |
|
||||||
|
| **依赖组件** | 需要导入 TextMeshPro 包 |
|
||||||
|
|
||||||
|
#### 8.9.4 验证部署
|
||||||
|
|
||||||
|
部署完成后,在Unity编辑器中验证:
|
||||||
|
|
||||||
|
1. 打开Unity编辑器
|
||||||
|
2. 检查菜单 `Tools > UI` 是否存在
|
||||||
|
3. 检查菜单 `Tools > External` 是否存在
|
||||||
|
4. 在Console窗口确认无编译错误
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**版本**: v1.1
|
**版本**: v1.2
|
||||||
**适用**: StrayFog框架UI拼接开发人员
|
**适用**: StrayFog框架UI拼接开发人员
|
||||||
194
06_工具脚本/UI工具/ExternalCommandListener.cs
Normal file
194
06_工具脚本/UI工具/ExternalCommandListener.cs
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
[InitializeOnLoad]
|
||||||
|
public static class ExternalCommandListener
|
||||||
|
{
|
||||||
|
private static FileSystemWatcher watcher;
|
||||||
|
private static string triggerFilePath;
|
||||||
|
private static bool isInitialized = false;
|
||||||
|
|
||||||
|
static ExternalCommandListener()
|
||||||
|
{
|
||||||
|
EditorApplication.update += InitializeOnFirstUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void InitializeOnFirstUpdate()
|
||||||
|
{
|
||||||
|
if (!isInitialized)
|
||||||
|
{
|
||||||
|
isInitialized = true;
|
||||||
|
EditorApplication.update -= InitializeOnFirstUpdate;
|
||||||
|
SetupFileWatcher();
|
||||||
|
Debug.Log("ExternalCommandListener started");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetupFileWatcher()
|
||||||
|
{
|
||||||
|
triggerFilePath = Path.Combine(Application.dataPath, "..", "Trigger_Command.txt");
|
||||||
|
string watchFolder = Path.GetDirectoryName(triggerFilePath);
|
||||||
|
|
||||||
|
if (watcher != null) watcher.Dispose();
|
||||||
|
|
||||||
|
watcher = new FileSystemWatcher(watchFolder, "Trigger_Command.txt");
|
||||||
|
watcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.LastWrite;
|
||||||
|
watcher.Created += OnFileChanged;
|
||||||
|
watcher.Changed += OnFileChanged;
|
||||||
|
watcher.EnableRaisingEvents = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnFileChanged(object sender, FileSystemEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.ChangeType != WatcherChangeTypes.Created && e.ChangeType != WatcherChangeTypes.Changed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EditorApplication.delayCall += ExecuteCommandFromFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ExecuteCommandFromFile()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!File.Exists(triggerFilePath)) return;
|
||||||
|
|
||||||
|
string content = File.ReadAllText(triggerFilePath).Trim();
|
||||||
|
File.Delete(triggerFilePath);
|
||||||
|
|
||||||
|
ParseAndExecute(content);
|
||||||
|
}
|
||||||
|
catch (System.Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError("Execute failed: " + ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ParseAndExecute(string content)
|
||||||
|
{
|
||||||
|
content = content.Trim().Trim('"', '\'');
|
||||||
|
|
||||||
|
string[] parts = content.Split(':');
|
||||||
|
if (parts.Length == 0) return;
|
||||||
|
|
||||||
|
string command = parts[0].Trim();
|
||||||
|
string[] args = parts.Length > 1 ? parts[1..] : new string[0];
|
||||||
|
|
||||||
|
ExecuteCommand(command, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ExecuteCommand(string command, string[] args)
|
||||||
|
{
|
||||||
|
switch (command)
|
||||||
|
{
|
||||||
|
case "ReadJson":
|
||||||
|
ExecuteReadJson(args);
|
||||||
|
break;
|
||||||
|
case "GenerateUIPrefab":
|
||||||
|
ExecuteGenerateUIPrefab(args);
|
||||||
|
break;
|
||||||
|
case "ExportPrefabToJson":
|
||||||
|
ExecuteExportPrefabToJson(args);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug.LogWarning("Unknown command: " + command);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ExecuteReadJson(string[] args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var method = typeof(RemoteCommand).GetMethod("ReadJson",
|
||||||
|
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static,
|
||||||
|
null,
|
||||||
|
new[] { typeof(string[]) },
|
||||||
|
null);
|
||||||
|
|
||||||
|
if (method != null)
|
||||||
|
{
|
||||||
|
method.Invoke(null, new object[] { args });
|
||||||
|
Debug.Log("Executed: ReadJson(" + string.Join(", ", args) + ")");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("RemoteCommand.ReadJson not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (System.Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError("ReadJson failed: " + ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ExecuteGenerateUIPrefab(string[] args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var method = typeof(RemoteCommand).GetMethod("GenerateUIPrefab",
|
||||||
|
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static,
|
||||||
|
null,
|
||||||
|
new[] { typeof(string[]) },
|
||||||
|
null);
|
||||||
|
|
||||||
|
if (method != null)
|
||||||
|
{
|
||||||
|
method.Invoke(null, new object[] { args });
|
||||||
|
Debug.Log("Executed: GenerateUIPrefab(" + string.Join(", ", args) + ")");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("RemoteCommand.GenerateUIPrefab not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (System.Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError("GenerateUIPrefab failed: " + ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("Tools/External/Test ReadJson")]
|
||||||
|
public static void TestExecuteReadJson()
|
||||||
|
{
|
||||||
|
ExecuteReadJson(new string[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("Tools/External/Test GenerateUIPrefab")]
|
||||||
|
public static void TestExecuteGenerateUIPrefab()
|
||||||
|
{
|
||||||
|
ExecuteGenerateUIPrefab(new[] { "Assets/Editor/UI/BagWindow.json" });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ExecuteExportPrefabToJson(string[] args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var method = typeof(RemoteCommand).GetMethod("ExportPrefabToJson",
|
||||||
|
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static,
|
||||||
|
null,
|
||||||
|
new[] { typeof(string[]) },
|
||||||
|
null);
|
||||||
|
|
||||||
|
if (method != null)
|
||||||
|
{
|
||||||
|
method.Invoke(null, new object[] { args });
|
||||||
|
Debug.Log("Executed: ExportPrefabToJson(" + string.Join(", ", args) + ")");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("RemoteCommand.ExportPrefabToJson not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (System.Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError("ExportPrefabToJson failed: " + ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("Tools/External/Test ExportPrefabToJson")]
|
||||||
|
public static void TestExecuteExportPrefabToJson()
|
||||||
|
{
|
||||||
|
ExecuteExportPrefabToJson(new[] { "Assets/Game/GameHFResource/CN/UIWindows/BagWindow/BagWindow.prefab" });
|
||||||
|
}
|
||||||
|
}
|
||||||
11
06_工具脚本/UI工具/ExternalCommandListener.cs.meta
Normal file
11
06_工具脚本/UI工具/ExternalCommandListener.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 93f1f8f942aa53347a7e58bb4c561893
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
39
06_工具脚本/UI工具/RemoteCommand.cs
Normal file
39
06_工具脚本/UI工具/RemoteCommand.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
public static class RemoteCommand
|
||||||
|
{
|
||||||
|
public static void ReadJson(string[] args)
|
||||||
|
{
|
||||||
|
SFP.Error("收到参数: " + string.Join(", ", args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void GenerateUIPrefab(string[] args)
|
||||||
|
{
|
||||||
|
if (args.Length == 0)
|
||||||
|
{
|
||||||
|
SFP.Error("GenerateUIPrefab: 需要提供JSON文件路径参数");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string jsonPath = args[0];
|
||||||
|
string prefabPath = args.Length > 1 ? args[1] : null;
|
||||||
|
|
||||||
|
SFP.Error("GenerateUIPrefab: 开始生成UI, JSON路径: " + jsonPath);
|
||||||
|
|
||||||
|
UIPrefabGenerator.GeneratePrefabFromJson(jsonPath, prefabPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ExportPrefabToJson(string[] args)
|
||||||
|
{
|
||||||
|
if (args.Length == 0)
|
||||||
|
{
|
||||||
|
SFP.Error("ExportPrefabToJson: 需要提供预制体文件路径参数");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string prefabPath = args[0];
|
||||||
|
string jsonPath = args.Length > 1 ? args[1] : null;
|
||||||
|
|
||||||
|
SFP.Error("ExportPrefabToJson: 开始导出JSON, 预制体路径: " + prefabPath);
|
||||||
|
|
||||||
|
UIPrefabToJson.ExportPrefabToJson(prefabPath, jsonPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
06_工具脚本/UI工具/RemoteCommand.cs.meta
Normal file
11
06_工具脚本/UI工具/RemoteCommand.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 359ded64689f3f64c87c561d88cead9d
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
624
06_工具脚本/UI工具/UIPrefabGenerator.cs
Normal file
624
06_工具脚本/UI工具/UIPrefabGenerator.cs
Normal file
@@ -0,0 +1,624 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityEditor;
|
||||||
|
using TMPro;
|
||||||
|
|
||||||
|
public static class UIPrefabGenerator
|
||||||
|
{
|
||||||
|
[MenuItem("Tools/UI/Generate BagWindow Prefab")]
|
||||||
|
public static void GenerateBagWindowPrefab()
|
||||||
|
{
|
||||||
|
string jsonPath = "Assets/Editor/UI/BagWindow.json";
|
||||||
|
string prefabPath = "Assets/Game/GameHFResource/CN/UIWindows/BagWindow/BagWindow.prefab";
|
||||||
|
|
||||||
|
if (!File.Exists(jsonPath))
|
||||||
|
{
|
||||||
|
Debug.LogError("JSON file not found: " + jsonPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string jsonContent = File.ReadAllText(jsonPath);
|
||||||
|
UILayoutData layoutData = JsonUtility.FromJson<UILayoutData>(jsonContent);
|
||||||
|
|
||||||
|
GameObject root = new GameObject(layoutData.name);
|
||||||
|
root.layer = 5;
|
||||||
|
|
||||||
|
Canvas canvas = root.AddComponent<Canvas>();
|
||||||
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||||
|
canvas.pixelPerfect = layoutData.canvas.pixelPerfect;
|
||||||
|
|
||||||
|
root.AddComponent<CanvasScaler>();
|
||||||
|
root.AddComponent<GraphicRaycaster>();
|
||||||
|
|
||||||
|
RectTransform rootRect = root.GetComponent<RectTransform>();
|
||||||
|
SetRectTransform(rootRect, layoutData.rectTransform);
|
||||||
|
|
||||||
|
foreach (var childData in layoutData.children)
|
||||||
|
{
|
||||||
|
CreateUIElement(childData, root.transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
CreatePrefab(root, prefabPath);
|
||||||
|
GameObject.DestroyImmediate(root);
|
||||||
|
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
Debug.Log("UI Prefab generated successfully: " + prefabPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void GeneratePrefabFromJson(string jsonPath, string prefabPath = null)
|
||||||
|
{
|
||||||
|
if (!File.Exists(jsonPath))
|
||||||
|
{
|
||||||
|
Debug.LogError("JSON file not found: " + jsonPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string jsonContent = File.ReadAllText(jsonPath);
|
||||||
|
UILayoutData layoutData = JsonUtility.FromJson<UILayoutData>(jsonContent);
|
||||||
|
|
||||||
|
if (layoutData == null)
|
||||||
|
{
|
||||||
|
Debug.LogError("Failed to parse JSON file: " + jsonPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(prefabPath))
|
||||||
|
{
|
||||||
|
prefabPath = "Assets/Game/GameHFResource/CN/UIWindows/" + layoutData.name + "/" + layoutData.name + ".prefab";
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject root = new GameObject(layoutData.name);
|
||||||
|
root.layer = layoutData.layer;
|
||||||
|
|
||||||
|
Canvas canvas = root.AddComponent<Canvas>();
|
||||||
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||||
|
if (layoutData.canvas != null)
|
||||||
|
{
|
||||||
|
canvas.pixelPerfect = layoutData.canvas.pixelPerfect;
|
||||||
|
}
|
||||||
|
|
||||||
|
root.AddComponent<CanvasScaler>();
|
||||||
|
root.AddComponent<GraphicRaycaster>();
|
||||||
|
|
||||||
|
RectTransform rootRect = root.GetComponent<RectTransform>();
|
||||||
|
SetRectTransform(rootRect, layoutData.rectTransform);
|
||||||
|
|
||||||
|
foreach (var childData in layoutData.children)
|
||||||
|
{
|
||||||
|
CreateUIElement(childData, root.transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
CreatePrefab(root, prefabPath);
|
||||||
|
GameObject.DestroyImmediate(root);
|
||||||
|
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
Debug.Log("UI Prefab generated successfully: " + prefabPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateUIElement(UIElementData data, Transform parent)
|
||||||
|
{
|
||||||
|
GameObject obj = new GameObject(data.name);
|
||||||
|
obj.transform.SetParent(parent, false);
|
||||||
|
|
||||||
|
RectTransform rect = obj.AddComponent<RectTransform>();
|
||||||
|
SetRectTransform(rect, data.rectTransform);
|
||||||
|
|
||||||
|
switch (data.type)
|
||||||
|
{
|
||||||
|
case "Image":
|
||||||
|
case "SFUI_Image":
|
||||||
|
CreateImage(obj, data.image);
|
||||||
|
break;
|
||||||
|
case "Button":
|
||||||
|
case "SFUI_Button":
|
||||||
|
CreateButton(obj, data.button, data.image);
|
||||||
|
break;
|
||||||
|
case "TextMeshProUGUI":
|
||||||
|
case "SFUI_TextMeshProUGUI":
|
||||||
|
CreateTextMeshPro(obj, data.text);
|
||||||
|
break;
|
||||||
|
case "RectTransform":
|
||||||
|
case "SFUI_Viewport":
|
||||||
|
case "SFUI_Content":
|
||||||
|
CreateRectTransform(obj, data.layoutGroup);
|
||||||
|
break;
|
||||||
|
case "ScrollRect":
|
||||||
|
case "SFUI_ScrollRect":
|
||||||
|
CreateScrollRect(obj, data.scrollRect);
|
||||||
|
break;
|
||||||
|
case "GridLayoutGroup":
|
||||||
|
CreateGridLayoutGroup(obj, data.layoutGroup);
|
||||||
|
break;
|
||||||
|
case "VerticalLayoutGroup":
|
||||||
|
CreateVerticalLayoutGroup(obj, data.layoutGroup);
|
||||||
|
break;
|
||||||
|
case "HorizontalLayoutGroup":
|
||||||
|
CreateHorizontalLayoutGroup(obj, data.layoutGroup);
|
||||||
|
break;
|
||||||
|
case "Toggle":
|
||||||
|
case "SFUI_Toggle":
|
||||||
|
CreateToggle(obj, data.toggle);
|
||||||
|
break;
|
||||||
|
case "Slider":
|
||||||
|
case "SFUI_Slider":
|
||||||
|
CreateSlider(obj, data.slider);
|
||||||
|
break;
|
||||||
|
case "InputField":
|
||||||
|
case "SFUI_InputField":
|
||||||
|
CreateInputField(obj, data.inputField);
|
||||||
|
break;
|
||||||
|
case "CanvasScaler":
|
||||||
|
case "GraphicRaycaster":
|
||||||
|
break;
|
||||||
|
case "SFUI_ListViewItem":
|
||||||
|
CreateListViewItemPlaceholder(obj);
|
||||||
|
break;
|
||||||
|
case "Canvas":
|
||||||
|
case "SFUI_Window":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.children != null)
|
||||||
|
{
|
||||||
|
foreach (var childData in data.children)
|
||||||
|
{
|
||||||
|
CreateUIElement(childData, obj.transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetRectTransform(RectTransform rect, RectTransformData data)
|
||||||
|
{
|
||||||
|
if (data == null) return;
|
||||||
|
|
||||||
|
rect.anchorMin = new Vector2(data.anchorMin[0], data.anchorMin[1]);
|
||||||
|
rect.anchorMax = new Vector2(data.anchorMax[0], data.anchorMax[1]);
|
||||||
|
rect.anchoredPosition3D = new Vector3(data.position[0], data.position[1], data.position[2]);
|
||||||
|
rect.sizeDelta = new Vector2(data.sizeDelta[0], data.sizeDelta[1]);
|
||||||
|
rect.pivot = new Vector2(data.pivot[0], data.pivot[1]);
|
||||||
|
|
||||||
|
if (data.localScale != null && data.localScale.Length >= 3)
|
||||||
|
{
|
||||||
|
rect.localScale = new Vector3(data.localScale[0], data.localScale[1], data.localScale[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.localRotation != null && data.localRotation.Length >= 3)
|
||||||
|
{
|
||||||
|
rect.localEulerAngles = new Vector3(data.localRotation[0], data.localRotation[1], data.localRotation[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateImage(GameObject obj, ImageData data)
|
||||||
|
{
|
||||||
|
if (data == null) return;
|
||||||
|
|
||||||
|
Image image = obj.AddComponent<Image>();
|
||||||
|
if (!string.IsNullOrEmpty(data.sprite))
|
||||||
|
{
|
||||||
|
Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(data.sprite);
|
||||||
|
if (sprite != null)
|
||||||
|
{
|
||||||
|
image.sprite = sprite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
image.type = (Image.Type)Enum.Parse(typeof(Image.Type), data.type);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
image.type = Image.Type.Simple;
|
||||||
|
}
|
||||||
|
|
||||||
|
image.color = new Color(data.color[0], data.color[1], data.color[2], data.color[3]);
|
||||||
|
image.raycastTarget = data.raycastTarget;
|
||||||
|
image.preserveAspect = data.preserveAspect;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateButton(GameObject obj, ButtonData buttonData, ImageData imageData)
|
||||||
|
{
|
||||||
|
Button button = obj.AddComponent<Button>();
|
||||||
|
if (buttonData != null)
|
||||||
|
{
|
||||||
|
button.interactable = buttonData.interactable;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
button.transition = (Selectable.Transition)Enum.Parse(typeof(Selectable.Transition), buttonData.transition);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
button.transition = Selectable.Transition.ColorTint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageData != null)
|
||||||
|
{
|
||||||
|
CreateImage(obj, imageData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateTextMeshPro(GameObject obj, TextData data)
|
||||||
|
{
|
||||||
|
if (data == null) return;
|
||||||
|
|
||||||
|
TextMeshProUGUI text = obj.AddComponent<TextMeshProUGUI>();
|
||||||
|
text.text = data.text;
|
||||||
|
text.fontSize = data.fontSize;
|
||||||
|
text.color = new Color(data.color[0], data.color[1], data.color[2], data.color[3]);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(data.font))
|
||||||
|
{
|
||||||
|
TMP_FontAsset fontAsset = AssetDatabase.LoadAssetAtPath<TMP_FontAsset>(data.font);
|
||||||
|
if (fontAsset != null)
|
||||||
|
{
|
||||||
|
text.font = fontAsset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(data.materialPreset))
|
||||||
|
{
|
||||||
|
Material material = AssetDatabase.LoadAssetAtPath<Material>(data.materialPreset);
|
||||||
|
if (material != null)
|
||||||
|
{
|
||||||
|
text.material = material;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
text.alignment = (TextAlignmentOptions)Enum.Parse(typeof(TextAlignmentOptions), data.alignment);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
text.alignment = TextAlignmentOptions.Center;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
text.verticalAlignment = (VerticalAlignmentOptions)Enum.Parse(typeof(VerticalAlignmentOptions), data.verticalAlignment);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
text.verticalAlignment = VerticalAlignmentOptions.Middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
text.richText = data.richText;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
text.overflowMode = (TextOverflowModes)Enum.Parse(typeof(TextOverflowModes), data.overflowMode);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
text.overflowMode = TextOverflowModes.Truncate;
|
||||||
|
}
|
||||||
|
|
||||||
|
text.enableWordWrapping = data.enableWordWrapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateRectTransform(GameObject obj, LayoutGroupData layoutData)
|
||||||
|
{
|
||||||
|
if (layoutData != null)
|
||||||
|
{
|
||||||
|
switch (layoutData.type)
|
||||||
|
{
|
||||||
|
case "GridLayoutGroup":
|
||||||
|
CreateGridLayoutGroup(obj, layoutData);
|
||||||
|
break;
|
||||||
|
case "VerticalLayoutGroup":
|
||||||
|
CreateVerticalLayoutGroup(obj, layoutData);
|
||||||
|
break;
|
||||||
|
case "HorizontalLayoutGroup":
|
||||||
|
CreateHorizontalLayoutGroup(obj, layoutData);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateGridLayoutGroup(GameObject obj, LayoutGroupData layoutData)
|
||||||
|
{
|
||||||
|
if (layoutData == null) return;
|
||||||
|
|
||||||
|
GridLayoutGroup grid = obj.AddComponent<GridLayoutGroup>();
|
||||||
|
grid.cellSize = new Vector2(layoutData.cellSize[0], layoutData.cellSize[1]);
|
||||||
|
grid.spacing = new Vector2(layoutData.spacing[0], layoutData.spacing[1]);
|
||||||
|
grid.constraint = (GridLayoutGroup.Constraint)layoutData.constraint;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
grid.childAlignment = (TextAnchor)Enum.Parse(typeof(TextAnchor), layoutData.childAlignment);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
grid.childAlignment = TextAnchor.UpperLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
grid.padding = new RectOffset(layoutData.padding[0], layoutData.padding[1], layoutData.padding[2], layoutData.padding[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateVerticalLayoutGroup(GameObject obj, LayoutGroupData layoutData)
|
||||||
|
{
|
||||||
|
if (layoutData == null) return;
|
||||||
|
|
||||||
|
VerticalLayoutGroup vertical = obj.AddComponent<VerticalLayoutGroup>();
|
||||||
|
vertical.spacing = layoutData.spacing[1];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
vertical.childAlignment = (TextAnchor)Enum.Parse(typeof(TextAnchor), layoutData.childAlignment);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
vertical.childAlignment = TextAnchor.UpperLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertical.padding = new RectOffset(layoutData.padding[0], layoutData.padding[1], layoutData.padding[2], layoutData.padding[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateHorizontalLayoutGroup(GameObject obj, LayoutGroupData layoutData)
|
||||||
|
{
|
||||||
|
if (layoutData == null) return;
|
||||||
|
|
||||||
|
HorizontalLayoutGroup horizontal = obj.AddComponent<HorizontalLayoutGroup>();
|
||||||
|
horizontal.spacing = layoutData.spacing[0];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
horizontal.childAlignment = (TextAnchor)Enum.Parse(typeof(TextAnchor), layoutData.childAlignment);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
horizontal.childAlignment = TextAnchor.UpperLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
horizontal.padding = new RectOffset(layoutData.padding[0], layoutData.padding[1], layoutData.padding[2], layoutData.padding[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateScrollRect(GameObject obj, ScrollRectData data)
|
||||||
|
{
|
||||||
|
if (data == null) return;
|
||||||
|
|
||||||
|
ScrollRect scrollRect = obj.AddComponent<ScrollRect>();
|
||||||
|
scrollRect.horizontal = data.horizontal;
|
||||||
|
scrollRect.vertical = data.vertical;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scrollRect.movementType = (ScrollRect.MovementType)Enum.Parse(typeof(ScrollRect.MovementType), data.movementType);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
scrollRect.movementType = ScrollRect.MovementType.Clamped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateToggle(GameObject obj, ToggleData data)
|
||||||
|
{
|
||||||
|
if (data == null) return;
|
||||||
|
|
||||||
|
Toggle toggle = obj.AddComponent<Toggle>();
|
||||||
|
toggle.isOn = data.isOn;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
toggle.toggleTransition = (Toggle.ToggleTransition)Enum.Parse(typeof(Toggle.ToggleTransition), data.toggleTransition);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
toggle.toggleTransition = Toggle.ToggleTransition.Fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
toggle.transition = (Selectable.Transition)Enum.Parse(typeof(Selectable.Transition), data.transition);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
toggle.transition = Selectable.Transition.ColorTint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateSlider(GameObject obj, SliderData data)
|
||||||
|
{
|
||||||
|
if (data == null) return;
|
||||||
|
|
||||||
|
Slider slider = obj.AddComponent<Slider>();
|
||||||
|
slider.minValue = data.minValue;
|
||||||
|
slider.maxValue = data.maxValue;
|
||||||
|
slider.value = data.value;
|
||||||
|
slider.wholeNumbers = data.wholeNumbers;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
slider.direction = (Slider.Direction)Enum.Parse(typeof(Slider.Direction), data.direction);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
slider.direction = Slider.Direction.LeftToRight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateInputField(GameObject obj, InputFieldData data)
|
||||||
|
{
|
||||||
|
if (data == null) return;
|
||||||
|
|
||||||
|
InputField inputField = obj.AddComponent<InputField>();
|
||||||
|
inputField.text = data.text;
|
||||||
|
inputField.characterLimit = data.characterLimit;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
inputField.contentType = (InputField.ContentType)Enum.Parse(typeof(InputField.ContentType), data.contentType);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
inputField.contentType = InputField.ContentType.Standard;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
inputField.inputType = (InputField.InputType)Enum.Parse(typeof(InputField.InputType), data.inputType);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
inputField.inputType = InputField.InputType.Standard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateListViewItemPlaceholder(GameObject obj)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreatePrefab(GameObject root, string path)
|
||||||
|
{
|
||||||
|
string directory = Path.GetDirectoryName(path);
|
||||||
|
if (!Directory.Exists(directory))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrefabUtility.SaveAsPrefabAsset(root, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class UILayoutData
|
||||||
|
{
|
||||||
|
public string name;
|
||||||
|
public string type;
|
||||||
|
public int layer;
|
||||||
|
public RectTransformData rectTransform;
|
||||||
|
public CanvasData canvas;
|
||||||
|
public List<UIElementData> children;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class UIElementData
|
||||||
|
{
|
||||||
|
public string name;
|
||||||
|
public string type;
|
||||||
|
public RectTransformData rectTransform;
|
||||||
|
public ImageData image;
|
||||||
|
public ButtonData button;
|
||||||
|
public TextData text;
|
||||||
|
public LayoutGroupData layoutGroup;
|
||||||
|
public ScrollRectData scrollRect;
|
||||||
|
public ToggleData toggle;
|
||||||
|
public SliderData slider;
|
||||||
|
public InputFieldData inputField;
|
||||||
|
public List<CustomComponentData> customComponents;
|
||||||
|
public List<UIElementData> children;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class RectTransformData
|
||||||
|
{
|
||||||
|
public float[] anchorMin;
|
||||||
|
public float[] anchorMax;
|
||||||
|
public float[] position;
|
||||||
|
public float[] sizeDelta;
|
||||||
|
public float[] pivot;
|
||||||
|
public float[] localScale;
|
||||||
|
public float[] localRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class CanvasData
|
||||||
|
{
|
||||||
|
public string renderMode;
|
||||||
|
public bool pixelPerfect;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class ImageData
|
||||||
|
{
|
||||||
|
public string sprite;
|
||||||
|
public string type;
|
||||||
|
public float[] color;
|
||||||
|
public bool raycastTarget;
|
||||||
|
public bool preserveAspect;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class ButtonData
|
||||||
|
{
|
||||||
|
public bool interactable;
|
||||||
|
public string transition;
|
||||||
|
public string navigationMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class TextData
|
||||||
|
{
|
||||||
|
public string text;
|
||||||
|
public float fontSize;
|
||||||
|
public string font;
|
||||||
|
public string materialPreset;
|
||||||
|
public string alignment;
|
||||||
|
public string verticalAlignment;
|
||||||
|
public float[] color;
|
||||||
|
public bool richText;
|
||||||
|
public string overflowMode;
|
||||||
|
public bool enableWordWrapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class LayoutGroupData
|
||||||
|
{
|
||||||
|
public string type;
|
||||||
|
public float[] cellSize;
|
||||||
|
public float[] spacing;
|
||||||
|
public int constraint;
|
||||||
|
public string childAlignment;
|
||||||
|
public int[] padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class ScrollRectData
|
||||||
|
{
|
||||||
|
public bool horizontal;
|
||||||
|
public bool vertical;
|
||||||
|
public string movementType;
|
||||||
|
public string horizontalScrollbarVisibility;
|
||||||
|
public string verticalScrollbarVisibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class ToggleData
|
||||||
|
{
|
||||||
|
public bool isOn;
|
||||||
|
public string toggleTransition;
|
||||||
|
public string transition;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class SliderData
|
||||||
|
{
|
||||||
|
public float minValue;
|
||||||
|
public float maxValue;
|
||||||
|
public float value;
|
||||||
|
public bool wholeNumbers;
|
||||||
|
public string direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class InputFieldData
|
||||||
|
{
|
||||||
|
public string text;
|
||||||
|
public string placeholder;
|
||||||
|
public int characterLimit;
|
||||||
|
public string contentType;
|
||||||
|
public string inputType;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class CustomComponentData
|
||||||
|
{
|
||||||
|
public string typeName;
|
||||||
|
}
|
||||||
11
06_工具脚本/UI工具/UIPrefabGenerator.cs.meta
Normal file
11
06_工具脚本/UI工具/UIPrefabGenerator.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 31deea0e57bec2f4893548b0a41853cb
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
379
06_工具脚本/UI工具/UIPrefabToJson.cs
Normal file
379
06_工具脚本/UI工具/UIPrefabToJson.cs
Normal file
@@ -0,0 +1,379 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using UnityEditor;
|
||||||
|
using TMPro;
|
||||||
|
|
||||||
|
public static class UIPrefabToJson
|
||||||
|
{
|
||||||
|
[MenuItem("Tools/UI/Export Prefab to JSON")]
|
||||||
|
public static void ExportPrefabToJsonMenu()
|
||||||
|
{
|
||||||
|
string prefabPath = EditorUtility.OpenFilePanel("选择预制体", "Assets", "prefab");
|
||||||
|
if (!string.IsNullOrEmpty(prefabPath))
|
||||||
|
{
|
||||||
|
string projectPath = Application.dataPath.Replace("/Assets", "");
|
||||||
|
string relativePath = prefabPath.Replace(projectPath + "/", "");
|
||||||
|
string jsonPath = relativePath.Replace(".prefab", ".json");
|
||||||
|
ExportPrefabToJson(relativePath, jsonPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ExportPrefabToJson(string prefabPath, string jsonPath = null)
|
||||||
|
{
|
||||||
|
if (!AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath))
|
||||||
|
{
|
||||||
|
Debug.LogError("Prefab not found: " + prefabPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(jsonPath))
|
||||||
|
{
|
||||||
|
jsonPath = prefabPath.Replace(".prefab", ".json");
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
||||||
|
UILayoutData layoutData = ConvertPrefabToLayoutData(prefab);
|
||||||
|
|
||||||
|
string jsonContent = JsonUtility.ToJson(layoutData, true);
|
||||||
|
string fullPath = Path.Combine(Application.dataPath, "..", jsonPath);
|
||||||
|
string directory = Path.GetDirectoryName(fullPath);
|
||||||
|
|
||||||
|
if (!Directory.Exists(directory))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
File.WriteAllText(fullPath, jsonContent);
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
|
||||||
|
Debug.Log("JSON exported successfully: " + jsonPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static UILayoutData ConvertPrefabToLayoutData(GameObject prefab)
|
||||||
|
{
|
||||||
|
UILayoutData data = new UILayoutData();
|
||||||
|
data.name = prefab.name;
|
||||||
|
data.type = "Canvas";
|
||||||
|
data.layer = prefab.layer;
|
||||||
|
|
||||||
|
Canvas canvas = prefab.GetComponent<Canvas>();
|
||||||
|
if (canvas != null)
|
||||||
|
{
|
||||||
|
data.canvas = new CanvasData();
|
||||||
|
data.canvas.renderMode = canvas.renderMode.ToString();
|
||||||
|
data.canvas.pixelPerfect = canvas.pixelPerfect;
|
||||||
|
}
|
||||||
|
|
||||||
|
RectTransform rectTransform = prefab.GetComponent<RectTransform>();
|
||||||
|
if (rectTransform != null)
|
||||||
|
{
|
||||||
|
data.rectTransform = ConvertRectTransform(rectTransform);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.children = new List<UIElementData>();
|
||||||
|
foreach (Transform child in prefab.transform)
|
||||||
|
{
|
||||||
|
UIElementData childData = ConvertTransformToElement(child);
|
||||||
|
if (childData != null)
|
||||||
|
{
|
||||||
|
data.children.Add(childData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static UIElementData ConvertTransformToElement(Transform transform)
|
||||||
|
{
|
||||||
|
UIElementData data = new UIElementData();
|
||||||
|
data.name = transform.name;
|
||||||
|
|
||||||
|
RectTransform rectTransform = transform.GetComponent<RectTransform>();
|
||||||
|
if (rectTransform != null)
|
||||||
|
{
|
||||||
|
data.rectTransform = ConvertRectTransform(rectTransform);
|
||||||
|
}
|
||||||
|
|
||||||
|
Component[] components = transform.GetComponents<Component>();
|
||||||
|
List<string> componentTypes = new List<string>();
|
||||||
|
|
||||||
|
foreach (Component comp in components)
|
||||||
|
{
|
||||||
|
if (comp == null) continue;
|
||||||
|
|
||||||
|
string compTypeName = comp.GetType().Name;
|
||||||
|
componentTypes.Add(compTypeName);
|
||||||
|
|
||||||
|
switch (compTypeName)
|
||||||
|
{
|
||||||
|
case "Image":
|
||||||
|
case "SFUI_Image":
|
||||||
|
data.type = compTypeName;
|
||||||
|
data.image = ConvertImage((Image)comp);
|
||||||
|
break;
|
||||||
|
case "Button":
|
||||||
|
case "SFUI_Button":
|
||||||
|
data.type = compTypeName;
|
||||||
|
data.button = ConvertButton((Button)comp);
|
||||||
|
break;
|
||||||
|
case "TextMeshProUGUI":
|
||||||
|
case "SFUI_TextMeshProUGUI":
|
||||||
|
data.type = compTypeName;
|
||||||
|
data.text = ConvertText((TextMeshProUGUI)comp);
|
||||||
|
break;
|
||||||
|
case "ScrollRect":
|
||||||
|
case "SFUI_ScrollRect":
|
||||||
|
data.type = compTypeName;
|
||||||
|
data.scrollRect = ConvertScrollRect((ScrollRect)comp);
|
||||||
|
break;
|
||||||
|
case "GridLayoutGroup":
|
||||||
|
data.type = compTypeName;
|
||||||
|
data.layoutGroup = ConvertGridLayoutGroup((GridLayoutGroup)comp);
|
||||||
|
break;
|
||||||
|
case "VerticalLayoutGroup":
|
||||||
|
data.type = compTypeName;
|
||||||
|
data.layoutGroup = ConvertVerticalLayoutGroup((VerticalLayoutGroup)comp);
|
||||||
|
break;
|
||||||
|
case "HorizontalLayoutGroup":
|
||||||
|
data.type = compTypeName;
|
||||||
|
data.layoutGroup = ConvertHorizontalLayoutGroup((HorizontalLayoutGroup)comp);
|
||||||
|
break;
|
||||||
|
case "Toggle":
|
||||||
|
case "SFUI_Toggle":
|
||||||
|
data.type = compTypeName;
|
||||||
|
data.toggle = ConvertToggle((Toggle)comp);
|
||||||
|
break;
|
||||||
|
case "Slider":
|
||||||
|
case "SFUI_Slider":
|
||||||
|
data.type = compTypeName;
|
||||||
|
data.slider = ConvertSlider((Slider)comp);
|
||||||
|
break;
|
||||||
|
case "InputField":
|
||||||
|
case "SFUI_InputField":
|
||||||
|
data.type = compTypeName;
|
||||||
|
data.inputField = ConvertInputField((InputField)comp);
|
||||||
|
break;
|
||||||
|
case "RectTransform":
|
||||||
|
if (string.IsNullOrEmpty(data.type))
|
||||||
|
data.type = compTypeName;
|
||||||
|
break;
|
||||||
|
case "Canvas":
|
||||||
|
if (string.IsNullOrEmpty(data.type))
|
||||||
|
data.type = compTypeName;
|
||||||
|
break;
|
||||||
|
case "CanvasScaler":
|
||||||
|
data.type = compTypeName;
|
||||||
|
break;
|
||||||
|
case "GraphicRaycaster":
|
||||||
|
data.type = compTypeName;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (compTypeName != "Transform" && compTypeName != "RectTransform")
|
||||||
|
{
|
||||||
|
if (data.customComponents == null)
|
||||||
|
data.customComponents = new List<CustomComponentData>();
|
||||||
|
data.customComponents.Add(ConvertCustomComponent(comp));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(data.type))
|
||||||
|
{
|
||||||
|
data.type = "Transform";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transform.childCount > 0)
|
||||||
|
{
|
||||||
|
data.children = new List<UIElementData>();
|
||||||
|
foreach (Transform child in transform)
|
||||||
|
{
|
||||||
|
UIElementData childData = ConvertTransformToElement(child);
|
||||||
|
if (childData != null)
|
||||||
|
{
|
||||||
|
data.children.Add(childData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RectTransformData ConvertRectTransform(RectTransform rect)
|
||||||
|
{
|
||||||
|
RectTransformData data = new RectTransformData();
|
||||||
|
data.anchorMin = new float[] { rect.anchorMin.x, rect.anchorMin.y };
|
||||||
|
data.anchorMax = new float[] { rect.anchorMax.x, rect.anchorMax.y };
|
||||||
|
data.position = new float[] { rect.anchoredPosition3D.x, rect.anchoredPosition3D.y, rect.anchoredPosition3D.z };
|
||||||
|
data.sizeDelta = new float[] { rect.sizeDelta.x, rect.sizeDelta.y };
|
||||||
|
data.pivot = new float[] { rect.pivot.x, rect.pivot.y };
|
||||||
|
data.localScale = new float[] { rect.localScale.x, rect.localScale.y, rect.localScale.z };
|
||||||
|
data.localRotation = new float[] { rect.localEulerAngles.x, rect.localEulerAngles.y, rect.localEulerAngles.z };
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ImageData ConvertImage(Image image)
|
||||||
|
{
|
||||||
|
ImageData data = new ImageData();
|
||||||
|
data.type = image.type.ToString();
|
||||||
|
data.color = new float[] { image.color.r, image.color.g, image.color.b, image.color.a };
|
||||||
|
data.raycastTarget = image.raycastTarget;
|
||||||
|
data.preserveAspect = image.preserveAspect;
|
||||||
|
|
||||||
|
if (image.sprite != null)
|
||||||
|
{
|
||||||
|
string spritePath = AssetDatabase.GetAssetPath(image.sprite);
|
||||||
|
if (!string.IsNullOrEmpty(spritePath))
|
||||||
|
{
|
||||||
|
data.sprite = spritePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ButtonData ConvertButton(Button button)
|
||||||
|
{
|
||||||
|
ButtonData data = new ButtonData();
|
||||||
|
data.interactable = button.interactable;
|
||||||
|
data.transition = button.transition.ToString();
|
||||||
|
data.navigationMode = button.navigation.mode.ToString();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TextData ConvertText(TextMeshProUGUI text)
|
||||||
|
{
|
||||||
|
TextData data = new TextData();
|
||||||
|
data.text = text.text;
|
||||||
|
data.fontSize = text.fontSize;
|
||||||
|
data.color = new float[] { text.color.r, text.color.g, text.color.b, text.color.a };
|
||||||
|
data.alignment = text.alignment.ToString();
|
||||||
|
data.verticalAlignment = text.verticalAlignment.ToString();
|
||||||
|
data.richText = text.richText;
|
||||||
|
data.overflowMode = text.overflowMode.ToString();
|
||||||
|
data.enableWordWrapping = text.enableWordWrapping;
|
||||||
|
|
||||||
|
if (text.font != null)
|
||||||
|
{
|
||||||
|
string fontPath = AssetDatabase.GetAssetPath(text.font);
|
||||||
|
if (!string.IsNullOrEmpty(fontPath))
|
||||||
|
{
|
||||||
|
data.font = fontPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text.material != null)
|
||||||
|
{
|
||||||
|
string materialPath = AssetDatabase.GetAssetPath(text.material);
|
||||||
|
if (!string.IsNullOrEmpty(materialPath))
|
||||||
|
{
|
||||||
|
data.materialPreset = materialPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ScrollRectData ConvertScrollRect(ScrollRect scrollRect)
|
||||||
|
{
|
||||||
|
ScrollRectData data = new ScrollRectData();
|
||||||
|
data.horizontal = scrollRect.horizontal;
|
||||||
|
data.vertical = scrollRect.vertical;
|
||||||
|
data.movementType = scrollRect.movementType.ToString();
|
||||||
|
data.horizontalScrollbarVisibility = scrollRect.horizontalScrollbarVisibility.ToString();
|
||||||
|
data.verticalScrollbarVisibility = scrollRect.verticalScrollbarVisibility.ToString();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LayoutGroupData ConvertGridLayoutGroup(GridLayoutGroup layout)
|
||||||
|
{
|
||||||
|
LayoutGroupData data = new LayoutGroupData();
|
||||||
|
data.type = "GridLayoutGroup";
|
||||||
|
data.cellSize = new float[] { layout.cellSize.x, layout.cellSize.y };
|
||||||
|
data.spacing = new float[] { layout.spacing.x, layout.spacing.y };
|
||||||
|
data.constraint = (int)layout.constraint;
|
||||||
|
data.childAlignment = layout.childAlignment.ToString();
|
||||||
|
data.padding = new int[] { layout.padding.left, layout.padding.right, layout.padding.top, layout.padding.bottom };
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LayoutGroupData ConvertVerticalLayoutGroup(VerticalLayoutGroup layout)
|
||||||
|
{
|
||||||
|
LayoutGroupData data = new LayoutGroupData();
|
||||||
|
data.type = "VerticalLayoutGroup";
|
||||||
|
data.spacing = new float[] { layout.spacing, layout.spacing };
|
||||||
|
data.childAlignment = layout.childAlignment.ToString();
|
||||||
|
data.padding = new int[] { layout.padding.left, layout.padding.right, layout.padding.top, layout.padding.bottom };
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LayoutGroupData ConvertHorizontalLayoutGroup(HorizontalLayoutGroup layout)
|
||||||
|
{
|
||||||
|
LayoutGroupData data = new LayoutGroupData();
|
||||||
|
data.type = "HorizontalLayoutGroup";
|
||||||
|
data.spacing = new float[] { layout.spacing, layout.spacing };
|
||||||
|
data.childAlignment = layout.childAlignment.ToString();
|
||||||
|
data.padding = new int[] { layout.padding.left, layout.padding.right, layout.padding.top, layout.padding.bottom };
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ToggleData ConvertToggle(Toggle toggle)
|
||||||
|
{
|
||||||
|
ToggleData data = new ToggleData();
|
||||||
|
data.isOn = toggle.isOn;
|
||||||
|
data.toggleTransition = toggle.toggleTransition.ToString();
|
||||||
|
data.transition = toggle.transition.ToString();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SliderData ConvertSlider(Slider slider)
|
||||||
|
{
|
||||||
|
SliderData data = new SliderData();
|
||||||
|
data.minValue = slider.minValue;
|
||||||
|
data.maxValue = slider.maxValue;
|
||||||
|
data.value = slider.value;
|
||||||
|
data.wholeNumbers = slider.wholeNumbers;
|
||||||
|
data.direction = slider.direction.ToString();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InputFieldData ConvertInputField(InputField inputField)
|
||||||
|
{
|
||||||
|
InputFieldData data = new InputFieldData();
|
||||||
|
data.text = inputField.text;
|
||||||
|
|
||||||
|
if (inputField.placeholder != null)
|
||||||
|
{
|
||||||
|
Text textPlaceholder = inputField.placeholder as Text;
|
||||||
|
if (textPlaceholder != null)
|
||||||
|
{
|
||||||
|
data.placeholder = textPlaceholder.text;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TextMeshProUGUI tmpPlaceholder = inputField.placeholder as TextMeshProUGUI;
|
||||||
|
if (tmpPlaceholder != null)
|
||||||
|
{
|
||||||
|
data.placeholder = tmpPlaceholder.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.characterLimit = inputField.characterLimit;
|
||||||
|
data.contentType = inputField.contentType.ToString();
|
||||||
|
data.inputType = inputField.inputType.ToString();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CustomComponentData ConvertCustomComponent(Component comp)
|
||||||
|
{
|
||||||
|
CustomComponentData data = new CustomComponentData();
|
||||||
|
data.typeName = comp.GetType().Name;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
06_工具脚本/UI工具/UIPrefabToJson.cs.meta
Normal file
11
06_工具脚本/UI工具/UIPrefabToJson.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 33906f611de8963438be24b30bc8592e
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Reference in New Issue
Block a user