Initial release: HSUI v1.0.0.0 - HUD replacement with configurable hotbars
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,233 @@
|
||||
using Dalamud.Interface.GameFonts;
|
||||
using Dalamud.Interface.ManagedFontAtlas;
|
||||
using Dalamud.Interface.Utility;
|
||||
using HSUI.Config;
|
||||
using HSUI.Interface.GeneralElements;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace HSUI.Helpers
|
||||
{
|
||||
public class FontScope : IDisposable
|
||||
{
|
||||
private readonly IFontHandle? _handle;
|
||||
|
||||
public FontScope(IFontHandle? handle)
|
||||
{
|
||||
_handle = handle;
|
||||
_handle?.Push();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_handle?.Pop();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
public class FontsManager : IDisposable
|
||||
{
|
||||
#region Singleton
|
||||
private FontsManager(string basePath)
|
||||
{
|
||||
DefaultFontsPath = Path.GetDirectoryName(basePath) + "\\Media\\Fonts\\";
|
||||
}
|
||||
|
||||
public static void Initialize(string basePath)
|
||||
{
|
||||
Instance = new FontsManager(basePath);
|
||||
}
|
||||
|
||||
public static FontsManager Instance { get; private set; } = null!;
|
||||
private FontsConfig? _config;
|
||||
|
||||
public void LoadConfig()
|
||||
{
|
||||
if (_config != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_config = ConfigurationManager.Instance.GetConfigObject<FontsConfig>();
|
||||
ConfigurationManager.Instance.ResetEvent += OnConfigReset;
|
||||
}
|
||||
|
||||
private void OnConfigReset(ConfigurationManager sender)
|
||||
{
|
||||
_config = sender.GetConfigObject<FontsConfig>();
|
||||
}
|
||||
|
||||
~FontsManager()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigurationManager.Instance.ResetEvent -= OnConfigReset;
|
||||
Instance = null!;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public readonly string DefaultFontsPath;
|
||||
|
||||
public bool DefaultFontBuilt { get; private set; }
|
||||
public IFontHandle? DefaultFont { get; private set; } = null!;
|
||||
|
||||
private List<IFontHandle> _fonts = new List<IFontHandle>();
|
||||
public IReadOnlyCollection<IFontHandle> Fonts => _fonts.AsReadOnly();
|
||||
|
||||
public FontScope PushDefaultFont()
|
||||
{
|
||||
if (DefaultFontBuilt && DefaultFont != null)
|
||||
{
|
||||
return new FontScope(DefaultFont);
|
||||
}
|
||||
|
||||
return new FontScope(null);
|
||||
}
|
||||
|
||||
public FontScope PushFont(string? fontId)
|
||||
{
|
||||
if (fontId == null || _config == null || !_config.Fonts.ContainsKey(fontId))
|
||||
{
|
||||
return new FontScope(null);
|
||||
}
|
||||
|
||||
var index = _config.Fonts.IndexOfKey(fontId);
|
||||
if (index < 0 || index >= _fonts.Count)
|
||||
{
|
||||
return new FontScope(null);
|
||||
}
|
||||
|
||||
return new FontScope(_fonts[index]);
|
||||
}
|
||||
|
||||
public void ClearFonts()
|
||||
{
|
||||
foreach (IFontHandle font in _fonts)
|
||||
{
|
||||
font.Dispose();
|
||||
}
|
||||
|
||||
_fonts.Clear();
|
||||
}
|
||||
|
||||
public unsafe void BuildFonts()
|
||||
{
|
||||
ClearFonts();
|
||||
DefaultFontBuilt = false;
|
||||
|
||||
FontsConfig config = ConfigurationManager.Instance.GetConfigObject<FontsConfig>();
|
||||
ImGuiIOPtr io = ImGui.GetIO();
|
||||
ushort[]? ranges = GetCharacterRanges(config, io);
|
||||
|
||||
foreach (KeyValuePair<string, FontData> fontData in config.Fonts)
|
||||
{
|
||||
bool isGameFont = config.GameFontMap.ContainsValue(fontData.Value.Name);
|
||||
string path = DefaultFontsPath + fontData.Value.Name + ".ttf";
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
path = config.ValidatedFontsPath + fontData.Value.Name + ".ttf";
|
||||
|
||||
if (!File.Exists(path) && !isGameFont)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
IFontHandle font;
|
||||
|
||||
if (isGameFont)
|
||||
{
|
||||
GameFontFamily fontFamily = (GameFontFamily)Enum.Parse(
|
||||
typeof(GameFontFamily),
|
||||
config.GameFontMap.FirstOrDefault(x => x.Value == fontData.Value.Name).Key
|
||||
);
|
||||
GameFontStyle style = new GameFontStyle(fontFamily, fontData.Value.Size);
|
||||
|
||||
font = Plugin.UiBuilder.FontAtlas.NewGameFontHandle(style);
|
||||
}
|
||||
else
|
||||
{
|
||||
font = Plugin.UiBuilder.FontAtlas.NewDelegateFontHandle
|
||||
(
|
||||
e => e.OnPreBuild
|
||||
(
|
||||
tk => tk.AddFontFromFile
|
||||
(
|
||||
path,
|
||||
new SafeFontConfig
|
||||
{
|
||||
SizePx = fontData.Value.Size,
|
||||
GlyphRanges = ranges
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
_fonts.Add(font);
|
||||
|
||||
// save default font
|
||||
if (fontData.Key == FontsConfig.DefaultBigFontKey)
|
||||
{
|
||||
DefaultFont = font;
|
||||
DefaultFontBuilt = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Plugin.Logger.Error($"Error loading font from path {path}:\n{ex.Message}");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe ushort[]? GetCharacterRanges(FontsConfig config, ImGuiIOPtr io)
|
||||
{
|
||||
if (!config.SupportChineseCharacters && !config.SupportKoreanCharacters && !config.SupportCyrillicCharacters)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var builder = new ImFontGlyphRangesBuilderPtr(ImGuiNative.ImFontGlyphRangesBuilder());
|
||||
|
||||
if (config.SupportChineseCharacters)
|
||||
{
|
||||
// GetGlyphRangesChineseFull() includes Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs
|
||||
// https://skia.googlesource.com/external/github.com/ocornut/imgui/+/v1.53/extra_fonts/README.txt
|
||||
builder.AddRanges(io.Fonts.GetGlyphRangesChineseFull());
|
||||
}
|
||||
|
||||
if (config.SupportKoreanCharacters)
|
||||
{
|
||||
builder.AddRanges(io.Fonts.GetGlyphRangesKorean());
|
||||
}
|
||||
|
||||
if (config.SupportCyrillicCharacters)
|
||||
{
|
||||
builder.AddRanges(io.Fonts.GetGlyphRangesCyrillic());
|
||||
}
|
||||
|
||||
return builder.BuildRangesToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user