mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 12:14:17 +01:00
Change Redrawing to be simpler and not use a queue or settings.
This commit is contained in:
parent
7540694050
commit
b08bf388cc
7 changed files with 182 additions and 428 deletions
|
|
@ -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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -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" )]
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue