Apply ImRaii to TexWidget

This commit is contained in:
Infi 2026-01-03 21:24:57 +01:00
parent e4ef56b878
commit 8c26d67739

View file

@ -14,6 +14,7 @@ using Dalamud.Interface.Textures.Internal.SharedImmediateTextures;
using Dalamud.Interface.Textures.TextureWraps; using Dalamud.Interface.Textures.TextureWraps;
using Dalamud.Interface.Utility; using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Internal; using Dalamud.Interface.Utility.Internal;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Dalamud.Storage.Assets; using Dalamud.Storage.Assets;
using Dalamud.Utility; using Dalamud.Utility;
@ -28,6 +29,10 @@ namespace Dalamud.Interface.Internal.Windows.Data.Widgets;
/// </summary> /// </summary>
internal class TexWidget : IDataWindowWidget internal class TexWidget : IDataWindowWidget
{ {
private const ImGuiTableFlags TableFlags = ImGuiTableFlags.Sortable | ImGuiTableFlags.SortTristate | ImGuiTableFlags.SortMulti |
ImGuiTableFlags.Reorderable | ImGuiTableFlags.Resizable | ImGuiTableFlags.NoBordersInBodyUntilResize |
ImGuiTableFlags.NoSavedSettings;
// TODO: move tracking implementation to PluginStats where applicable, // TODO: move tracking implementation to PluginStats where applicable,
// and show stats over there instead of TexWidget. // and show stats over there instead of TexWidget.
private static readonly Dictionary< private static readonly Dictionary<
@ -43,12 +48,12 @@ internal class TexWidget : IDataWindowWidget
[DrawBlameTableColumnUserId.NativeAddress] = static x => x.ResourceAddress, [DrawBlameTableColumnUserId.NativeAddress] = static x => x.ResourceAddress,
}; };
private readonly List<TextureEntry> addedTextures = new(); private readonly List<TextureEntry> addedTextures = [];
private string allLoadedTexturesTableName = "##table"; private string allLoadedTexturesTableName = "##table";
private string iconId = "18"; private string iconId = "18";
private bool hiRes = true; private bool hiRes = true;
private bool hq = false; private bool hq;
private string inputTexPath = string.Empty; private string inputTexPath = string.Empty;
private string inputFilePath = string.Empty; private string inputFilePath = string.Empty;
private Assembly[]? inputManifestResourceAssemblyCandidates; private Assembly[]? inputManifestResourceAssemblyCandidates;
@ -83,7 +88,7 @@ internal class TexWidget : IDataWindowWidget
} }
/// <inheritdoc/> /// <inheritdoc/>
public string[]? CommandShortcuts { get; init; } = { "tex", "texture" }; public string[]? CommandShortcuts { get; init; } = ["tex", "texture"];
/// <inheritdoc/> /// <inheritdoc/>
public string DisplayName { get; init; } = "Tex"; public string DisplayName { get; init; } = "Tex";
@ -140,45 +145,39 @@ internal class TexWidget : IDataWindowWidget
var allBlames = this.textureManager.BlameTracker; var allBlames = this.textureManager.BlameTracker;
lock (allBlames) lock (allBlames)
{ {
ImGui.PushID("blames"u8); using var pushedId = ImRaii.PushId("blames"u8);
var sizeSum = allBlames.Sum(static x => Math.Max(0, x.RawSpecs.EstimatedBytes)); var sizeSum = allBlames.Sum(static x => Math.Max(0, x.RawSpecs.EstimatedBytes));
if (ImGui.CollapsingHeader( if (ImGui.CollapsingHeader($"All Loaded Textures: {allBlames.Count:n0} ({Util.FormatBytes(sizeSum)})###header"))
$"All Loaded Textures: {allBlames.Count:n0} ({Util.FormatBytes(sizeSum)})###header"))
this.DrawBlame(allBlames); this.DrawBlame(allBlames);
ImGui.PopID();
} }
ImGui.PushID("loadedGameTextures"u8); using (ImRaii.PushId("loadedGameTextures"u8))
if (ImGui.CollapsingHeader( {
$"Loaded Game Textures: {this.textureManager.Shared.ForDebugGamePathTextures.Count:n0}###header")) if (ImGui.CollapsingHeader($"Loaded Game Textures: {this.textureManager.Shared.ForDebugGamePathTextures.Count:n0}###header"))
this.DrawLoadedTextures(this.textureManager.Shared.ForDebugGamePathTextures); this.DrawLoadedTextures(this.textureManager.Shared.ForDebugGamePathTextures);
ImGui.PopID(); }
ImGui.PushID("loadedFileTextures"u8); using (ImRaii.PushId("loadedFileTextures"u8))
if (ImGui.CollapsingHeader( {
$"Loaded File Textures: {this.textureManager.Shared.ForDebugFileSystemTextures.Count:n0}###header")) if (ImGui.CollapsingHeader($"Loaded File Textures: {this.textureManager.Shared.ForDebugFileSystemTextures.Count:n0}###header"))
this.DrawLoadedTextures(this.textureManager.Shared.ForDebugFileSystemTextures); this.DrawLoadedTextures(this.textureManager.Shared.ForDebugFileSystemTextures);
ImGui.PopID(); }
ImGui.PushID("loadedManifestResourceTextures"u8); using (ImRaii.PushId("loadedManifestResourceTextures"u8))
if (ImGui.CollapsingHeader( {
$"Loaded Manifest Resource Textures: {this.textureManager.Shared.ForDebugManifestResourceTextures.Count:n0}###header")) if (ImGui.CollapsingHeader($"Loaded Manifest Resource Textures: {this.textureManager.Shared.ForDebugManifestResourceTextures.Count:n0}###header"))
this.DrawLoadedTextures(this.textureManager.Shared.ForDebugManifestResourceTextures); this.DrawLoadedTextures(this.textureManager.Shared.ForDebugManifestResourceTextures);
ImGui.PopID(); }
lock (this.textureManager.Shared.ForDebugInvalidatedTextures) lock (this.textureManager.Shared.ForDebugInvalidatedTextures)
{ {
ImGui.PushID("invalidatedTextures"u8); using var pushedId = ImRaii.PushId("invalidatedTextures"u8);
if (ImGui.CollapsingHeader( if (ImGui.CollapsingHeader($"Invalidated: {this.textureManager.Shared.ForDebugInvalidatedTextures.Count:n0}###header"))
$"Invalidated: {this.textureManager.Shared.ForDebugInvalidatedTextures.Count:n0}###header"))
{
this.DrawLoadedTextures(this.textureManager.Shared.ForDebugInvalidatedTextures); this.DrawLoadedTextures(this.textureManager.Shared.ForDebugInvalidatedTextures);
}
ImGui.PopID();
} }
ImGui.Dummy(new(ImGui.GetTextLineHeightWithSpacing())); var textHeightSpacing = new Vector2(ImGui.GetTextLineHeightWithSpacing());
ImGui.Dummy(textHeightSpacing);
if (!this.textureManager.HasClipboardImage()) if (!this.textureManager.HasClipboardImage())
{ {
@ -191,59 +190,53 @@ internal class TexWidget : IDataWindowWidget
if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromGameIcon))) if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromGameIcon)))
{ {
ImGui.PushID(nameof(this.DrawGetFromGameIcon)); using var pushedId = ImRaii.PushId(nameof(this.DrawGetFromGameIcon));
this.DrawGetFromGameIcon(); this.DrawGetFromGameIcon();
ImGui.PopID();
} }
if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromGame))) if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromGame)))
{ {
ImGui.PushID(nameof(this.DrawGetFromGame)); using var pushedId = ImRaii.PushId(nameof(this.DrawGetFromGame));
this.DrawGetFromGame(); this.DrawGetFromGame();
ImGui.PopID();
} }
if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromFile))) if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromFile)))
{ {
ImGui.PushID(nameof(this.DrawGetFromFile)); using var pushedId = ImRaii.PushId(nameof(this.DrawGetFromFile));
this.DrawGetFromFile(); this.DrawGetFromFile();
ImGui.PopID();
} }
if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromManifestResource))) if (ImGui.CollapsingHeader(nameof(ITextureProvider.GetFromManifestResource)))
{ {
ImGui.PushID(nameof(this.DrawGetFromManifestResource)); using var pushedId = ImRaii.PushId(nameof(this.DrawGetFromManifestResource));
this.DrawGetFromManifestResource(); this.DrawGetFromManifestResource();
ImGui.PopID();
} }
if (ImGui.CollapsingHeader(nameof(ITextureProvider.CreateFromImGuiViewportAsync))) if (ImGui.CollapsingHeader(nameof(ITextureProvider.CreateFromImGuiViewportAsync)))
{ {
ImGui.PushID(nameof(this.DrawCreateFromImGuiViewportAsync)); using var pushedId = ImRaii.PushId(nameof(this.DrawCreateFromImGuiViewportAsync));
this.DrawCreateFromImGuiViewportAsync(); this.DrawCreateFromImGuiViewportAsync();
ImGui.PopID();
} }
if (ImGui.CollapsingHeader("UV"u8)) if (ImGui.CollapsingHeader("UV"u8))
{ {
ImGui.PushID(nameof(this.DrawUvInput)); using var pushedId = ImRaii.PushId(nameof(this.DrawUvInput));
this.DrawUvInput(); this.DrawUvInput();
ImGui.PopID();
} }
if (ImGui.CollapsingHeader($"CropCopy##{nameof(this.DrawExistingTextureModificationArgs)}")) if (ImGui.CollapsingHeader($"CropCopy##{nameof(this.DrawExistingTextureModificationArgs)}"))
{ {
ImGui.PushID(nameof(this.DrawExistingTextureModificationArgs)); using var pushedId = ImRaii.PushId(nameof(this.DrawExistingTextureModificationArgs));
this.DrawExistingTextureModificationArgs(); this.DrawExistingTextureModificationArgs();
ImGui.PopID();
} }
ImGui.Dummy(new(ImGui.GetTextLineHeightWithSpacing())); ImGui.Dummy(textHeightSpacing);
Action? runLater = null; Action? runLater = null;
foreach (var t in this.addedTextures) foreach (var t in this.addedTextures)
{ {
ImGui.PushID(t.Id); using var pushedId = ImRaii.PushId(t.Id);
if (ImGui.CollapsingHeader($"Tex #{t.Id} {t}###header", ImGuiTreeNodeFlags.DefaultOpen)) if (ImGui.CollapsingHeader($"Tex #{t.Id} {t}###header", ImGuiTreeNodeFlags.DefaultOpen))
{ {
if (ImGui.Button("X"u8)) if (ImGui.Button("X"u8))
@ -335,8 +328,6 @@ internal class TexWidget : IDataWindowWidget
ImGui.Text(e.ToString()); ImGui.Text(e.ToString());
} }
} }
ImGui.PopID();
} }
runLater?.Invoke(); runLater?.Invoke();
@ -356,18 +347,16 @@ internal class TexWidget : IDataWindowWidget
if (ImGui.Button("Reset Columns"u8)) if (ImGui.Button("Reset Columns"u8))
this.allLoadedTexturesTableName = "##table" + Environment.TickCount64; this.allLoadedTexturesTableName = "##table" + Environment.TickCount64;
if (!ImGui.BeginTable( using var table = ImRaii.Table(this.allLoadedTexturesTableName, (int)DrawBlameTableColumnUserId.ColumnCount, TableFlags);
this.allLoadedTexturesTableName, if (!table.Success)
(int)DrawBlameTableColumnUserId.ColumnCount,
ImGuiTableFlags.Sortable | ImGuiTableFlags.SortTristate | ImGuiTableFlags.SortMulti |
ImGuiTableFlags.Reorderable | ImGuiTableFlags.Resizable | ImGuiTableFlags.NoBordersInBodyUntilResize |
ImGuiTableFlags.NoSavedSettings))
return; return;
const int numIcons = 1; const int numIcons = 1;
float iconWidths; float iconWidths;
using (im.IconFontHandle?.Push()) using (im.IconFontHandle?.Push())
{
iconWidths = ImGui.CalcTextSize(FontAwesomeIcon.Save.ToIconString()).X; iconWidths = ImGui.CalcTextSize(FontAwesomeIcon.Save.ToIconString()).X;
}
ImGui.TableSetupScrollFreeze(0, 1); ImGui.TableSetupScrollFreeze(0, 1);
ImGui.TableSetupColumn( ImGui.TableSetupColumn(
@ -462,7 +451,8 @@ internal class TexWidget : IDataWindowWidget
{ {
var wrap = allBlames[i]; var wrap = allBlames[i];
ImGui.TableNextRow(); ImGui.TableNextRow();
ImGui.PushID(i);
using var pushedId = ImRaii.PushId(i);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
@ -479,9 +469,8 @@ internal class TexWidget : IDataWindowWidget
if (ImGui.IsItemHovered()) if (ImGui.IsItemHovered())
{ {
ImGui.BeginTooltip(); using var tooltip = ImRaii.Tooltip();
ImGui.Image(wrap.Handle, wrap.Size); ImGui.Image(wrap.Handle, wrap.Size);
ImGui.EndTooltip();
} }
ImGui.TableNextColumn(); ImGui.TableNextColumn();
@ -503,21 +492,19 @@ internal class TexWidget : IDataWindowWidget
ImGui.TableNextColumn(); ImGui.TableNextColumn();
lock (wrap.OwnerPlugins) lock (wrap.OwnerPlugins)
this.TextColumnCopiable(string.Join(", ", wrap.OwnerPlugins.Select(static x => x.Name)), false, true); this.TextColumnCopiable(string.Join(", ", wrap.OwnerPlugins.Select(static x => x.Name)), false, true);
ImGui.PopID();
} }
} }
clipper.Destroy(); clipper.Destroy();
ImGui.EndTable();
ImGuiHelpers.ScaledDummy(10); ImGuiHelpers.ScaledDummy(10);
} }
private unsafe void DrawLoadedTextures(ICollection<SharedImmediateTexture> textures) private void DrawLoadedTextures(ICollection<SharedImmediateTexture> textures)
{ {
var im = Service<InterfaceManager>.Get(); var im = Service<InterfaceManager>.Get();
if (!ImGui.BeginTable("##table"u8, 6)) using var table = ImRaii.Table("##table"u8, 6);
if (!table.Success)
return; return;
const int numIcons = 4; const int numIcons = 4;
@ -575,7 +562,7 @@ internal class TexWidget : IDataWindowWidget
} }
var remain = texture.SelfReferenceExpiresInForDebug; var remain = texture.SelfReferenceExpiresInForDebug;
ImGui.PushID(row); using var pushedId = ImRaii.PushId(row);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding(); ImGui.AlignTextToFramePadding();
@ -602,28 +589,26 @@ internal class TexWidget : IDataWindowWidget
if (ImGui.IsItemHovered() && texture.GetWrapOrDefault(null) is { } immediate) if (ImGui.IsItemHovered() && texture.GetWrapOrDefault(null) is { } immediate)
{ {
ImGui.BeginTooltip(); using var tooltip = ImRaii.Tooltip();
ImGui.Image(immediate.Handle, immediate.Size); ImGui.Image(immediate.Handle, immediate.Size);
ImGui.EndTooltip();
} }
ImGui.SameLine(); ImGui.SameLine();
if (ImGuiComponents.IconButton(FontAwesomeIcon.Sync)) if (ImGuiComponents.IconButton(FontAwesomeIcon.Sync))
this.textureManager.InvalidatePaths(new[] { texture.SourcePathForDebug }); this.textureManager.InvalidatePaths([texture.SourcePathForDebug]);
if (ImGui.IsItemHovered()) if (ImGui.IsItemHovered())
ImGui.SetTooltip($"Call {nameof(ITextureSubstitutionProvider.InvalidatePaths)}."); ImGui.SetTooltip($"Call {nameof(ITextureSubstitutionProvider.InvalidatePaths)}.");
ImGui.SameLine(); ImGui.SameLine();
if (remain <= 0) using (ImRaii.Disabled(remain <= 0))
ImGui.BeginDisabled(); {
if (ImGuiComponents.IconButton(FontAwesomeIcon.Trash)) if (ImGuiComponents.IconButton(FontAwesomeIcon.Trash))
texture.ReleaseSelfReference(true); texture.ReleaseSelfReference(true);
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
ImGui.SetTooltip("Release self-reference immediately."u8);
if (remain <= 0)
ImGui.EndDisabled();
ImGui.PopID(); if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
ImGui.SetTooltip("Release self-reference immediately."u8);
}
} }
if (!valid) if (!valid)
@ -632,7 +617,6 @@ internal class TexWidget : IDataWindowWidget
} }
clipper.Destroy(); clipper.Destroy();
ImGui.EndTable();
ImGuiHelpers.ScaledDummy(10); ImGuiHelpers.ScaledDummy(10);
} }
@ -751,10 +735,7 @@ internal class TexWidget : IDataWindowWidget
{ {
ImGui.SameLine(); ImGui.SameLine();
if (ImGui.Button("Load File (Async)"u8)) if (ImGui.Button("Load File (Async)"u8))
{ this.addedTextures.Add(new(Api10: this.textureManager.Shared.GetFromManifestResource(assembly, name).RentAsync()));
this.addedTextures.Add(
new(Api10: this.textureManager.Shared.GetFromManifestResource(assembly, name).RentAsync()));
}
ImGui.SameLine(); ImGui.SameLine();
if (ImGui.Button("Load File (Immediate)"u8)) if (ImGui.Button("Load File (Immediate)"u8))
@ -767,21 +748,20 @@ internal class TexWidget : IDataWindowWidget
private void DrawCreateFromImGuiViewportAsync() private void DrawCreateFromImGuiViewportAsync()
{ {
var viewports = ImGui.GetPlatformIO().Viewports; var viewports = ImGui.GetPlatformIO().Viewports;
if (ImGui.BeginCombo( using (var combo = ImRaii.Combo(nameof(this.viewportTextureArgs.ViewportId), $"{this.viewportIndexInt}. {viewports[this.viewportIndexInt].ID:X08}"))
nameof(this.viewportTextureArgs.ViewportId),
$"{this.viewportIndexInt}. {viewports[this.viewportIndexInt].ID:X08}"))
{ {
for (var i = 0; i < viewports.Size; i++) if (combo.Success)
{ {
var sel = this.viewportIndexInt == i; for (var i = 0; i < viewports.Size; i++)
if (ImGui.Selectable($"#{i}: {viewports[i].ID:X08}", ref sel))
{ {
this.viewportIndexInt = i; var sel = this.viewportIndexInt == i;
ImGui.SetItemDefaultFocus(); if (ImGui.Selectable($"#{i}: {viewports[i].ID:X08}", ref sel))
{
this.viewportIndexInt = i;
ImGui.SetItemDefaultFocus();
}
} }
} }
ImGui.EndCombo();
} }
var b = this.viewportTextureArgs.KeepTransparency; var b = this.viewportTextureArgs.KeepTransparency;
@ -843,17 +823,12 @@ internal class TexWidget : IDataWindowWidget
} }
this.supportedRenderTargetFormatNames ??= this.supportedRenderTargetFormats.Select(Enum.GetName).ToArray(); this.supportedRenderTargetFormatNames ??= this.supportedRenderTargetFormats.Select(Enum.GetName).ToArray();
ImGui.Combo( ImGui.Combo(nameof(this.textureModificationArgs.DxgiFormat), ref this.renderTargetChoiceInt, this.supportedRenderTargetFormatNames);
nameof(this.textureModificationArgs.DxgiFormat),
ref this.renderTargetChoiceInt,
this.supportedRenderTargetFormatNames);
Span<int> wh = stackalloc int[2]; Span<int> wh = stackalloc int[2];
wh[0] = this.textureModificationArgs.NewWidth; wh[0] = this.textureModificationArgs.NewWidth;
wh[1] = this.textureModificationArgs.NewHeight; wh[1] = this.textureModificationArgs.NewHeight;
if (ImGui.InputInt( if (ImGui.InputInt($"{nameof(this.textureModificationArgs.NewWidth)}/{nameof(this.textureModificationArgs.NewHeight)}", wh))
$"{nameof(this.textureModificationArgs.NewWidth)}/{nameof(this.textureModificationArgs.NewHeight)}",
wh))
{ {
this.textureModificationArgs.NewWidth = wh[0]; this.textureModificationArgs.NewWidth = wh[0];
this.textureModificationArgs.NewHeight = wh[1]; this.textureModificationArgs.NewHeight = wh[1];