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