f37369cdda
Co-authored-by: Cursor <cursoragent@cursor.com>
402 lines
13 KiB
C#
402 lines
13 KiB
C#
using Dalamud.Interface;
|
|
using Dalamud.Interface.ImGuiFileDialog;
|
|
using HSUI.Config;
|
|
using HSUI.Config.Attributes;
|
|
using HSUI.Helpers;
|
|
using Dalamud.Bindings.ImGui;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using Dalamud.Interface.GameFonts;
|
|
using Dalamud.Logging;
|
|
using HSUI.Enums;
|
|
using HSUI.Interface.Bars;
|
|
|
|
namespace HSUI.Interface.GeneralElements
|
|
{
|
|
public struct FontData
|
|
{
|
|
public string Name;
|
|
public int Size;
|
|
|
|
public FontData(string name, int size)
|
|
{
|
|
Name = name;
|
|
Size = size;
|
|
}
|
|
}
|
|
|
|
[Disableable(false)]
|
|
[Section("Customization")]
|
|
[SubSection("Fonts", 0)]
|
|
public class FontsConfig : PluginConfigObject
|
|
{
|
|
public new static FontsConfig DefaultConfig() { return new FontsConfig(); }
|
|
|
|
public string FontsPath = "C:\\";
|
|
[JsonIgnore] public string ValidatedFontsPath => ValidatePath(FontsPath);
|
|
|
|
public SortedList<string, FontData> Fonts = new SortedList<string, FontData>();
|
|
public bool SupportChineseCharacters = false;
|
|
public bool SupportKoreanCharacters = false;
|
|
public bool SupportCyrillicCharacters = false;
|
|
[JsonIgnore] public readonly Dictionary<string, string> GameFontMap = new Dictionary<string, string>()
|
|
{
|
|
{"Axis", "axis-ffxiv"},
|
|
{"Jupiter", "jupiter-ffxiv"},
|
|
{"JupiterNumeric", "jupiter-numeric-ffxiv"},
|
|
{"MiedingerMid", "meidinger-ffxiv"},
|
|
{"Meidinger", "meidinger-numberic-ffxiv"},
|
|
{"TrumpGothic", "trumpgothic-ffxiv"},
|
|
|
|
};
|
|
|
|
[JsonIgnore] public static readonly List<string> DefaultFontsKeys = new List<string>() { "Expressway_18", "Expressway_14", "Expressway_12" };
|
|
|
|
[JsonIgnore] public static string DefaultBigFontKey => DefaultFontsKeys[0];
|
|
[JsonIgnore] public static string DefaultMediumFontKey => DefaultFontsKeys[1];
|
|
[JsonIgnore] public static string DefaultSmallFontKey => DefaultFontsKeys[2];
|
|
|
|
[JsonIgnore] private int _inputFont = 0;
|
|
[JsonIgnore] private int _inputSize = 23;
|
|
|
|
[JsonIgnore] private string[] _fonts = null!;
|
|
[JsonIgnore] private string[] _sizes = null!;
|
|
|
|
[JsonIgnore] private int _removingIndex = -1;
|
|
[JsonIgnore] private int _applyingIndex = -1!;
|
|
|
|
[JsonIgnore] private FileDialogManager _fileDialogManager = new FileDialogManager();
|
|
|
|
public FontsConfig()
|
|
{
|
|
ReloadFonts();
|
|
|
|
// default fonts
|
|
foreach (string key in DefaultFontsKeys)
|
|
{
|
|
if (!Fonts.ContainsKey(key))
|
|
{
|
|
string[] str = key.Split("_", StringSplitOptions.RemoveEmptyEntries);
|
|
var defaultFont = new FontData(str[0], int.Parse(str[1]));
|
|
Fonts.Add(key, defaultFont);
|
|
}
|
|
}
|
|
|
|
// sizes
|
|
_sizes = new string[100];
|
|
for (int i = 0; i < _sizes.Length; i++)
|
|
{
|
|
_sizes[i] = (i + 1).ToString();
|
|
}
|
|
}
|
|
|
|
private bool IsDefaultFont(string key)
|
|
{
|
|
return DefaultFontsKeys.Contains(key);
|
|
}
|
|
|
|
private string ValidatePath(string path)
|
|
{
|
|
if (path.EndsWith("\\") || path.EndsWith("/"))
|
|
{
|
|
return path;
|
|
}
|
|
|
|
return path + "\\";
|
|
}
|
|
|
|
private string[] FontsFromPath(string path)
|
|
{
|
|
string[] fonts;
|
|
try
|
|
{
|
|
fonts = Directory.GetFiles(path, "*.ttf");
|
|
}
|
|
catch
|
|
{
|
|
fonts = new string[0];
|
|
}
|
|
|
|
for (int i = 0; i < fonts.Length; i++)
|
|
{
|
|
fonts[i] = fonts[i]
|
|
.Replace(path, "")
|
|
.Replace(".ttf", "")
|
|
.Replace(".TTF", "");
|
|
}
|
|
|
|
return fonts;
|
|
}
|
|
|
|
private string[] FontsFromGame()
|
|
{
|
|
string[] gameFontArray = Enum.GetNames(typeof(GameFontFamily)).Skip(1).ToArray();
|
|
string[] fonts = new string[gameFontArray.Length];
|
|
|
|
for (int i = 0; i < gameFontArray.Length; i++)
|
|
{
|
|
fonts[i] = GameFontMap[gameFontArray[i]];
|
|
}
|
|
|
|
return fonts;
|
|
}
|
|
|
|
private void ReloadFonts()
|
|
{
|
|
string defaultFontsPath = ValidatePath(FontsManager.Instance.DefaultFontsPath);
|
|
string[] defaultFonts = FontsFromPath(defaultFontsPath);
|
|
string[] gameFonts = FontsFromGame();
|
|
string[] userFonts = FontsFromPath(ValidatedFontsPath);
|
|
|
|
_fonts = new string[defaultFonts.Length + gameFonts.Length + userFonts.Length];
|
|
defaultFonts.CopyTo(_fonts, 0);
|
|
gameFonts.CopyTo(_fonts, defaultFonts.Length);
|
|
userFonts.CopyTo(_fonts, defaultFonts.Length + gameFonts.Length);
|
|
}
|
|
|
|
private bool AddNewEntry(int font, int size)
|
|
{
|
|
if (font < 0 || font > _fonts.Length)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (size <= 0 || size > _sizes.Length)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string fontName = _fonts[font];
|
|
string key = fontName + "_" + size.ToString();
|
|
|
|
if (Fonts.ContainsKey(key))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
FontData fontData = new FontData(fontName, size);
|
|
Fonts.Add(key, fontData);
|
|
|
|
FontsManager.Instance.BuildFonts();
|
|
|
|
return true;
|
|
}
|
|
|
|
private void SelectFolder()
|
|
{
|
|
Action<bool, string> callback = (finished, path) =>
|
|
{
|
|
if (finished && path.Length > 0)
|
|
{
|
|
FontsPath = path;
|
|
ReloadFonts();
|
|
}
|
|
};
|
|
|
|
_fileDialogManager.OpenFolderDialog("Select Fonts Folder", callback);
|
|
}
|
|
|
|
[ManualDraw]
|
|
public bool Draw(ref bool changed)
|
|
{
|
|
ImGuiTableFlags flags =
|
|
ImGuiTableFlags.RowBg |
|
|
ImGuiTableFlags.Borders |
|
|
ImGuiTableFlags.BordersOuter |
|
|
ImGuiTableFlags.BordersInner |
|
|
ImGuiTableFlags.ScrollY |
|
|
ImGuiTableFlags.SizingFixedSame;
|
|
|
|
if (ImGui.BeginChild("Fonts", new Vector2(800, 500), false, ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse))
|
|
{
|
|
if (_fonts.Length == 0)
|
|
{
|
|
ImGuiHelper.Tab();
|
|
ImGui.Text("Default font not found in \"%appdata%/Roaming/XIVLauncher/InstalledPlugins/HSUI/Media/Fonts/Expressway.ttf\"");
|
|
return false;
|
|
}
|
|
|
|
ImGuiHelper.NewLineAndTab();
|
|
if (ImGui.InputText("Path", ref FontsPath, 200, ImGuiInputTextFlags.EnterReturnsTrue))
|
|
{
|
|
changed = true;
|
|
ReloadFonts();
|
|
}
|
|
|
|
ImGui.SameLine();
|
|
ImGui.PushFont(UiBuilder.IconFont);
|
|
if (ImGui.Button(FontAwesomeIcon.Folder.ToIconString(), new Vector2(0, 0)))
|
|
{
|
|
SelectFolder();
|
|
}
|
|
ImGui.PopFont();
|
|
|
|
ImGuiHelper.Tab();
|
|
ImGui.Combo("Font ##font", ref _inputFont, _fonts, 10);
|
|
|
|
ImGui.SameLine();
|
|
ImGui.PushFont(UiBuilder.IconFont);
|
|
if (ImGui.Button("\uf2f9", new Vector2(0, 0)))
|
|
{
|
|
ReloadFonts();
|
|
}
|
|
ImGui.PopFont();
|
|
|
|
ImGuiHelper.Tab();
|
|
ImGui.Combo("Size ##size", ref _inputSize, _sizes, 10);
|
|
|
|
ImGui.SameLine();
|
|
ImGui.PushFont(UiBuilder.IconFont);
|
|
if (ImGui.Button(FontAwesomeIcon.Plus.ToIconString(), new Vector2(0, 0)))
|
|
{
|
|
changed |= AddNewEntry(_inputFont, _inputSize + 1);
|
|
}
|
|
ImGui.PopFont();
|
|
|
|
ImGuiHelper.NewLineAndTab();
|
|
if (ImGui.BeginTable("table", 3, flags, new Vector2(326, 300)))
|
|
{
|
|
ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthStretch, 0, 0);
|
|
ImGui.TableSetupColumn("Size", ImGuiTableColumnFlags.WidthFixed, 0, 1);
|
|
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.WidthFixed, 0, 2);
|
|
|
|
ImGui.TableSetupScrollFreeze(0, 1);
|
|
ImGui.TableHeadersRow();
|
|
|
|
for (int i = 0; i < Fonts.Count; i++)
|
|
{
|
|
var key = Fonts.Keys[i];
|
|
var fontData = Fonts.Values[i];
|
|
|
|
ImGui.PushID(i.ToString());
|
|
ImGui.TableNextRow(ImGuiTableRowFlags.None);
|
|
|
|
// icon
|
|
if (ImGui.TableSetColumnIndex(0))
|
|
{
|
|
ImGui.Text(fontData.Name);
|
|
}
|
|
|
|
// id
|
|
if (ImGui.TableSetColumnIndex(1))
|
|
{
|
|
ImGui.Text(fontData.Size.ToString());
|
|
}
|
|
|
|
// remove
|
|
if (ImGui.TableSetColumnIndex(2))
|
|
{
|
|
ImGui.PushFont(UiBuilder.IconFont);
|
|
ImGui.PushStyleColor(ImGuiCol.Button, Vector4.Zero);
|
|
ImGui.PushStyleColor(ImGuiCol.ButtonActive, Vector4.Zero);
|
|
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, Vector4.Zero);
|
|
|
|
if (ImGui.Button(FontAwesomeIcon.ArrowAltCircleUp.ToIconString()))
|
|
{
|
|
_applyingIndex = i;
|
|
}
|
|
|
|
if (!IsDefaultFont(key))
|
|
{
|
|
ImGui.SameLine();
|
|
if (ImGui.Button(FontAwesomeIcon.Trash.ToIconString()))
|
|
{
|
|
_removingIndex = i;
|
|
}
|
|
}
|
|
|
|
ImGui.PopFont();
|
|
ImGui.PopStyleColor(3);
|
|
}
|
|
ImGui.PopID();
|
|
}
|
|
|
|
ImGui.EndTable();
|
|
}
|
|
|
|
ImGuiHelper.NewLineAndTab();
|
|
if (ImGui.Checkbox("Support Chinese", ref SupportChineseCharacters))
|
|
{
|
|
changed = true;
|
|
FontsManager.Instance.BuildFonts();
|
|
}
|
|
|
|
ImGui.SameLine();
|
|
if (ImGui.Checkbox("Support Korean", ref SupportKoreanCharacters))
|
|
{
|
|
changed = true;
|
|
FontsManager.Instance.BuildFonts();
|
|
}
|
|
|
|
ImGui.SameLine();
|
|
if (ImGui.Checkbox("Support Cyrillic", ref SupportCyrillicCharacters))
|
|
{
|
|
changed = true;
|
|
FontsManager.Instance.BuildFonts();
|
|
}
|
|
}
|
|
|
|
// apply confirmation
|
|
if (_applyingIndex >= 0)
|
|
{
|
|
string[] lines = new string[] { "Are you sure you want to apply this font", "to all labels using a font with the same size?" };
|
|
var (didConfirm, didClose) = ImGuiHelper.DrawConfirmationModal("Apply to all labels?", lines);
|
|
|
|
if (didConfirm)
|
|
{
|
|
var (key, font) = Fonts.ElementAt(_applyingIndex);
|
|
|
|
List<LabelConfig> labelConfigs = ConfigurationManager.Instance.GetObjects<LabelConfig>();
|
|
foreach (LabelConfig label in labelConfigs)
|
|
{
|
|
if (label.FontID != null && Fonts.TryGetValue(label.FontID, out FontData value))
|
|
{
|
|
if (font.Size == value.Size)
|
|
{
|
|
label.FontID = key;
|
|
}
|
|
}
|
|
}
|
|
|
|
changed = true;
|
|
ConfigurationManager.Instance.SaveConfigurations(forced: true);
|
|
}
|
|
|
|
if (didConfirm || didClose)
|
|
{
|
|
_applyingIndex = -1;
|
|
}
|
|
}
|
|
|
|
// delete confirmation
|
|
if (_removingIndex >= 0)
|
|
{
|
|
string[] lines = new string[] { "Are you sure you want to remove this font?" };
|
|
var (didConfirm, didClose) = ImGuiHelper.DrawConfirmationModal("Remove custom font?", lines);
|
|
|
|
if (didConfirm)
|
|
{
|
|
Fonts.RemoveAt(_removingIndex);
|
|
FontsManager.Instance.BuildFonts();
|
|
changed = true;
|
|
}
|
|
|
|
if (didConfirm || didClose)
|
|
{
|
|
_removingIndex = -1;
|
|
}
|
|
}
|
|
|
|
ImGui.EndChild();
|
|
|
|
_fileDialogManager.Draw();
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|