1156 lines
50 KiB
C#
1156 lines
50 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.CrashSight;
|
||
using Logic.Multilingual;
|
||
using TMPro;
|
||
using UnityEditor;
|
||
using UnityEditor.SceneManagement;
|
||
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 Dictionary<uint, bool> _isProperNounDict = new Dictionary<uint, bool>();
|
||
private Dictionary<uint, bool> _isDialogueDict = new Dictionary<uint, bool>();
|
||
private Dictionary<uint, bool> _isDeprecatedDict = new Dictionary<uint, bool>();
|
||
private Dictionary<uint, string> _speakerDict = new Dictionary<uint, string>();
|
||
private HashSet<uint> _activeSet = new HashSet<uint>();
|
||
private HashSet<uint> _specialTermSet = new HashSet<uint>();
|
||
private Dictionary<uint, string> _descDict = new Dictionary<uint, string>();
|
||
private uint _idIndex;
|
||
private int _showIndex = 0;
|
||
private List<TMP_FontAsset> _assets = new List<TMP_FontAsset>();
|
||
private HashSet<char> characterSet = new HashSet<char>();
|
||
private HashSet<char> gameSet = new HashSet<char>();
|
||
private List<char> characterList = new List<char>();
|
||
private MultilingualType _selectType = MultilingualType.ZH;
|
||
|
||
private TextAsset _importedTxtFile;
|
||
private string _txtFilePath;
|
||
|
||
private bool _isActive = true;
|
||
private bool _isProperNoun = false;
|
||
private bool _isDialogue = false;
|
||
private bool _isDeprecated = false;
|
||
private bool _isENNoTranslate = false;
|
||
private bool _isTDZHNoTranslate = false;
|
||
private bool _isJPNoTranslate = false;
|
||
private bool _isKRNoTranslate = false;
|
||
private bool _isRUNoTranslate = false;
|
||
private bool _isESNoTranslate = false;
|
||
private bool _isPTNoTranslate = false;
|
||
private bool _isFRNoTranslate = false;
|
||
private bool _isAnyNoTranslate = false;
|
||
private bool _isSpecialTermSet = false;
|
||
|
||
|
||
[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);
|
||
}
|
||
EditorSceneManager.MarkSceneDirty(uiObj.scene);
|
||
|
||
// 先处理 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<MultilingualTextMono>(true).ToList();
|
||
foreach (var com in prefabComs)
|
||
{
|
||
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);
|
||
}
|
||
prefabList.Add(prefab);
|
||
}
|
||
}
|
||
foreach (var prefab in prefabList) EditorUtility.SetDirty(prefab);
|
||
AssetDatabase.SaveAssets();
|
||
AssetDatabase.Refresh();
|
||
}
|
||
/*
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("设置 font ban = ban"))
|
||
{
|
||
var uiObj = GameObject.Find("UICanvas");
|
||
var coms = uiObj.GetComponentsInChildren<MultilingualTextMono>(true).ToList();
|
||
foreach (var com in coms)
|
||
{
|
||
com.FontBan = com.Ban;
|
||
}
|
||
EditorSceneManager.MarkSceneDirty(uiObj.scene);
|
||
|
||
// 先处理 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<MultilingualTextMono>(true).ToList();
|
||
foreach (var com in prefabComs)
|
||
{
|
||
com.FontBan = com.Ban;
|
||
}
|
||
prefabList.Add(prefab);
|
||
}
|
||
}
|
||
foreach (var prefab in prefabList) EditorUtility.SetDirty(prefab);
|
||
AssetDatabase.SaveAssets();
|
||
AssetDatabase.Refresh();
|
||
}
|
||
*/
|
||
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());
|
||
}
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
|
||
EditorGUILayout.BeginHorizontal();
|
||
_selectType = (MultilingualType)EditorGUILayout.EnumPopup(_selectType, GUILayout.Width(200));
|
||
if (_selectType != MultilingualType.None)
|
||
{
|
||
if (InspectorUtils.InspectorButtonWithTextWidth($"检查字符集 {_selectType} 是否有新增"))
|
||
{
|
||
string path = $"Assets/Fonts/{_selectType}CharSet.txt";
|
||
if (!File.Exists(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)
|
||
{
|
||
var str = item.GetStrByType(_selectType);
|
||
if (string.IsNullOrEmpty(str)) continue;
|
||
foreach (var c in str)
|
||
{
|
||
if (!characterSet.Contains(c)) isNeedUpdate = true;
|
||
}
|
||
}
|
||
|
||
if (isNeedUpdate) EditorUtility.DisplayDialog("字符集提示", "有新增,请创建新的字符集TXT", "确定");
|
||
else EditorUtility.DisplayDialog("字符集提示", "无新增,无需理会", "确定");
|
||
}
|
||
}
|
||
InspectorUtils.InspectorTextWidthRich($"{_selectType} TXT并集:");
|
||
_importedTxtFile = (TextAsset)EditorGUILayout.ObjectField(_importedTxtFile, typeof(TextAsset), false, GUILayout.Width(300));
|
||
if (InspectorUtils.InspectorButtonWithTextWidth($"创建新的 {_selectType} 字符集TXT"))
|
||
{
|
||
OnBuildTxt(_selectType);
|
||
}
|
||
}
|
||
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
EditorGUILayout.Space();
|
||
EditorGUILayout.BeginVertical(_redBoxStyle);
|
||
_isActive = EditorGUILayout.Toggle("筛选活跃文本", _isActive);
|
||
_isProperNoun = EditorGUILayout.Toggle("筛选专有名词", _isProperNoun);
|
||
_isDialogue = EditorGUILayout.Toggle("筛选对话文本", _isDialogue);
|
||
_isDeprecated = EditorGUILayout.Toggle("筛选已废弃文本", _isDeprecated);
|
||
_isENNoTranslate = EditorGUILayout.Toggle("筛选英文未翻译文本", _isENNoTranslate);
|
||
_isTDZHNoTranslate = EditorGUILayout.Toggle("筛选繁中未翻译文本", _isTDZHNoTranslate);
|
||
_isJPNoTranslate = EditorGUILayout.Toggle("筛选日文未翻译文本", _isJPNoTranslate);
|
||
_isKRNoTranslate = EditorGUILayout.Toggle("筛选韩文未翻译文本", _isKRNoTranslate);
|
||
_isRUNoTranslate = EditorGUILayout.Toggle("筛选俄语未翻译文本", _isRUNoTranslate);
|
||
_isESNoTranslate = EditorGUILayout.Toggle("筛选西班牙语未翻译文本", _isESNoTranslate);
|
||
_isPTNoTranslate = EditorGUILayout.Toggle("筛选葡萄牙语未翻译文本", _isPTNoTranslate);
|
||
_isFRNoTranslate = EditorGUILayout.Toggle("筛选法语未翻译文本", _isFRNoTranslate);
|
||
_isAnyNoTranslate = EditorGUILayout.Toggle("筛选任意未翻译文本", _isAnyNoTranslate);
|
||
_isSpecialTermSet = EditorGUILayout.Toggle("筛选专有名词", _isSpecialTermSet);
|
||
|
||
if (InspectorUtils.InspectorButtonWithTextWidth("导出 Excel 筛选类型文本"))
|
||
{
|
||
AssetExportToExcel(true);
|
||
}
|
||
EditorGUILayout.EndVertical();
|
||
EditorGUILayout.Space();
|
||
|
||
EditorGUILayout.BeginVertical(_whiteBoxStyle);
|
||
if (_asset.TargetTypes.Count != (int)MultilingualType.Max)
|
||
{
|
||
_asset.TargetTypes.Clear();
|
||
for (int i = (int)MultilingualType.ZH; i < (int)MultilingualType.Max; 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));
|
||
fontGroup.RUFont =
|
||
(TMP_FontAsset)EditorGUILayout.ObjectField(fontGroup.RUFont, typeof(TMP_FontAsset), false, GUILayout.Width(400));
|
||
fontGroup.ESFont =
|
||
(TMP_FontAsset)EditorGUILayout.ObjectField(fontGroup.ESFont, typeof(TMP_FontAsset), false, GUILayout.Width(400));
|
||
fontGroup.PTFont =
|
||
(TMP_FontAsset)EditorGUILayout.ObjectField(fontGroup.PTFont, typeof(TMP_FontAsset), false, GUILayout.Width(400));
|
||
fontGroup.FRFont =
|
||
(TMP_FontAsset)EditorGUILayout.ObjectField(fontGroup.FRFont, 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}");
|
||
if (!string.IsNullOrEmpty(item.RU))
|
||
InspectorUtils.InspectorTextWidthRich($" <b>俄语:</b> {item.RU}");
|
||
if (!string.IsNullOrEmpty(item.ES))
|
||
InspectorUtils.InspectorTextWidthRich($" <b>西班牙语:</b> {item.ES}");
|
||
if (!string.IsNullOrEmpty(item.PT))
|
||
InspectorUtils.InspectorTextWidthRich($" <b>葡萄牙语:</b> {item.PT}");
|
||
if (!string.IsNullOrEmpty(item.FR))
|
||
InspectorUtils.InspectorTextWidthRich($" <b>法语:</b> {item.FR}");
|
||
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 >= 3)
|
||
{
|
||
var str = RemoveCsvQuotes(cells[2]);
|
||
if (!string.IsNullOrEmpty(str)) item.ZH = str;
|
||
}
|
||
if (cells.Length >= 4)
|
||
{
|
||
var str = RemoveCsvQuotes(cells[3]);
|
||
if (!string.IsNullOrEmpty(str)) item.TDZH = str;
|
||
}
|
||
if (cells.Length >= 5)
|
||
{
|
||
var str = RemoveCsvQuotes(cells[4]);
|
||
if (!string.IsNullOrEmpty(str)) item.EN = str;
|
||
}
|
||
if (cells.Length >= 6)
|
||
{
|
||
var str = RemoveCsvQuotes(cells[5]);
|
||
if (!string.IsNullOrEmpty(str)) item.JP = str;
|
||
}
|
||
if (cells.Length >= 7)
|
||
{
|
||
var str = RemoveCsvQuotes(cells[6]);
|
||
if (!string.IsNullOrEmpty(str)) item.KR = str;
|
||
}
|
||
if (cells.Length >= 8)
|
||
{
|
||
var str = RemoveCsvQuotes(cells[7]);
|
||
if (!string.IsNullOrEmpty(str)) item.IsProperNoun = MultilingualItem.ParseBoolStr(str);
|
||
}
|
||
if (cells.Length >= 9)
|
||
{
|
||
var str = RemoveCsvQuotes(cells[8]);
|
||
if (!string.IsNullOrEmpty(str)) item.IsDialogue = MultilingualItem.ParseBoolStr(str);
|
||
}
|
||
if (cells.Length >= 10)
|
||
{
|
||
var str = RemoveCsvQuotes(cells[9]);
|
||
if (!string.IsNullOrEmpty(str)) item.DialogueSpeaker = str;
|
||
}
|
||
if (cells.Length >= 11)
|
||
{
|
||
var str = RemoveCsvQuotes(cells[10]);
|
||
if (!string.IsNullOrEmpty(str)) item.IsDeprecated = MultilingualItem.ParseBoolStr(str);
|
||
}
|
||
if (cells.Length >= 12)
|
||
{
|
||
var str = RemoveCsvQuotes(cells[11]);
|
||
if (!string.IsNullOrEmpty(str)) item.IsProperNoun = MultilingualItem.ParseBoolStr(str);
|
||
}
|
||
if (cells.Length >= 13)
|
||
{
|
||
var str = RemoveCsvQuotes(cells[12]);
|
||
if (!string.IsNullOrEmpty(str)) item.IsDialogue = MultilingualItem.ParseBoolStr(str);
|
||
}
|
||
if (cells.Length >= 14)
|
||
{
|
||
var str = RemoveCsvQuotes(cells[13]);
|
||
if (!string.IsNullOrEmpty(str)) item.DialogueSpeaker = str;
|
||
}
|
||
if (cells.Length >= 15)
|
||
{
|
||
var str = RemoveCsvQuotes(cells[14]);
|
||
if (!string.IsNullOrEmpty(str)) item.IsDeprecated = MultilingualItem.ParseBoolStr(str);
|
||
}
|
||
if (cells.Length >= 16)
|
||
{
|
||
var str = RemoveCsvQuotes(cells[15]);
|
||
if (!string.IsNullOrEmpty(str)) item.IsCustom = MultilingualItem.ParseBoolStr(str);
|
||
}
|
||
}
|
||
|
||
_asset.RefreshDict();
|
||
foreach (var item in _asset.Items)
|
||
{
|
||
// 中文先转换 [[str]] -> [[id]]
|
||
item.ZH = _asset.UnResolveEmbeddedStrings(item.ZH, MultilingualType.ZH);
|
||
|
||
// 其他语言对齐中文的 [[id]]
|
||
item.TDZH = _asset.AlignEmbeddedStringsToZH(item.ZH, item.TDZH, MultilingualType.TDZH, item.ID);
|
||
item.EN = _asset.AlignEmbeddedStringsToZH(item.ZH, item.EN, MultilingualType.EN, item.ID);
|
||
item.JP = _asset.AlignEmbeddedStringsToZH(item.ZH, item.JP, MultilingualType.JP, item.ID);
|
||
item.KR = _asset.AlignEmbeddedStringsToZH(item.ZH, item.KR, MultilingualType.KR, item.ID);
|
||
item.RU = _asset.AlignEmbeddedStringsToZH(item.ZH, item.RU, MultilingualType.RU, item.ID);
|
||
item.ES = _asset.AlignEmbeddedStringsToZH(item.ZH, item.ES, MultilingualType.ES, item.ID);
|
||
item.PT = _asset.AlignEmbeddedStringsToZH(item.ZH, item.PT, MultilingualType.PT, item.ID);
|
||
item.FR = _asset.AlignEmbeddedStringsToZH(item.ZH, item.FR, MultilingualType.FR, item.ID);
|
||
|
||
item.Refresh();
|
||
}
|
||
|
||
EditorUtility.SetDirty(_asset);
|
||
AssetDatabase.SaveAssets();
|
||
AssetDatabase.Refresh();
|
||
}
|
||
|
||
private void AssetExportToExcel(bool isFilter = false)
|
||
{
|
||
DuplicateRemoval();
|
||
_zhStrDict.Clear();
|
||
_activeSet.Clear();
|
||
_specialTermSet.Clear();
|
||
_isProperNounDict.Clear();
|
||
_isDialogueDict.Clear();
|
||
_isDeprecatedDict.Clear();
|
||
_speakerDict.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();
|
||
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 (textCom.NoExport) continue;
|
||
|
||
if (_zhStrDict.ContainsKey(com.text))
|
||
{
|
||
textCom.ID = _zhStrDict[com.text];
|
||
}
|
||
else
|
||
{
|
||
textCom.ID = _idIndex;
|
||
_zhStrDict[com.text] = _idIndex;
|
||
_idIndex++;
|
||
}
|
||
|
||
_activeSet.Add(textCom.ID);
|
||
_descDict[textCom.ID] = GetGameObjectPath(com.gameObject);
|
||
EditorUtility.SetDirty(textCom);
|
||
PrefabUtility.RecordPrefabInstancePropertyModifications(textCom);
|
||
}
|
||
|
||
EditorSceneManager.MarkSceneDirty(uiObj.scene);
|
||
|
||
// 先处理 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)
|
||
{
|
||
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 (textCom.NoExport) continue;
|
||
|
||
if (_zhStrDict.ContainsKey(com.text))
|
||
{
|
||
textCom.ID = _zhStrDict[com.text];
|
||
}
|
||
else
|
||
{
|
||
textCom.ID = _idIndex;
|
||
_zhStrDict[com.text] = _idIndex;
|
||
_idIndex++;
|
||
}
|
||
|
||
_activeSet.Add(textCom.ID);
|
||
_descDict[textCom.ID] = prefab.name + " : " + GetGameObjectPath(com.gameObject);
|
||
}
|
||
|
||
prefabList.Add(prefab);
|
||
}
|
||
}
|
||
|
||
// 最后处理 assets
|
||
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);
|
||
}
|
||
|
||
var newStr = new Dictionary<string, uint>();
|
||
var replaceStr = new Dictionary<string, string>();
|
||
// 匹配 [[...]]
|
||
var regex = new Regex(@"\[\[(.+?)\]\]");
|
||
|
||
foreach (var kv in _zhStrDict)
|
||
{
|
||
var original = kv.Key;
|
||
var id = kv.Value;
|
||
|
||
var matches = regex.Matches(original);
|
||
if (matches.Count == 0) continue;
|
||
|
||
var replaced = original;
|
||
bool isReplaced = false;
|
||
// 从后往前替换,避免索引偏移
|
||
for (int i = matches.Count - 1; i >= 0; i--)
|
||
{
|
||
var match = matches[i];
|
||
// [[]] 内的内容
|
||
var innerContent = match.Groups[1].Value;
|
||
|
||
// 检查嵌套:内部不应再包含 [[ 或 ]]
|
||
if (innerContent.Contains("[[") || innerContent.Contains("]]"))
|
||
{
|
||
LogSystem.LogError($"检测到嵌套的[[]],ID: {id},内容: {original}");
|
||
continue;
|
||
}
|
||
|
||
// 检查是否以 [n] 开头
|
||
string prefix = null;
|
||
string actualStr = innerContent;
|
||
var prefixRegex = new Regex(@"^\[([^\]]*)\](.*)$", RegexOptions.Singleline);
|
||
var prefixMatch = prefixRegex.Match(innerContent);
|
||
if (prefixMatch.Success)
|
||
{
|
||
var prefixValue = prefixMatch.Groups[1].Value;
|
||
// 检查 n 是否为数字
|
||
if (!int.TryParse(prefixValue, out _))
|
||
{
|
||
LogSystem.LogError($"[[]]内的前缀[n]中n不是数字,ID: {id},内容: {innerContent}");
|
||
continue;
|
||
}
|
||
|
||
prefix = prefixValue;
|
||
actualStr = prefixMatch.Groups[2].Value;
|
||
}
|
||
|
||
// 已经是转化后的ID格式了,不需要再转化了
|
||
if (uint.TryParse(actualStr, out var strId))
|
||
{
|
||
_activeSet.Add(strId);
|
||
continue;
|
||
}
|
||
if (string.IsNullOrEmpty(actualStr)) continue;
|
||
|
||
// 检查子字符串是否已存在
|
||
uint subId;
|
||
if (_zhStrDict.TryGetValue(actualStr, out var existingId))
|
||
{
|
||
subId = existingId;
|
||
}
|
||
else if (newStr.TryGetValue(actualStr, out var newExistingId))
|
||
{
|
||
subId = newExistingId;
|
||
}
|
||
else
|
||
{
|
||
subId = _idIndex;
|
||
newStr[actualStr] = _idIndex;
|
||
_idIndex++;
|
||
}
|
||
|
||
// 构建替换字符串
|
||
string replacement;
|
||
if (prefix != null)
|
||
{
|
||
replacement = $"[[[{prefix}]{subId}]]";
|
||
}
|
||
else
|
||
{
|
||
replacement = $"[[{subId}]]";
|
||
}
|
||
|
||
|
||
_specialTermSet.Add(subId);
|
||
_activeSet.Add(subId);
|
||
replaced = replaced.Substring(0, match.Index) + replacement +
|
||
replaced.Substring(match.Index + match.Length);
|
||
isReplaced = true;
|
||
}
|
||
if (isReplaced) replaceStr[replaced] = original;
|
||
}
|
||
|
||
foreach (var kv in replaceStr)
|
||
{
|
||
var zh = kv.Value;
|
||
var id = _zhStrDict[zh];
|
||
_zhStrDict.Remove(zh);
|
||
if (!_zhStrDict.TryAdd(kv.Key, id)) continue;
|
||
}
|
||
|
||
foreach (var kv in newStr)
|
||
{
|
||
_zhStrDict[kv.Key] = kv.Value;
|
||
}
|
||
|
||
_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);
|
||
}
|
||
|
||
foreach (var item in _asset.Items)
|
||
{
|
||
item.IsSpecialTerm = _specialTermSet.Contains(item.ID);
|
||
if (!_descDict.ContainsKey(item.ID)) continue;
|
||
item.Desc = _descDict[item.ID];
|
||
}
|
||
|
||
// 排序 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)
|
||
{
|
||
if (!item.IsCustom)
|
||
{
|
||
if (_isProperNounDict.ContainsKey(item.ID)) item.IsProperNoun = _isProperNounDict[item.ID];
|
||
if (_isDialogueDict.ContainsKey(item.ID)) item.IsDialogue = _isDialogueDict[item.ID];
|
||
if (_isDeprecatedDict.ContainsKey(item.ID)) item.IsDeprecated = _isDeprecatedDict[item.ID];
|
||
if (_speakerDict.ContainsKey(item.ID)) item.DialogueSpeaker = _speakerDict[item.ID];
|
||
}
|
||
|
||
if (isFilter)
|
||
{
|
||
if (_isActive && !_activeSet.Contains(item.ID)) continue;
|
||
if (_isProperNoun && !item.IsProperNoun) continue;
|
||
if (_isDialogue && !item.IsDialogue) continue;
|
||
if (_isDeprecated && !item.IsDeprecated) continue;
|
||
if (_isENNoTranslate && item.IsTranslate(MultilingualType.EN)) continue;
|
||
if (_isTDZHNoTranslate && item.IsTranslate(MultilingualType.TDZH)) continue;
|
||
if (_isJPNoTranslate && item.IsTranslate(MultilingualType.JP)) continue;
|
||
if (_isKRNoTranslate && item.IsTranslate(MultilingualType.KR)) continue;
|
||
if (_isRUNoTranslate && item.IsTranslate(MultilingualType.RU)) continue;
|
||
if (_isESNoTranslate && item.IsTranslate(MultilingualType.ES)) continue;
|
||
if (_isPTNoTranslate && item.IsTranslate(MultilingualType.PT)) continue;
|
||
if (_isFRNoTranslate && item.IsTranslate(MultilingualType.FR)) continue;
|
||
if (_isAnyNoTranslate && item.IsTranslate(MultilingualType.None)) continue;
|
||
if (_isSpecialTermSet && !item.IsSpecialTerm) continue;
|
||
}
|
||
|
||
var active = _activeSet.Contains(item.ID);
|
||
var zh = _asset.GetMultilingualStrEditor(item.ID, MultilingualType.ZH);
|
||
var tdzh = _asset.GetMultilingualStrEditor(item.ID, MultilingualType.TDZH);
|
||
var en = _asset.GetMultilingualStrEditor(item.ID, MultilingualType.EN);
|
||
var jp = _asset.GetMultilingualStrEditor(item.ID, MultilingualType.JP);
|
||
var kr = _asset.GetMultilingualStrEditor(item.ID, MultilingualType.KR);
|
||
var ru = _asset.GetMultilingualStrEditor(item.ID, MultilingualType.RU);
|
||
var es = _asset.GetMultilingualStrEditor(item.ID, MultilingualType.ES);
|
||
var pt = _asset.GetMultilingualStrEditor(item.ID, MultilingualType.PT);
|
||
var fr = _asset.GetMultilingualStrEditor(item.ID, MultilingualType.FR);
|
||
|
||
sb.Append(
|
||
$"{item.ID}%$#@!{active}%$#@!{zh}%$#@!{tdzh}%$#@!{en}%$#@!{jp}%$#@!{kr}" +
|
||
$"%$#@!{ru}%$#@!{es}%$#@!{pt}%$#@!{fr}" +
|
||
$"%$#@!{item.IsProperNoun}%$#@!{item.IsDialogue}%$#@!{item.DialogueSpeaker}" +
|
||
$"%$#@!{item.IsDeprecated}%$#@!{item.IsCustom}%$#@!{item.Desc}%$#@!{item.IsSpecialTerm}!@#$%");
|
||
}
|
||
|
||
sw.Write(sb.ToString());
|
||
}
|
||
|
||
WriteToExcel();
|
||
foreach (var prefab in prefabList) EditorUtility.SetDirty(prefab);
|
||
EditorUtility.SetDirty(_asset);
|
||
AssetDatabase.SaveAssets();
|
||
AssetDatabase.Refresh();
|
||
}
|
||
|
||
private string GetGameObjectPath(GameObject go)
|
||
{
|
||
if (go == null) return string.Empty;
|
||
|
||
if (go.transform.parent == null)
|
||
return go.name;
|
||
|
||
return GetGameObjectPath(go.transform.parent.gameObject) + "/" + go.name;
|
||
}
|
||
|
||
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 assetType = asset.GetType();
|
||
var fields = asset.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
|
||
// 检查是否拥有 GetSpeaker() 方法并调用
|
||
var getSpeakerMethod = assetType.GetMethod("GetSpeaker", BindingFlags.Public | BindingFlags.Instance);
|
||
string speaker = null;
|
||
if (getSpeakerMethod != null && getSpeakerMethod.ReturnType == typeof(string))
|
||
{
|
||
speaker = getSpeakerMethod.Invoke(asset, null) as string;
|
||
}
|
||
|
||
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]);
|
||
_descDict[_zhStrDict[str]] = assetType.Name + " : " + field.Name;
|
||
_isProperNounDict[_zhStrDict[str]] = attr.IsProperNoun;
|
||
_isDialogueDict[_zhStrDict[str]] = attr.IsDialogue;
|
||
_isDeprecatedDict[_zhStrDict[str]] = attr.IsDeprecated;
|
||
if (attr.IsDialogue && !string.IsNullOrEmpty(speaker)) _speakerDict[_zhStrDict[str]] = speaker;
|
||
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]);
|
||
_descDict[_zhStrDict[str]] = assetType.Name + " : " + field.Name;
|
||
_isProperNounDict[_zhStrDict[str]] = attr.IsProperNoun;
|
||
_isDialogueDict[_zhStrDict[str]] = attr.IsDialogue;
|
||
_isDeprecatedDict[_zhStrDict[str]] = attr.IsDeprecated;
|
||
if (attr.IsDialogue && !string.IsNullOrEmpty(speaker)) _speakerDict[_zhStrDict[str]] = speaker;
|
||
}
|
||
|
||
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,
|
||
StandardOutputEncoding = 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,
|
||
StandardOutputEncoding = 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 OnBuildTxt(MultilingualType multilingualType)
|
||
{
|
||
characterSet.Clear();
|
||
gameSet.Clear();
|
||
characterList.Clear();
|
||
if (_importedTxtFile != null)
|
||
{
|
||
_txtFilePath = AssetDatabase.GetAssetPath(_importedTxtFile);
|
||
foreach (var c in _importedTxtFile.text) characterSet.Add(c);
|
||
}
|
||
AddBasicCharacters();
|
||
ExtractFromI2Languages(multilingualType);
|
||
foreach (var c in gameSet) characterList.Add(c);
|
||
foreach (var c in characterSet) characterList.Add(c);
|
||
ExportCharacterList(multilingualType);
|
||
}
|
||
|
||
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 ExtractFromI2Languages(MultilingualType multilingualType)
|
||
{
|
||
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)
|
||
{
|
||
var str = item.GetStrByType(multilingualType);
|
||
if (string.IsNullOrEmpty(str)) continue;
|
||
foreach (var c in str)
|
||
{
|
||
if (characterSet.Contains(c)) continue;
|
||
gameSet.Add(c);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void ExportCharacterList(MultilingualType multilingualType)
|
||
{
|
||
var path = $"Assets/Fonts/{multilingualType}CharSet.txt";
|
||
string directory = Path.GetDirectoryName(path);
|
||
if (!Directory.Exists(directory)) if (directory != null) Directory.CreateDirectory(directory);
|
||
File.WriteAllText(path, string.Join("", characterList), Encoding.UTF8);
|
||
EditorUtility.DisplayDialog("成功", "字符集已导出!", "确定");
|
||
}
|
||
}
|
||
} |