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

238 lines
7.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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");
}
}
}