using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using Dalamud.Interface; using Dalamud.Interface.GameFonts; using Dalamud.Interface.Internal; using Dalamud.Interface.Textures; using Dalamud.Interface.Textures.TextureWraps; using Dalamud.Logging; using HSUI.Config; using HSUI.Interface.GeneralElements; using Dalamud.Bindings.ImGui; namespace HSUI.Helpers { public struct BarTextureData { public string Name; public string Path; public bool IsCustom; public BarTextureData(string name, string path, bool isCustom) { Name = name; Path = path; IsCustom = isCustom; } } public class BarTexturesManager : IDisposable { #region Singleton private BarTexturesManager(string basePath) { DefaultBarTexturesPath = Path.GetDirectoryName(basePath) + "\\Media\\Images\\textures\\"; } public static void Initialize(string basePath) { Instance = new BarTexturesManager(basePath); } public static BarTexturesManager Instance { get; private set; } = null!; private BarTexturesConfig? _config; public void LoadConfig() { if (_config != null) { return; } _config = ConfigurationManager.Instance.GetConfigObject(); ConfigurationManager.Instance.ResetEvent += OnConfigReset; ReloadTextures(); } private void OnConfigReset(ConfigurationManager sender) { _config = sender.GetConfigObject(); } ~BarTexturesManager() { 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 DefaultBarTexturesPath; public static readonly string DefaultBarTextureName = "Default"; public bool DefaultFontBuilt { get; private set; } public ImFontPtr DefaultFont { get; private set; } = null; private List _textures = new List(); public IReadOnlyCollection BarTextures => _textures.AsReadOnly(); private List _textureNames = new List(); public IReadOnlyCollection BarTextureNames => _textureNames.AsReadOnly(); private Dictionary _cache = new(); public IDalamudTextureWrap? GetBarTexture(string? name) { if (name == null || name == DefaultBarTextureName) { return null; } // get cached texture if (_cache.TryGetValue(name, out ISharedImmediateTexture? cachedTexture) && cachedTexture != null) { return cachedTexture.GetWrapOrDefault(); } // lazy load BarTextureData? data = _textures.FirstOrDefault(o => o.Name == name); if (!data.HasValue) { return null; } if (File.Exists(data.Value.Path)) { try { ISharedImmediateTexture? texture = Plugin.TextureProvider.GetFromFile(data.Value.Path); if (texture != null) { _cache.Add(name, texture); } return texture?.GetWrapOrDefault(); } catch (Exception ex) { Plugin.Logger.Warning($"Image failed to load. {data.Value.Path}: " + ex.Message); } } return null; } public void ReloadTextures() { _textures.Clear(); // embedded textures _textures.AddRange(TexturesFromPath(DefaultBarTexturesPath, true)); // custom textures if (_config != null) { _textures.AddRange(TexturesFromPath(_config.ValidatedBarTexturesPath, true)); } // sort by name _textures = _textures.OrderBy(o => o.Name).ToList(); // default always first _textures.Insert(0, new BarTextureData(DefaultBarTextureName, "", false)); _textureNames = _textures.Select(o => o.Name).ToList(); } private List TexturesFromPath(string path, bool isCustom) { string[] textures; try { string[] allowedExtensions = new string[] { ".png", ".tga" }; textures = Directory .GetFiles(path) .Where(file => allowedExtensions.Any(file.ToLower().EndsWith)) .ToArray(); } catch { textures = new string[0]; } List result = new List(textures.Length); for (int i = 0; i < textures.Length; i++) { string name = SanitizedTextureName(textures[i].Replace(path, "")); result.Add(new BarTextureData(name, textures[i], isCustom)); } return result; } private string SanitizedTextureName(string name) { return name .Replace(".png", "") .Replace(".PNG", "") .Replace(".tga", "") .Replace(".TGA", ""); } } }