using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using TyphoonGUIStyle; using UnityEditor; using UnityEngine; namespace TyphoonFontTool { /// /// 字符识别工具 /// public class FontCharactersParser : EditorWindow { [MenuItem("Typhoon/FontTool/解析字体")] public static void Open() { var win = GetWindow(); win.minSize = new Vector2(320, 200); win.titleContent = new GUIContent("解析字体"); win.Show(); } //字体文件 private static Font _font; //字符信息文件 private static TextAsset _infoFile; private void OnGUI() { var area = new Rect(Vector2.zero, position.size); var center = area.center; var draw = area; draw.width -= 8; draw.height -= 8; draw.center = center; GUILayout.BeginArea(draw); GUILayout.Label("字体解析插件", Styles.TitleBar); GUILayout.Label(new GUIContent("外置工具,可以解析字体文件所有的码点值", Styles.IconInfo), Styles.HelpBox); if (GUILayout.Button("启动插件", GUILayout.Height(28))) { OpenParserExeApplication(); } if (GUILayout.Button("使用说明", GUILayout.Height(28))) { OpenParserExeReadme(); } var last = GUILayoutUtility.GetLastRect(); var line = last; line.height = 1; line.y = last.yMax; line.y += 5; EditorGUI.DrawRect(line, Color.black); GUILayout.Space(10); GUILayout.Label("生成FontSourceData", Styles.TitleBar); _font = EditorGUILayout.ObjectField("字体", _font, typeof(Font), false) as Font; _infoFile = EditorGUILayout.ObjectField("码点信息(.txt)", _infoFile, typeof(TextAsset), false) as TextAsset; GUILayout.Space(3); if (GUILayout.Button("生成资源", GUILayout.Height(26))) { CreateFontSourceData(_font, _infoFile); } GUILayout.EndArea(); } private string CopyReadFontToolPlugin() { //识别插件目录 var original = $"{_Editor.RootPath}/readfontinfo~"; var copy = $".typhoon/fonttool/{Path.GetFileName(original)}"; //复制识别插件到本地目录中 if (!Directory.Exists(copy)) { //复制工具到copy路径下 _Editor.CopyFolder(original, copy); } return copy; } public void OpenParserExeApplication() { var copy = CopyReadFontToolPlugin(); //调用exe var exe = $"{copy}/readfontfile.exe"; if (!File.Exists(exe)) { throw new Exception($"找不到:{exe}"); } var path = _Editor.UnityToFullPath(exe); Application.OpenURL(path); } public void OpenParserExeReadme() { var copy = CopyReadFontToolPlugin(); var readme = $"{copy}/使用说明.pdf"; if (!File.Exists(readme)) { throw new Exception($"找不到:{readme}"); } var fullpath = _Editor.UnityToFullPath(readme); using (Process.Start("explorer.exe", $"\"{fullpath}\"")) { } } public static void CreateFontSourceData(Font font, TextAsset info, bool forceCover = false) { if (font == null) { _Editor.ShowMessageBox("字体文件为空!"); return; } if (info == null) { _Editor.ShowMessageBox("字体信息文件为空!"); return; } var output = $"Assets/Typhoon_Gen/FontTool/FontSourceData/FSD_{font.name}.asset"; var skip = false; if (File.Exists(output) && forceCover == false) { skip = !_Editor.ShowMessageBox($"存在相同文件:{output},是否覆盖?不可撤消!"); } if (skip) { return; } //解析txt string[] lines = info.text.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); var first = lines.FirstOrDefault(e => e.StartsWith("style 1")); var end = lines.FirstOrDefault(e => e.StartsWith("style 2")); if (first == null || end == null) { throw new Exception("字体信息文件有误无法完整识别:行:style 1 到 行:style 2 区间"); } var indexStart = lines.ToList().IndexOf(first); var indexEnd = lines.ToList().IndexOf(end); //截取区间,剔除空白行 var match = lines.Skip(indexStart + 1) .Take(indexEnd - indexStart).FirstOrDefault(e => !string.IsNullOrWhiteSpace(e)); if (match != null) { //解析码点值 var ranges = match.Split(',').Select(e => { var items = e.Split('-'); var from = items[0]; var to = items[0]; if (items.Length > 1) { to = items[1]; } var fromValue = Convert.ToInt32(from, 16); var toValue = Convert.ToInt32(to, 16); //解析 return new { fromValue, toValue }; }); var codes = new HashSet(); foreach (var item in ranges) { for (int i = item.fromValue; i <= item.toValue; i++) { codes.Add(i); } } var asset = AssetDatabase.LoadAssetAtPath(output); if (asset == null) { asset = CreateInstance(); _Editor.CreateFileDirectoryIfNotExists(output); AssetDatabase.CreateAsset(asset, output); AssetDatabase.Refresh(); } asset.Font = font; asset.Codes = codes.ToList(); var characters = new List(); foreach (var code in codes) { characters.Add(char.ConvertFromUtf32(code)); } EditorUtility.SetDirty(asset); AssetDatabase.SaveAssets(); _Editor.Ping(asset); // Debug.Log(codes.Count); } } } }