diff --git a/Craftimizer/Plugin.cs b/Craftimizer/Plugin.cs index 75363ce..0ce76a6 100644 --- a/Craftimizer/Plugin.cs +++ b/Craftimizer/Plugin.cs @@ -1,12 +1,9 @@ -using Craftimizer.Plugin.Utils; using Craftimizer.Plugin.Windows; using Craftimizer.Simulator; using Craftimizer.Simulator.Actions; using Craftimizer.Utils; using Craftimizer.Windows; using Dalamud.Interface.ImGuiNotification; -using Dalamud.Interface.Textures; -using Dalamud.Interface.Textures.TextureWraps; using Dalamud.Interface.Windowing; using Dalamud.Plugin; using System; @@ -20,7 +17,7 @@ public sealed class Plugin : IDalamudPlugin public string Version { get; } public string Author { get; } public string BuildConfiguration { get; } - public ISharedImmediateTexture Icon { get; } + public ILoadedTextureIcon Icon { get; } public WindowSystem WindowSystem { get; } public Settings SettingsWindow { get; } @@ -31,6 +28,7 @@ public sealed class Plugin : IDalamudPlugin public MacroClipboard? ClipboardWindow { get; private set; } public Configuration Configuration { get; } + public IconManager IconManager { get; } public Hooks Hooks { get; } public Chat Chat { get; } public CommunityMacros CommunityMacros { get; } @@ -42,6 +40,7 @@ public Plugin(IDalamudPluginInterface pluginInterface) WindowSystem = new("Craftimizer"); Configuration = Configuration.Load(); + IconManager = new(); Hooks = new(); Chat = new(); CommunityMacros = new(); @@ -51,8 +50,7 @@ public Plugin(IDalamudPluginInterface pluginInterface) Version = assembly.GetCustomAttribute()!.InformationalVersion.Split('+')[0]; Author = assembly.GetCustomAttribute()!.Company; BuildConfiguration = assembly.GetCustomAttribute()!.Configuration; - var now = DateTime.Now; - if (now.Day == 1 && now.Month == 4) + if (DateTime.Now is { Day: 1, Month: 4 }) Icon = IconManager.GetAssemblyTexture("horse_icon.png"); else Icon = IconManager.GetAssemblyTexture("icon.png"); @@ -167,6 +165,8 @@ public void Dispose() ListWindow.Dispose(); EditorWindow?.Dispose(); ClipboardWindow?.Dispose(); + IconManager.Dispose(); Hooks.Dispose(); + Icon.Dispose(); } } diff --git a/Craftimizer/Service.cs b/Craftimizer/Service.cs index 5a12113..3e3fb93 100644 --- a/Craftimizer/Service.cs +++ b/Craftimizer/Service.cs @@ -28,6 +28,7 @@ public sealed class Service public static Plugin Plugin { get; private set; } public static Configuration Configuration => Plugin.Configuration; + public static IconManager IconManager => Plugin.IconManager; public static WindowSystem WindowSystem => Plugin.WindowSystem; public static Chat Chat => Plugin.Chat; public static CommunityMacros CommunityMacros => Plugin.CommunityMacros; diff --git a/Craftimizer/SimulatorUtils.cs b/Craftimizer/SimulatorUtils.cs index 8369925..ba63f07 100644 --- a/Craftimizer/SimulatorUtils.cs +++ b/Craftimizer/SimulatorUtils.cs @@ -87,15 +87,15 @@ public static string GetName(this ActionType me, ClassJob classJob) return "Unknown"; } - public static ISharedImmediateTexture GetIcon(this ActionType me, ClassJob classJob) + public static ITextureIcon GetIcon(this ActionType me, ClassJob classJob) { var (craftAction, action) = GetActionRow(me, classJob); if (craftAction != null) - return IconManager.GetIcon(craftAction.Icon); + return Service.IconManager.GetIconCached(craftAction.Icon); if (action != null) - return IconManager.GetIcon(action.Icon); + return Service.IconManager.GetIconCached(action.Icon); // Old "Steady Hand" action icon - return IconManager.GetIcon(1953); + return Service.IconManager.GetIconCached(1953); } public static ActionType? GetActionTypeFromId(uint actionId, ClassJob classJob, bool isCraftAction) @@ -331,8 +331,8 @@ public static ushort GetIconId(this EffectType me, int strength) return (ushort)iconId; } - public static ISharedImmediateTexture GetIcon(this EffectType me, int strength) => - IconManager.GetIcon(me.GetIconId(strength)); + public static ITextureIcon GetIcon(this EffectType me, int strength) => + Service.IconManager.GetIconCached(me.GetIconId(strength)); public static string GetTooltip(this EffectType me, int strength, int duration) { diff --git a/Craftimizer/Utils/IconManager.cs b/Craftimizer/Utils/IconManager.cs index 329544b..48ddba2 100644 --- a/Craftimizer/Utils/IconManager.cs +++ b/Craftimizer/Utils/IconManager.cs @@ -1,27 +1,124 @@ using Craftimizer.Plugin; using Dalamud.Interface.Textures; +using Dalamud.Interface.Textures.TextureWraps; +using Dalamud.Utility; using System; +using System.Collections.Generic; +using System.Numerics; using System.Reflection; +using System.Threading; +using System.Threading.Tasks; namespace Craftimizer.Utils; -public static class IconManager +public interface ITextureIcon { - public static ISharedImmediateTexture GetIcon(uint id, bool isHq = false) + ISharedImmediateTexture Source { get; } + + Vector2? Dimensions { get; } + + float? AspectRatio => Dimensions is { } d ? d.X / d.Y : null; + + nint ImGuiHandle { get; } +} + +public interface ILoadedTextureIcon : ITextureIcon, IDisposable { } + +public sealed class IconManager : IDisposable +{ + private sealed class LoadedIcon : ILoadedTextureIcon + { + // 10: DXGI_FORMAT_R16G16B16A16_FLOAT + public static IDalamudTextureWrap EmptyTexture { get; } = Service.TextureProvider.CreateEmpty(new(4, 4, 10), false, false); + + public ISharedImmediateTexture Source { get; } + + public Vector2? Dimensions => GetWrap()?.Size; + + public nint ImGuiHandle => GetWrapOrEmpty().ImGuiHandle; + + private Task TextureWrapTask { get; } + private CancellationTokenSource DisposeToken { get; } + + public LoadedIcon(ISharedImmediateTexture source) + { + Source = source; + DisposeToken = new(); + TextureWrapTask = source.RentAsync(DisposeToken.Token); + } + + public IDalamudTextureWrap? GetWrap() + { + if (TextureWrapTask.IsCompletedSuccessfully) + return TextureWrapTask.Result; + return null; + } + + public IDalamudTextureWrap GetWrapOrEmpty() => GetWrap() ?? EmptyTexture; + + public void Dispose() + { + DisposeToken.Cancel(); + TextureWrapTask.ToContentDisposedTask(true).Wait(); + } + } + + // TODO: Unload when unused, but with a custom timer? + private sealed class CachedIcon : ITextureIcon { - return Service.TextureProvider.GetFromGameIcon(new GameIconLookup(id, itemHq: isHq)); + private LoadedIcon Base { get; } + + public ISharedImmediateTexture Source => Base.Source; + + public Vector2? Dimensions => Base.Dimensions; + + public nint ImGuiHandle => Base.ImGuiHandle; + + public CachedIcon(ISharedImmediateTexture source) + { + Base = new(source); + } + + public void Release() + { + Base.Dispose(); + } } - public static ISharedImmediateTexture GetTexture(string path) + private Dictionary<(uint Id, bool IsHq), CachedIcon> IconCache { get; } = []; + private Dictionary AssemblyTextureCache { get; } = []; + + private static ISharedImmediateTexture GetIconInternal(uint id, bool isHq = false) => + Service.TextureProvider.GetFromGameIcon(new GameIconLookup(id, itemHq: isHq)); + + private static ISharedImmediateTexture GetAssemblyTextureInternal(string filename) => + Service.TextureProvider.GetFromManifestResource(Assembly.GetExecutingAssembly(), $"Craftimizer.{filename}"); + + public static ILoadedTextureIcon GetIcon(uint id, bool isHq = false) => + new LoadedIcon(GetIconInternal(id, isHq)); + + public static ILoadedTextureIcon GetAssemblyTexture(string filename) => + new LoadedIcon(GetAssemblyTextureInternal(filename)); + + public ITextureIcon GetIconCached(uint id, bool isHq = false) { - return Service.TextureProvider.GetFromGame(path); + if (IconCache.TryGetValue((id, isHq), out var icon)) + return icon; + return IconCache[(id, isHq)] = new(GetIconInternal(id, isHq)); } - public static ISharedImmediateTexture GetAssemblyTexture(string filename) + public ITextureIcon GetAssemblyTextureCached(string filename) { - return Service.TextureProvider.GetFromManifestResource(Assembly.GetExecutingAssembly(), $"Craftimizer.{filename}"); + if (AssemblyTextureCache.TryGetValue(filename, out var texture)) + return texture; + return AssemblyTextureCache[filename] = new(GetAssemblyTextureInternal(filename)); } - public static nint GetHandle(this ISharedImmediateTexture me) => - me.GetWrapOrEmpty().ImGuiHandle; + public void Dispose() + { + foreach (var value in IconCache.Values) + value.Release(); + foreach (var value in AssemblyTextureCache.Values) + value.Release(); + } } diff --git a/Craftimizer/Windows/MacroEditor.cs b/Craftimizer/Windows/MacroEditor.cs index 2518e5e..ca116f1 100644 --- a/Craftimizer/Windows/MacroEditor.cs +++ b/Craftimizer/Windows/MacroEditor.cs @@ -92,16 +92,16 @@ public CrafterBuffs(StatusList? statuses) private Solver.Solver? SolverObject { get; set; } private bool SolverRunning => SolverTokenSource != null; - private ISharedImmediateTexture ExpertBadge { get; } - private ISharedImmediateTexture CollectibleBadge { get; } - private ISharedImmediateTexture SplendorousBadge { get; } - private ISharedImmediateTexture SpecialistBadge { get; } - private ISharedImmediateTexture NoManipulationBadge { get; } - private ISharedImmediateTexture ManipulationBadge { get; } - private ISharedImmediateTexture WellFedBadge { get; } - private ISharedImmediateTexture MedicatedBadge { get; } - private ISharedImmediateTexture InControlBadge { get; } - private ISharedImmediateTexture EatFromTheHandBadge { get; } + private ILoadedTextureIcon ExpertBadge { get; } + private ILoadedTextureIcon CollectibleBadge { get; } + private ILoadedTextureIcon SplendorousBadge { get; } + private ILoadedTextureIcon SpecialistBadge { get; } + private ILoadedTextureIcon NoManipulationBadge { get; } + private ITextureIcon ManipulationBadge { get; } + private ILoadedTextureIcon WellFedBadge { get; } + private ILoadedTextureIcon MedicatedBadge { get; } + private ILoadedTextureIcon InControlBadge { get; } + private ILoadedTextureIcon EatFromTheHandBadge { get; } private IFontHandle AxisFont { get; } private string popupSaveAsMacroName = string.Empty; @@ -224,7 +224,7 @@ private bool DrawCharacterParams() uv0 /= new Vector2(56); uv1 /= new Vector2(56); - ImGui.Image(IconManager.GetIcon(RecipeData.ClassJob.GetIconId()).GetHandle(), new Vector2(imageSize), uv0, uv1); + ImGui.Image(Service.IconManager.GetIconCached(RecipeData.ClassJob.GetIconId()).ImGuiHandle, new Vector2(imageSize), uv0, uv1); ImGui.SameLine(0, 5); AxisFont.Text(textClassName); @@ -311,7 +311,7 @@ void DrawStat(string name, int value, Action setter) { var v = CharacterStats.HasSplendorousBuff; var tint = v ? Vector4.One : disabledTint; - if (ImGui.ImageButton(SplendorousBadge.GetHandle(), new Vector2(imageButtonSize), default, Vector2.One, imageButtonPadding, default, tint)) + if (ImGui.ImageButton(SplendorousBadge.ImGuiHandle, new Vector2(imageButtonSize), default, Vector2.One, imageButtonPadding, default, tint)) CharacterStats = CharacterStats with { HasSplendorousBuff = !v }; } if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled)) @@ -329,7 +329,7 @@ void DrawStat(string name, int value, Action setter) using (var d = ImRaii.Disabled(specialistLevel > CharacterStats.Level)) { var tint = new Vector4(0.99f, 0.97f, 0.62f, 1f) * (v ? Vector4.One : disabledTint); - if (ImGui.ImageButton(SpecialistBadge.GetHandle(), new Vector2(imageButtonSize), default, Vector2.One, imageButtonPadding, default, tint)) + if (ImGui.ImageButton(SpecialistBadge.ImGuiHandle, new Vector2(imageButtonSize), default, Vector2.One, imageButtonPadding, default, tint)) { v = !v; newIsSpecialist = v; @@ -345,7 +345,7 @@ void DrawStat(string name, int value, Action setter) { var v = CharacterStats.CanUseManipulation && manipLevel <= CharacterStats.Level; var tint = (v || manipLevel > CharacterStats.Level) ? disabledTint : Vector4.One; - if (ImGui.ImageButton(v ? ManipulationBadge.GetHandle() : NoManipulationBadge.GetHandle(), new Vector2(imageButtonSize), default, Vector2.One, imageButtonPadding, default, tint)) + if (ImGui.ImageButton((v ? ManipulationBadge : NoManipulationBadge).ImGuiHandle, new Vector2(imageButtonSize), default, Vector2.One, imageButtonPadding, default, tint)) CharacterStats = CharacterStats with { CanUseManipulation = !v }; } if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled)) @@ -354,10 +354,10 @@ void DrawStat(string name, int value, Action setter) ImGui.TableNextColumn(); + var buffBadgeSize = new Vector2(imageSize * (WellFedBadge.AspectRatio ?? 1), imageSize); + (uint ItemId, bool HQ)? newFoodBuff = null; - var buffBadge = WellFedBadge.GetWrapOrEmpty(); - var buffImageSize = new Vector2(imageSize * buffBadge.Width / buffBadge.Height, imageSize); - ImGui.Image(buffBadge.ImGuiHandle, buffImageSize); + ImGui.Image(WellFedBadge.ImGuiHandle, buffBadgeSize); if (ImGui.IsItemHovered()) ImGuiUtils.Tooltip("Food"); ImGui.SameLine(0, 5); @@ -392,9 +392,7 @@ void DrawStat(string name, int value, Action setter) } (uint ItemId, bool HQ)? newMedicineBuff = null; - buffBadge = MedicatedBadge.GetWrapOrEmpty(); - buffImageSize = new Vector2(imageSize * buffBadge.Width / buffBadge.Height, imageSize); - ImGui.Image(buffBadge.ImGuiHandle, buffImageSize); + ImGui.Image(MedicatedBadge.ImGuiHandle, buffBadgeSize); if (ImGui.IsItemHovered()) ImGuiUtils.Tooltip("Medicine"); ImGui.SameLine(0, 5); @@ -431,9 +429,7 @@ void DrawStat(string name, int value, Action setter) ImGui.TableNextColumn(); int? newFCCraftsmanshipBuff = null; - buffBadge = EatFromTheHandBadge.GetWrapOrEmpty(); - buffImageSize = new Vector2(imageSize * buffBadge.Width / buffBadge.Height, imageSize); - ImGui.Image(buffBadge.ImGuiHandle, buffImageSize); + ImGui.Image(EatFromTheHandBadge.ImGuiHandle, buffBadgeSize); var fcBuffName = "Eat from the Hand"; var fcStatName = "Craftsmanship"; if (ImGui.IsItemHovered()) @@ -460,9 +456,7 @@ void DrawStat(string name, int value, Action setter) } int? newFCControlBuff = null; - buffBadge = InControlBadge.GetWrapOrEmpty(); - buffImageSize = new Vector2(imageSize * buffBadge.Width / buffBadge.Height, imageSize); - ImGui.Image(buffBadge.ImGuiHandle, buffImageSize); + ImGui.Image(InControlBadge.ImGuiHandle, buffBadgeSize); fcBuffName = "In Control"; fcStatName = "Control"; if (ImGui.IsItemHovered()) @@ -712,8 +706,7 @@ private bool DrawRecipeParams() var isCollectable = RecipeData.Recipe.ItemResult.Value!.IsCollectable; var imageSize = ImGui.GetFrameHeight(); var textSize = ImGui.GetFontSize(); - var badge = ExpertBadge.GetWrapOrEmpty(); - var badgeSize = new Vector2(textSize * badge.Width / badge.Height, textSize); + var badgeSize = new Vector2(textSize * (ExpertBadge.AspectRatio ?? 1), textSize); var badgeOffset = (imageSize - badgeSize.Y) / 2; var rightSideWidth = @@ -723,7 +716,7 @@ private bool DrawRecipeParams() (isExpert ? badgeSize.X + 3 : 0); ImGui.AlignTextToFramePadding(); - ImGui.Image(IconManager.GetIcon(RecipeData.Recipe.ItemResult.Value!.Icon).GetHandle(), new Vector2(imageSize)); + ImGui.Image(Service.IconManager.GetIconCached(RecipeData.Recipe.ItemResult.Value!.Icon).ImGuiHandle, new Vector2(imageSize)); ImGui.SameLine(0, 5); @@ -761,7 +754,7 @@ private bool DrawRecipeParams() uv1 /= new Vector2(56); ImGui.SetCursorPosY(ImGui.GetCursorPosY() + ImGui.GetStyle().FramePadding.Y / 2); - ImGui.Image(IconManager.GetIcon(classJob.GetIconId()).GetHandle(), new Vector2(imageSize), uv0, uv1); + ImGui.Image(Service.IconManager.GetIconCached(classJob.GetIconId()).ImGuiHandle, new Vector2(imageSize), uv0, uv1); ImGui.SameLine(0, 5); ImGui.SetCursorPosY(ImGui.GetCursorPosY() + (fontHandle.FontSize - textLevelSize.Y) / 2); ImGui.TextUnformatted(textLevel); @@ -787,7 +780,7 @@ private bool DrawRecipeParams() { ImGui.SameLine(0, 3); ImGui.SetCursorPosY(ImGui.GetCursorPosY() + badgeOffset); - ImGui.Image(CollectibleBadge.GetHandle(), badgeSize); + ImGui.Image(CollectibleBadge.ImGuiHandle, badgeSize); if (ImGui.IsItemHovered()) ImGuiUtils.Tooltip($"Collectible"); } @@ -796,7 +789,7 @@ private bool DrawRecipeParams() { ImGui.SameLine(0, 3); ImGui.SetCursorPosY(ImGui.GetCursorPosY() + badgeOffset); - ImGui.Image(ExpertBadge.GetHandle(), badgeSize); + ImGui.Image(ExpertBadge.ImGuiHandle, badgeSize); if (ImGui.IsItemHovered()) ImGuiUtils.Tooltip($"Expert Recipe"); } @@ -883,11 +876,11 @@ private void DrawIngredientHQEntry(int idx) var hqCount = HQIngredientCounts[idx]; var canHq = ingredient.Item.CanBeHq; - var icon = IconManager.GetIcon(ingredient.Item.Icon, canHq); + var icon = Service.IconManager.GetIconCached(ingredient.Item.Icon, canHq); var imageSize = ImGui.GetFrameHeight(); using (var d = ImRaii.Disabled(!canHq)) - ImGui.Image(icon.GetHandle(), new Vector2(imageSize)); + ImGui.Image(icon.ImGuiHandle, new Vector2(imageSize)); if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled)) { if (canHq) @@ -955,7 +948,7 @@ private void DrawActionHotbars() { var actionBase = actions[i].Base(); var canUse = actionBase.CanUse(sim); - if (ImGui.ImageButton(actions[i].GetIcon(RecipeData!.ClassJob).GetHandle(), new(imageSize), default, Vector2.One, 0, default, !canUse ? new(1, 1, 1, ImGui.GetStyle().DisabledAlpha) : Vector4.One) && !SolverRunning) + if (ImGui.ImageButton(actions[i].GetIcon(RecipeData!.ClassJob).ImGuiHandle, new(imageSize), default, Vector2.One, 0, default, !canUse ? new(1, 1, 1, ImGui.GetStyle().DisabledAlpha) : Vector4.One) && !SolverRunning) AddStep(actions[i]); if (!canUse && (CharacterStats.Level < actionBase.Level || @@ -979,7 +972,7 @@ private void DrawActionHotbars() if (_source) { ImGuiExtras.SetDragDropPayload("macroActionInsert", actions[i]); - ImGui.ImageButton(actions[i].GetIcon(RecipeData!.ClassJob).GetHandle(), new(imageSize)); + ImGui.ImageButton(actions[i].GetIcon(RecipeData!.ClassJob).ImGuiHandle, new(imageSize)); } } } @@ -1093,8 +1086,8 @@ void DrawCondition(DynamicBars.DrawerParams drawerParams) using (var group = ImRaii.Group()) { - var icon = effect.GetIcon(effects.GetStrength(effect)).GetWrapOrEmpty(); - var size = new Vector2(iconHeight * icon.Width / icon.Height, iconHeight); + var icon = effect.GetIcon(effects.GetStrength(effect)); + var size = new Vector2(iconHeight * (icon.AspectRatio ?? 1), iconHeight); ImGui.Image(icon.ImGuiHandle, size); if (!effect.IsIndefinite()) @@ -1143,7 +1136,7 @@ private void DrawMacro() var actionBase = action.Base(); var failedAction = response != ActionResponse.UsedAction; using var id = ImRaii.PushId(i); - if (ImGui.ImageButton(action.GetIcon(RecipeData!.ClassJob).GetHandle(), new(imageSize), default, Vector2.One, 0, default, failedAction ? new(1, 1, 1, ImGui.GetStyle().DisabledAlpha) : Vector4.One)) + if (ImGui.ImageButton(action.GetIcon(RecipeData!.ClassJob).ImGuiHandle, new(imageSize), default, Vector2.One, 0, default, failedAction ? new(1, 1, 1, ImGui.GetStyle().DisabledAlpha) : Vector4.One)) RemoveStep(i); if (response is ActionResponse.ActionNotUnlocked || ( @@ -1172,7 +1165,7 @@ private void DrawMacro() if (_source) { ImGuiExtras.SetDragDropPayload("macroAction", i); - ImGui.ImageButton(action.GetIcon(RecipeData!.ClassJob).GetHandle(), new(imageSize)); + ImGui.ImageButton(action.GetIcon(RecipeData!.ClassJob).ImGuiHandle, new(imageSize)); } } using (var _target = ImRaii.DragDropTarget()) @@ -1598,6 +1591,15 @@ public void Dispose() { Service.WindowSystem.RemoveWindow(this); + ExpertBadge.Dispose(); + CollectibleBadge.Dispose(); + SplendorousBadge.Dispose(); + SpecialistBadge.Dispose(); + NoManipulationBadge.Dispose(); + WellFedBadge.Dispose(); + MedicatedBadge.Dispose(); + InControlBadge.Dispose(); + EatFromTheHandBadge.Dispose(); AxisFont.Dispose(); } } diff --git a/Craftimizer/Windows/MacroList.cs b/Craftimizer/Windows/MacroList.cs index 744fdd2..225c9cd 100644 --- a/Craftimizer/Windows/MacroList.cs +++ b/Craftimizer/Windows/MacroList.cs @@ -274,7 +274,7 @@ private void DrawMacro(Macro macro, float width = -1) var shouldShowMore = i + 1 == itemsPerRow * 2 && i + 1 < itemCount; if (!shouldShowMore) { - ImGui.Image(macro.Actions[i].GetIcon(RecipeData!.ClassJob).GetHandle(), new(miniRowHeight)); + ImGui.Image(macro.Actions[i].GetIcon(RecipeData!.ClassJob).ImGuiHandle, new(miniRowHeight)); if (ImGui.IsItemHovered()) ImGuiUtils.Tooltip(macro.Actions[i].GetName(RecipeData!.ClassJob)); } @@ -282,7 +282,7 @@ private void DrawMacro(Macro macro, float width = -1) { var amtMore = itemCount - itemsPerRow * 2; var pos = ImGui.GetCursorPos(); - ImGui.Image(macro.Actions[i].GetIcon(RecipeData!.ClassJob).GetHandle(), new(miniRowHeight), default, Vector2.One, new(1, 1, 1, .5f)); + ImGui.Image(macro.Actions[i].GetIcon(RecipeData!.ClassJob).ImGuiHandle, new(miniRowHeight), default, Vector2.One, new(1, 1, 1, .5f)); if (ImGui.IsItemHovered()) ImGuiUtils.Tooltip($"{macro.Actions[i].GetName(RecipeData!.ClassJob)}\nand {amtMore} more"); ImGui.SetCursorPos(pos); diff --git a/Craftimizer/Windows/RecipeNote.cs b/Craftimizer/Windows/RecipeNote.cs index 1e2d77e..6622a34 100644 --- a/Craftimizer/Windows/RecipeNote.cs +++ b/Craftimizer/Windows/RecipeNote.cs @@ -107,11 +107,11 @@ public void Dispose() => private Solver.Solver? BestMacroSolver { get; set; } public bool HasSavedMacro { get; private set; } - private ISharedImmediateTexture ExpertBadge { get; } - private ISharedImmediateTexture CollectibleBadge { get; } - private ISharedImmediateTexture SplendorousBadge { get; } - private ISharedImmediateTexture SpecialistBadge { get; } - private ISharedImmediateTexture NoManipulationBadge { get; } + private ILoadedTextureIcon ExpertBadge { get; } + private ILoadedTextureIcon CollectibleBadge { get; } + private ILoadedTextureIcon SplendorousBadge { get; } + private ILoadedTextureIcon SpecialistBadge { get; } + private ILoadedTextureIcon NoManipulationBadge { get; } private IFontHandle AxisFont { get; } public RecipeNote() : base(WindowNamePinned) @@ -481,7 +481,7 @@ private void DrawCharacterStats() uv0 /= new Vector2(56); uv1 /= new Vector2(56); - ImGui.Image(IconManager.GetIcon(RecipeData.ClassJob.GetIconId()).GetHandle(), new Vector2(imageSize), uv0, uv1); + ImGui.Image(Service.IconManager.GetIconCached(RecipeData.ClassJob.GetIconId()).ImGuiHandle, new Vector2(imageSize), uv0, uv1); ImGui.SameLine(0, 5); if (level != 0) @@ -495,7 +495,7 @@ private void DrawCharacterStats() if (hasSplendorous) { ImGui.SameLine(0, 3); - ImGui.Image(SplendorousBadge.GetHandle(), new Vector2(imageSize)); + ImGui.Image(SplendorousBadge.ImGuiHandle, new Vector2(imageSize)); if (ImGui.IsItemHovered()) ImGuiUtils.Tooltip($"Splendorous Tool"); } @@ -503,7 +503,7 @@ private void DrawCharacterStats() if (hasSpecialist) { ImGui.SameLine(0, 3); - ImGui.Image(SpecialistBadge.GetHandle(), new Vector2(imageSize), Vector2.Zero, Vector2.One, new(0.99f, 0.97f, 0.62f, 1f)); + ImGui.Image(SpecialistBadge.ImGuiHandle, new Vector2(imageSize), Vector2.Zero, Vector2.One, new(0.99f, 0.97f, 0.62f, 1f)); if (ImGui.IsItemHovered()) ImGuiUtils.Tooltip($"Specialist"); } @@ -511,7 +511,7 @@ private void DrawCharacterStats() if (shouldHaveManip) { ImGui.SameLine(0, 3); - ImGui.Image(NoManipulationBadge.GetHandle(), new Vector2(imageSize)); + ImGui.Image(NoManipulationBadge.ImGuiHandle, new Vector2(imageSize)); if (ImGui.IsItemHovered()) ImGuiUtils.Tooltip($"No Manipulation (Missing Job Quest)"); } @@ -585,7 +585,7 @@ private void DrawCharacterStats() ImGuiUtils.TextCentered($"You are missing the required equipment."); ImGuiUtils.AlignCentered(imageSize + 5 + ImGui.CalcTextSize(itemName).X); ImGui.AlignTextToFramePadding(); - ImGui.Image(IconManager.GetIcon(item.Icon).GetHandle(), new(imageSize)); + ImGui.Image(Service.IconManager.GetIconCached(item.Icon).ImGuiHandle, new(imageSize)); ImGui.SameLine(0, 5); ImGui.TextUnformatted(itemName); } @@ -594,8 +594,8 @@ private void DrawCharacterStats() { var status = RecipeData.Recipe.StatusRequired.Value!; var statusName = status.Name.ToDalamudString().ToString(); - var statusIcon = IconManager.GetIcon(status.Icon).GetWrapOrEmpty(); - var imageSize = new Vector2(ImGui.GetFrameHeight() * statusIcon.Width / statusIcon.Height, ImGui.GetFrameHeight()); + var statusIcon = Service.IconManager.GetIconCached(status.Icon); + var imageSize = new Vector2(ImGui.GetFrameHeight() * (statusIcon.AspectRatio ?? 1), ImGui.GetFrameHeight()); ImGuiUtils.TextCentered($"You are missing the required status effect."); ImGuiUtils.AlignCentered(imageSize.X + 5 + ImGui.CalcTextSize(statusName).X); @@ -665,8 +665,7 @@ private void DrawRecipeStats() var isCollectable = RecipeData.Recipe.ItemResult.Value!.IsCollectable; var imageSize = ImGui.GetFrameHeight(); var textSize = ImGui.GetFontSize(); - var badge = ExpertBadge.GetWrapOrEmpty(); - var badgeSize = new Vector2(textSize * badge.Width / badge.Height, textSize); + var badgeSize = new Vector2(textSize * (ExpertBadge.AspectRatio ?? 1), textSize); var badgeOffset = (imageSize - badgeSize.Y) / 2; ImGuiUtils.AlignCentered( @@ -678,7 +677,7 @@ private void DrawRecipeStats() ); ImGui.AlignTextToFramePadding(); - ImGui.Image(IconManager.GetIcon(RecipeData.Recipe.ItemResult.Value!.Icon).GetHandle(), new Vector2(imageSize)); + ImGui.Image(Service.IconManager.GetIconCached(RecipeData.Recipe.ItemResult.Value!.Icon).ImGuiHandle, new Vector2(imageSize)); ImGui.SameLine(0, 5); ImGui.TextUnformatted(textLevel); @@ -696,7 +695,7 @@ private void DrawRecipeStats() { ImGui.SameLine(0, 3); ImGui.SetCursorPosY(ImGui.GetCursorPosY() + badgeOffset); - ImGui.Image(CollectibleBadge.GetHandle(), badgeSize); + ImGui.Image(CollectibleBadge.ImGuiHandle, badgeSize); if (ImGui.IsItemHovered()) ImGuiUtils.Tooltip($"Collectible"); } @@ -705,7 +704,7 @@ private void DrawRecipeStats() { ImGui.SameLine(0, 3); ImGui.SetCursorPosY(ImGui.GetCursorPosY() + badgeOffset); - ImGui.Image(ExpertBadge.GetHandle(), badgeSize); + ImGui.Image(ExpertBadge.ImGuiHandle, badgeSize); if (ImGui.IsItemHovered()) ImGuiUtils.Tooltip($"Expert Recipe"); } @@ -1006,7 +1005,7 @@ private void DrawMacro(in MacroTaskState state, float panelWidth) var shouldShowMore = i + 1 == itemsPerRow * 2 && i + 1 < itemCount; if (!shouldShowMore) { - ImGui.Image(actions[i].GetIcon(RecipeData!.ClassJob).GetHandle(), new(miniRowHeight)); + ImGui.Image(actions[i].GetIcon(RecipeData!.ClassJob).ImGuiHandle, new(miniRowHeight)); if (ImGui.IsItemHovered()) ImGuiUtils.Tooltip(actions[i].GetName(RecipeData!.ClassJob)); } @@ -1014,7 +1013,7 @@ private void DrawMacro(in MacroTaskState state, float panelWidth) { var amtMore = itemCount - itemsPerRow * 2; var pos = ImGui.GetCursorPos(); - ImGui.Image(actions[i].GetIcon(RecipeData!.ClassJob).GetHandle(), new(miniRowHeight), default, Vector2.One, new(1, 1, 1, .5f)); + ImGui.Image(actions[i].GetIcon(RecipeData!.ClassJob).ImGuiHandle, new(miniRowHeight), default, Vector2.One, new(1, 1, 1, .5f)); if (ImGui.IsItemHovered()) ImGuiUtils.Tooltip($"{actions[i].GetName(RecipeData!.ClassJob)}\nand {amtMore} more"); ImGui.SetCursorPos(pos); @@ -1226,5 +1225,10 @@ public void Dispose() CommunityMacroTask?.Dispose(); Service.WindowSystem.RemoveWindow(this); AxisFont?.Dispose(); + ExpertBadge.Dispose(); + CollectibleBadge.Dispose(); + SplendorousBadge.Dispose(); + SpecialistBadge.Dispose(); + NoManipulationBadge.Dispose(); } } diff --git a/Craftimizer/Windows/Settings.cs b/Craftimizer/Windows/Settings.cs index 9397b33..4d7fb22 100644 --- a/Craftimizer/Windows/Settings.cs +++ b/Craftimizer/Windows/Settings.cs @@ -683,7 +683,7 @@ private static void DrawActionPool(ref ActionType[] actionPool, float poolWidth, iconTint = new(1, 1f, .5f, 1); else if (isRisky) iconTint = new(1, .5f, .5f, 1); - if (ImGui.ImageButton(actions[i].GetIcon(recipeData.ClassJob).GetHandle(), new(imageSize), default, Vector2.One, 0, default, iconTint)) + if (ImGui.ImageButton(actions[i].GetIcon(recipeData.ClassJob).ImGuiHandle, new(imageSize), default, Vector2.One, 0, default, iconTint)) { isDirty = true; if (isEnabled) @@ -921,19 +921,20 @@ private void DrawTabAbout() ImGuiHelpers.ScaledDummy(5); var plugin = Service.Plugin; - var icon = plugin.Icon.GetWrapOrEmpty(); + var icon = plugin.Icon; + var iconDim = icon.Dimensions ?? new(128); using (var table = ImRaii.Table("settingsAboutTable", 2)) { if (table) { - ImGui.TableSetupColumn("", ImGuiTableColumnFlags.WidthFixed, icon.Width); + ImGui.TableSetupColumn("", ImGuiTableColumnFlags.WidthFixed, iconDim.X); ImGui.TableNextColumn(); - ImGui.Image(icon.ImGuiHandle, new(icon.Width, icon.Height)); + ImGui.Image(icon.ImGuiHandle, iconDim); ImGui.TableNextColumn(); - ImGuiUtils.AlignMiddle(new(float.PositiveInfinity, HeaderFont.GetFontSize() + SubheaderFont.GetFontSize() + ImGui.GetFontSize() * 3 + ImGui.GetStyle().ItemSpacing.Y * 4), new(0, icon.Height)); + ImGuiUtils.AlignMiddle(new(float.PositiveInfinity, HeaderFont.GetFontSize() + SubheaderFont.GetFontSize() + ImGui.GetFontSize() * 3 + ImGui.GetStyle().ItemSpacing.Y * 4), new(0, iconDim.Y)); using (HeaderFont.Push()) { diff --git a/Craftimizer/Windows/SynthHelper.cs b/Craftimizer/Windows/SynthHelper.cs index a30ec79..eafa6db 100644 --- a/Craftimizer/Windows/SynthHelper.cs +++ b/Craftimizer/Windows/SynthHelper.cs @@ -310,7 +310,7 @@ private void DrawMacro() isPressed = ImGuiExtras.ButtonBehavior(bb, id, out isHovered, out isHeld, ImGuiButtonFlags.None); } - ImGui.ImageButton(action.GetIcon(RecipeData!.ClassJob).GetHandle(), new(imageSize), default, Vector2.One, 0, default, failedAction ? new(1, 1, 1, ImGui.GetStyle().DisabledAlpha) : Vector4.One); + ImGui.ImageButton(action.GetIcon(RecipeData!.ClassJob).ImGuiHandle, new(imageSize), default, Vector2.One, 0, default, failedAction ? new(1, 1, 1, ImGui.GetStyle().DisabledAlpha) : Vector4.One); if (isPressed || IsSuggestedActionExecutionQueued) { if (canExecute && i == 0) @@ -359,8 +359,8 @@ private void DrawMacroInfo() using (var group = ImRaii.Group()) { - var icon = effect.GetIcon(effects.GetStrength(effect)).GetWrapOrEmpty(); - var size = new Vector2(iconHeight * icon.Width / icon.Height, iconHeight); + var icon = effect.GetIcon(effects.GetStrength(effect)); + var size = new Vector2(iconHeight * (icon.AspectRatio ?? 1), iconHeight); ImGui.Image(icon.ImGuiHandle, size); if (!effect.IsIndefinite())