NLDClient-yudde/ProjectNLD/Assets/Editor/UIInfoBuilder/UIInfoExtractor.cs

238 lines
7.9 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UIInfoBuilder.ComponentExtractors;
using UIInfoBuilder.Data;
using UnityEditor;
using UnityEngine;
namespace UIInfoBuilder
{
public class UIInfoExtractor
{
private static readonly List<IComponentExtractor> _extractors = new List<IComponentExtractor>();
private static readonly DefaultComponentExtractor _defaultExtractor = new DefaultComponentExtractor();
static UIInfoExtractor()
{
// 注册特殊组件提取器(优先级高的放前面)
_extractors.Add(new RectTransformExtractor());
_extractors.Add(new ImageExtractor());
_extractors.Add(new TextExtractor());
_extractors.Add(new ButtonExtractor());
}
[MenuItem("Assets/UIInfoBuilder/ExtractPrefab")]
private static void _AssetHandle()
{
var selectedObjects = Selection.gameObjects;
foreach (var obj in selectedObjects)
{
string savePath = Application.dataPath + "/../ExtractedPrefabs/" + obj.name + ".json";
ExtractPrefab(obj, savePath);
Debug.Log($"[UIInfoBuilder] Extracted: {obj.name} -> {savePath}");
}
}
/// <summary>
/// 提取 Prefab 信息并保存为 JSON
/// </summary>
public static void ExtractPrefab(GameObject prefab, string savePath)
{
var rootNode = _ExtractNode(prefab);
_SaveToJson(rootNode, savePath);
}
/// <summary>
/// 递归提取节点信息
/// </summary>
private static UIInfoNode _ExtractNode(GameObject go)
{
var node = new UIInfoNode
{
name = go.name,
active = go.activeSelf
};
// 提取所有组件
var components = go.GetComponents<Component>();
foreach (var component in components)
{
if (component == null)
continue;
var compInfo = _ExtractComponent(component);
node.components.Add(compInfo);
}
// 递归提取子节点
for (int i = 0; i < go.transform.childCount; i++)
{
var child = go.transform.GetChild(i).gameObject;
var childNode = _ExtractNode(child);
node.children.Add(childNode);
}
return node;
}
/// <summary>
/// 提取单个组件信息
/// </summary>
private static UIInfoComponent _ExtractComponent(Component component)
{
var info = new UIInfoComponent
{
componentName = component.GetType().Name,
enable = _GetComponentEnabled(component)
};
// 查找匹配的特殊提取器
IComponentExtractor extractor = null;
foreach (var ext in _extractors)
{
if (ext.CanExtract(component))
{
extractor = ext;
break;
}
}
// 使用特殊提取器或默认提取器
if (extractor != null)
{
extractor.Extract(component, info);
}
else
{
_defaultExtractor.Extract(component, info);
}
return info;
}
/// <summary>
/// 获取组件的启用状态
/// </summary>
private static bool _GetComponentEnabled(Component component)
{
// Behaviour 类型的组件有 enabled 属性
if (component is Behaviour behaviour)
{
return behaviour.enabled;
}
// Renderer 类型的组件有 enabled 属性
if (component is Renderer renderer)
{
return renderer.enabled;
}
// Collider 类型的组件有 enabled 属性
if (component is Collider collider)
{
return collider.enabled;
}
// 其他组件默认返回 true
return true;
}
/// <summary>
/// 保存为 JSON 文件
/// </summary>
private static void _SaveToJson(UIInfoNode node, string savePath)
{
// 确保目录存在
string directory = Path.GetDirectoryName(savePath);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
// 使用自定义递归序列化JsonUtility 不支持嵌套 List 递归)
var sb = new StringBuilder();
_SerializeNode(node, sb, 0);
File.WriteAllText(savePath, sb.ToString());
}
/// <summary>
/// 递归序列化节点为 JSON
/// </summary>
private static void _SerializeNode(UIInfoNode node, StringBuilder sb, int indent)
{
string indentStr = new string(' ', indent * 2);
string indentStr1 = new string(' ', (indent + 1) * 2);
string indentStr2 = new string(' ', (indent + 2) * 2);
string indentStr3 = new string(' ', (indent + 3) * 2);
sb.AppendLine($"{indentStr}{{");
sb.AppendLine($"{indentStr1}\"name\": \"{_EscapeJsonString(node.name)}\",");
sb.AppendLine($"{indentStr1}\"active\": {node.active.ToString().ToLower()},");
// Components
sb.AppendLine($"{indentStr1}\"components\": [");
for (int i = 0; i < node.components.Count; i++)
{
var comp = node.components[i];
sb.AppendLine($"{indentStr2}{{");
sb.AppendLine($"{indentStr3}\"componentName\": \"{_EscapeJsonString(comp.componentName)}\",");
sb.AppendLine($"{indentStr3}\"enable\": {comp.enable.ToString().ToLower()},");
sb.Append($"{indentStr3}\"properties\": [");
if (comp.properties.Count > 0)
{
sb.AppendLine();
for (int j = 0; j < comp.properties.Count; j++)
{
string comma = j < comp.properties.Count - 1 ? "," : "";
sb.AppendLine($"{indentStr3} \"{_EscapeJsonString(comp.properties[j])}\"{comma}");
}
sb.AppendLine($"{indentStr3}]");
}
else
{
sb.AppendLine("]");
}
string compComma = i < node.components.Count - 1 ? "," : "";
sb.AppendLine($"{indentStr2}}}{compComma}");
}
sb.AppendLine($"{indentStr1}],");
// Children
sb.AppendLine($"{indentStr1}\"children\": [");
for (int i = 0; i < node.children.Count; i++)
{
_SerializeNode(node.children[i], sb, indent + 2);
if (i < node.children.Count - 1)
{
// 在上一个 } 后面加逗号
sb.Length -= Environment.NewLine.Length; // 移除换行
sb.AppendLine(",");
}
}
sb.AppendLine($"{indentStr1}]");
sb.AppendLine($"{indentStr}}}");
}
/// <summary>
/// 转义 JSON 字符串中的特殊字符
/// </summary>
private static string _EscapeJsonString(string str)
{
if (string.IsNullOrEmpty(str))
return str;
return str
.Replace("\\", "\\\\")
.Replace("\"", "\\\"")
.Replace("\n", "\\n")
.Replace("\r", "\\r")
.Replace("\t", "\\t");
}
}
}