From 69a4e2b52ef7ce0485d9881ddc5007bd2edd8f29 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Fri, 3 Nov 2023 12:59:35 +0100 Subject: [PATCH 1/3] Fix Linking changed items not working. --- Penumbra/Penumbra.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Penumbra/Penumbra.cs b/Penumbra/Penumbra.cs index 73d1013e..99a81fd1 100644 --- a/Penumbra/Penumbra.cs +++ b/Penumbra/Penumbra.cs @@ -19,6 +19,7 @@ using Penumbra.UI.Tabs; using ChangedItemClick = Penumbra.Communication.ChangedItemClick; using ChangedItemHover = Penumbra.Communication.ChangedItemHover; using OtterGui.Tasks; +using Penumbra.GameData.Enums; using Penumbra.Interop.Structs; using Penumbra.UI; using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManager; @@ -111,13 +112,13 @@ public class Penumbra : IDalamudPlugin _services.GetRequiredService(); _communicatorService.ChangedItemHover.Subscribe(it => { - if (it is Item) + if (it is (Item, FullEquipType)) ImGui.TextUnformatted("Left Click to create an item link in chat."); }, ChangedItemHover.Priority.Link); _communicatorService.ChangedItemClick.Subscribe((button, it) => { - if (button == MouseButton.Left && it is Item item) + if (button == MouseButton.Left && it is (Item item, FullEquipType type)) Messager.LinkItem(item); }, ChangedItemClick.Priority.Link); } From 79c43fe7b1edc00d1afb357f37e447ddfde35773 Mon Sep 17 00:00:00 2001 From: Exter-N Date: Thu, 2 Nov 2023 21:01:40 +0100 Subject: [PATCH 2/3] PathResolving: Better function signatures? (names + types + TMB param count + dedupe) --- Penumbra/Interop/PathResolving/PathState.cs | 2 +- .../Interop/PathResolving/ResolvePathHooks.cs | 175 +++++++----------- 2 files changed, 71 insertions(+), 106 deletions(-) diff --git a/Penumbra/Interop/PathResolving/PathState.cs b/Penumbra/Interop/PathResolving/PathState.cs index 4fb3d31d..f300a666 100644 --- a/Penumbra/Interop/PathResolving/PathState.cs +++ b/Penumbra/Interop/PathResolving/PathState.cs @@ -42,7 +42,7 @@ public unsafe class PathState : IDisposable MetaState = metaState; CharacterUtility = characterUtility; _human = new ResolvePathHooks(interop, this, _humanVTable, ResolvePathHooks.Type.Human); - _weapon = new ResolvePathHooks(interop, this, _weaponVTable, ResolvePathHooks.Type.Weapon); + _weapon = new ResolvePathHooks(interop, this, _weaponVTable, ResolvePathHooks.Type.Other); _demiHuman = new ResolvePathHooks(interop, this, _demiHumanVTable, ResolvePathHooks.Type.Other); _monster = new ResolvePathHooks(interop, this, _monsterVTable, ResolvePathHooks.Type.Other); _human.Enable(); diff --git a/Penumbra/Interop/PathResolving/ResolvePathHooks.cs b/Penumbra/Interop/PathResolving/ResolvePathHooks.cs index f9a341b9..9d010d64 100644 --- a/Penumbra/Interop/PathResolving/ResolvePathHooks.cs +++ b/Penumbra/Interop/PathResolving/ResolvePathHooks.cs @@ -12,45 +12,47 @@ public unsafe class ResolvePathHooks : IDisposable public enum Type { Human, - Weapon, Other, } - private delegate nint GeneralResolveDelegate(nint drawObject, nint path, nint unk3, uint unk4); - private delegate nint MPapResolveDelegate(nint drawObject, nint path, nint unk3, uint unk4, uint unk5); - private delegate nint MaterialResolveDelegate(nint drawObject, nint path, nint unk3, uint unk4, ulong unk5); - private delegate nint EidResolveDelegate(nint drawObject, nint path, nint unk3); + private delegate nint MPapResolveDelegate(nint drawObject, nint pathBuffer, nint pathBufferSize, uint slotIndex, uint sId); + private delegate nint NamedResolveDelegate(nint drawObject, nint pathBuffer, nint pathBufferSize, uint slotIndex, nint name); + private delegate nint PerSlotResolveDelegate(nint drawObject, nint pathBuffer, nint pathBufferSize, uint slotIndex); + private delegate nint SingleResolveDelegate(nint drawObject, nint pathBuffer, nint pathBufferSize); + private delegate nint TmbResolveDelegate(nint drawObject, nint pathBuffer, nint pathBufferSize, nint timelineName); + // Kept separate from NamedResolveDelegate because the 5th parameter has out semantics here, instead of in. + private delegate nint VfxResolveDelegate(nint drawObject, nint pathBuffer, nint pathBufferSize, uint slotIndex, nint unkOutParam); - private readonly Hook _resolveDecalPathHook; - private readonly Hook _resolveEidPathHook; - private readonly Hook _resolveImcPathHook; - private readonly Hook _resolveMPapPathHook; - private readonly Hook _resolveMdlPathHook; - private readonly Hook _resolveMtrlPathHook; - private readonly Hook _resolvePapPathHook; - private readonly Hook _resolvePhybPathHook; - private readonly Hook _resolveSklbPathHook; - private readonly Hook _resolveSkpPathHook; - private readonly Hook _resolveTmbPathHook; - private readonly Hook _resolveVfxPathHook; + private readonly Hook _resolveDecalPathHook; + private readonly Hook _resolveEidPathHook; + private readonly Hook _resolveImcPathHook; + private readonly Hook _resolveMPapPathHook; + private readonly Hook _resolveMdlPathHook; + private readonly Hook _resolveMtrlPathHook; + private readonly Hook _resolvePapPathHook; + private readonly Hook _resolvePhybPathHook; + private readonly Hook _resolveSklbPathHook; + private readonly Hook _resolveSkpPathHook; + private readonly Hook _resolveTmbPathHook; + private readonly Hook _resolveVfxPathHook; private readonly PathState _parent; public ResolvePathHooks(IGameInteropProvider interop, PathState parent, nint* vTable, Type type) { _parent = parent; - _resolveDecalPathHook = Create(interop, vTable[83], type, ResolveDecalWeapon, ResolveDecal); - _resolveEidPathHook = Create(interop, vTable[85], type, ResolveEidWeapon, ResolveEid); - _resolveImcPathHook = Create(interop, vTable[81], type, ResolveImcWeapon, ResolveImc); - _resolveMPapPathHook = Create(interop, vTable[79], type, ResolveMPapWeapon, ResolveMPap); - _resolveMdlPathHook = Create(interop, vTable[73], type, ResolveMdlWeapon, ResolveMdl, ResolveMdlHuman); - _resolveMtrlPathHook = Create(interop, vTable[82], type, ResolveMtrlWeapon, ResolveMtrl); - _resolvePapPathHook = Create(interop, vTable[76], type, ResolvePapWeapon, ResolvePap, ResolvePapHuman); - _resolvePhybPathHook = Create(interop, vTable[75], type, ResolvePhybWeapon, ResolvePhyb, ResolvePhybHuman); - _resolveSklbPathHook = Create(interop, vTable[72], type, ResolveSklbWeapon, ResolveSklb, ResolveSklbHuman); - _resolveSkpPathHook = Create(interop, vTable[74], type, ResolveSkpWeapon, ResolveSkp, ResolveSkpHuman); - _resolveTmbPathHook = Create(interop, vTable[77], type, ResolveTmbWeapon, ResolveTmb); - _resolveVfxPathHook = Create(interop, vTable[84], type, ResolveVfxWeapon, ResolveVfx); + _resolveDecalPathHook = Create(interop, vTable[83], ResolveDecal); + _resolveEidPathHook = Create(interop, vTable[85], ResolveEid); + _resolveImcPathHook = Create(interop, vTable[81], ResolveImc); + _resolveMPapPathHook = Create(interop, vTable[79], ResolveMPap); + _resolveMdlPathHook = Create(interop, vTable[73], type, ResolveMdl, ResolveMdlHuman); + _resolveMtrlPathHook = Create(interop, vTable[82], ResolveMtrl); + _resolvePapPathHook = Create(interop, vTable[76], type, ResolvePap, ResolvePapHuman); + _resolvePhybPathHook = Create(interop, vTable[75], type, ResolvePhyb, ResolvePhybHuman); + _resolveSklbPathHook = Create(interop, vTable[72], type, ResolveSklb, ResolveSklbHuman); + _resolveSkpPathHook = Create(interop, vTable[74], type, ResolveSkp, ResolveSkpHuman); + _resolveTmbPathHook = Create(interop, vTable[77], ResolveTmb); + _resolveVfxPathHook = Create(interop, vTable[84], ResolveVfx); } public void Enable() @@ -101,74 +103,74 @@ public unsafe class ResolvePathHooks : IDisposable _resolveVfxPathHook.Dispose(); } - private nint ResolveDecal(nint drawObject, nint path, nint unk3, uint unk4) - => ResolvePath(drawObject, _resolveDecalPathHook.Original(drawObject, path, unk3, unk4)); + private nint ResolveDecal(nint drawObject, nint pathBuffer, nint pathBufferSize, uint slotIndex) + => ResolvePath(drawObject, _resolveDecalPathHook.Original(drawObject, pathBuffer, pathBufferSize, slotIndex)); - private nint ResolveEid(nint drawObject, nint path, nint unk3) - => ResolvePath(drawObject, _resolveEidPathHook.Original(drawObject, path, unk3)); + private nint ResolveEid(nint drawObject, nint pathBuffer, nint pathBufferSize) + => ResolvePath(drawObject, _resolveEidPathHook.Original(drawObject, pathBuffer, pathBufferSize)); - private nint ResolveImc(nint drawObject, nint path, nint unk3, uint unk4) - => ResolvePath(drawObject, _resolveImcPathHook.Original(drawObject, path, unk3, unk4)); + private nint ResolveImc(nint drawObject, nint pathBuffer, nint pathBufferSize, uint slotIndex) + => ResolvePath(drawObject, _resolveImcPathHook.Original(drawObject, pathBuffer, pathBufferSize, slotIndex)); - private nint ResolveMPap(nint drawObject, nint path, nint unk3, uint unk4, uint unk5) - => ResolvePath(drawObject, _resolveMPapPathHook.Original(drawObject, path, unk3, unk4, unk5)); + private nint ResolveMPap(nint drawObject, nint pathBuffer, nint pathBufferSize, uint slotIndex, uint unkSId) + => ResolvePath(drawObject, _resolveMPapPathHook.Original(drawObject, pathBuffer, pathBufferSize, slotIndex, unkSId)); - private nint ResolveMdl(nint drawObject, nint path, nint unk3, uint modelType) - => ResolvePath(drawObject, _resolveMdlPathHook.Original(drawObject, path, unk3, modelType)); + private nint ResolveMdl(nint drawObject, nint pathBuffer, nint pathBufferSize, uint slotIndex) + => ResolvePath(drawObject, _resolveMdlPathHook.Original(drawObject, pathBuffer, pathBufferSize, slotIndex)); - private nint ResolveMtrl(nint drawObject, nint path, nint unk3, uint unk4, ulong unk5) - => ResolvePath(drawObject, _resolveMtrlPathHook.Original(drawObject, path, unk3, unk4, unk5)); + private nint ResolveMtrl(nint drawObject, nint pathBuffer, nint pathBufferSize, uint slotIndex, nint mtrlFileName) + => ResolvePath(drawObject, _resolveMtrlPathHook.Original(drawObject, pathBuffer, pathBufferSize, slotIndex, mtrlFileName)); - private nint ResolvePap(nint drawObject, nint path, nint unk3, uint unk4, ulong unk5) - => ResolvePath(drawObject, _resolvePapPathHook.Original(drawObject, path, unk3, unk4, unk5)); + private nint ResolvePap(nint drawObject, nint pathBuffer, nint pathBufferSize, uint unkAnimationIndex, nint animationName) + => ResolvePath(drawObject, _resolvePapPathHook.Original(drawObject, pathBuffer, pathBufferSize, unkAnimationIndex, animationName)); - private nint ResolvePhyb(nint drawObject, nint path, nint unk3, uint unk4) - => ResolvePath(drawObject, _resolvePhybPathHook.Original(drawObject, path, unk3, unk4)); + private nint ResolvePhyb(nint drawObject, nint pathBuffer, nint pathBufferSize, uint partialSkeletonIndex) + => ResolvePath(drawObject, _resolvePhybPathHook.Original(drawObject, pathBuffer, pathBufferSize, partialSkeletonIndex)); - private nint ResolveSklb(nint drawObject, nint path, nint unk3, uint unk4) - => ResolvePath(drawObject, _resolveSklbPathHook.Original(drawObject, path, unk3, unk4)); + private nint ResolveSklb(nint drawObject, nint pathBuffer, nint pathBufferSize, uint partialSkeletonIndex) + => ResolvePath(drawObject, _resolveSklbPathHook.Original(drawObject, pathBuffer, pathBufferSize, partialSkeletonIndex)); - private nint ResolveSkp(nint drawObject, nint path, nint unk3, uint unk4) - => ResolvePath(drawObject, _resolveSkpPathHook.Original(drawObject, path, unk3, unk4)); + private nint ResolveSkp(nint drawObject, nint pathBuffer, nint pathBufferSize, uint partialSkeletonIndex) + => ResolvePath(drawObject, _resolveSkpPathHook.Original(drawObject, pathBuffer, pathBufferSize, partialSkeletonIndex)); - private nint ResolveTmb(nint drawObject, nint path, nint unk3) - => ResolvePath(drawObject, _resolveTmbPathHook.Original(drawObject, path, unk3)); + private nint ResolveTmb(nint drawObject, nint pathBuffer, nint pathBufferSize, nint timelineName) + => ResolvePath(drawObject, _resolveTmbPathHook.Original(drawObject, pathBuffer, pathBufferSize, timelineName)); - private nint ResolveVfx(nint drawObject, nint path, nint unk3, uint unk4, ulong unk5) - => ResolvePath(drawObject, _resolveVfxPathHook.Original(drawObject, path, unk3, unk4, unk5)); + private nint ResolveVfx(nint drawObject, nint pathBuffer, nint pathBufferSize, uint slotIndex, nint unkOutParam) + => ResolvePath(drawObject, _resolveVfxPathHook.Original(drawObject, pathBuffer, pathBufferSize, slotIndex, unkOutParam)); - private nint ResolveMdlHuman(nint drawObject, nint path, nint unk3, uint modelType) + private nint ResolveMdlHuman(nint drawObject, nint pathBuffer, nint pathBufferSize, uint slotIndex) { var data = _parent.CollectionResolver.IdentifyCollection((DrawObject*)drawObject, true); - using var eqdp = modelType > 9 + using var eqdp = slotIndex > 9 ? DisposableContainer.Empty - : _parent.MetaState.ResolveEqdpData(data.ModCollection, MetaState.GetHumanGenderRace(drawObject), modelType < 5, modelType > 4); - return ResolvePath(data, _resolveMdlPathHook.Original(drawObject, path, unk3, modelType)); + : _parent.MetaState.ResolveEqdpData(data.ModCollection, MetaState.GetHumanGenderRace(drawObject), slotIndex < 5, slotIndex > 4); + return ResolvePath(data, _resolveMdlPathHook.Original(drawObject, pathBuffer, pathBufferSize, slotIndex)); } - private nint ResolvePapHuman(nint drawObject, nint path, nint unk3, uint unk4, ulong unk5) + private nint ResolvePapHuman(nint drawObject, nint pathBuffer, nint pathBufferSize, uint unkAnimationIndex, nint animationName) { using var est = GetEstChanges(drawObject, out var data); - return ResolvePath(data, _resolvePapPathHook.Original(drawObject, path, unk3, unk4, unk5)); + return ResolvePath(data, _resolvePapPathHook.Original(drawObject, pathBuffer, pathBufferSize, unkAnimationIndex, animationName)); } - private nint ResolvePhybHuman(nint drawObject, nint path, nint unk3, uint unk4) + private nint ResolvePhybHuman(nint drawObject, nint pathBuffer, nint pathBufferSize, uint partialSkeletonIndex) { using var est = GetEstChanges(drawObject, out var data); - return ResolvePath(data, _resolvePhybPathHook.Original(drawObject, path, unk3, unk4)); + return ResolvePath(data, _resolvePhybPathHook.Original(drawObject, pathBuffer, pathBufferSize, partialSkeletonIndex)); } - private nint ResolveSklbHuman(nint drawObject, nint path, nint unk3, uint unk4) + private nint ResolveSklbHuman(nint drawObject, nint pathBuffer, nint pathBufferSize, uint partialSkeletonIndex) { using var est = GetEstChanges(drawObject, out var data); - return ResolvePath(data, _resolveSklbPathHook.Original(drawObject, path, unk3, unk4)); + return ResolvePath(data, _resolveSklbPathHook.Original(drawObject, pathBuffer, pathBufferSize, partialSkeletonIndex)); } - private nint ResolveSkpHuman(nint drawObject, nint path, nint unk3, uint unk4) + private nint ResolveSkpHuman(nint drawObject, nint pathBuffer, nint pathBufferSize, uint partialSkeletonIndex) { using var est = GetEstChanges(drawObject, out var data); - return ResolvePath(data, _resolveSkpPathHook.Original(drawObject, path, unk3, unk4)); + return ResolvePath(data, _resolveSkpPathHook.Original(drawObject, pathBuffer, pathBufferSize, partialSkeletonIndex)); } private DisposableContainer GetEstChanges(nint drawObject, out ResolveData data) @@ -180,58 +182,21 @@ public unsafe class ResolvePathHooks : IDisposable data.ModCollection.TemporarilySetEstFile(_parent.CharacterUtility, EstManipulation.EstType.Head)); } - private nint ResolveDecalWeapon(nint drawObject, nint path, nint unk3, uint unk4) - => ResolvePath(drawObject, _resolveDecalPathHook.Original(drawObject, path, unk3, unk4)); - - private nint ResolveEidWeapon(nint drawObject, nint path, nint unk3) - => ResolvePath(drawObject, _resolveEidPathHook.Original(drawObject, path, unk3)); - - private nint ResolveImcWeapon(nint drawObject, nint path, nint unk3, uint unk4) - => ResolvePath(drawObject, _resolveImcPathHook.Original(drawObject, path, unk3, unk4)); - - private nint ResolveMPapWeapon(nint drawObject, nint path, nint unk3, uint unk4, uint unk5) - => ResolvePath(drawObject, _resolveMPapPathHook.Original(drawObject, path, unk3, unk4, unk5)); - - private nint ResolveMdlWeapon(nint drawObject, nint path, nint unk3, uint modelType) - => ResolvePath(drawObject, _resolveMdlPathHook.Original(drawObject, path, unk3, modelType)); - - private nint ResolveMtrlWeapon(nint drawObject, nint path, nint unk3, uint unk4, ulong unk5) - => ResolvePath(drawObject, _resolveMtrlPathHook.Original(drawObject, path, unk3, unk4, unk5)); - - private nint ResolvePapWeapon(nint drawObject, nint path, nint unk3, uint unk4, ulong unk5) - => ResolvePath(drawObject, _resolvePapPathHook.Original(drawObject, path, unk3, unk4, unk5)); - - private nint ResolvePhybWeapon(nint drawObject, nint path, nint unk3, uint unk4) - => ResolvePath(drawObject, _resolvePhybPathHook.Original(drawObject, path, unk3, unk4)); - - private nint ResolveSklbWeapon(nint drawObject, nint path, nint unk3, uint unk4) - => ResolvePath(drawObject, _resolveSklbPathHook.Original(drawObject, path, unk3, unk4)); - - private nint ResolveSkpWeapon(nint drawObject, nint path, nint unk3, uint unk4) - => ResolvePath(drawObject, _resolveSkpPathHook.Original(drawObject, path, unk3, unk4)); - - private nint ResolveTmbWeapon(nint drawObject, nint path, nint unk3) - => ResolvePath(drawObject, _resolveTmbPathHook.Original(drawObject, path, unk3)); - - private nint ResolveVfxWeapon(nint drawObject, nint path, nint unk3, uint unk4, ulong unk5) - => ResolvePath(drawObject, _resolveVfxPathHook.Original(drawObject, path, unk3, unk4, unk5)); - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static Hook Create(IGameInteropProvider interop, nint address, Type type, T weapon, T other, T human) where T : Delegate + private static Hook Create(IGameInteropProvider interop, nint address, Type type, T other, T human) where T : Delegate { var del = type switch { Type.Human => human, - Type.Weapon => weapon, _ => other, }; return interop.HookFromAddress(address, del); } [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static Hook Create(IGameInteropProvider interop, nint address, Type type, T weapon, T other) where T : Delegate - => Create(interop, address, type, weapon, other, other); + private static Hook Create(IGameInteropProvider interop, nint address, T del) where T : Delegate + => interop.HookFromAddress(address, del); // Implementation From 7dabb3c647b08848dfa99915f2e46e1e746a7b29 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Fri, 3 Nov 2023 15:23:48 +0100 Subject: [PATCH 3/3] Add some Redrawing Debug UI. --- Penumbra/Interop/Services/RedrawService.cs | 16 +++++++- Penumbra/UI/Tabs/DebugTab.cs | 46 +++++++++++++++++++++- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/Penumbra/Interop/Services/RedrawService.cs b/Penumbra/Interop/Services/RedrawService.cs index 5cc493ad..ec858290 100644 --- a/Penumbra/Interop/Services/RedrawService.cs +++ b/Penumbra/Interop/Services/RedrawService.cs @@ -18,10 +18,13 @@ public unsafe partial class RedrawService public const int GPoseSlots = 42; public const int GPoseEndIdx = GPosePlayerIdx + GPoseSlots; - private readonly string?[] _gPoseNames = new string?[GPoseSlots]; + private readonly string?[] _gPoseNames = new string?[GPoseSlots]; private int _gPoseNameCounter; - private bool InGPose + internal IReadOnlyList GPoseNames + => _gPoseNames; + + internal bool InGPose => _clientState.IsGPosing; // VFuncs that disable and enable draw, used only for GPose actors. @@ -108,6 +111,15 @@ public sealed unsafe partial class RedrawService : IDisposable private readonly List _afterGPoseQueue = new(GPoseSlots); private int _target = -1; + internal IReadOnlyList Queue + => _queue; + + internal IReadOnlyList AfterGPoseQueue + => _afterGPoseQueue; + + internal int Target + => _target; + public event GameObjectRedrawnDelegate? GameObjectRedrawn; public RedrawService(IFramework framework, IObjectTable objects, ITargetManager targets, ICondition conditions, IClientState clientState) diff --git a/Penumbra/UI/Tabs/DebugTab.cs b/Penumbra/UI/Tabs/DebugTab.cs index 5abb3c2f..dc39707a 100644 --- a/Penumbra/UI/Tabs/DebugTab.cs +++ b/Penumbra/UI/Tabs/DebugTab.cs @@ -65,6 +65,7 @@ public class DebugTab : Window, ITab private readonly TextureManager _textureManager; private readonly SkinFixer _skinFixer; private readonly IdentifierService _identifier; + private readonly RedrawService _redraws; public DebugTab(StartTracker timer, PerformanceTracker performance, Configuration config, CollectionManager collectionManager, ValidityChecker validityChecker, ModManager modManager, HttpApi httpApi, ActorService actorService, @@ -72,7 +73,7 @@ public class DebugTab : Window, ITab ResourceManagerService resourceManager, PenumbraIpcProviders ipc, CollectionResolver collectionResolver, DrawObjectState drawObjectState, PathState pathState, SubfileHelper subfileHelper, IdentifiedCollectionCache identifiedCollectionCache, CutsceneService cutsceneService, ModImportManager modImporter, ImportPopup importPopup, FrameworkManager framework, - TextureManager textureManager, SkinFixer skinFixer, IdentifierService identifier) + TextureManager textureManager, SkinFixer skinFixer, IdentifierService identifier, RedrawService redraws) : base("Penumbra Debug Window", ImGuiWindowFlags.NoCollapse) { IsOpen = true; @@ -107,6 +108,7 @@ public class DebugTab : Window, ITab _textureManager = textureManager; _skinFixer = skinFixer; _identifier = identifier; + _redraws = redraws; } public ReadOnlySpan Label @@ -317,6 +319,48 @@ public class DebugTab : Window, ITab } } } + + using (var tree = TreeNode("Redraw Service")) + { + if (tree) + { + using var table = Table("##redraws", 3, ImGuiTableFlags.RowBg); + if (table) + { + ImGuiUtil.DrawTableColumn("In GPose"); + ImGuiUtil.DrawTableColumn(_redraws.InGPose.ToString()); + ImGui.TableNextColumn(); + + ImGuiUtil.DrawTableColumn("Target"); + ImGuiUtil.DrawTableColumn(_redraws.Target.ToString()); + ImGui.TableNextColumn(); + + foreach (var (objectIdx, idx) in _redraws.Queue.WithIndex()) + { + var (actualIdx, state) = objectIdx < 0 ? (~objectIdx, "Queued") : (objectIdx, "Invisible"); + ImGuiUtil.DrawTableColumn($"Redraw Queue #{idx}"); + ImGuiUtil.DrawTableColumn(actualIdx.ToString()); + ImGuiUtil.DrawTableColumn(state); + } + + foreach (var (objectIdx, idx) in _redraws.AfterGPoseQueue.WithIndex()) + { + var (actualIdx, state) = objectIdx < 0 ? (~objectIdx, "Queued") : (objectIdx, "Invisible"); + ImGuiUtil.DrawTableColumn($"GPose Queue #{idx}"); + ImGuiUtil.DrawTableColumn(actualIdx.ToString()); + ImGuiUtil.DrawTableColumn(state); + } + + foreach (var (name, idx) in _redraws.GPoseNames.OfType().WithIndex()) + { + ImGuiUtil.DrawTableColumn($"GPose Name #{idx}"); + ImGuiUtil.DrawTableColumn(name); + ImGui.TableNextColumn(); + } + + } + } + } } private void DrawPerformanceTab()