Change Redrawing to be simpler and not use a queue or settings.

This commit is contained in:
Ottermandias 2022-03-21 14:09:40 +01:00
parent 7540694050
commit b08bf388cc
7 changed files with 182 additions and 428 deletions

View file

@ -1,14 +1,9 @@
namespace Penumbra.GameData.Enums namespace Penumbra.GameData.Enums;
public enum RedrawType
{ {
public enum RedrawType Redraw,
{ Unload,
WithoutSettings, Load,
WithSettings, AfterGPose,
OnlyWithSettings,
Unload,
RedrawWithoutSettings,
RedrawWithSettings,
AfterGPoseWithSettings,
AfterGPoseWithoutSettings,
}
} }

View file

@ -24,8 +24,7 @@ public class ModsController : WebApiController
x.Data.Meta, x.Data.Meta,
BasePath = x.Data.BasePath.FullName, BasePath = x.Data.BasePath.FullName,
Files = x.Data.Resources.ModFiles.Select( fi => fi.FullName ), Files = x.Data.Resources.ModFiles.Select( fi => fi.FullName ),
} ) } );
?? null;
} }
[Route( HttpVerbs.Post, "/mods" )] [Route( HttpVerbs.Post, "/mods" )]

View file

@ -7,14 +7,13 @@ using Dalamud.Logging;
using Lumina.Data; using Lumina.Data;
using Penumbra.GameData.ByteString; using Penumbra.GameData.ByteString;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.GameData.Util;
using Penumbra.Mods; using Penumbra.Mods;
namespace Penumbra.Api; namespace Penumbra.Api;
public class PenumbraApi : IDisposable, IPenumbraApi public class PenumbraApi : IDisposable, IPenumbraApi
{ {
public int ApiVersion { get; } = 3; public int ApiVersion { get; } = 4;
private Penumbra? _penumbra; private Penumbra? _penumbra;
private Lumina.GameData? _lumina; private Lumina.GameData? _lumina;

View file

@ -4,32 +4,31 @@ using EmbedIO.Routing;
using EmbedIO.WebApi; using EmbedIO.WebApi;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
namespace Penumbra.Api namespace Penumbra.Api;
public class RedrawController : WebApiController
{ {
public class RedrawController : WebApiController private readonly Penumbra _penumbra;
public RedrawController( Penumbra penumbra )
=> _penumbra = penumbra;
[Route( HttpVerbs.Post, "/redraw" )]
public async Task Redraw()
{ {
private readonly Penumbra _penumbra; var data = await HttpContext.GetRequestDataAsync< RedrawData >();
_penumbra.Api.RedrawObject( data.Name, data.Type );
}
public RedrawController( Penumbra penumbra ) [Route( HttpVerbs.Post, "/redrawAll" )]
=> _penumbra = penumbra; public void RedrawAll()
{
_penumbra.Api.RedrawAll( RedrawType.Redraw );
}
[Route( HttpVerbs.Post, "/redraw" )] public class RedrawData
public async Task Redraw() {
{ public string Name { get; set; } = string.Empty;
RedrawData data = await HttpContext.GetRequestDataAsync<RedrawData>(); public RedrawType Type { get; set; } = RedrawType.Redraw;
_penumbra.Api.RedrawObject( data.Name, data.Type );
}
[Route( HttpVerbs.Post, "/redrawAll" )]
public void RedrawAll()
{
_penumbra.Api.RedrawAll(RedrawType.WithoutSettings);
}
public class RedrawData
{
public string Name { get; set; } = string.Empty;
public RedrawType Type { get; set; } = RedrawType.WithSettings;
}
} }
} }

View file

@ -1,35 +1,29 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Objects.Types;
using Penumbra.GameData.Enums; using Penumbra.GameData.Enums;
using Penumbra.Interop.Structs; using Penumbra.Interop.Structs;
using Penumbra.Mods;
namespace Penumbra.Interop; namespace Penumbra.Interop;
public unsafe class ObjectReloader : IDisposable public unsafe class ObjectReloader : IDisposable
{ {
private delegate void ManipulateDraw( IntPtr actor );
private const uint NpcObjectId = unchecked( ( uint )-536870912 );
public const int GPosePlayerIdx = 201; public const int GPosePlayerIdx = 201;
public const int GPoseEndIdx = GPosePlayerIdx + 48; public const int GPoseSlots = 42;
public const int GPoseEndIdx = GPosePlayerIdx + GPoseSlots;
private readonly ModManager _mods; private readonly List< int > _unloadedObjects = new(Dalamud.Objects.Length);
private readonly Queue< (uint actorId, string name, RedrawType s) > _actorIds = new(); private readonly List< int > _afterGPoseObjects = new(GPoseSlots);
private int _target = -1;
private int _waitFrame = 0;
private int _currentFrame; public ObjectReloader()
private bool _changedSettings; => Dalamud.Framework.Update += OnUpdateEvent;
private uint _currentObjectId = uint.MaxValue;
private DrawState _currentObjectStartState = 0; public void Dispose()
private RedrawType _currentRedrawType = RedrawType.Unload; => Dalamud.Framework.Update -= OnUpdateEvent;
private string? _currentObjectName;
private bool _wasTarget;
private bool _inGPose;
public static DrawState* ActorDrawState( GameObject actor ) public static DrawState* ActorDrawState( GameObject actor )
=> ( DrawState* )( actor.Address + 0x0104 ); => ( DrawState* )( actor.Address + 0x0104 );
@ -40,236 +34,122 @@ public unsafe class ObjectReloader : IDisposable
private static void EnableDraw( GameObject actor ) private static void EnableDraw( GameObject actor )
=> ( ( delegate* unmanaged< IntPtr, void >** )actor.Address )[ 0 ][ 16 ]( actor.Address ); => ( ( delegate* unmanaged< IntPtr, void >** )actor.Address )[ 0 ][ 16 ]( actor.Address );
public ObjectReloader( ModManager mods ) private static int ObjectTableIndex( GameObject actor )
=> _mods = mods; => ( ( FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* )actor.Address )->ObjectIndex;
private void ChangeSettings() private static void WriteInvisible( GameObject? actor )
{ {
if( _currentObjectName != null && _mods.Collections.CharacterCollection.TryGetValue( _currentObjectName, out var collection ) ) if( actor == null )
{ {
_changedSettings = true; return;
} }
}
private void RestoreSettings()
{
_changedSettings = false;
}
private void WriteInvisible( GameObject actor, int actorIdx )
{
_currentObjectStartState = *ActorDrawState( actor );
*ActorDrawState( actor ) |= DrawState.Invisibility; *ActorDrawState( actor ) |= DrawState.Invisibility;
if( _inGPose ) if( ObjectTableIndex( actor ) is >= GPosePlayerIdx and < GPoseEndIdx )
{ {
DisableDraw( actor ); DisableDraw( actor );
} }
} }
private bool StillLoading( DrawState* renderPtr ) private static void WriteVisible( GameObject? actor )
{ {
const DrawState stillLoadingFlags = DrawState.SomeNpcFlag if( actor == null )
| DrawState.MaybeCulled
| DrawState.MaybeHiddenMinion
| DrawState.MaybeHiddenSummon;
if( renderPtr != null )
{ {
var loadingFlags = *( DrawState* )renderPtr; return;
if( loadingFlags == _currentObjectStartState )
{
return false;
}
return !( loadingFlags == 0 || ( loadingFlags & stillLoadingFlags ) != 0 );
} }
return false;
}
private void WriteVisible( GameObject actor, int actorIdx )
{
*ActorDrawState( actor ) &= ~DrawState.Invisibility; *ActorDrawState( actor ) &= ~DrawState.Invisibility;
if( _inGPose ) if( ObjectTableIndex( actor ) is >= GPosePlayerIdx and < GPoseEndIdx )
{ {
EnableDraw( actor ); EnableDraw( actor );
} }
} }
private bool CheckObject( GameObject actor ) private void ReloadActor( GameObject? actor )
{ {
if( _currentObjectId != actor.ObjectId )
{
return false;
}
if( _currentObjectId != NpcObjectId )
{
return true;
}
return _currentObjectName == actor.Name.ToString();
}
private bool CheckObjectGPose( GameObject actor )
=> actor.ObjectId == NpcObjectId && _currentObjectName == actor.Name.ToString();
private (GameObject?, int) FindCurrentObject()
{
if( _inGPose )
{
for( var i = GPosePlayerIdx; i < GPoseEndIdx; ++i )
{
var actor = Dalamud.Objects[ i ];
if( actor == null )
{
break;
}
if( CheckObjectGPose( actor ) )
{
return ( actor, i );
}
}
}
for( var i = 0; i < Dalamud.Objects.Length; ++i )
{
if( i == GPosePlayerIdx )
{
i = GPoseEndIdx;
}
var actor = Dalamud.Objects[ i ];
if( actor != null && CheckObject( actor ) )
{
return ( actor, i );
}
}
return ( null, -1 );
}
private void PopObject()
{
if( _actorIds.Count > 0 )
{
var (id, name, s) = _actorIds.Dequeue();
_currentObjectName = name;
_currentObjectId = id;
_currentRedrawType = s;
var (actor, _) = FindCurrentObject();
if( actor == null )
{
return;
}
_wasTarget = actor.Address == Dalamud.Targets.Target?.Address;
++_currentFrame;
}
else
{
Dalamud.Framework.Update -= OnUpdateEvent;
}
}
private void ApplySettingsOrRedraw()
{
var (actor, idx) = FindCurrentObject();
if( actor == null )
{
_currentFrame = 0;
return;
}
switch( _currentRedrawType )
{
case RedrawType.Unload:
WriteInvisible( actor, idx );
_currentFrame = 0;
break;
case RedrawType.RedrawWithSettings:
ChangeSettings();
++_currentFrame;
break;
case RedrawType.RedrawWithoutSettings:
WriteVisible( actor, idx );
_currentFrame = 0;
break;
case RedrawType.WithoutSettings:
WriteInvisible( actor, idx );
++_currentFrame;
break;
case RedrawType.WithSettings:
ChangeSettings();
WriteInvisible( actor, idx );
++_currentFrame;
break;
case RedrawType.OnlyWithSettings:
ChangeSettings();
if( !_changedSettings )
{
return;
}
WriteInvisible( actor, idx );
++_currentFrame;
break;
case RedrawType.AfterGPoseWithSettings:
case RedrawType.AfterGPoseWithoutSettings:
if( _inGPose )
{
_actorIds.Enqueue( ( _currentObjectId, _currentObjectName!, _currentRedrawType ) );
_currentFrame = 0;
}
else
{
_currentRedrawType = _currentRedrawType == RedrawType.AfterGPoseWithSettings
? RedrawType.WithSettings
: RedrawType.WithoutSettings;
}
break;
default: throw new InvalidEnumArgumentException();
}
}
private void StartRedrawAndWait()
{
var (actor, idx) = FindCurrentObject();
if( actor == null )
{
RevertSettings();
return;
}
WriteVisible( actor, idx );
_currentFrame = _changedSettings || _wasTarget ? _currentFrame + 1 : 0;
}
private void RevertSettings()
{
var (actor, _) = FindCurrentObject();
if( actor != null ) if( actor != null )
{ {
if( !StillLoading( ActorDrawState( actor ) ) ) WriteInvisible( actor );
var idx = ObjectTableIndex( actor );
if( actor.Address == Dalamud.Targets.Target?.Address )
{ {
RestoreSettings(); _target = idx;
if( _wasTarget && Dalamud.Targets.Target == null )
{
Dalamud.Targets.SetTarget( actor );
}
_currentFrame = 0;
} }
_unloadedObjects.Add( idx );
_waitFrame = 1;
} }
else }
private void ReloadActorAfterGPose( GameObject? actor )
{
if( Dalamud.Objects[ GPosePlayerIdx ] != null )
{ {
_currentFrame = 0; ReloadActor( actor );
return;
} }
if( actor != null )
{
WriteInvisible( actor );
_afterGPoseObjects.Add( ObjectTableIndex( actor ) );
_waitFrame = 1;
}
}
private void HandleTarget()
{
if( _target < 0 )
{
return;
}
var actor = Dalamud.Objects[ _target ];
if( actor == null || Dalamud.Targets.Target != null )
{
_target = -1;
return;
}
if( ( ( FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* )actor.Address )->DrawObject == null )
{
return;
}
Dalamud.Targets.SetTarget( actor );
_target = -1;
}
private void HandleRedraw()
{
if( _unloadedObjects.Count == 0 )
{
return;
}
foreach( var idx in _unloadedObjects )
{
WriteVisible( Dalamud.Objects[ idx ] );
}
_unloadedObjects.Clear();
}
private void HandleAfterGPose()
{
if( _afterGPoseObjects.Count == 0 || Dalamud.Objects[ GPosePlayerIdx ] != null )
{
return;
}
foreach( var idx in _afterGPoseObjects )
{
WriteVisible( Dalamud.Objects[ idx ] );
}
_afterGPoseObjects.Clear();
} }
private void OnUpdateEvent( object framework ) private void OnUpdateEvent( object framework )
@ -281,47 +161,34 @@ public unsafe class ObjectReloader : IDisposable
return; return;
} }
_inGPose = Dalamud.Objects[ GPosePlayerIdx ] != null; if( _waitFrame > 0 )
switch( _currentFrame )
{
case 0:
PopObject();
break;
case 1:
ApplySettingsOrRedraw();
break;
case 2:
StartRedrawAndWait();
break;
case 3:
RevertSettings();
break;
default:
_currentFrame = 0;
break;
}
}
private void RedrawObjectIntern( uint objectId, string actorName, RedrawType settings )
{
if( _actorIds.Contains( ( objectId, actorName, settings ) ) )
{ {
--_waitFrame;
return; return;
} }
_actorIds.Enqueue( ( objectId, actorName, settings ) ); HandleRedraw();
if( _actorIds.Count == 1 ) HandleAfterGPose();
{ HandleTarget();
Dalamud.Framework.Update += OnUpdateEvent;
}
} }
public void RedrawObject( GameObject? actor, RedrawType settings = RedrawType.WithSettings ) public void RedrawObject( GameObject? actor, RedrawType settings )
{ {
if( actor != null ) switch( settings )
{ {
RedrawObjectIntern( actor.ObjectId, actor.Name.ToString(), RedrawType.WithoutSettings ); // TODO settings ); case RedrawType.Redraw:
ReloadActor( actor );
break;
case RedrawType.Unload:
WriteInvisible( actor );
break;
case RedrawType.Load:
WriteVisible( actor );
break;
case RedrawType.AfterGPose:
ReloadActorAfterGPose( actor );
break;
default: throw new ArgumentOutOfRangeException( nameof( settings ), settings, null );
} }
} }
@ -331,47 +198,45 @@ public unsafe class ObjectReloader : IDisposable
return gPosePlayer ?? Dalamud.Objects[ 0 ]; return gPosePlayer ?? Dalamud.Objects[ 0 ];
} }
private GameObject? GetName( string name ) private bool GetName( string lowerName, out GameObject? actor )
{ {
var lowerName = name.ToLowerInvariant(); ( actor, var ret ) = lowerName switch
return lowerName switch
{ {
"" => null, "" => ( null, true ),
"<me>" => GetLocalPlayer(), "<me>" => ( GetLocalPlayer(), true ),
"self" => GetLocalPlayer(), "self" => ( GetLocalPlayer(), true ),
"<t>" => Dalamud.Targets.Target, "<t>" => ( Dalamud.Targets.Target, true ),
"target" => Dalamud.Targets.Target, "target" => ( Dalamud.Targets.Target, true ),
"<f>" => Dalamud.Targets.FocusTarget, "<f>" => ( Dalamud.Targets.FocusTarget, true ),
"focus" => Dalamud.Targets.FocusTarget, "focus" => ( Dalamud.Targets.FocusTarget, true ),
"<mo>" => Dalamud.Targets.MouseOverTarget, "<mo>" => ( Dalamud.Targets.MouseOverTarget, true ),
"mouseover" => Dalamud.Targets.MouseOverTarget, "mouseover" => ( Dalamud.Targets.MouseOverTarget, true ),
_ => Dalamud.Objects.FirstOrDefault( _ => ( null, false ),
a => string.Equals( a.Name.ToString(), lowerName, StringComparison.InvariantCultureIgnoreCase ) ),
}; };
return ret;
} }
public void RedrawObject( string name, RedrawType settings = RedrawType.WithSettings ) public void RedrawObject( string name, RedrawType settings )
=> RedrawObject( GetName( name ), settings ); {
var lowerName = name.ToLowerInvariant();
public void RedrawAll( RedrawType settings = RedrawType.WithSettings ) if( GetName( lowerName, out var target ) )
{
RedrawObject( target, settings );
}
else
{
foreach( var actor in Dalamud.Objects.Where( a => a.Name.ToString().ToLowerInvariant() == lowerName ) )
{
RedrawObject( actor, settings );
}
}
}
public void RedrawAll( RedrawType settings )
{ {
Clear();
foreach( var actor in Dalamud.Objects ) foreach( var actor in Dalamud.Objects )
{ {
RedrawObject( actor, settings ); RedrawObject( actor, settings );
} }
} }
public void Clear()
{
RestoreSettings();
_currentFrame = 0;
}
public void Dispose()
{
RevertSettings();
_actorIds.Clear();
Dalamud.Framework.Update -= OnUpdateEvent;
}
} }

View file

@ -66,7 +66,7 @@ public class Penumbra : IDalamudPlugin
ResourceLogger = new ResourceLogger( ResourceLoader ); ResourceLogger = new ResourceLogger( ResourceLoader );
ModManager = new ModManager(); ModManager = new ModManager();
ModManager.DiscoverMods(); ModManager.DiscoverMods();
ObjectReloader = new ObjectReloader( ModManager ); ObjectReloader = new ObjectReloader();
PathResolver = new PathResolver( ResourceLoader ); PathResolver = new PathResolver( ResourceLoader );
Dalamud.Commands.AddHandler( CommandName, new CommandInfo( OnCommand ) Dalamud.Commands.AddHandler( CommandName, new CommandInfo( OnCommand )
@ -121,7 +121,7 @@ public class Penumbra : IDalamudPlugin
ResidentResources.Reload(); ResidentResources.Reload();
Config.Save(); Config.Save();
ObjectReloader.RedrawAll( RedrawType.WithSettings ); ObjectReloader.RedrawAll( RedrawType.Redraw );
return true; return true;
} }
@ -137,7 +137,7 @@ public class Penumbra : IDalamudPlugin
ResidentResources.Reload(); ResidentResources.Reload();
Config.Save(); Config.Save();
ObjectReloader.RedrawAll( RedrawType.WithoutSettings ); ObjectReloader.RedrawAll( RedrawType.Redraw );
return true; return true;
} }
@ -272,11 +272,11 @@ public class Penumbra : IDalamudPlugin
{ {
if( args.Length > 1 ) if( args.Length > 1 )
{ {
ObjectReloader.RedrawObject( args[ 1 ] ); ObjectReloader.RedrawObject( args[ 1 ], RedrawType.Redraw );
} }
else else
{ {
ObjectReloader.RedrawAll(); ObjectReloader.RedrawAll( RedrawType.Redraw );
} }
break; break;

View file

@ -63,107 +63,6 @@ public partial class SettingsInterface
PrintValue( "Mod Manager Valid", manager.Valid.ToString() ); PrintValue( "Mod Manager Valid", manager.Valid.ToString() );
//PrintValue( "Resource Loader Enabled", _penumbra.ResourceLoader.IsEnabled.ToString() ); //PrintValue( "Resource Loader Enabled", _penumbra.ResourceLoader.IsEnabled.ToString() );
} }
private unsafe void DrawDebugTabRedraw()
{
if( !ImGui.CollapsingHeader( "Redrawing##Debug" ) )
{
return;
}
var queue = ( Queue< (int, string, RedrawType) >? )_penumbra.ObjectReloader.GetType()
.GetField( "_objectIds", BindingFlags.Instance | BindingFlags.NonPublic )
?.GetValue( _penumbra.ObjectReloader )
?? new Queue< (int, string, RedrawType) >();
var currentFrame = ( int? )_penumbra.ObjectReloader.GetType()
.GetField( "_currentFrame", BindingFlags.Instance | BindingFlags.NonPublic )
?.GetValue( _penumbra.ObjectReloader );
var changedSettings = ( bool? )_penumbra.ObjectReloader.GetType()
.GetField( "_changedSettings", BindingFlags.Instance | BindingFlags.NonPublic )
?.GetValue( _penumbra.ObjectReloader );
var currentObjectId = ( uint? )_penumbra.ObjectReloader.GetType()
.GetField( "_currentObjectId", BindingFlags.Instance | BindingFlags.NonPublic )
?.GetValue( _penumbra.ObjectReloader );
var currentObjectName = ( string? )_penumbra.ObjectReloader.GetType()
.GetField( "_currentObjectName", BindingFlags.Instance | BindingFlags.NonPublic )
?.GetValue( _penumbra.ObjectReloader );
var currentObjectStartState = ( DrawState? )_penumbra.ObjectReloader.GetType()
.GetField( "_currentObjectStartState", BindingFlags.Instance | BindingFlags.NonPublic )
?.GetValue( _penumbra.ObjectReloader );
var currentRedrawType = ( RedrawType? )_penumbra.ObjectReloader.GetType()
.GetField( "_currentRedrawType", BindingFlags.Instance | BindingFlags.NonPublic )
?.GetValue( _penumbra.ObjectReloader );
var (currentObject, currentObjectIdx) = ( (GameObject?, int) )_penumbra.ObjectReloader.GetType()
.GetMethod( "FindCurrentObject", BindingFlags.NonPublic | BindingFlags.Instance )?
.Invoke( _penumbra.ObjectReloader, Array.Empty< object >() )!;
var currentRender = currentObject != null
? ObjectReloader.ActorDrawState( currentObject )
: null;
var waitFrames = ( int? )_penumbra.ObjectReloader.GetType()
.GetField( "_waitFrames", BindingFlags.Instance | BindingFlags.NonPublic )
?.GetValue( _penumbra.ObjectReloader );
var wasTarget = ( bool? )_penumbra.ObjectReloader.GetType()
.GetField( "_wasTarget", BindingFlags.Instance | BindingFlags.NonPublic )
?.GetValue( _penumbra.ObjectReloader );
var gPose = ( bool? )_penumbra.ObjectReloader.GetType()
.GetField( "_inGPose", BindingFlags.Instance | BindingFlags.NonPublic )
?.GetValue( _penumbra.ObjectReloader );
using var raii = new ImGuiRaii.EndStack();
if( ImGui.BeginTable( "##RedrawData", 2, ImGuiTableFlags.SizingFixedFit,
new Vector2( -1, ImGui.GetTextLineHeightWithSpacing() * 7 ) ) )
{
raii.Push( ImGui.EndTable );
PrintValue( "Current Wait Frame", waitFrames?.ToString() ?? "null" );
PrintValue( "Current Frame", currentFrame?.ToString() ?? "null" );
PrintValue( "Currently in GPose", gPose?.ToString() ?? "null" );
PrintValue( "Current Changed Settings", changedSettings?.ToString() ?? "null" );
PrintValue( "Current Object Id", currentObjectId?.ToString( "X8" ) ?? "null" );
PrintValue( "Current Object Name", currentObjectName ?? "null" );
PrintValue( "Current Object Start State", ( ( int? )currentObjectStartState )?.ToString( "X8" ) ?? "null" );
PrintValue( "Current Object Was Target", wasTarget?.ToString() ?? "null" );
PrintValue( "Current Object Redraw", currentRedrawType?.ToString() ?? "null" );
PrintValue( "Current Object Address", currentObject?.Address.ToString( "X16" ) ?? "null" );
PrintValue( "Current Object Index", currentObjectIdx >= 0 ? currentObjectIdx.ToString() : "null" );
PrintValue( "Current Object Render Flags", ( ( int? )currentRender )?.ToString( "X8" ) ?? "null" );
}
if( queue.Any()
&& ImGui.BeginTable( "##RedrawTable", 3, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.ScrollX,
new Vector2( -1, ImGui.GetTextLineHeightWithSpacing() * queue.Count ) ) )
{
raii.Push( ImGui.EndTable );
foreach( var (objectId, objectName, redraw) in queue )
{
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.Text( objectName );
ImGui.TableNextColumn();
ImGui.Text( $"0x{objectId:X8}" );
ImGui.TableNextColumn();
ImGui.Text( redraw.ToString() );
}
}
if( queue.Any() && ImGui.Button( "Clear" ) )
{
queue.Clear();
_penumbra.ObjectReloader.GetType()
.GetField( "_currentFrame", BindingFlags.Instance | BindingFlags.NonPublic )?.SetValue( _penumbra.ObjectReloader, 0 );
}
}
private void DrawDebugTabIpc() private void DrawDebugTabIpc()
{ {
if( !ImGui.CollapsingHeader( "IPC##Debug" ) ) if( !ImGui.CollapsingHeader( "IPC##Debug" ) )
@ -436,8 +335,6 @@ public partial class SettingsInterface
ImGui.NewLine(); ImGui.NewLine();
DrawDebugResidentResources(); DrawDebugResidentResources();
ImGui.NewLine(); ImGui.NewLine();
DrawDebugTabRedraw();
ImGui.NewLine();
DrawDebugTabIpc(); DrawDebugTabIpc();
ImGui.NewLine(); ImGui.NewLine();
} }