IndieGame/client/Assets/Plugins/zbitmap/zbitmapfont/Editor/BitmapFontTool.cs
2024-10-22 17:38:59 +08:00

458 lines
15 KiB
C#

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.IO;
using System.Collections.Generic;
using UnityEditor;
using UnityEditorInternal;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using System.Linq;
using System;
namespace zbitmapfont
{
public class BitmapFontTool
{
[MenuItem("Assets/zbitmapfont/Rename")]
public static void Rename()
{
foreach (var a in Selection.assetGUIDs)
{
var p = AssetDatabase.GUIDToAssetPath(a);
if (!System.IO.File.Exists(p))
{
continue;
}
var f = System.IO.Path.GetFileNameWithoutExtension(p);
var c = ConvertToChar(f);
InputDialog.ShowWindow(c.ToString(), (a) =>
{
if (string.IsNullOrEmpty(a))
{
return;
}
a = ConvertToFileName(a[0]);
string b = $"{System.IO.Path.GetDirectoryName(p)}/{a}{System.IO.Path.GetExtension(p)}";
if (System.IO.File.Exists(b))
{
Debug.LogError("file existed: " + b);
return;
}
System.IO.File.Move(p, b);
System.IO.File.Move(p + ".meta", b + ".meta");
AssetDatabase.Refresh();
});
break;
}
AssetDatabase.Refresh();
}
[MenuItem("Assets/zbitmapfont/CreateBitmapFont")]
public static void CreateBitmapFont()
{
foreach (var a in Selection.assetGUIDs)
{
var p = AssetDatabase.GUIDToAssetPath(a);
if (!System.IO.Directory.Exists(p))
{
continue;
}
string destPath = p;
if (!CreateBitmapFont(p, destPath))
{
throw new System.Exception("CreateBitmapFont failed: " + p);
}
}
AssetDatabase.Refresh();
}
[MenuItem("Assets/zbitmapfont/CreateFontAsset")]
public static void CreateFontAsset()
{
foreach (var a in Selection.assetGUIDs)
{
var p = AssetDatabase.GUIDToAssetPath(a);
if (!System.IO.Directory.Exists(p))
{
continue;
}
string destPath = p;
if (!CreateBitmapFont(p, destPath))
{
throw new System.Exception("CreateBitmapFont failed: " + p);
}
CreateBitmapFontMaterial(destPath);
CreateFontAsset(destPath);
}
AssetDatabase.Refresh();
}
public static string GetCurrentScriptPath()
{
System.Diagnostics.StackTrace stackTrace = new System.Diagnostics.StackTrace(true);
System.Diagnostics.StackFrame frame = stackTrace.GetFrame(0);
string filePath = frame.GetFileName();
return filePath;
}
static char ConvertToChar(string fileName)
{
char index = fileName[0];
try
{
if (fileName.Length == 4)
{
int temp = System.Convert.ToInt32(fileName, 16);
index = (char)temp;
}
else if (fileName.Length > 1 && fileName[1] == '_')
{
if (fileName[0] == '_')
{
index = ' ';
}
else
{
index = (char)('A' - 'a' + index);
}
}
}
catch (Exception e) { }
return index;
}
static string ConvertToFileName(char c)
{
string fileName = c.ToString();
try
{
if (System.IO.Path.GetInvalidFileNameChars().Contains(c))
{
fileName = ((int)c).ToString("x4");
}
else if (c == ' ')
{
return "__";
}
else if (c >= 'A' && c <= 'Z')
{
fileName = (char)(c - 'A' + 'a') + "_";
}
}
catch (Exception e) { }
return fileName;
}
public static bool CreateBitmapFont(string srcPath, string destPath)
{
destPath = System.IO.Path.GetFullPath(destPath);
var paths = System.IO.Directory.GetFiles(srcPath, "*.png", SearchOption.TopDirectoryOnly);
List<int> chars = new();
List<string> icons = new();
var sumSize = 0;
foreach (var path in paths)
{
var fileName = Path.GetFileNameWithoutExtension(path);
int index = ConvertToChar(fileName);
//int index = fileName[0];
//if (fileName.Length == 4)
//{
// int temp = System.Convert.ToInt32(fileName, 16);
// index = (char)temp;
//}
//else if (fileName.Length > 1 && fileName[1] == '_')
//{
// if (fileName[0] == '_')
// {
// index = ' ';
// }
// else
// {
// index = (char)('A' - 'a' + index);
// }
//}
chars.Add(index);
icons.Add($"icon=\"{System.IO.Path.GetFullPath(path)}\",{index},0,0,0");
var tex = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
sumSize += tex.width * tex.height;
}
var pngWidth = Mathf.Pow(2, Mathf.CeilToInt(Mathf.Log(Mathf.Sqrt(sumSize), 2)));
//var pngWidth = Mathf.CeilToInt(Mathf.Sqrt(sumSize));
var templateConfigStr = System.IO.File.ReadAllText($"{System.IO.Path.GetDirectoryName(GetCurrentScriptPath())}/../template.bmfc");
for (; pngWidth <= 4096; pngWidth *= 2)
{
var configStr = string.Format(templateConfigStr, string.Join(",", chars), string.Join("\n", icons), pngWidth, pngWidth);
var tempPath = $"{destPath}.bmfc";
System.IO.File.WriteAllText(tempPath, configStr);
var exePath = $"{System.IO.Path.GetDirectoryName(GetCurrentScriptPath())}/../bmfont1.14a~/bmfont64.com";
var param = $"-c \"{tempPath}\" -o \"{destPath}\"";
var ret = CommandLineTool.RunCommand2(exePath, param, Application.dataPath);
if (ret.ExitCode != 0)
{
Debug.LogError(ret.StdErr);
Debug.LogError(ret.StdOut);
}
else
{
int count = 0;
for (int i = 0; true; i++)
{
var pngPath = $"{destPath}_{i}.png";
if (!System.IO.File.Exists(pngPath))
{
break;
}
else
{
if (i > 0)
{
System.IO.File.Delete(pngPath);
}
}
count++;
}
if (count <= 0)
{
return false;
}
if (count == 1)
{
break;
}
}
}
AssetDatabase.Refresh();
{
var pngPath = System.IO.Path.GetRelativePath(System.IO.Path.GetDirectoryName(Application.dataPath), $"{destPath}_0.png");
var importer = TextureImporter.GetAtPath(pngPath) as TextureImporter;
importer.mipmapEnabled = false;
importer.alphaIsTransparency = true;
importer.npotScale = TextureImporterNPOTScale.None;
importer.SaveAndReimport();
}
return true;
}
static void CreateBitmapFontMaterial(string destPath)
{
string pngPath = destPath + "_0.png";
Texture2D tex = AssetDatabase.LoadAssetAtPath(pngPath, typeof(Texture2D)) as Texture2D;
Shader shader = Shader.Find("UI/Default");
Material material = new Material(shader);
material.mainTexture = tex;
AssetDatabase.CreateAsset(material, destPath + ".mat");
AssetDatabase.Refresh();
}
static void CreateFontAsset(string bitmapfontPath)
{
var fntPath = $"{bitmapfontPath}.fnt";
var pngPath = $"{bitmapfontPath}_0.png";
var matPath = $"{bitmapfontPath}.mat";
Material mat = AssetDatabase.LoadAssetAtPath(matPath, typeof(Material)) as Material;
Texture2D tex = AssetDatabase.LoadAssetAtPath(pngPath, typeof(Texture2D)) as Texture2D;
var fntConfigStr = System.IO.File.ReadAllText(fntPath);
StringReader sr = new StringReader(fntConfigStr);
List<string> charStrs = new();
while (true)
{
var line = sr.ReadLine();
if (string.IsNullOrEmpty(line))
{
break;
}
if (line.StartsWith("char "))
{
charStrs.Add(line);
}
}
CharacterInfo[] charInfos = new CharacterInfo[charStrs.Count];
float fontSize = 0;
for (int j = 0; j < charStrs.Count; j++)
{
var cStr = charStrs[j];
Dictionary<string, int> charparams = new();
var splitedStrings = cStr.Split(' ');
foreach (var a in splitedStrings)
{
if (a.Contains('='))
{
var b = a.Split('=');
var key = b[0];
var value = b[1];
charparams.Add(key, int.Parse(value));
}
}
int index = charparams["id"];
CharacterInfo charInfo = new CharacterInfo();
charInfo.index = index;
charInfo.advance = charparams["width"];
{
Rect r = new Rect();
r.x = (float)charparams["x"] / tex.width;
//r.y = (float)(tex.height - charparams["y"] - charparams["height"]) / tex.height;
r.y = (float)(tex.height - charparams["y"]) / tex.height;
r.width = (float)charparams["width"] / tex.width;
r.height = -(float)charparams["height"] / tex.height;
charInfo.uvBottomLeft = new Vector2(r.x, r.y);
charInfo.uvBottomRight = new Vector2(r.x + r.width, r.y);
charInfo.uvTopLeft = new Vector2(r.x, r.y + r.height);
charInfo.uvTopRight = new Vector2(r.x + r.width, r.y + r.height);
charInfo.minX = 0;
charInfo.minY = charparams["height"] / 2;
charInfo.maxX = charparams["width"];
charInfo.maxY = -charparams["height"] / 2;
charInfo.advance = charparams["xadvance"];
fontSize = charparams["height"];
}
//{
// Vector4 padding = TextureTool.getSpritePadding(info.pivot, info.rect, 1, sprite.rect);
// Rect r = new Rect();
// r.x = padding[0];
// r.y = padding[3];
// r.width = info.rect.width;
// r.height = info.rect.height;
// r.y = -r.y;
// r.height = -r.height;
// charInfo.vert = r;
// fontSize = info.rect.height + Mathf.Abs(padding[1]) + Mathf.Abs(padding[3]);
//}
charInfos[j] = charInfo;
}
string fontPath = bitmapfontPath + ".fontsettings";
Font font = null;
if (System.IO.File.Exists(fontPath))
{
font = AssetDatabase.LoadAssetAtPath<Font>(fontPath);
}
else
{
font = new Font();
}
font.material = mat;
font.name = System.IO.Path.GetFileName(bitmapfontPath);
font.characterInfo = charInfos;
string metaStr = null;
if (System.IO.File.Exists(fontPath + ".meta"))
{
metaStr = System.IO.File.ReadAllText(fontPath + ".meta");
}
if (System.IO.File.Exists(fontPath))
{
AssetDatabase.SaveAssets();
// System.IO.File.Delete(fontPath);
// AssetDatabase.Refresh();
}
else
{
AssetDatabase.CreateAsset(font, fontPath);
}
AssetDatabase.Refresh();
if (!string.IsNullOrEmpty(metaStr))
{
System.IO.File.WriteAllText(fontPath + ".meta", metaStr);
}
// string content = File.ReadAllText(fontPath);
//content = Regex.Replace(content, "(\\s+m_LineSpacing:\\s*)(.*)", "${1}" + fontSize);
//content = Regex.Replace(content, "(\\s+m_FontSize:\\s*)(.*)", "${1}" + fontSize);
//System.IO.File.WriteAllText(fontPath, content);
//AssetDatabase.ImportAsset(fontPath);
SerializedObject serializedFont = new SerializedObject(font);
SerializedProperty serializedLineSpacing = serializedFont.FindProperty("m_LineSpacing");
serializedLineSpacing.floatValue = fontSize;
SerializedProperty serializedFontSize = serializedFont.FindProperty("m_FontSize");
serializedFontSize.floatValue = fontSize;
SerializedProperty serializedAscent = serializedFont.FindProperty("m_Ascent");
serializedAscent.floatValue = fontSize / 2;
SerializedProperty serializedDescent = serializedFont.FindProperty("m_Descent");
serializedDescent.floatValue = -fontSize / 2;
serializedFont.ApplyModifiedProperties();
}
}
}