mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 20:24:17 +01:00
Update variables drawer.
This commit is contained in:
parent
b377ca372c
commit
22541b3fd8
2 changed files with 154 additions and 132 deletions
|
|
@ -6,7 +6,6 @@ using Dalamud.Utility;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Group;
|
using FFXIVClientStructs.FFXIV.Client.Game.Group;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.System.Resource;
|
using FFXIVClientStructs.FFXIV.Client.System.Resource;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
|
@ -35,8 +34,6 @@ using Penumbra.UI.Classes;
|
||||||
using Penumbra.Util;
|
using Penumbra.Util;
|
||||||
using static OtterGui.Raii.ImRaii;
|
using static OtterGui.Raii.ImRaii;
|
||||||
using CharacterBase = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.CharacterBase;
|
using CharacterBase = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.CharacterBase;
|
||||||
using CharacterUtility = Penumbra.Interop.Services.CharacterUtility;
|
|
||||||
using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManager;
|
|
||||||
using ImGuiClip = OtterGui.ImGuiClip;
|
using ImGuiClip = OtterGui.ImGuiClip;
|
||||||
using Penumbra.Api.IpcTester;
|
using Penumbra.Api.IpcTester;
|
||||||
using Penumbra.Interop.Hooks.PostProcessing;
|
using Penumbra.Interop.Hooks.PostProcessing;
|
||||||
|
|
@ -80,8 +77,7 @@ public class DebugTab : Window, ITab, IUiService
|
||||||
private readonly HttpApi _httpApi;
|
private readonly HttpApi _httpApi;
|
||||||
private readonly ActorManager _actors;
|
private readonly ActorManager _actors;
|
||||||
private readonly StainService _stains;
|
private readonly StainService _stains;
|
||||||
private readonly CharacterUtility _characterUtility;
|
private readonly GlobalVariablesDrawer _globalVariablesDrawer;
|
||||||
private readonly ResidentResourceManager _residentResources;
|
|
||||||
private readonly ResourceManagerService _resourceManager;
|
private readonly ResourceManagerService _resourceManager;
|
||||||
private readonly CollectionResolver _collectionResolver;
|
private readonly CollectionResolver _collectionResolver;
|
||||||
private readonly DrawObjectState _drawObjectState;
|
private readonly DrawObjectState _drawObjectState;
|
||||||
|
|
@ -109,13 +105,12 @@ public class DebugTab : Window, ITab, IUiService
|
||||||
public DebugTab(PerformanceTracker performance, Configuration config, CollectionManager collectionManager, ObjectManager objects,
|
public DebugTab(PerformanceTracker performance, Configuration config, CollectionManager collectionManager, ObjectManager objects,
|
||||||
IClientState clientState, IDataManager dataManager,
|
IClientState clientState, IDataManager dataManager,
|
||||||
ValidityChecker validityChecker, ModManager modManager, HttpApi httpApi, ActorManager actors, StainService stains,
|
ValidityChecker validityChecker, ModManager modManager, HttpApi httpApi, ActorManager actors, StainService stains,
|
||||||
CharacterUtility characterUtility, ResidentResourceManager residentResources,
|
|
||||||
ResourceManagerService resourceManager, CollectionResolver collectionResolver,
|
ResourceManagerService resourceManager, CollectionResolver collectionResolver,
|
||||||
DrawObjectState drawObjectState, PathState pathState, SubfileHelper subfileHelper, IdentifiedCollectionCache identifiedCollectionCache,
|
DrawObjectState drawObjectState, PathState pathState, SubfileHelper subfileHelper, IdentifiedCollectionCache identifiedCollectionCache,
|
||||||
CutsceneService cutsceneService, ModImportManager modImporter, ImportPopup importPopup, FrameworkManager framework,
|
CutsceneService cutsceneService, ModImportManager modImporter, ImportPopup importPopup, FrameworkManager framework,
|
||||||
TextureManager textureManager, ShaderReplacementFixer shaderReplacementFixer, RedrawService redraws, DictEmote emotes,
|
TextureManager textureManager, ShaderReplacementFixer shaderReplacementFixer, RedrawService redraws, DictEmote emotes,
|
||||||
Diagnostics diagnostics, IpcTester ipcTester, CrashHandlerPanel crashHandlerPanel, TexHeaderDrawer texHeaderDrawer,
|
Diagnostics diagnostics, IpcTester ipcTester, CrashHandlerPanel crashHandlerPanel, TexHeaderDrawer texHeaderDrawer,
|
||||||
HookOverrideDrawer hookOverrides, RsfService rsfService)
|
HookOverrideDrawer hookOverrides, RsfService rsfService, GlobalVariablesDrawer globalVariablesDrawer)
|
||||||
: base("Penumbra Debug Window", ImGuiWindowFlags.NoCollapse)
|
: base("Penumbra Debug Window", ImGuiWindowFlags.NoCollapse)
|
||||||
{
|
{
|
||||||
IsOpen = true;
|
IsOpen = true;
|
||||||
|
|
@ -132,8 +127,6 @@ public class DebugTab : Window, ITab, IUiService
|
||||||
_httpApi = httpApi;
|
_httpApi = httpApi;
|
||||||
_actors = actors;
|
_actors = actors;
|
||||||
_stains = stains;
|
_stains = stains;
|
||||||
_characterUtility = characterUtility;
|
|
||||||
_residentResources = residentResources;
|
|
||||||
_resourceManager = resourceManager;
|
_resourceManager = resourceManager;
|
||||||
_collectionResolver = collectionResolver;
|
_collectionResolver = collectionResolver;
|
||||||
_drawObjectState = drawObjectState;
|
_drawObjectState = drawObjectState;
|
||||||
|
|
@ -154,6 +147,7 @@ public class DebugTab : Window, ITab, IUiService
|
||||||
_texHeaderDrawer = texHeaderDrawer;
|
_texHeaderDrawer = texHeaderDrawer;
|
||||||
_hookOverrides = hookOverrides;
|
_hookOverrides = hookOverrides;
|
||||||
_rsfService = rsfService;
|
_rsfService = rsfService;
|
||||||
|
_globalVariablesDrawer = globalVariablesDrawer;
|
||||||
_objects = objects;
|
_objects = objects;
|
||||||
_clientState = clientState;
|
_clientState = clientState;
|
||||||
_dataManager = dataManager;
|
_dataManager = dataManager;
|
||||||
|
|
@ -185,14 +179,13 @@ public class DebugTab : Window, ITab, IUiService
|
||||||
DrawActorsDebug();
|
DrawActorsDebug();
|
||||||
DrawCollectionCaches();
|
DrawCollectionCaches();
|
||||||
_texHeaderDrawer.Draw();
|
_texHeaderDrawer.Draw();
|
||||||
DrawDebugCharacterUtility();
|
|
||||||
DrawShaderReplacementFixer();
|
DrawShaderReplacementFixer();
|
||||||
DrawData();
|
DrawData();
|
||||||
DrawCrcCache();
|
DrawCrcCache();
|
||||||
DrawResourceProblems();
|
DrawResourceProblems();
|
||||||
_hookOverrides.Draw();
|
_hookOverrides.Draw();
|
||||||
DrawPlayerModelInfo();
|
DrawPlayerModelInfo();
|
||||||
DrawGlobalVariableInfo();
|
_globalVariablesDrawer.Draw();
|
||||||
DrawDebugTabIpc();
|
DrawDebugTabIpc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -217,9 +210,11 @@ public class DebugTab : Window, ITab, IUiService
|
||||||
{
|
{
|
||||||
if (resourceNode)
|
if (resourceNode)
|
||||||
foreach (var (path, resource) in collection._cache!.CustomResources)
|
foreach (var (path, resource) in collection._cache!.CustomResources)
|
||||||
|
{
|
||||||
ImUtf8.TreeNode($"{path} -> 0x{(ulong)resource.ResourceHandle:X}",
|
ImUtf8.TreeNode($"{path} -> 0x{(ulong)resource.ResourceHandle:X}",
|
||||||
ImGuiTreeNodeFlags.Bullet | ImGuiTreeNodeFlags.Leaf).Dispose();
|
ImGuiTreeNodeFlags.Bullet | ImGuiTreeNodeFlags.Leaf).Dispose();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
using var modNode = ImUtf8.TreeNode("Enabled Mods"u8);
|
using var modNode = ImUtf8.TreeNode("Enabled Mods"u8);
|
||||||
if (modNode)
|
if (modNode)
|
||||||
|
|
@ -485,9 +480,11 @@ public class DebugTab : Window, ITab, IUiService
|
||||||
? $"{identifier.DataId} | {obj.AsObject->BaseId}"
|
? $"{identifier.DataId} | {obj.AsObject->BaseId}"
|
||||||
: identifier.DataId.ToString();
|
: identifier.DataId.ToString();
|
||||||
ImGuiUtil.DrawTableColumn(id);
|
ImGuiUtil.DrawTableColumn(id);
|
||||||
ImGuiUtil.DrawTableColumn(obj.Address != nint.Zero ? $"0x{(*(nint*)obj.Address):X}" : "NULL");
|
ImGuiUtil.DrawTableColumn(obj.Address != nint.Zero ? $"0x{*(nint*)obj.Address:X}" : "NULL");
|
||||||
ImGuiUtil.DrawTableColumn(obj.Address != nint.Zero ? $"0x{obj.AsObject->EntityId:X}" : "NULL");
|
ImGuiUtil.DrawTableColumn(obj.Address != nint.Zero ? $"0x{obj.AsObject->EntityId:X}" : "NULL");
|
||||||
ImGuiUtil.DrawTableColumn(obj.Address != nint.Zero ? obj.AsObject->IsCharacter() ? $"Character: {obj.AsCharacter->ObjectKind}" : "No Character" : "NULL");
|
ImGuiUtil.DrawTableColumn(obj.Address != nint.Zero
|
||||||
|
? obj.AsObject->IsCharacter() ? $"Character: {obj.AsCharacter->ObjectKind}" : "No Character"
|
||||||
|
: "NULL");
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -795,68 +792,6 @@ public class DebugTab : Window, ITab, IUiService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draw information about the character utility class from SE,
|
|
||||||
/// displaying all files, their sizes, the default files and the default sizes.
|
|
||||||
/// </summary>
|
|
||||||
private unsafe void DrawDebugCharacterUtility()
|
|
||||||
{
|
|
||||||
if (!ImGui.CollapsingHeader("Character Utility"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
using var table = Table("##CharacterUtility", 7, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit,
|
|
||||||
-Vector2.UnitX);
|
|
||||||
if (!table)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (var idx = 0; idx < CharacterUtility.ReverseIndices.Length; ++idx)
|
|
||||||
{
|
|
||||||
var intern = CharacterUtility.ReverseIndices[idx];
|
|
||||||
var resource = _characterUtility.Address->Resource(idx);
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
ImGui.TextUnformatted($"[{idx}]");
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
ImGui.TextUnformatted($"0x{(ulong)resource:X}");
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
if (resource == null)
|
|
||||||
{
|
|
||||||
ImGui.TableNextRow();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
UiHelpers.Text(resource);
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
var data = (nint)resource->CsHandle.GetData();
|
|
||||||
var length = resource->CsHandle.GetLength();
|
|
||||||
if (ImGui.Selectable($"0x{data:X}"))
|
|
||||||
if (data != nint.Zero && length > 0)
|
|
||||||
ImGui.SetClipboardText(string.Join("\n",
|
|
||||||
new ReadOnlySpan<byte>((byte*)data, (int)length).ToArray().Select(b => b.ToString("X2"))));
|
|
||||||
|
|
||||||
ImGuiUtil.HoverTooltip("Click to copy bytes to clipboard.");
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
ImGui.TextUnformatted(length.ToString());
|
|
||||||
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
if (intern.Value != -1)
|
|
||||||
{
|
|
||||||
ImGui.Selectable($"0x{_characterUtility.DefaultResource(intern).Address:X}");
|
|
||||||
if (ImGui.IsItemClicked())
|
|
||||||
ImGui.SetClipboardText(string.Join("\n",
|
|
||||||
new ReadOnlySpan<byte>((byte*)_characterUtility.DefaultResource(intern).Address,
|
|
||||||
_characterUtility.DefaultResource(intern).Size).ToArray().Select(b => b.ToString("X2"))));
|
|
||||||
|
|
||||||
ImGuiUtil.HoverTooltip("Click to copy bytes to clipboard.");
|
|
||||||
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
ImGui.TextUnformatted($"{_characterUtility.DefaultResource(intern).Size}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawShaderReplacementFixer()
|
private void DrawShaderReplacementFixer()
|
||||||
{
|
{
|
||||||
|
|
@ -946,45 +881,6 @@ public class DebugTab : Window, ITab, IUiService
|
||||||
ImGui.TextUnformatted($"{slowPathCallDeltas.Skin}");
|
ImGui.TextUnformatted($"{slowPathCallDeltas.Skin}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Draw information about the resident resource files. </summary>
|
|
||||||
private unsafe void DrawDebugResidentResources()
|
|
||||||
{
|
|
||||||
using var tree = TreeNode("Resident Resources");
|
|
||||||
if (!tree)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_residentResources.Address == null || _residentResources.Address->NumResources == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
using var table = Table("##ResidentResources", 2, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit,
|
|
||||||
-Vector2.UnitX);
|
|
||||||
if (!table)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (var i = 0; i < _residentResources.Address->NumResources; ++i)
|
|
||||||
{
|
|
||||||
var resource = _residentResources.Address->ResourceList[i];
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
ImGui.TextUnformatted($"0x{(ulong)resource:X}");
|
|
||||||
ImGui.TableNextColumn();
|
|
||||||
UiHelpers.Text(resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void DrawCopyableAddress(string label, nint address)
|
|
||||||
{
|
|
||||||
using (var _ = PushFont(UiBuilder.MonoFont))
|
|
||||||
{
|
|
||||||
if (ImGui.Selectable($"0x{address:X16} {label}"))
|
|
||||||
ImGui.SetClipboardText($"{address:X16}");
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGuiUtil.HoverTooltip("Click to copy address to clipboard.");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static unsafe void DrawCopyableAddress(string label, void* address)
|
|
||||||
=> DrawCopyableAddress(label, (nint)address);
|
|
||||||
|
|
||||||
/// <summary> Draw information about the models, materials and resources currently loaded by the local player. </summary>
|
/// <summary> Draw information about the models, materials and resources currently loaded by the local player. </summary>
|
||||||
private unsafe void DrawPlayerModelInfo()
|
private unsafe void DrawPlayerModelInfo()
|
||||||
{
|
{
|
||||||
|
|
@ -993,13 +889,13 @@ public class DebugTab : Window, ITab, IUiService
|
||||||
if (!ImGui.CollapsingHeader($"Player Model Info: {name}##Draw") || player == null)
|
if (!ImGui.CollapsingHeader($"Player Model Info: {name}##Draw") || player == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DrawCopyableAddress("PlayerCharacter", player.Address);
|
DrawCopyableAddress("PlayerCharacter"u8, player.Address);
|
||||||
|
|
||||||
var model = (CharacterBase*)((Character*)player.Address)->GameObject.GetDrawObject();
|
var model = (CharacterBase*)((Character*)player.Address)->GameObject.GetDrawObject();
|
||||||
if (model == null)
|
if (model == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DrawCopyableAddress("CharacterBase", model);
|
DrawCopyableAddress("CharacterBase"u8, model);
|
||||||
|
|
||||||
using (var t1 = Table("##table", 2, ImGuiTableFlags.SizingFixedFit))
|
using (var t1 = Table("##table", 2, ImGuiTableFlags.SizingFixedFit))
|
||||||
{
|
{
|
||||||
|
|
@ -1054,20 +950,6 @@ public class DebugTab : Window, ITab, IUiService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Draw information about some game global variables. </summary>
|
|
||||||
private unsafe void DrawGlobalVariableInfo()
|
|
||||||
{
|
|
||||||
var header = ImGui.CollapsingHeader("Global Variables");
|
|
||||||
ImGuiUtil.HoverTooltip("Draw information about global variables. Can provide useful starting points for a memory viewer.");
|
|
||||||
if (!header)
|
|
||||||
return;
|
|
||||||
|
|
||||||
DrawCopyableAddress("CharacterUtility", _characterUtility.Address);
|
|
||||||
DrawCopyableAddress("ResidentResourceManager", _residentResources.Address);
|
|
||||||
DrawCopyableAddress("Device", Device.Instance());
|
|
||||||
DrawDebugResidentResources();
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _crcInput = string.Empty;
|
private string _crcInput = string.Empty;
|
||||||
private FullPath _crcPath = FullPath.Empty;
|
private FullPath _crcPath = FullPath.Empty;
|
||||||
|
|
||||||
|
|
@ -1169,4 +1051,18 @@ public class DebugTab : Window, ITab, IUiService
|
||||||
_config.Ephemeral.DebugSeparateWindow = false;
|
_config.Ephemeral.DebugSeparateWindow = false;
|
||||||
_config.Ephemeral.Save();
|
_config.Ephemeral.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static unsafe void DrawCopyableAddress(ReadOnlySpan<byte> label, void* address)
|
||||||
|
{
|
||||||
|
using (var _ = ImRaii.PushFont(UiBuilder.MonoFont))
|
||||||
|
{
|
||||||
|
if (ImUtf8.Selectable($"0x{(nint)address:X16} {label}"))
|
||||||
|
ImUtf8.SetClipboardText($"0x{(nint)address:X16}");
|
||||||
|
}
|
||||||
|
|
||||||
|
ImUtf8.HoverTooltip("Click to copy address to clipboard."u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static unsafe void DrawCopyableAddress(ReadOnlySpan<byte> label, nint address)
|
||||||
|
=> DrawCopyableAddress(label, (void*)address);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
126
Penumbra/UI/Tabs/Debug/GlobalVariablesDrawer.cs
Normal file
126
Penumbra/UI/Tabs/Debug/GlobalVariablesDrawer.cs
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
||||||
|
using ImGuiNET;
|
||||||
|
using OtterGui.Services;
|
||||||
|
using OtterGui.Text;
|
||||||
|
using Penumbra.Interop.Services;
|
||||||
|
|
||||||
|
namespace Penumbra.UI.Tabs.Debug;
|
||||||
|
|
||||||
|
public unsafe class GlobalVariablesDrawer(CharacterUtility characterUtility, ResidentResourceManager residentResources) : IUiService
|
||||||
|
{
|
||||||
|
/// <summary> Draw information about some game global variables. </summary>
|
||||||
|
public void Draw()
|
||||||
|
{
|
||||||
|
var header = ImUtf8.CollapsingHeader("Global Variables"u8);
|
||||||
|
ImUtf8.HoverTooltip("Draw information about global variables. Can provide useful starting points for a memory viewer."u8);
|
||||||
|
if (!header)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DebugTab.DrawCopyableAddress("CharacterUtility"u8, characterUtility.Address);
|
||||||
|
DebugTab.DrawCopyableAddress("ResidentResourceManager"u8, residentResources.Address);
|
||||||
|
DebugTab.DrawCopyableAddress("Device"u8, Device.Instance());
|
||||||
|
DrawCharacterUtility();
|
||||||
|
DrawResidentResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draw information about the character utility class from SE,
|
||||||
|
/// displaying all files, their sizes, the default files and the default sizes.
|
||||||
|
/// </summary>
|
||||||
|
private void DrawCharacterUtility()
|
||||||
|
{
|
||||||
|
using var tree = ImUtf8.TreeNode("Character Utility"u8);
|
||||||
|
if (!tree)
|
||||||
|
return;
|
||||||
|
|
||||||
|
using var table = ImUtf8.Table("##CharacterUtility"u8, 7, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit,
|
||||||
|
-Vector2.UnitX);
|
||||||
|
if (!table)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (var idx = 0; idx < CharacterUtility.ReverseIndices.Length; ++idx)
|
||||||
|
{
|
||||||
|
var intern = CharacterUtility.ReverseIndices[idx];
|
||||||
|
var resource = characterUtility.Address->Resource(idx);
|
||||||
|
ImUtf8.DrawTableColumn($"[{idx}]");
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
ImUtf8.CopyOnClickSelectable($"0x{(ulong)resource:X}");
|
||||||
|
if (resource == null)
|
||||||
|
{
|
||||||
|
ImGui.TableNextRow();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImUtf8.DrawTableColumn(resource->CsHandle.FileName.AsSpan());
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
var data = (nint)resource->CsHandle.GetData();
|
||||||
|
var length = resource->CsHandle.GetLength();
|
||||||
|
if (ImUtf8.Selectable($"0x{data:X}"))
|
||||||
|
if (data != nint.Zero && length > 0)
|
||||||
|
ImUtf8.SetClipboardText(string.Join("\n",
|
||||||
|
new ReadOnlySpan<byte>((byte*)data, (int)length).ToArray().Select(b => b.ToString("X2"))));
|
||||||
|
|
||||||
|
ImUtf8.HoverTooltip("Click to copy bytes to clipboard."u8);
|
||||||
|
ImUtf8.DrawTableColumn(length.ToString());
|
||||||
|
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
if (intern.Value != -1)
|
||||||
|
{
|
||||||
|
ImUtf8.Selectable($"0x{characterUtility.DefaultResource(intern).Address:X}");
|
||||||
|
if (ImGui.IsItemClicked())
|
||||||
|
ImUtf8.SetClipboardText(string.Join("\n",
|
||||||
|
new ReadOnlySpan<byte>((byte*)characterUtility.DefaultResource(intern).Address,
|
||||||
|
characterUtility.DefaultResource(intern).Size).ToArray().Select(b => b.ToString("X2"))));
|
||||||
|
|
||||||
|
ImUtf8.HoverTooltip("Click to copy bytes to clipboard."u8);
|
||||||
|
|
||||||
|
ImUtf8.DrawTableColumn($"{characterUtility.DefaultResource(intern).Size}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Draw information about the resident resource files. </summary>
|
||||||
|
private void DrawResidentResources()
|
||||||
|
{
|
||||||
|
using var tree = ImUtf8.TreeNode("Resident Resources"u8);
|
||||||
|
if (!tree)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (residentResources.Address == null || residentResources.Address->NumResources == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
using var table = ImUtf8.Table("##ResidentResources"u8, 5, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit,
|
||||||
|
-Vector2.UnitX);
|
||||||
|
if (!table)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (var idx = 0; idx < residentResources.Address->NumResources; ++idx)
|
||||||
|
{
|
||||||
|
var resource = residentResources.Address->ResourceList[idx];
|
||||||
|
ImUtf8.DrawTableColumn($"[{idx}]");
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
ImUtf8.CopyOnClickSelectable($"0x{(ulong)resource:X}");
|
||||||
|
if (resource == null)
|
||||||
|
{
|
||||||
|
ImGui.TableNextRow();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImUtf8.DrawTableColumn(resource->CsHandle.FileName.AsSpan());
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
var data = (nint)resource->CsHandle.GetData();
|
||||||
|
var length = resource->CsHandle.GetLength();
|
||||||
|
if (ImUtf8.Selectable($"0x{data:X}"))
|
||||||
|
if (data != nint.Zero && length > 0)
|
||||||
|
ImUtf8.SetClipboardText(string.Join("\n",
|
||||||
|
new ReadOnlySpan<byte>((byte*)data, (int)length).ToArray().Select(b => b.ToString("X2"))));
|
||||||
|
|
||||||
|
ImUtf8.HoverTooltip("Click to copy bytes to clipboard."u8);
|
||||||
|
ImUtf8.DrawTableColumn(length.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue