mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Cache collections instead of looking them up for every single file.
This commit is contained in:
parent
f676bd1889
commit
2fac923452
12 changed files with 194 additions and 28 deletions
|
|
@ -162,10 +162,15 @@ public partial class ActorManager
|
||||||
((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor)->NameID);
|
((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor)->NameID);
|
||||||
}
|
}
|
||||||
case ObjectKind.EventNpc:
|
case ObjectKind.EventNpc:
|
||||||
|
{
|
||||||
|
var dataId = actor->DataID;
|
||||||
|
// Special case for squadron that is also in the game functions, cf. E8 ?? ?? ?? ?? 89 87 ?? ?? ?? ?? 4C 89 BF
|
||||||
|
if (dataId == 0xf845d)
|
||||||
|
dataId = actor->GetNpcID();
|
||||||
return check
|
return check
|
||||||
? CreateNpc(ObjectKind.EventNpc, actor->DataID, actor->ObjectIndex)
|
? CreateNpc(ObjectKind.EventNpc, dataId, actor->ObjectIndex)
|
||||||
: CreateIndividualUnchecked(IdentifierType.Npc, ByteString.Empty, actor->ObjectIndex, ObjectKind.EventNpc,
|
: CreateIndividualUnchecked(IdentifierType.Npc, ByteString.Empty, actor->ObjectIndex, ObjectKind.EventNpc, dataId);
|
||||||
actor->ObjectIndex);
|
}
|
||||||
case ObjectKind.MountType:
|
case ObjectKind.MountType:
|
||||||
case ObjectKind.Companion:
|
case ObjectKind.Companion:
|
||||||
case (ObjectKind)15: // TODO: CS Update
|
case (ObjectKind)15: // TODO: CS Update
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@ public class TempModManager
|
||||||
public bool CollectionByName( string name, [NotNullWhen( true )] out ModCollection? collection )
|
public bool CollectionByName( string name, [NotNullWhen( true )] out ModCollection? collection )
|
||||||
=> Collections.Values.FindFirst( c => string.Equals( c.Name, name, StringComparison.OrdinalIgnoreCase ), out collection );
|
=> Collections.Values.FindFirst( c => string.Equals( c.Name, name, StringComparison.OrdinalIgnoreCase ), out collection );
|
||||||
|
|
||||||
|
public event ModCollection.Manager.CollectionChangeDelegate? CollectionChanged;
|
||||||
|
|
||||||
// These functions to check specific redirections or meta manipulations for existence are currently unused.
|
// These functions to check specific redirections or meta manipulations for existence are currently unused.
|
||||||
//public bool IsRegistered( string tag, ModCollection? collection, Utf8GamePath gamePath, out FullPath? fullPath, out int priority )
|
//public bool IsRegistered( string tag, ModCollection? collection, Utf8GamePath gamePath, out FullPath? fullPath, out int priority )
|
||||||
//{
|
//{
|
||||||
|
|
@ -151,6 +153,7 @@ public class TempModManager
|
||||||
{
|
{
|
||||||
var collection = ModCollection.CreateNewTemporary( tag, characterName );
|
var collection = ModCollection.CreateNewTemporary( tag, characterName );
|
||||||
_collections[ characterName ] = collection;
|
_collections[ characterName ] = collection;
|
||||||
|
CollectionChanged?.Invoke(CollectionType.Temporary, null, collection );
|
||||||
return collection.Name;
|
return collection.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,6 +163,7 @@ public class TempModManager
|
||||||
{
|
{
|
||||||
_mods.Remove( c );
|
_mods.Remove( c );
|
||||||
c.ClearCache();
|
c.ClearCache();
|
||||||
|
CollectionChanged?.Invoke( CollectionType.Temporary, c, null );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ public partial class ModCollection
|
||||||
RemoveCache( oldCollectionIdx );
|
RemoveCache( oldCollectionIdx );
|
||||||
|
|
||||||
UpdateCurrentCollectionInUse();
|
UpdateCurrentCollectionInUse();
|
||||||
CollectionChanged.Invoke( collectionType, this[ oldCollectionIdx ], newCollection, Individuals[ individualIndex ].DisplayName );
|
CollectionChanged.Invoke( collectionType, this[ oldCollectionIdx ], newCollection, collectionType == CollectionType.Individual ? Individuals[ individualIndex ].DisplayName : string.Empty );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateCurrentCollectionInUse()
|
private void UpdateCurrentCollectionInUse()
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@ public enum CollectionType : byte
|
||||||
Interface, // The ui collection was changed
|
Interface, // The ui collection was changed
|
||||||
Individual, // An individual collection was changed
|
Individual, // An individual collection was changed
|
||||||
Current, // The current collection was changed
|
Current, // The current collection was changed
|
||||||
|
Temporary, // A temporary collections was set or deleted via IPC
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CollectionTypeExtensions
|
public static class CollectionTypeExtensions
|
||||||
|
|
|
||||||
129
Penumbra/Interop/Resolver/IdentifiedCollectionCache.cs
Normal file
129
Penumbra/Interop/Resolver/IdentifiedCollectionCache.cs
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Dalamud.Hooking;
|
||||||
|
using Dalamud.Utility.Signatures;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
||||||
|
using Penumbra.Collections;
|
||||||
|
using Penumbra.GameData.Actors;
|
||||||
|
|
||||||
|
namespace Penumbra.Interop.Resolver;
|
||||||
|
|
||||||
|
public unsafe class IdentifiedCollectionCache : IDisposable, IEnumerable< (IntPtr Address, ActorIdentifier Identifier, ModCollection Collection) >
|
||||||
|
{
|
||||||
|
private readonly Dictionary< IntPtr, (ActorIdentifier, ModCollection) > _cache = new(317);
|
||||||
|
private bool _dirty = false;
|
||||||
|
private bool _enabled = false;
|
||||||
|
|
||||||
|
public IdentifiedCollectionCache()
|
||||||
|
{
|
||||||
|
SignatureHelper.Initialise( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Enable()
|
||||||
|
{
|
||||||
|
if( _enabled )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Penumbra.CollectionManager.CollectionChanged += CollectionChangeClear;
|
||||||
|
Penumbra.TempMods.CollectionChanged += CollectionChangeClear;
|
||||||
|
Dalamud.ClientState.TerritoryChanged += TerritoryClear;
|
||||||
|
_characterDtorHook.Enable();
|
||||||
|
_enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Disable()
|
||||||
|
{
|
||||||
|
if( !_enabled )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Penumbra.CollectionManager.CollectionChanged -= CollectionChangeClear;
|
||||||
|
Penumbra.TempMods.CollectionChanged -= CollectionChangeClear;
|
||||||
|
Dalamud.ClientState.TerritoryChanged -= TerritoryClear;
|
||||||
|
_characterDtorHook.Disable();
|
||||||
|
_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResolveData Set( ModCollection collection, ActorIdentifier identifier, GameObject* data )
|
||||||
|
{
|
||||||
|
if( _dirty )
|
||||||
|
{
|
||||||
|
_dirty = false;
|
||||||
|
_cache.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
_cache[ ( IntPtr )data ] = ( identifier, collection );
|
||||||
|
return collection.ToResolveData( data );
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetValue( GameObject* gameObject, out ResolveData resolve )
|
||||||
|
{
|
||||||
|
if( _dirty )
|
||||||
|
{
|
||||||
|
_dirty = false;
|
||||||
|
_cache.Clear();
|
||||||
|
}
|
||||||
|
else if( _cache.TryGetValue( ( IntPtr )gameObject, out var p ) )
|
||||||
|
{
|
||||||
|
resolve = p.Item2.ToResolveData( gameObject );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Disable();
|
||||||
|
_characterDtorHook.Dispose();
|
||||||
|
GC.SuppressFinalize( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator< (IntPtr Address, ActorIdentifier Identifier, ModCollection Collection) > GetEnumerator()
|
||||||
|
{
|
||||||
|
foreach( var (address, (identifier, collection)) in _cache )
|
||||||
|
{
|
||||||
|
if( _dirty )
|
||||||
|
{
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return ( address, identifier, collection );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~IdentifiedCollectionCache()
|
||||||
|
=> Dispose();
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
=> GetEnumerator();
|
||||||
|
|
||||||
|
private void CollectionChangeClear( CollectionType type, ModCollection? _1, ModCollection? _2, string _3 )
|
||||||
|
{
|
||||||
|
if( type is not (CollectionType.Current or CollectionType.Interface or CollectionType.Inactive) )
|
||||||
|
{
|
||||||
|
_dirty = _cache.Count > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TerritoryClear( object? _1, ushort _2 )
|
||||||
|
=> _dirty = _cache.Count > 0;
|
||||||
|
|
||||||
|
private delegate void CharacterDestructorDelegate( Character* character );
|
||||||
|
|
||||||
|
[Signature( "48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC ?? 48 8D 05 ?? ?? ?? ?? 48 8B D9 48 89 01 48 8D 05 ?? ?? ?? ?? 48 89 81 ?? ?? ?? ?? 48 8D 05",
|
||||||
|
DetourName = nameof( CharacterDestructorDetour ) )]
|
||||||
|
private Hook< CharacterDestructorDelegate > _characterDtorHook = null!;
|
||||||
|
|
||||||
|
private void CharacterDestructorDetour( Character* character )
|
||||||
|
{
|
||||||
|
_cache.Remove( ( IntPtr )character );
|
||||||
|
_characterDtorHook.Original( character );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -118,7 +118,7 @@ public unsafe partial class PathResolver
|
||||||
if( idx >= 0 && idx < Dalamud.Objects.Length )
|
if( idx >= 0 && idx < Dalamud.Objects.Length )
|
||||||
{
|
{
|
||||||
var obj = Dalamud.Objects[ idx ];
|
var obj = Dalamud.Objects[ idx ];
|
||||||
_animationLoadData = obj != null ? IdentifyCollection( ( GameObject* )obj.Address ) : ResolveData.Invalid;
|
_animationLoadData = obj != null ? IdentifyCollection( ( GameObject* )obj.Address, true ) : ResolveData.Invalid;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -165,7 +165,7 @@ public unsafe partial class PathResolver
|
||||||
private ulong LoadSomeAvfxDetour( uint a1, IntPtr gameObject, IntPtr gameObject2, float unk1, IntPtr unk2, IntPtr unk3 )
|
private ulong LoadSomeAvfxDetour( uint a1, IntPtr gameObject, IntPtr gameObject2, float unk1, IntPtr unk2, IntPtr unk3 )
|
||||||
{
|
{
|
||||||
var last = _animationLoadData;
|
var last = _animationLoadData;
|
||||||
_animationLoadData = IdentifyCollection( ( GameObject* )gameObject );
|
_animationLoadData = IdentifyCollection( ( GameObject* )gameObject, true );
|
||||||
var ret = _loadSomeAvfxHook.Original( a1, gameObject, gameObject2, unk1, unk2, unk3 );
|
var ret = _loadSomeAvfxHook.Original( a1, gameObject, gameObject2, unk1, unk2, unk3 );
|
||||||
_animationLoadData = last;
|
_animationLoadData = last;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -187,7 +187,7 @@ public unsafe partial class PathResolver
|
||||||
var actorIdx = ( int )( *( *( ulong** )timelinePtr + 1 ) >> 3 );
|
var actorIdx = ( int )( *( *( ulong** )timelinePtr + 1 ) >> 3 );
|
||||||
if( actorIdx >= 0 && actorIdx < Dalamud.Objects.Length )
|
if( actorIdx >= 0 && actorIdx < Dalamud.Objects.Length )
|
||||||
{
|
{
|
||||||
_animationLoadData = IdentifyCollection( ( GameObject* )( Dalamud.Objects[ actorIdx ]?.Address ?? IntPtr.Zero ) );
|
_animationLoadData = IdentifyCollection( ( GameObject* )( Dalamud.Objects[ actorIdx ]?.Address ?? IntPtr.Zero ), true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,7 +202,7 @@ public unsafe partial class PathResolver
|
||||||
private void SomeActionLoadDetour( IntPtr gameObject )
|
private void SomeActionLoadDetour( IntPtr gameObject )
|
||||||
{
|
{
|
||||||
var last = _animationLoadData;
|
var last = _animationLoadData;
|
||||||
_animationLoadData = IdentifyCollection( ( GameObject* )gameObject );
|
_animationLoadData = IdentifyCollection( ( GameObject* )gameObject, true );
|
||||||
_someActionLoadHook.Original( gameObject );
|
_someActionLoadHook.Original( gameObject );
|
||||||
_animationLoadData = last;
|
_animationLoadData = last;
|
||||||
}
|
}
|
||||||
|
|
@ -214,7 +214,7 @@ public unsafe partial class PathResolver
|
||||||
{
|
{
|
||||||
var last = _animationLoadData;
|
var last = _animationLoadData;
|
||||||
var gameObject = ( GameObject* )( unk - 0x8D0 );
|
var gameObject = ( GameObject* )( unk - 0x8D0 );
|
||||||
_animationLoadData = IdentifyCollection( gameObject );
|
_animationLoadData = IdentifyCollection( gameObject, true );
|
||||||
_someOtherAvfxHook.Original( unk );
|
_someOtherAvfxHook.Original( unk );
|
||||||
_animationLoadData = last;
|
_animationLoadData = last;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ public unsafe partial class PathResolver
|
||||||
{
|
{
|
||||||
if( parentObject == IntPtr.Zero && LastGameObject != null )
|
if( parentObject == IntPtr.Zero && LastGameObject != null )
|
||||||
{
|
{
|
||||||
var collection = IdentifyCollection( LastGameObject );
|
var collection = IdentifyCollection( LastGameObject, true );
|
||||||
_drawObjectToObject[ drawObject ] = ( collection, LastGameObject->ObjectIndex );
|
_drawObjectToObject[ drawObject ] = ( collection, LastGameObject->ObjectIndex );
|
||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
|
|
@ -86,6 +86,7 @@ public unsafe partial class PathResolver
|
||||||
_weaponReloadHook.Enable();
|
_weaponReloadHook.Enable();
|
||||||
InitializeDrawObjects();
|
InitializeDrawObjects();
|
||||||
Penumbra.CollectionManager.CollectionChanged += CheckCollections;
|
Penumbra.CollectionManager.CollectionChanged += CheckCollections;
|
||||||
|
Penumbra.TempMods.CollectionChanged += CheckCollections;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Disable()
|
public void Disable()
|
||||||
|
|
@ -95,6 +96,7 @@ public unsafe partial class PathResolver
|
||||||
_enableDrawHook.Disable();
|
_enableDrawHook.Disable();
|
||||||
_weaponReloadHook.Disable();
|
_weaponReloadHook.Disable();
|
||||||
Penumbra.CollectionManager.CollectionChanged -= CheckCollections;
|
Penumbra.CollectionManager.CollectionChanged -= CheckCollections;
|
||||||
|
Penumbra.TempMods.CollectionChanged -= CheckCollections;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|
@ -139,7 +141,7 @@ public unsafe partial class PathResolver
|
||||||
var meta = DisposableContainer.Empty;
|
var meta = DisposableContainer.Empty;
|
||||||
if( LastGameObject != null )
|
if( LastGameObject != null )
|
||||||
{
|
{
|
||||||
_lastCreatedCollection = IdentifyCollection( LastGameObject );
|
_lastCreatedCollection = IdentifyCollection( LastGameObject, false );
|
||||||
// Change the transparent or 1.0 Decal if necessary.
|
// Change the transparent or 1.0 Decal if necessary.
|
||||||
var decal = new CharacterUtility.DecalReverter( _lastCreatedCollection.ModCollection, UsesDecal( a, c ) );
|
var decal = new CharacterUtility.DecalReverter( _lastCreatedCollection.ModCollection, UsesDecal( a, c ) );
|
||||||
// Change the rsp parameters if necessary.
|
// Change the rsp parameters if necessary.
|
||||||
|
|
@ -235,7 +237,7 @@ public unsafe partial class PathResolver
|
||||||
_drawObjectToObject.Remove( key );
|
_drawObjectToObject.Remove( key );
|
||||||
}
|
}
|
||||||
|
|
||||||
var newCollection = IdentifyCollection( obj );
|
var newCollection = IdentifyCollection( obj, false );
|
||||||
_drawObjectToObject[ key ] = ( newCollection, idx );
|
_drawObjectToObject[ key ] = ( newCollection, idx );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -249,7 +251,7 @@ public unsafe partial class PathResolver
|
||||||
var ptr = ( GameObject* )Dalamud.Objects.GetObjectAddress( i );
|
var ptr = ( GameObject* )Dalamud.Objects.GetObjectAddress( i );
|
||||||
if( ptr != null && ptr->IsCharacter() && ptr->DrawObject != null )
|
if( ptr != null && ptr->IsCharacter() && ptr->DrawObject != null )
|
||||||
{
|
{
|
||||||
_drawObjectToObject[ ( IntPtr )ptr->DrawObject ] = ( IdentifyCollection( ptr ), ptr->ObjectIndex );
|
_drawObjectToObject[ ( IntPtr )ptr->DrawObject ] = ( IdentifyCollection( ptr, false ), ptr->ObjectIndex );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ namespace Penumbra.Interop.Resolver;
|
||||||
public unsafe partial class PathResolver
|
public unsafe partial class PathResolver
|
||||||
{
|
{
|
||||||
// Identify the correct collection for a GameObject by index and name.
|
// Identify the correct collection for a GameObject by index and name.
|
||||||
private static ResolveData IdentifyCollection( GameObject* gameObject )
|
private static ResolveData IdentifyCollection( GameObject* gameObject, bool useCache )
|
||||||
{
|
{
|
||||||
if( gameObject == null )
|
if( gameObject == null )
|
||||||
{
|
{
|
||||||
|
|
@ -26,6 +26,11 @@ public unsafe partial class PathResolver
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if( useCache && IdentifiedCache.TryGetValue( gameObject, out var data ) )
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
// Login screen. Names are populated after actors are drawn,
|
// Login screen. Names are populated after actors are drawn,
|
||||||
// so it is not possible to fetch names from the ui list.
|
// so it is not possible to fetch names from the ui list.
|
||||||
// Actors are also not named. So use Yourself > Players > Racial > Default.
|
// Actors are also not named. So use Yourself > Players > Racial > Default.
|
||||||
|
|
@ -34,7 +39,7 @@ public unsafe partial class PathResolver
|
||||||
var collection = Penumbra.CollectionManager.ByType( CollectionType.Yourself )
|
var collection = Penumbra.CollectionManager.ByType( CollectionType.Yourself )
|
||||||
?? CollectionByAttributes( gameObject )
|
?? CollectionByAttributes( gameObject )
|
||||||
?? Penumbra.CollectionManager.Default;
|
?? Penumbra.CollectionManager.Default;
|
||||||
return collection.ToResolveData( gameObject );
|
return IdentifiedCache.Set( collection, ActorIdentifier.Invalid, gameObject );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -44,7 +49,7 @@ public unsafe partial class PathResolver
|
||||||
?? CollectionByAttributes( gameObject )
|
?? CollectionByAttributes( gameObject )
|
||||||
?? CheckOwnedCollection( identifier, gameObject )
|
?? CheckOwnedCollection( identifier, gameObject )
|
||||||
?? Penumbra.CollectionManager.Default;
|
?? Penumbra.CollectionManager.Default;
|
||||||
return collection.ToResolveData( gameObject );
|
return IdentifiedCache.Set( collection, identifier, gameObject );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch( Exception e )
|
catch( Exception e )
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ using System.Runtime.CompilerServices;
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
using Penumbra.GameData.Enums;
|
|
||||||
using Penumbra.Meta.Manipulations;
|
using Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
namespace Penumbra.Interop.Resolver;
|
namespace Penumbra.Interop.Resolver;
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ public partial class PathResolver : IDisposable
|
||||||
private static readonly CutsceneCharacters Cutscenes = new();
|
private static readonly CutsceneCharacters Cutscenes = new();
|
||||||
private static readonly DrawObjectState DrawObjects = new();
|
private static readonly DrawObjectState DrawObjects = new();
|
||||||
private static readonly BitArray ValidHumanModels;
|
private static readonly BitArray ValidHumanModels;
|
||||||
|
internal static readonly IdentifiedCollectionCache IdentifiedCache = new();
|
||||||
private readonly AnimationState _animations;
|
private readonly AnimationState _animations;
|
||||||
private readonly PathState _paths;
|
private readonly PathState _paths;
|
||||||
private readonly MetaState _meta;
|
private readonly MetaState _meta;
|
||||||
|
|
@ -87,6 +88,7 @@ public partial class PathResolver : IDisposable
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
Cutscenes.Enable();
|
Cutscenes.Enable();
|
||||||
DrawObjects.Enable();
|
DrawObjects.Enable();
|
||||||
|
IdentifiedCache.Enable();
|
||||||
_animations.Enable();
|
_animations.Enable();
|
||||||
_paths.Enable();
|
_paths.Enable();
|
||||||
_meta.Enable();
|
_meta.Enable();
|
||||||
|
|
@ -107,6 +109,7 @@ public partial class PathResolver : IDisposable
|
||||||
_animations.Disable();
|
_animations.Disable();
|
||||||
DrawObjects.Disable();
|
DrawObjects.Disable();
|
||||||
Cutscenes.Disable();
|
Cutscenes.Disable();
|
||||||
|
IdentifiedCache.Disable();
|
||||||
_paths.Disable();
|
_paths.Disable();
|
||||||
_meta.Disable();
|
_meta.Disable();
|
||||||
_materials.Disable();
|
_materials.Disable();
|
||||||
|
|
@ -122,6 +125,7 @@ public partial class PathResolver : IDisposable
|
||||||
_animations.Dispose();
|
_animations.Dispose();
|
||||||
DrawObjects.Dispose();
|
DrawObjects.Dispose();
|
||||||
Cutscenes.Dispose();
|
Cutscenes.Dispose();
|
||||||
|
IdentifiedCache.Dispose();
|
||||||
_meta.Dispose();
|
_meta.Dispose();
|
||||||
_materials.Dispose();
|
_materials.Dispose();
|
||||||
}
|
}
|
||||||
|
|
@ -147,11 +151,11 @@ public partial class PathResolver : IDisposable
|
||||||
if( DrawObjects.LastGameObject != null
|
if( DrawObjects.LastGameObject != null
|
||||||
&& ( DrawObjects.LastGameObject->DrawObject == null || DrawObjects.LastGameObject->DrawObject == ( DrawObject* )drawObject ) )
|
&& ( DrawObjects.LastGameObject->DrawObject == null || DrawObjects.LastGameObject->DrawObject == ( DrawObject* )drawObject ) )
|
||||||
{
|
{
|
||||||
resolveData = IdentifyCollection( DrawObjects.LastGameObject );
|
resolveData = IdentifyCollection( DrawObjects.LastGameObject, true );
|
||||||
return DrawObjects.LastGameObject;
|
return DrawObjects.LastGameObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveData = IdentifyCollection( null );
|
resolveData = IdentifyCollection( null, true );
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
using Penumbra.GameData.Actors;
|
|
||||||
|
|
||||||
namespace Penumbra.UI.Classes;
|
namespace Penumbra.UI.Classes;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ using OtterGui.Raii;
|
||||||
using Penumbra.GameData.Actors;
|
using Penumbra.GameData.Actors;
|
||||||
using Penumbra.GameData.Files;
|
using Penumbra.GameData.Files;
|
||||||
using Penumbra.Interop.Loader;
|
using Penumbra.Interop.Loader;
|
||||||
|
using Penumbra.Interop.Resolver;
|
||||||
using Penumbra.Interop.Structs;
|
using Penumbra.Interop.Structs;
|
||||||
using Penumbra.String;
|
using Penumbra.String;
|
||||||
using CharacterUtility = Penumbra.Interop.CharacterUtility;
|
using CharacterUtility = Penumbra.Interop.CharacterUtility;
|
||||||
|
|
@ -250,6 +251,23 @@ public partial class ConfigWindow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using( var identifiedTree = ImRaii.TreeNode( "Identified Collections" ) )
|
||||||
|
{
|
||||||
|
if( identifiedTree )
|
||||||
|
{
|
||||||
|
using var table = ImRaii.Table( "##PathCollectionsIdentifiedTable", 3, ImGuiTableFlags.SizingFixedFit );
|
||||||
|
if( table )
|
||||||
|
{
|
||||||
|
foreach( var (address, identifier, collection) in PathResolver.IdentifiedCache )
|
||||||
|
{
|
||||||
|
ImGuiUtil.DrawTableColumn( $"0x{address:X}" );
|
||||||
|
ImGuiUtil.DrawTableColumn( identifier.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( collection.Name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
using var cutsceneTree = ImRaii.TreeNode( "Cutscene Actors" );
|
using var cutsceneTree = ImRaii.TreeNode( "Cutscene Actors" );
|
||||||
if( cutsceneTree )
|
if( cutsceneTree )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue