mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-01-03 06:13:40 +01:00
Minor interface adjustments (#2121)
- Further ImRaii safety in UiDebug2 - Set some mistakenly internal methods in ImGuiComponents to public - Added SpanFullWidth flag to trees in Util.ShowStruct
This commit is contained in:
parent
de999b7895
commit
c950b15a22
18 changed files with 282 additions and 264 deletions
|
|
@ -28,6 +28,8 @@ using Windows.Win32.Storage.FileSystem;
|
|||
using Windows.Win32.System.Memory;
|
||||
using Windows.Win32.System.Ole;
|
||||
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
|
||||
using static TerraFX.Interop.Windows.Windows;
|
||||
|
||||
using Win32_PInvoke = Windows.Win32.PInvoke;
|
||||
|
|
@ -1028,74 +1030,71 @@ public static class Util
|
|||
dm.Invoke(null, new[] { obj, path, addr });
|
||||
}
|
||||
|
||||
#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
|
||||
|
||||
private static unsafe void ShowSpanPrivate<T>(ulong addr, IList<string> path, int offset, bool isTop, in Span<T> spanobj)
|
||||
{
|
||||
#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
|
||||
if (isTop)
|
||||
{
|
||||
fixed (void* p = spanobj)
|
||||
{
|
||||
if (!ImGui.TreeNode(
|
||||
$"Span<{typeof(T).Name}> of length {spanobj.Length:n0} (0x{spanobj.Length:X})" +
|
||||
$"##print-obj-{addr:X}-{string.Join("-", path)}-head"))
|
||||
using var tree = ImRaii.TreeNode($"Span<{typeof(T).Name}> of length {spanobj.Length:n0} (0x{spanobj.Length:X})" + $"##print-obj-{addr:X}-{string.Join("-", path)}-head", ImGuiTreeNodeFlags.SpanFullWidth);
|
||||
if (tree.Success)
|
||||
{
|
||||
return;
|
||||
ShowSpanEntryPrivate(addr, path, offset, spanobj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
else
|
||||
{
|
||||
const int batchSize = 20;
|
||||
if (spanobj.Length > batchSize)
|
||||
{
|
||||
var skip = batchSize;
|
||||
while ((spanobj.Length + skip - 1) / skip > batchSize)
|
||||
skip *= batchSize;
|
||||
for (var i = 0; i < spanobj.Length; i += skip)
|
||||
{
|
||||
var next = Math.Min(i + skip, spanobj.Length);
|
||||
path.Add($"{offset + i:X}_{skip}");
|
||||
if (ImGui.TreeNode(
|
||||
$"{offset + i:n0} ~ {offset + next - 1:n0} (0x{offset + i:X} ~ 0x{offset + next - 1:X})" +
|
||||
$"##print-obj-{addr:X}-{string.Join("-", path)}"))
|
||||
{
|
||||
try
|
||||
{
|
||||
ShowSpanPrivate(addr, path, offset + i, false, spanobj[i..next]);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ImGui.TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
path.RemoveAt(path.Count - 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fixed (T* p = spanobj)
|
||||
{
|
||||
var pointerType = typeof(T*);
|
||||
for (var i = 0; i < spanobj.Length; i++)
|
||||
{
|
||||
ImGui.TextUnformatted($"[{offset + i:n0} (0x{offset + i:X})] ");
|
||||
ImGui.SameLine();
|
||||
path.Add($"{offset + i}");
|
||||
ShowValue(addr, path, pointerType, Pointer.Box(p + i, pointerType), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
ShowSpanEntryPrivate(addr, path, offset, spanobj);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (isTop)
|
||||
ImGui.TreePop();
|
||||
}
|
||||
#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
|
||||
}
|
||||
|
||||
private static unsafe void ShowSpanEntryPrivate<T>(ulong addr, IList<string> path, int offset, Span<T> spanobj) {
|
||||
const int batchSize = 20;
|
||||
if (spanobj.Length > batchSize)
|
||||
{
|
||||
var skip = batchSize;
|
||||
while ((spanobj.Length + skip - 1) / skip > batchSize)
|
||||
{
|
||||
skip *= batchSize;
|
||||
}
|
||||
|
||||
for (var i = 0; i < spanobj.Length; i += skip)
|
||||
{
|
||||
var next = Math.Min(i + skip, spanobj.Length);
|
||||
path.Add($"{offset + i:X}_{skip}");
|
||||
|
||||
using (var tree = ImRaii.TreeNode($"{offset + i:n0} ~ {offset + next - 1:n0} (0x{offset + i:X} ~ 0x{offset + next - 1:X})" + $"##print-obj-{addr:X}-{string.Join("-", path)}", ImGuiTreeNodeFlags.SpanFullWidth))
|
||||
{
|
||||
if (tree.Success)
|
||||
{
|
||||
ShowSpanEntryPrivate(addr, path, offset + i, spanobj[i..next]);
|
||||
}
|
||||
}
|
||||
|
||||
path.RemoveAt(path.Count - 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fixed (T* p = spanobj)
|
||||
{
|
||||
var pointerType = typeof(T*);
|
||||
for (var i = 0; i < spanobj.Length; i++)
|
||||
{
|
||||
ImGui.TextUnformatted($"[{offset + i:n0} (0x{offset + i:X})] ");
|
||||
ImGui.SameLine();
|
||||
path.Add($"{offset + i}");
|
||||
ShowValue(addr, path, pointerType, Pointer.Box(p + i, pointerType), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
|
||||
|
||||
private static unsafe void ShowValue(ulong addr, IList<string> path, Type type, object value, bool hideAddress)
|
||||
{
|
||||
if (type.IsPointer)
|
||||
|
|
@ -1111,9 +1110,10 @@ public static class Util
|
|||
if (moduleStartAddr > 0 && unboxedAddr >= moduleStartAddr && unboxedAddr <= moduleEndAddr)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, 0xffcbc0ff);
|
||||
ImGuiHelpers.ClickToCopyText($"ffxiv_dx11.exe+{unboxedAddr - moduleStartAddr:X}");
|
||||
ImGui.PopStyleColor();
|
||||
using (ImRaii.PushColor(ImGuiCol.Text, 0xffcbc0ff))
|
||||
{
|
||||
ImGuiHelpers.ClickToCopyText($"ffxiv_dx11.exe+{unboxedAddr - moduleStartAddr:X}");
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
|
@ -1165,125 +1165,135 @@ public static class Util
|
|||
/// <param name="hideAddress">Do not print addresses. Use when displaying a copied value.</param>
|
||||
private static void ShowStructInternal(object obj, ulong addr, bool autoExpand = false, IEnumerable<string>? path = null, bool hideAddress = false)
|
||||
{
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(3, 2));
|
||||
path ??= new List<string>();
|
||||
var pathList = path is List<string> ? (List<string>)path : path.ToList();
|
||||
|
||||
if (moduleEndAddr == 0 && moduleStartAddr == 0)
|
||||
using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, new Vector2(3, 2)))
|
||||
{
|
||||
try
|
||||
path ??= new List<string>();
|
||||
var pathList = path as List<string> ?? path.ToList();
|
||||
|
||||
if (moduleEndAddr == 0 && moduleStartAddr == 0)
|
||||
{
|
||||
var processModule = Process.GetCurrentProcess().MainModule;
|
||||
if (processModule != null)
|
||||
try
|
||||
{
|
||||
moduleStartAddr = (ulong)processModule.BaseAddress.ToInt64();
|
||||
moduleEndAddr = moduleStartAddr + (ulong)processModule.ModuleMemorySize;
|
||||
var processModule = Process.GetCurrentProcess().MainModule;
|
||||
if (processModule != null)
|
||||
{
|
||||
moduleStartAddr = (ulong)processModule.BaseAddress.ToInt64();
|
||||
moduleEndAddr = moduleStartAddr + (ulong)processModule.ModuleMemorySize;
|
||||
}
|
||||
else
|
||||
{
|
||||
moduleEndAddr = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
catch
|
||||
{
|
||||
moduleEndAddr = 1;
|
||||
}
|
||||
}
|
||||
catch
|
||||
|
||||
if (autoExpand)
|
||||
{
|
||||
moduleEndAddr = 1;
|
||||
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, 0xFF00FFFF);
|
||||
if (autoExpand)
|
||||
{
|
||||
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
|
||||
}
|
||||
using var col = ImRaii.PushColor(ImGuiCol.Text, 0xFF00FFFF);
|
||||
using var tree = ImRaii.TreeNode($"{obj}##print-obj-{addr:X}-{string.Join("-", pathList)}", ImGuiTreeNodeFlags.SpanFullWidth);
|
||||
col.Pop();
|
||||
|
||||
if (ImGui.TreeNode($"{obj}##print-obj-{addr:X}-{string.Join("-", pathList)}"))
|
||||
{
|
||||
ImGui.PopStyleColor();
|
||||
foreach (var f in obj.GetType()
|
||||
.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance))
|
||||
if (tree.Success)
|
||||
{
|
||||
var fixedBuffer = (FixedBufferAttribute)f.GetCustomAttribute(typeof(FixedBufferAttribute));
|
||||
var offset = (FieldOffsetAttribute)f.GetCustomAttribute(typeof(FieldOffsetAttribute));
|
||||
ImGui.PopStyleColor();
|
||||
foreach (var f in obj.GetType()
|
||||
.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance))
|
||||
{
|
||||
var fixedBuffer = (FixedBufferAttribute)f.GetCustomAttribute(typeof(FixedBufferAttribute));
|
||||
var offset = (FieldOffsetAttribute)f.GetCustomAttribute(typeof(FieldOffsetAttribute));
|
||||
|
||||
if (fixedBuffer != null)
|
||||
{
|
||||
ImGui.Text($"fixed");
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.9f, 1),
|
||||
$"{fixedBuffer.ElementType.Name}[0x{fixedBuffer.Length:X}]");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (offset != null)
|
||||
if (fixedBuffer != null)
|
||||
{
|
||||
ImGui.TextDisabled($"[0x{offset.Value:X}]");
|
||||
ImGui.Text("fixed");
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.9f, 1), $"{fixedBuffer.ElementType.Name}[0x{fixedBuffer.Length:X}]");
|
||||
}
|
||||
ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.9f, 1), $"{f.FieldType.Name}");
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.4f, 1), $"{f.Name}: ");
|
||||
ImGui.SameLine();
|
||||
|
||||
pathList.Add(f.Name);
|
||||
try
|
||||
{
|
||||
if (f.FieldType.IsGenericType && (f.FieldType.IsByRef || f.FieldType.IsByRefLike))
|
||||
ImGui.Text("Cannot preview ref typed fields."); // object never contains ref struct
|
||||
else if (f.FieldType == typeof(bool) && offset != null)
|
||||
ShowValue(addr, pathList, f.FieldType, Marshal.ReadByte((nint)addr + offset.Value) > 0, hideAddress);
|
||||
else
|
||||
ShowValue(addr, pathList, f.FieldType, f.GetValue(obj), hideAddress);
|
||||
{
|
||||
if (offset != null)
|
||||
{
|
||||
ImGui.TextDisabled($"[0x{offset.Value:X}]");
|
||||
ImGui.SameLine();
|
||||
}
|
||||
ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.9f, 1), $"{f.FieldType.Name}");
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.4f, 1), $"{f.Name}: ");
|
||||
ImGui.SameLine();
|
||||
|
||||
pathList.Add(f.Name);
|
||||
try
|
||||
{
|
||||
if (f.FieldType.IsGenericType && (f.FieldType.IsByRef || f.FieldType.IsByRefLike))
|
||||
{
|
||||
ImGui.Text("Cannot preview ref typed fields."); // object never contains ref struct
|
||||
}
|
||||
else if (f.FieldType == typeof(bool) && offset != null)
|
||||
{
|
||||
ShowValue(addr, pathList, f.FieldType, Marshal.ReadByte((nint)addr + offset.Value) > 0, hideAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowValue(addr, pathList, f.FieldType, f.GetValue(obj), hideAddress);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
using (ImRaii.PushColor(ImGuiCol.Text, new Vector4(1f, 0.4f, 0.4f, 1f)))
|
||||
{
|
||||
ImGui.TextUnformatted($"Error: {ex.GetType().Name}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
pathList.RemoveAt(pathList.Count - 1);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
foreach (var p in obj.GetType().GetProperties().Where(static p => p.GetGetMethod()?.GetParameters().Length == 0))
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1f, 0.4f, 0.4f, 1f));
|
||||
ImGui.TextUnformatted($"Error: {ex.GetType().Name}: {ex.Message}");
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
finally
|
||||
{
|
||||
pathList.RemoveAt(pathList.Count - 1);
|
||||
ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.9f, 1), $"{p.PropertyType.Name}");
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(0.2f, 0.6f, 0.4f, 1), $"{p.Name}: ");
|
||||
ImGui.SameLine();
|
||||
|
||||
pathList.Add(p.Name);
|
||||
try
|
||||
{
|
||||
if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == GenericSpanType)
|
||||
{
|
||||
ShowSpanProperty(addr, pathList, p, obj);
|
||||
}
|
||||
else if (p.PropertyType.IsGenericType && (p.PropertyType.IsByRef || p.PropertyType.IsByRefLike))
|
||||
{
|
||||
ImGui.Text("Cannot preview ref typed properties.");
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowValue(addr, pathList, p.PropertyType, p.GetValue(obj), hideAddress);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
using (ImRaii.PushColor(ImGuiCol.Text, new Vector4(1f, 0.4f, 0.4f, 1f)))
|
||||
{
|
||||
ImGui.TextUnformatted($"Error: {ex.GetType().Name}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
pathList.RemoveAt(pathList.Count - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var p in obj.GetType().GetProperties().Where(p => p.GetGetMethod()?.GetParameters().Length == 0))
|
||||
{
|
||||
ImGui.TextColored(new Vector4(0.2f, 0.9f, 0.9f, 1), $"{p.PropertyType.Name}");
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(0.2f, 0.6f, 0.4f, 1), $"{p.Name}: ");
|
||||
ImGui.SameLine();
|
||||
|
||||
pathList.Add(p.Name);
|
||||
try
|
||||
{
|
||||
if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == GenericSpanType)
|
||||
ShowSpanProperty(addr, pathList, p, obj);
|
||||
else if (p.PropertyType.IsGenericType && (p.PropertyType.IsByRef || p.PropertyType.IsByRefLike))
|
||||
ImGui.Text("Cannot preview ref typed properties.");
|
||||
else
|
||||
ShowValue(addr, pathList, p.PropertyType, p.GetValue(obj), hideAddress);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1f, 0.4f, 0.4f, 1f));
|
||||
ImGui.TextUnformatted($"Error: {ex.GetType().Name}: {ex.Message}");
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
finally
|
||||
{
|
||||
pathList.RemoveAt(pathList.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.TreePop();
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui.PopStyleVar();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue