700 lines
27 KiB
C#
700 lines
27 KiB
C#
/*
|
||
* @Author: 白哉
|
||
* @Description:
|
||
* @Date: 2025年05月26日 星期一 17:05:14
|
||
* @Modify:
|
||
*/
|
||
|
||
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using System.Text;
|
||
using System.Text.RegularExpressions;
|
||
using Logic.Multilingual;
|
||
using TMPro;
|
||
using UnityEditor;
|
||
using UnityEngine;
|
||
using Debug = UnityEngine.Debug;
|
||
using Object = UnityEngine.Object;
|
||
|
||
|
||
namespace Logic.Editor
|
||
{
|
||
public class MultilingualEditorWindow : EditorWindow
|
||
{
|
||
// 滑条
|
||
private Vector2 _barPosition;
|
||
|
||
// 背景
|
||
private GUIStyle _redBoxStyle;
|
||
private GUIStyle _whiteBoxStyle;
|
||
|
||
private MultilingualData _asset;
|
||
|
||
private Dictionary<string, uint> _zhStrDict = new Dictionary<string, uint>();
|
||
private HashSet<uint> _activeSet = new HashSet<uint>();
|
||
private uint _idIndex;
|
||
private int _showIndex = 0;
|
||
private List<TMP_FontAsset> _assets = new List<TMP_FontAsset>();
|
||
private HashSet<char> characterSet = new HashSet<char>();
|
||
|
||
|
||
[MenuItem("Tools/多语言编辑器")]
|
||
private static void ShowWindow()
|
||
{
|
||
var window = CreateWindow<MultilingualEditorWindow>();
|
||
window.titleContent = new GUIContent("多语言编辑器");
|
||
window.Show();
|
||
window.minSize = new Vector2(500, 600);
|
||
}
|
||
|
||
protected virtual void OnEnable()
|
||
{
|
||
|
||
}
|
||
|
||
private void OnDisable()
|
||
{
|
||
|
||
}
|
||
|
||
private void OnGUI()
|
||
{
|
||
if (!_asset)
|
||
{
|
||
var path = $"Assets/Resources/Export/Multilingual.asset";
|
||
_asset = AssetDatabase.LoadAssetAtPath<MultilingualData>(path);
|
||
if (!_asset)
|
||
{
|
||
_asset = CreateInstance<MultilingualData>();
|
||
AssetDatabase.CreateAsset(_asset, path);
|
||
AssetDatabase.SaveAssets();
|
||
AssetDatabase.Refresh();
|
||
}
|
||
}
|
||
|
||
if (_assets.Count == 0)
|
||
{
|
||
var pathList = new List<string>();
|
||
pathList.Add($"Assets/Fonts/SourceHanSansCN-Bold SDF.asset");
|
||
pathList.Add($"Assets/Fonts/SourceHanSansCN-ExtraLight SDF.asset");
|
||
pathList.Add($"Assets/Fonts/SourceHanSansCN-Regular SDF.asset");
|
||
foreach (var path in pathList)
|
||
{
|
||
var asset = AssetDatabase.LoadAssetAtPath<TMP_FontAsset>(path);
|
||
if (asset) _assets.Add(asset);
|
||
}
|
||
}
|
||
|
||
if (_redBoxStyle == null)
|
||
{
|
||
_redBoxStyle = InspectorUtils.GetHelpBoxStyle();
|
||
InspectorUtils.AddBorder(_redBoxStyle, new Color(0.5f, 0.4f, 0.4f, 0.6f));
|
||
}
|
||
|
||
if (_whiteBoxStyle == null)
|
||
{
|
||
_whiteBoxStyle = InspectorUtils.GetHelpBoxStyle();
|
||
InspectorUtils.AddBorder(_whiteBoxStyle, new Color(1f, 1f, 1f, 0.2f));
|
||
}
|
||
|
||
GUI.skin.button.wordWrap = true;
|
||
_barPosition = EditorGUILayout.BeginScrollView(_barPosition);
|
||
|
||
EditorGUILayout.BeginHorizontal();
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("保存"))
|
||
{
|
||
EditorUtility.SetDirty(_asset);
|
||
AssetDatabase.SaveAssets();
|
||
AssetDatabase.Refresh();
|
||
}
|
||
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("清空"))
|
||
{
|
||
_asset.Items.Clear();
|
||
_asset.RefreshDict();
|
||
}
|
||
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("导出 Excel"))
|
||
{
|
||
AssetExportToExcel();
|
||
}
|
||
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("Excel 导回"))
|
||
{
|
||
ExcelExportToAsset();
|
||
}
|
||
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("生成基础配置(中文字体)"))
|
||
{
|
||
var uiObj = GameObject.Find("UICanvas");
|
||
var coms = uiObj.GetComponentsInChildren<MultilingualTextMono>(true).ToList();
|
||
foreach (var com in coms)
|
||
{
|
||
var textCom = com.gameObject.GetComponent<TextMeshProUGUI>();
|
||
if (!textCom) continue;
|
||
if (com.GetMultiTextConfig(MultilingualType.ZH) == null)
|
||
{
|
||
var cfg = new MultiTextConfig(textCom, MultilingualType.ZH);
|
||
com.TextCfg.Add(cfg);
|
||
}
|
||
|
||
if (com.FontID == 0) com.FontID = _asset.GetFontGroupID(textCom.font);
|
||
}
|
||
}
|
||
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("清除预览"))
|
||
{
|
||
var uiObj = GameObject.Find("UICanvas");
|
||
var coms = uiObj.GetComponentsInChildren<MultilingualTextMono>(true).ToList();
|
||
foreach (var com in coms)
|
||
{
|
||
var text = _asset.GetMultilingualStr(com.ID, MultilingualType.ZH);
|
||
var font = _asset.GetMultilingualFont(com.FontID, MultilingualType.ZH);
|
||
com.SetMultilingualText(text, MultilingualType.ZH, font);
|
||
var textCom = com.GetComponent<TextMeshProUGUI>();
|
||
textCom?.ForceMeshUpdate();
|
||
}
|
||
}
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
EditorGUILayout.BeginHorizontal();
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("添加字体组"))
|
||
{
|
||
_asset.FontGroups.Add(new MultilingualFontGroup());
|
||
}
|
||
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("检查字符集是否有新增"))
|
||
{
|
||
string path = "Assets/Fonts/ChineseCharSet.txt";
|
||
if (string.IsNullOrEmpty(path))
|
||
{
|
||
EditorUtility.DisplayDialog("字符集提示", "找不到字符集TXT", "确定");
|
||
}
|
||
else
|
||
{
|
||
characterSet.Clear();
|
||
string content = System.IO.File.ReadAllText(path);
|
||
foreach (var c in content) characterSet.Add(c);
|
||
bool isNeedUpdate = false;
|
||
foreach (var item in _asset.Items)
|
||
{
|
||
foreach (var c in item.ZH)
|
||
{
|
||
if (!IsChinese(c)) continue;
|
||
if (!characterSet.Contains(c)) isNeedUpdate = true;
|
||
}
|
||
}
|
||
if (isNeedUpdate)EditorUtility.DisplayDialog("字符集提示", "有新增,请创建新的字符集TXT", "确定");
|
||
else EditorUtility.DisplayDialog("字符集提示", "无新增,无需理会", "确定");
|
||
}
|
||
}
|
||
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("创建新的字符集TXT"))
|
||
{
|
||
OnBuildChineseTxt();
|
||
}
|
||
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
EditorGUILayout.BeginVertical(_whiteBoxStyle);
|
||
if (_asset.TargetTypes.Count != 5)
|
||
{
|
||
_asset.TargetTypes.Clear();
|
||
for (int i = (int)MultilingualType.ZH; i <= (int)MultilingualType.KR; i++)
|
||
_asset.TargetTypes.Add((MultilingualType)i);
|
||
}
|
||
|
||
for (int i = 0; i < _asset.TargetTypes.Count; i++)
|
||
{
|
||
EditorGUILayout.BeginHorizontal();
|
||
var type = (MultilingualType)(i + 1);
|
||
InspectorUtils.InspectorTextWidthRich($"<b>系统语言{type} 对应游戏语言: </b>");
|
||
_asset.TargetTypes[i] = (MultilingualType)EditorGUILayout.EnumPopup(_asset.TargetTypes[i], GUILayout.Width(200));
|
||
EditorGUILayout.EndHorizontal();
|
||
}
|
||
EditorGUILayout.EndVertical();
|
||
|
||
foreach (var asset in _assets)
|
||
{
|
||
EditorGUILayout.BeginHorizontal();
|
||
if (InspectorUtils.InspectorButtonWithTextWidth($"·")) Selection.activeObject = asset;
|
||
EditorGUI.BeginDisabledGroup(true); // 开始禁用组
|
||
EditorGUILayout.ObjectField(asset, typeof(TMP_FontAsset), GUILayout.Width(400));
|
||
EditorGUI.EndDisabledGroup(); // 结束禁用组
|
||
EditorGUILayout.EndHorizontal();
|
||
}
|
||
|
||
var deleteSet = new HashSet<MultilingualFontGroup>();
|
||
for (int i = 0; i < _asset.FontGroups.Count; i++)
|
||
{
|
||
_asset.FontGroups[i].FontID = (uint)i + 1;
|
||
if (!ShowFontGroup(_asset.FontGroups[i])) continue;
|
||
deleteSet.Add(_asset.FontGroups[i]);
|
||
}
|
||
foreach (var deleteGroup in deleteSet) _asset.FontGroups.Remove(deleteGroup);
|
||
ShowAllMultilingualItem();
|
||
EditorGUILayout.EndScrollView();
|
||
}
|
||
|
||
private void ShowAllMultilingualItem()
|
||
{
|
||
int maxIndex = (_asset.Items.Count - 1) / 10;
|
||
_showIndex = Mathf.Clamp(_showIndex, 0, maxIndex);
|
||
|
||
EditorGUILayout.BeginHorizontal();
|
||
if (_showIndex > 0 && InspectorUtils.InspectorButtonWithTextWidth("上一页")) _showIndex--;
|
||
if (_showIndex < maxIndex && InspectorUtils.InspectorButtonWithTextWidth("下一页")) _showIndex++;
|
||
EditorGUILayout.EndHorizontal();
|
||
for (int i = _showIndex * 10; i < (_showIndex + 1) * 10; i++)
|
||
{
|
||
if (i < 0 || i >= _asset.Items.Count) continue;
|
||
ShowMultilingualItem(_asset.Items[i]);
|
||
}
|
||
}
|
||
|
||
private bool ShowFontGroup(MultilingualFontGroup fontGroup)
|
||
{
|
||
var isDelete = false;
|
||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||
EditorGUILayout.BeginHorizontal();
|
||
InspectorUtils.InspectorTextWidthRich($"<b>ID : {fontGroup.FontID}</b>");
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("x")) isDelete = true;
|
||
EditorGUILayout.EndHorizontal();
|
||
fontGroup.ZHFont =
|
||
(TMP_FontAsset)EditorGUILayout.ObjectField(fontGroup.ZHFont, typeof(TMP_FontAsset), false, GUILayout.Width(400));
|
||
fontGroup.TDZHFont =
|
||
(TMP_FontAsset)EditorGUILayout.ObjectField(fontGroup.TDZHFont, typeof(TMP_FontAsset), false, GUILayout.Width(400));
|
||
fontGroup.ENFont =
|
||
(TMP_FontAsset)EditorGUILayout.ObjectField(fontGroup.ENFont, typeof(TMP_FontAsset), false, GUILayout.Width(400));
|
||
fontGroup.JPFont =
|
||
(TMP_FontAsset)EditorGUILayout.ObjectField(fontGroup.JPFont, typeof(TMP_FontAsset), false, GUILayout.Width(400));
|
||
fontGroup.KRFont =
|
||
(TMP_FontAsset)EditorGUILayout.ObjectField(fontGroup.KRFont, typeof(TMP_FontAsset), false, GUILayout.Width(400));
|
||
EditorGUILayout.EndVertical();
|
||
EditorGUILayout.Space();
|
||
return isDelete;
|
||
}
|
||
|
||
private void ShowMultilingualItem(MultilingualItem item)
|
||
{
|
||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||
InspectorUtils.InspectorTextWidthRich($"<b>{item.ID} : </b>");
|
||
InspectorUtils.InspectorTextWidthRich($" <b>中文:</b> {item.ZH}");
|
||
if (!string.IsNullOrEmpty(item.TDZH))
|
||
InspectorUtils.InspectorTextWidthRich($" <b>繁中:</b> {item.TDZH}");
|
||
if (!string.IsNullOrEmpty(item.EN))
|
||
InspectorUtils.InspectorTextWidthRich($" <b>英语:</b> {item.EN}");
|
||
if (!string.IsNullOrEmpty(item.JP))
|
||
InspectorUtils.InspectorTextWidthRich($" <b>日语:</b> {item.JP}");
|
||
if (!string.IsNullOrEmpty(item.KR))
|
||
InspectorUtils.InspectorTextWidthRich($" <b>韩语:</b> {item.KR}");
|
||
var unicode = "";
|
||
foreach (var c in item.ZH) unicode += $"{(int)c:X4} ";
|
||
InspectorUtils.InspectorTextWidthRich($" <b>Unicode:</b> {unicode}");
|
||
EditorGUILayout.EndVertical();
|
||
EditorGUILayout.Space();
|
||
}
|
||
|
||
private void DuplicateRemoval()
|
||
{
|
||
// 排序 asset.items 保证id从小到大
|
||
_asset.Items = _asset.Items.OrderBy(i => i.ID).ToList();
|
||
_zhStrDict.Clear();
|
||
var deleteItem = new HashSet<MultilingualItem>();
|
||
foreach (var item in _asset.Items)
|
||
{
|
||
item.Refresh();
|
||
if (_zhStrDict.ContainsKey(item.ZH))
|
||
{
|
||
deleteItem.Add(item);
|
||
continue;
|
||
}
|
||
|
||
_zhStrDict[item.ZH] = item.ID;
|
||
}
|
||
|
||
foreach (var item in deleteItem) _asset.Items.Remove(item);
|
||
_asset.RefreshDict();
|
||
}
|
||
|
||
private string RemoveCsvQuotes(string field)
|
||
{
|
||
if (string.IsNullOrEmpty(field)) return field;
|
||
// 去除首尾空格和换行符
|
||
field = field.Trim();
|
||
// 若字段以引号开头和结尾,则去除引号并处理内部转义
|
||
if (field.Length >= 2 && field.StartsWith("\"") && field.EndsWith("\""))
|
||
{
|
||
field = field.Substring(1, field.Length - 2) // 去除首尾引号
|
||
.Replace("\"\"", "\""); // 将转义引号还原为单个引号
|
||
}
|
||
|
||
return field;
|
||
}
|
||
|
||
private void ExcelExportToAsset()
|
||
{
|
||
GetExcelData();
|
||
_asset.RefreshDict();
|
||
|
||
string context;
|
||
using (var reader = new StreamReader("../Tools/MultilingualTxt.txt", Encoding.Default, true))
|
||
{
|
||
context = reader.ReadToEnd();
|
||
}
|
||
|
||
var lines = context.Split("!@#$%");
|
||
foreach (string line in lines)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(line)) continue; // 跳过空行
|
||
string[] cells = line.Split("%$#@!");
|
||
if (cells.Length == 0) continue;
|
||
|
||
var id = uint.Parse(cells[0]);
|
||
MultilingualItem item;
|
||
if (_asset.ItemDict.TryGetValue(id, out var value)) item = value;
|
||
else
|
||
{
|
||
item = new MultilingualItem();
|
||
_asset.Items.Add(item);
|
||
}
|
||
|
||
item.ID = id;
|
||
if (cells.Length >= 2) item.ZH = RemoveCsvQuotes(cells[1]);
|
||
if (cells.Length >= 3) item.TDZH = RemoveCsvQuotes(cells[2]);
|
||
if (cells.Length >= 4) item.EN = RemoveCsvQuotes(cells[3]);
|
||
if (cells.Length >= 5) item.JP = RemoveCsvQuotes(cells[4]);
|
||
if (cells.Length >= 6) item.KR = RemoveCsvQuotes(cells[5]);
|
||
}
|
||
|
||
EditorUtility.SetDirty(_asset);
|
||
AssetDatabase.SaveAssets();
|
||
AssetDatabase.Refresh();
|
||
}
|
||
|
||
private void AssetExportToExcel()
|
||
{
|
||
DuplicateRemoval();
|
||
_zhStrDict.Clear();
|
||
_activeSet.Clear();
|
||
foreach (var item in _asset.Items) _zhStrDict[item.ZH] = item.ID;
|
||
if (_asset.Items.Count != 0) _idIndex = _asset.Items[^1].ID + 1;
|
||
else _idIndex = 1;
|
||
|
||
var uiObj = GameObject.Find("UICanvas");
|
||
if (!uiObj)
|
||
{
|
||
Debug.LogError($"找不到UI根节点");
|
||
return;
|
||
}
|
||
|
||
var coms = uiObj.GetComponentsInChildren<TextMeshProUGUI>(true).ToList();
|
||
// 处理 Assets/Resources/Prefab 路径下的所有 prefab
|
||
var prefabList = new List<GameObject>();
|
||
var prefabPath = $"Assets/Resources/Prefab/";
|
||
if (Directory.Exists(prefabPath))
|
||
{
|
||
string[] prefabPaths = Directory.GetFiles(prefabPath, "*.prefab", SearchOption.AllDirectories);
|
||
foreach (var prefabAssetPath in prefabPaths)
|
||
{
|
||
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabAssetPath);
|
||
if (!prefab) continue;
|
||
|
||
var prefabComs = prefab.GetComponentsInChildren<TextMeshProUGUI>(true).ToList();
|
||
if (prefabComs.Count == 0) continue;
|
||
foreach (var com in prefabComs)coms.Add(com);
|
||
prefabList.Add(prefab);
|
||
}
|
||
}
|
||
|
||
foreach (var com in coms)
|
||
{
|
||
if (!Regex.IsMatch(com.text, @"[\u4E00-\u9FFF\u3400-\u4DBFa-zA-Z]")) continue;
|
||
// 去除首尾空格和换行符
|
||
com.text = com.text.Trim().Replace("\r\n", "\n");
|
||
|
||
var textCom = com.gameObject.GetComponent<MultilingualTextMono>();
|
||
if (!textCom) textCom = com.gameObject.AddComponent<MultilingualTextMono>();
|
||
|
||
if (_zhStrDict.ContainsKey(com.text))
|
||
{
|
||
textCom.ID = _zhStrDict[com.text];
|
||
}
|
||
else
|
||
{
|
||
textCom.ID = _idIndex;
|
||
_zhStrDict[com.text] = _idIndex;
|
||
_idIndex++;
|
||
}
|
||
_activeSet.Add(textCom.ID);
|
||
}
|
||
|
||
var path = $"Assets/Resources/DataAssets/";
|
||
string[] assetPaths = Directory.GetFiles(path, "*.asset", SearchOption.AllDirectories);
|
||
foreach (var assetPath in assetPaths)
|
||
{
|
||
var asset = AssetDatabase.LoadAssetAtPath<ScriptableObject>(assetPath);
|
||
if (!asset) continue;
|
||
ScriptableObject newAsset = Object.Instantiate(asset);
|
||
TraverseObject(newAsset);
|
||
SaveExportAsset(asset.name, newAsset);
|
||
}
|
||
|
||
_asset.RefreshDict();
|
||
foreach (var kv in _zhStrDict)
|
||
{
|
||
if (_asset.ItemDict.ContainsKey(kv.Value)) continue;
|
||
var item = new MultilingualItem();
|
||
item.ID = kv.Value;
|
||
item.ZH = kv.Key;
|
||
_asset.Items.Add(item);
|
||
}
|
||
|
||
// 排序 asset.items 保证id从小到大
|
||
_asset.Items = _asset.Items.OrderBy(i => i.ID).ToList();
|
||
|
||
string filePath = "../Tools/MultilingualTxt.txt";
|
||
if (!File.Exists(filePath))
|
||
{
|
||
using (File.Create(filePath))
|
||
{
|
||
} // 立即释放句柄
|
||
}
|
||
|
||
using (StreamWriter sw = new StreamWriter(filePath, false, Encoding.UTF8))
|
||
{
|
||
StringBuilder sb = new StringBuilder();
|
||
foreach (var item in _asset.Items)
|
||
{
|
||
var active = _activeSet.Contains(item.ID) ? 1 : 0;
|
||
sb.Append($"{item.ID}%$#@!{item.ZH}%$#@!{item.TDZH}%$#@!{item.EN}%$#@!{item.JP}%$#@!{item.KR}%$#@!{active}!@#$%");
|
||
}
|
||
sw.Write(sb.ToString());
|
||
}
|
||
|
||
WriteToExcel();
|
||
|
||
foreach (var prefab in prefabList) EditorUtility.SetDirty(prefab);
|
||
EditorUtility.SetDirty(_asset);
|
||
AssetDatabase.SaveAssets();
|
||
AssetDatabase.Refresh();
|
||
}
|
||
|
||
private void SaveExportAsset(string name, ScriptableObject target)
|
||
{
|
||
if (target == null) return;
|
||
|
||
// 处理目标路径
|
||
string targetPath = $"Assets/Resources/Export/{name}.asset";
|
||
if (AssetDatabase.LoadAssetAtPath<ScriptableObject>(targetPath) != null)
|
||
{
|
||
AssetDatabase.DeleteAsset(targetPath);
|
||
}
|
||
|
||
// 保存新实例
|
||
AssetDatabase.CreateAsset(target, targetPath);
|
||
AssetDatabase.SaveAssets();
|
||
AssetDatabase.Refresh();
|
||
}
|
||
|
||
private void TraverseObject(object asset)
|
||
{
|
||
if (asset == null) return;
|
||
|
||
var fields = asset.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
|
||
foreach (var field in fields)
|
||
{
|
||
var value = field.GetValue(asset);
|
||
var attr = field.GetCustomAttribute<MultilingualFieldAttribute>();
|
||
if (attr != null)
|
||
{
|
||
if (value is string s)
|
||
{
|
||
var str = s.Trim().Replace("\r\n", "\n");
|
||
if (string.IsNullOrEmpty(str)) continue;
|
||
|
||
if (_zhStrDict.TryGetValue(str, out var id))
|
||
{
|
||
field.SetValue(asset, id.ToString());
|
||
}
|
||
else
|
||
{
|
||
_zhStrDict[str] = _idIndex;
|
||
field.SetValue(asset, _zhStrDict[str].ToString());
|
||
_idIndex++;
|
||
}
|
||
_activeSet.Add(_zhStrDict[str]);
|
||
continue;
|
||
}
|
||
|
||
if (value is List<string> list)
|
||
{
|
||
for (int i = 0; i < list.Count; i++)
|
||
{
|
||
var str = list[i].Trim().Replace("\r\n", "\n");
|
||
if (string.IsNullOrEmpty(str)) continue;
|
||
|
||
if (_zhStrDict.TryGetValue(str, out var id))
|
||
{
|
||
list[i] = id.ToString();
|
||
}
|
||
else
|
||
{
|
||
_zhStrDict[str] = _idIndex;
|
||
list[i] = _zhStrDict[str].ToString();
|
||
_idIndex++;
|
||
}
|
||
_activeSet.Add(_zhStrDict[str]);
|
||
}
|
||
|
||
field.SetValue(asset, list);
|
||
continue;
|
||
}
|
||
}
|
||
|
||
if (value == null) continue;
|
||
if (value is IEnumerable enumerable)
|
||
{
|
||
foreach (object item in enumerable)
|
||
{
|
||
TraverseObject(item); // 递归处理集合项
|
||
}
|
||
}
|
||
// 如果是自定义对象(非基础类型),递归处理
|
||
else if (!value.GetType().IsPrimitive) TraverseObject(value);
|
||
}
|
||
}
|
||
|
||
public void WriteToExcel()
|
||
{
|
||
var pythonScript = $"../Tools/ExportStringToExcel.py";
|
||
|
||
ProcessStartInfo start = new ProcessStartInfo
|
||
{
|
||
FileName = "python",
|
||
Arguments = $"\"{pythonScript}\"",
|
||
RedirectStandardOutput = true,
|
||
RedirectStandardError = true,
|
||
UseShellExecute = false,
|
||
CreateNoWindow = true,
|
||
StandardErrorEncoding = Encoding.UTF8
|
||
};
|
||
|
||
using (var process = Process.Start(start))
|
||
{
|
||
string output = process.StandardOutput.ReadToEnd();
|
||
string error = process.StandardError.ReadToEnd(); // 获取错误信息
|
||
process.WaitForExit();
|
||
|
||
Debug.Log($"Exit Code: {process.ExitCode}"); // 打印退出码
|
||
Debug.Log($"Output: {output}");
|
||
Debug.Log($"Error: {error}"); // 打印错误信息
|
||
}
|
||
}
|
||
|
||
public void GetExcelData()
|
||
{
|
||
var pythonScript = $"../Tools/PrintExcelString.py";
|
||
|
||
ProcessStartInfo start = new ProcessStartInfo
|
||
{
|
||
FileName = "python",
|
||
Arguments = $"\"{pythonScript}\"",
|
||
RedirectStandardOutput = true,
|
||
RedirectStandardError = true,
|
||
UseShellExecute = false,
|
||
CreateNoWindow = true,
|
||
StandardErrorEncoding = Encoding.UTF8
|
||
};
|
||
|
||
using (var process = Process.Start(start))
|
||
{
|
||
string output = process.StandardOutput.ReadToEnd();
|
||
string error = process.StandardError.ReadToEnd(); // 获取错误信息
|
||
process.WaitForExit();
|
||
|
||
Debug.Log($"Exit Code: {process.ExitCode}"); // 打印退出码
|
||
Debug.Log($"Output: {output}");
|
||
Debug.Log($"Error: {error}"); // 打印错误信息
|
||
}
|
||
}
|
||
|
||
private void OnBuildChineseTxt()
|
||
{
|
||
characterSet.Clear();
|
||
AddBasicCharacters();
|
||
ExtractChineseFromI2Languages();
|
||
ExportCharacterSet();
|
||
}
|
||
|
||
private void AddBasicCharacters()
|
||
{
|
||
// 添加大写字母
|
||
for (char c = 'A'; c <= 'Z'; c++)
|
||
{
|
||
characterSet.Add(c);
|
||
}
|
||
|
||
// 添加小写字母
|
||
for (char c = 'a'; c <= 'z'; c++)
|
||
{
|
||
characterSet.Add(c);
|
||
}
|
||
|
||
// 添加数字
|
||
for (char c = '0'; c <= '9'; c++)
|
||
{
|
||
characterSet.Add(c);
|
||
}
|
||
|
||
// 添加常用标点符号
|
||
string punctuations = ",.!?;:\"'()[]{}+-*/=_<>@#$%^&|\\~|/\~{}[]【】「」『』《》〈〉:;“” ‘’"、,。?!…—--_+-=×÷";
|
||
foreach (char c in punctuations)
|
||
{
|
||
characterSet.Add(c);
|
||
}
|
||
}
|
||
|
||
private void ExtractChineseFromI2Languages()
|
||
{
|
||
var path = $"Assets/Resources/Export/Multilingual.asset";
|
||
var asset = AssetDatabase.LoadAssetAtPath<MultilingualData>(path);
|
||
if (asset == null)
|
||
{
|
||
EditorUtility.DisplayDialog("错误", "未找到多语言资源文件,请确认路径是否正确。", "确定");
|
||
return;
|
||
}
|
||
|
||
foreach (var item in asset.Items)
|
||
{
|
||
foreach (var c in item.ZH)
|
||
{
|
||
if (!IsChinese(c)) continue;
|
||
characterSet.Add(c);
|
||
}
|
||
}
|
||
}
|
||
|
||
private bool IsChinese(char c)
|
||
{
|
||
return (c >= 0x4E00 && c <= 0x9FFF) || // CJK统一汉字
|
||
(c >= 0x3400 && c <= 0x4DBF) || // CJK扩展A
|
||
(c >= 0x20000 && c <= 0x2A6DF); // CJK扩展B
|
||
}
|
||
|
||
private void ExportCharacterSet()
|
||
{
|
||
string path = EditorUtility.SaveFilePanel("保存字符集", "Assets/Fonts", "ChineseCharSet", "txt");
|
||
if (!string.IsNullOrEmpty(path))
|
||
{
|
||
File.WriteAllText(path, string.Join("", characterSet.OrderBy(c => c)), Encoding.UTF8);
|
||
EditorUtility.DisplayDialog("成功", "字符集已导出!", "确定");
|
||
}
|
||
}
|
||
}
|
||
} |