From e6752ade04ef16fbff648763fc875af2c57efdf0 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Thu, 17 Mar 2022 14:03:57 +0100 Subject: [PATCH] More fixes, some cleanup. --- Penumbra.GameData/ByteString/Utf8RelPath.cs | 6 +- .../ByteString/Utf8String.Construction.cs | 2 +- Penumbra/Configuration.cs | 2 - Penumbra/Interop/ObjectReloader.cs | 27 +--- .../Interop/Resolver/PathResolver.Data.cs | 13 +- .../Interop/Resolver/PathResolver.Material.cs | 2 + .../Interop/Resolver/PathResolver.Meta.cs | 19 +-- Penumbra/Interop/Resolver/PathResolver.cs | 6 + Penumbra/Interop/Structs/ResourceHandle.cs | 14 +- Penumbra/Meta/Files/EqdpFile.cs | 4 +- Penumbra/Meta/Files/ImcFile.cs | 4 +- Penumbra/Meta/Files/MetaBaseFile.cs | 12 +- Penumbra/Mods/CollectionManager.cs | 127 ++++++++++-------- Penumbra/Mods/ModManager.cs | 1 + Penumbra/Penumbra.cs | 39 +----- Penumbra/UI/MenuTabs/TabCollections.cs | 8 +- Penumbra/UI/MenuTabs/TabDebug.cs | 104 +------------- .../TabInstalledDetailsManipulations.cs | 112 ++++++--------- Penumbra/UI/MenuTabs/TabResourceManager.cs | 5 +- Penumbra/UI/MenuTabs/TabSettings.cs | 47 +------ 20 files changed, 193 insertions(+), 361 deletions(-) diff --git a/Penumbra.GameData/ByteString/Utf8RelPath.cs b/Penumbra.GameData/ByteString/Utf8RelPath.cs index d03ac745..d0259cc4 100644 --- a/Penumbra.GameData/ByteString/Utf8RelPath.cs +++ b/Penumbra.GameData/ByteString/Utf8RelPath.cs @@ -49,7 +49,7 @@ public readonly struct Utf8RelPath : IEquatable< Utf8RelPath >, IComparable< Utf return true; } - if( !Utf8String.FromString( substring, out var ascii ) || !ascii.IsAscii ) + if( !Utf8String.FromString( substring, out var ascii, true ) || !ascii.IsAscii ) { return false; } @@ -66,7 +66,7 @@ public readonly struct Utf8RelPath : IEquatable< Utf8RelPath >, IComparable< Utf return false; } - var substring = file.FullName[ baseDir.FullName.Length.. ]; + var substring = file.FullName[ (baseDir.FullName.Length + 1).. ]; return FromString( substring, out path ); } @@ -78,7 +78,7 @@ public readonly struct Utf8RelPath : IEquatable< Utf8RelPath >, IComparable< Utf return false; } - var substring = file.FullName[ baseDir.FullName.Length.. ]; + var substring = file.FullName[ (baseDir.FullName.Length + 1).. ]; return FromString( substring, out path ); } diff --git a/Penumbra.GameData/ByteString/Utf8String.Construction.cs b/Penumbra.GameData/ByteString/Utf8String.Construction.cs index 487b1a16..f6c47a8b 100644 --- a/Penumbra.GameData/ByteString/Utf8String.Construction.cs +++ b/Penumbra.GameData/ByteString/Utf8String.Construction.cs @@ -97,7 +97,7 @@ public sealed unsafe partial class Utf8String : IDisposable } Marshal.FreeHGlobal( ( IntPtr )_path ); - GC.RemoveMemoryPressure( Length ); + GC.RemoveMemoryPressure( Length + 1 ); _length = AsciiCheckedFlag | AsciiFlag | AsciiLowerCheckedFlag | AsciiLowerFlag | NullTerminatedFlag; _path = Null.NullBytePtr; _crc32 = 0; diff --git a/Penumbra/Configuration.cs b/Penumbra/Configuration.cs index fbfd7ddc..56be9eb2 100644 --- a/Penumbra/Configuration.cs +++ b/Penumbra/Configuration.cs @@ -31,8 +31,6 @@ public class Configuration : IPluginConfiguration public bool DisableSoundStreaming { get; set; } = true; public bool EnableHttpApi { get; set; } - public bool EnablePlayerWatch { get; set; } = false; - public int WaitFrames { get; set; } = 30; public string ModDirectory { get; set; } = string.Empty; diff --git a/Penumbra/Interop/ObjectReloader.cs b/Penumbra/Interop/ObjectReloader.cs index 5865602d..56a40584 100644 --- a/Penumbra/Interop/ObjectReloader.cs +++ b/Penumbra/Interop/ObjectReloader.cs @@ -2,8 +2,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; -using System.Runtime.InteropServices; -using System.Threading.Tasks; using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.Objects.Types; using Penumbra.GameData.Enums; @@ -16,18 +14,13 @@ public unsafe class ObjectReloader : IDisposable { private delegate void ManipulateDraw( IntPtr actor ); - private const int RenderModeOffset = 0x0104; - private const int UnloadAllRedrawDelay = 250; - private const uint NpcObjectId = unchecked( ( uint )-536870912 ); - public const int GPosePlayerIdx = 201; - public const int GPoseEndIdx = GPosePlayerIdx + 48; + private const uint NpcObjectId = unchecked( ( uint )-536870912 ); + public const int GPosePlayerIdx = 201; + public const int GPoseEndIdx = GPosePlayerIdx + 48; private readonly ModManager _mods; private readonly Queue< (uint actorId, string name, RedrawType s) > _actorIds = new(); - internal int DefaultWaitFrames; - - private int _waitFrames; private int _currentFrame; private bool _changedSettings; private uint _currentObjectId = uint.MaxValue; @@ -46,11 +39,8 @@ public unsafe class ObjectReloader : IDisposable private static delegate*< IntPtr, void > GetEnableDraw( GameObject actor ) => ( ( delegate*< IntPtr, void >** )actor.Address )[ 0 ][ 16 ]; - public ObjectReloader( ModManager mods, int defaultWaitFrames ) - { - _mods = mods; - DefaultWaitFrames = defaultWaitFrames; - } + public ObjectReloader( ModManager mods ) + => _mods = mods; private void ChangeSettings() { @@ -289,13 +279,6 @@ public unsafe class ObjectReloader : IDisposable || Dalamud.Conditions[ ConditionFlag.BetweenAreas ] || Dalamud.Conditions[ ConditionFlag.OccupiedInCutSceneEvent ] ) { - _waitFrames = DefaultWaitFrames; - return; - } - - if( _waitFrames > 0 ) - { - --_waitFrames; return; } diff --git a/Penumbra/Interop/Resolver/PathResolver.Data.cs b/Penumbra/Interop/Resolver/PathResolver.Data.cs index 3df5bd1c..229d6380 100644 --- a/Penumbra/Interop/Resolver/PathResolver.Data.cs +++ b/Penumbra/Interop/Resolver/PathResolver.Data.cs @@ -68,10 +68,12 @@ public unsafe partial class PathResolver CharacterBaseCreateHook?.Enable(); EnableDrawHook?.Enable(); CharacterBaseDestructorHook?.Enable(); + Penumbra.ModManager.Collections.CollectionChanged += CheckCollections; } private void DisableDataHooks() { + Penumbra.ModManager.Collections.CollectionChanged -= CheckCollections; CharacterBaseCreateHook?.Disable(); EnableDrawHook?.Disable(); CharacterBaseDestructorHook?.Disable(); @@ -178,8 +180,13 @@ public unsafe partial class PathResolver } // Update collections linked to Game/DrawObjects due to a change in collection configuration. - private void CheckCollections() + private void CheckCollections( ModCollection? _1, ModCollection? _2, CollectionType type, string? name ) { + if( type is not (CollectionType.Character or CollectionType.Default) ) + { + return; + } + foreach( var (key, (_, idx)) in DrawObjectToObject.ToArray() ) { if( !VerifyEntry( key, idx, out var obj ) ) @@ -187,8 +194,8 @@ public unsafe partial class PathResolver DrawObjectToObject.Remove( key ); } - var collection = IdentifyCollection( obj ); - DrawObjectToObject[ key ] = ( collection, idx ); + var newCollection = IdentifyCollection( obj ); + DrawObjectToObject[ key ] = ( newCollection, idx ); } } diff --git a/Penumbra/Interop/Resolver/PathResolver.Material.cs b/Penumbra/Interop/Resolver/PathResolver.Material.cs index 8afffdba..8fde48cc 100644 --- a/Penumbra/Interop/Resolver/PathResolver.Material.cs +++ b/Penumbra/Interop/Resolver/PathResolver.Material.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using Dalamud.Hooking; using Dalamud.Utility.Signatures; using Penumbra.GameData.ByteString; @@ -64,6 +65,7 @@ public unsafe partial class PathResolver var mtrlPath = Utf8String.FromSpanUnsafe( mtrl->Handle.FileNameSpan(), true, null, true ); var collection = PathCollections.TryGetValue( mtrlPath, out var c ) ? c : null; + var x = PathCollections.ToList(); for( var i = 0; i < mtrl->NumTex; ++i ) { var texString = new Utf8String( mtrl->TexString( i ) ); diff --git a/Penumbra/Interop/Resolver/PathResolver.Meta.cs b/Penumbra/Interop/Resolver/PathResolver.Meta.cs index bd843982..f92750e9 100644 --- a/Penumbra/Interop/Resolver/PathResolver.Meta.cs +++ b/Penumbra/Interop/Resolver/PathResolver.Meta.cs @@ -92,16 +92,17 @@ public unsafe partial class PathResolver } } - // GMP - public delegate void ApplyVisorDelegate( IntPtr drawObject, IntPtr unk1, float unk2, IntPtr unk3, ushort unk4, char unk5 ); + // GMP. This gets called every time when changing visor state, and it accesses the gmp file itself, + // but it only applies a changed gmp file after a redraw for some reason. + public delegate byte SetupVisorDelegate( IntPtr drawObject, ushort modelId, byte visorState ); - [Signature( "48 8B ?? 53 55 57 48 83 ?? ?? 48 8B", DetourName = "ApplyVisorDetour" )] - public Hook< ApplyVisorDelegate >? ApplyVisorHook; + [Signature( "48 8B ?? 53 55 57 48 83 ?? ?? 48 8B", DetourName = "SetupVisorDetour" )] + public Hook< SetupVisorDelegate >? SetupVisorHook; - private void ApplyVisorDetour( IntPtr drawObject, IntPtr unk1, float unk2, IntPtr unk3, ushort unk4, char unk5 ) + private byte SetupVisorDetour( IntPtr drawObject, ushort modelId, byte visorState ) { using var gmp = MetaChanger.ChangeGmp( this, drawObject ); - ApplyVisorHook!.Original( drawObject, unk1, unk2, unk3, unk4, unk5 ); + return SetupVisorHook!.Original( drawObject, modelId, visorState ); } // RSP @@ -132,7 +133,7 @@ public unsafe partial class PathResolver OnModelLoadCompleteHook?.Enable(); #endif #if USE_GMP - ApplyVisorHook?.Enable(); + SetupVisorHook?.Enable(); #endif #if USE_CMP RspSetupCharacterHook?.Enable(); @@ -144,7 +145,7 @@ public unsafe partial class PathResolver GetEqpIndirectHook?.Disable(); UpdateModelsHook?.Disable(); OnModelLoadCompleteHook?.Disable(); - ApplyVisorHook?.Disable(); + SetupVisorHook?.Disable(); RspSetupCharacterHook?.Disable(); } @@ -153,7 +154,7 @@ public unsafe partial class PathResolver GetEqpIndirectHook?.Dispose(); UpdateModelsHook?.Dispose(); OnModelLoadCompleteHook?.Dispose(); - ApplyVisorHook?.Dispose(); + SetupVisorHook?.Dispose(); RspSetupCharacterHook?.Dispose(); } diff --git a/Penumbra/Interop/Resolver/PathResolver.cs b/Penumbra/Interop/Resolver/PathResolver.cs index da0ae9b1..894727d4 100644 --- a/Penumbra/Interop/Resolver/PathResolver.cs +++ b/Penumbra/Interop/Resolver/PathResolver.cs @@ -49,6 +49,12 @@ public partial class PathResolver : IDisposable resolved = Penumbra.ModManager.Collections.ForcedCollection.ResolveSwappedOrReplacementPath( gamePath ); if( resolved == null ) { + // We also need to handle defaulted materials against a non-default collection. + if( nonDefault && gamePath.Path.EndsWith( 'm', 't', 'r', 'l' ) ) + { + SetCollection( gamePath.Path, collection ); + } + return ( null, collection ); } diff --git a/Penumbra/Interop/Structs/ResourceHandle.cs b/Penumbra/Interop/Structs/ResourceHandle.cs index 6ed2cc8e..9493a2eb 100644 --- a/Penumbra/Interop/Structs/ResourceHandle.cs +++ b/Penumbra/Interop/Structs/ResourceHandle.cs @@ -37,19 +37,31 @@ public unsafe struct ResourceHandle public ReadOnlySpan< byte > FileNameSpan() => new(FileName(), FileNameLength); + [FieldOffset( 0x00 )] + public void** VTable; + [FieldOffset( 0x48 )] public byte* FileNameData; [FieldOffset( 0x58 )] public int FileNameLength; + // May return null. + public static byte* GetData( ResourceHandle* handle ) + => ( ( delegate*< ResourceHandle*, byte* > )handle->VTable[ 23 ] )( handle ); + + public static ulong GetLength( ResourceHandle* handle ) + => ( ( delegate*< ResourceHandle*, ulong > )handle->VTable[ 17 ] )( handle ); + + + // Only use these if you know what you are doing. + // Those are actually only sure to be accessible for DefaultResourceHandles. [FieldOffset( 0xB0 )] public DataIndirection* Data; [FieldOffset( 0xB8 )] public uint DataLength; - public (IntPtr Data, int Length) GetData() => Data != null ? ( ( IntPtr )Data->DataPtr, ( int )Data->DataLength ) diff --git a/Penumbra/Meta/Files/EqdpFile.cs b/Penumbra/Meta/Files/EqdpFile.cs index 053d83f0..6d4ebe8d 100644 --- a/Penumbra/Meta/Files/EqdpFile.cs +++ b/Penumbra/Meta/Files/EqdpFile.cs @@ -121,7 +121,7 @@ public sealed unsafe class ExpandedEqdpFile : MetaBaseFile public static EqdpEntry GetDefault( int fileIdx, int setIdx ) { - var data = ( byte* )Penumbra.CharacterUtility.DefaultResources[ fileIdx ].Address; + var data = ( byte* )Penumbra.CharacterUtility.DefaultResource( fileIdx ).Address; var blockSize = *( ushort* )( data + IdentifierSize ); var totalBlockCount = *( ushort* )( data + IdentifierSize + 2 ); @@ -139,7 +139,7 @@ public sealed unsafe class ExpandedEqdpFile : MetaBaseFile var blockData = ( ushort* )( data + IdentifierSize + PreambleSize + totalBlockCount * 2 + block * 2 ); var x = new ReadOnlySpan< ushort >( blockData, blockSize ); - return (EqdpEntry) (*( blockData + setIdx % blockSize )); + return ( EqdpEntry )( *( blockData + setIdx % blockSize ) ); } public static EqdpEntry GetDefault( GenderRace raceCode, bool accessory, int setIdx ) diff --git a/Penumbra/Meta/Files/ImcFile.cs b/Penumbra/Meta/Files/ImcFile.cs index 35e53d66..f3ce0a4a 100644 --- a/Penumbra/Meta/Files/ImcFile.cs +++ b/Penumbra/Meta/Files/ImcFile.cs @@ -201,7 +201,9 @@ public unsafe class ImcFile : MetaBaseFile var file = Dalamud.GameData.GetFile( path.ToString() ); if( file == null ) { - throw new Exception(); + throw new Exception( + "Could not obtain default Imc File.\n" + + "Either the default file does not exist (possibly for offhand files from TexTools) or the installation is corrupted." ); } fixed( byte* ptr = file.Data ) diff --git a/Penumbra/Meta/Files/MetaBaseFile.cs b/Penumbra/Meta/Files/MetaBaseFile.cs index c566cd16..1d24cfb4 100644 --- a/Penumbra/Meta/Files/MetaBaseFile.cs +++ b/Penumbra/Meta/Files/MetaBaseFile.cs @@ -24,8 +24,10 @@ public unsafe class MetaBaseFile : IDisposable { Length = length; Data = ( byte* )MemoryHelper.GameAllocateDefault( ( ulong )length ); - ; - GC.AddMemoryPressure( length ); + if( length > 0 ) + { + GC.AddMemoryPressure( length ); + } } // Free memory. @@ -33,7 +35,11 @@ public unsafe class MetaBaseFile : IDisposable { var ptr = ( IntPtr )Data; MemoryHelper.GameFree( ref ptr, ( ulong )Length ); - GC.RemoveMemoryPressure( Length ); + if( Length > 0 ) + { + GC.RemoveMemoryPressure( Length ); + } + Length = 0; Data = null; } diff --git a/Penumbra/Mods/CollectionManager.cs b/Penumbra/Mods/CollectionManager.cs index bf52a347..fa3835da 100644 --- a/Penumbra/Mods/CollectionManager.cs +++ b/Penumbra/Mods/CollectionManager.cs @@ -1,14 +1,24 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; using Dalamud.Logging; -using Penumbra.Interop.Structs; using Penumbra.Mod; using Penumbra.Util; namespace Penumbra.Mods; +public enum CollectionType : byte +{ + Inactive, + Default, + Forced, + Character, + Current, +} + +public delegate void CollectionChangeDelegate( ModCollection? oldCollection, ModCollection? newCollection, CollectionType type, + string? characterName = null ); + // Contains all collections and respective functions, as well as the collection settings. public class CollectionManager { @@ -21,7 +31,10 @@ public class CollectionManager public ModCollection CurrentCollection { get; private set; } = ModCollection.Empty; public ModCollection DefaultCollection { get; private set; } = ModCollection.Empty; public ModCollection ForcedCollection { get; private set; } = ModCollection.Empty; - public ModCollection ActiveCollection { get; private set; } + public ModCollection ActiveCollection { get; private set; } = ModCollection.Empty; + + // Is invoked after the collections actually changed. + public event CollectionChangeDelegate? CollectionChanged; public CollectionManager( ModManager manager ) { @@ -29,7 +42,7 @@ public class CollectionManager ReadCollections(); LoadConfigCollections( Penumbra.Config ); - ActiveCollection = DefaultCollection; + SetActiveCollection( DefaultCollection, string.Empty ); } public bool SetActiveCollection( ModCollection newActive, string name ) @@ -44,14 +57,7 @@ public class CollectionManager { ActiveCollection = newActive; Penumbra.ResidentResources.Reload(); - if( ActiveCollection.Cache == null ) - { - Penumbra.CharacterUtility.ResetAll(); - } - else - { - ActiveCollection.Cache.MetaManipulations.SetFiles(); - } + ActiveCollection.SetFiles(); } else { @@ -131,8 +137,9 @@ public class CollectionManager var newCollection = new ModCollection( name, settings ); Collections.Add( name, newCollection ); + CollectionChanged?.Invoke( null, newCollection, CollectionType.Inactive ); newCollection.Save(); - SetCurrentCollection( newCollection ); + SetCollection( newCollection, CollectionType.Current ); return true; } @@ -149,26 +156,27 @@ public class CollectionManager return false; } + CollectionChanged?.Invoke( collection, null, CollectionType.Inactive ); if( CurrentCollection == collection ) { - SetCurrentCollection( Collections[ ModCollection.DefaultCollection ] ); + SetCollection( Collections[ ModCollection.DefaultCollection ], CollectionType.Current ); } if( ForcedCollection == collection ) { - SetForcedCollection( ModCollection.Empty ); + SetCollection( ModCollection.Empty, CollectionType.Forced ); } if( DefaultCollection == collection ) { - SetDefaultCollection( ModCollection.Empty ); + SetCollection( ModCollection.Empty, CollectionType.Default ); } foreach( var (characterName, characterCollection) in CharacterCollection.ToArray() ) { if( characterCollection == collection ) { - SetCharacterCollection( characterName, ModCollection.Empty ); + SetCollection( ModCollection.Empty, CollectionType.Character, characterName ); } } @@ -196,51 +204,63 @@ public class CollectionManager } } - private void SetCollection( ModCollection newCollection, ModCollection oldCollection, Action< ModCollection > setter, - Action< string > configSetter ) + public void SetCollection( ModCollection newCollection, CollectionType type, string? characterName = null ) { - if( newCollection.Name == oldCollection.Name ) + var oldCollection = type switch + { + CollectionType.Default => DefaultCollection, + CollectionType.Forced => ForcedCollection, + CollectionType.Current => CurrentCollection, + CollectionType.Character => characterName?.Length > 0 + ? CharacterCollection.TryGetValue( characterName, out var c ) + ? c + : ModCollection.Empty + : null, + _ => null, + }; + + if( oldCollection == null || newCollection.Name == oldCollection.Name ) { return; } AddCache( newCollection ); - - setter( newCollection ); RemoveCache( oldCollection ); - configSetter( newCollection.Name ); - Penumbra.Config.Save(); - } - - public void SetDefaultCollection( ModCollection newCollection ) - => SetCollection( newCollection, DefaultCollection, c => + switch( type ) { - if( CollectionChangedTo.Length == 0 ) - { - SetActiveCollection( c, string.Empty ); - } - - DefaultCollection = c; - }, s => Penumbra.Config.DefaultCollection = s ); - - public void SetForcedCollection( ModCollection newCollection ) - => SetCollection( newCollection, ForcedCollection, c => ForcedCollection = c, s => Penumbra.Config.ForcedCollection = s ); - - public void SetCurrentCollection( ModCollection newCollection ) - => SetCollection( newCollection, CurrentCollection, c => CurrentCollection = c, s => Penumbra.Config.CurrentCollection = s ); - - public void SetCharacterCollection( string characterName, ModCollection newCollection ) - => SetCollection( newCollection, - CharacterCollection.TryGetValue( characterName, out var oldCollection ) ? oldCollection : ModCollection.Empty, - c => - { - if( CollectionChangedTo == characterName && CharacterCollection.TryGetValue( characterName, out var collection ) ) + case CollectionType.Default: + DefaultCollection = newCollection; + Penumbra.Config.DefaultCollection = newCollection.Name; + if( CollectionChangedTo.Length == 0 ) { - SetActiveCollection( c, CollectionChangedTo ); + SetActiveCollection( newCollection, string.Empty ); } - CharacterCollection[ characterName ] = c; - }, s => Penumbra.Config.CharacterCollections[ characterName ] = s ); + break; + case CollectionType.Forced: + ForcedCollection = newCollection; + Penumbra.Config.ForcedCollection = newCollection.Name; + break; + case CollectionType.Current: + CurrentCollection = newCollection; + Penumbra.Config.CurrentCollection = newCollection.Name; + break; + case CollectionType.Character: + if( CollectionChangedTo == characterName && CharacterCollection.ContainsKey( characterName ) ) + { + SetActiveCollection( newCollection, CollectionChangedTo ); + } + + CharacterCollection[ characterName! ] = newCollection; + Penumbra.Config.CharacterCollections[ characterName! ] = newCollection.Name; + + break; + } + + CollectionChanged?.Invoke( oldCollection, newCollection, type, characterName ); + + Penumbra.Config.Save(); + } public bool CreateCharacterCollection( string characterName ) { @@ -252,7 +272,7 @@ public class CollectionManager CharacterCollection[ characterName ] = ModCollection.Empty; Penumbra.Config.CharacterCollections[ characterName ] = string.Empty; Penumbra.Config.Save(); - Penumbra.PlayerWatcher.AddPlayerToWatch( characterName ); + CollectionChanged?.Invoke( null, ModCollection.Empty, CollectionType.Character, characterName ); return true; } @@ -262,7 +282,7 @@ public class CollectionManager { RemoveCache( collection ); CharacterCollection.Remove( characterName ); - Penumbra.PlayerWatcher.RemovePlayerFromWatch( characterName ); + CollectionChanged?.Invoke( collection, null, CollectionType.Character, characterName ); } if( Penumbra.Config.CharacterCollections.Remove( characterName ) ) @@ -338,7 +358,6 @@ public class CollectionManager var configChanged = false; foreach( var (player, collectionName) in config.CharacterCollections.ToArray() ) { - Penumbra.PlayerWatcher.AddPlayerToWatch( player ); if( collectionName.Length == 0 ) { CharacterCollection.Add( player, ModCollection.Empty ); diff --git a/Penumbra/Mods/ModManager.cs b/Penumbra/Mods/ModManager.cs index 4538fa85..4a7ba3bd 100644 --- a/Penumbra/Mods/ModManager.cs +++ b/Penumbra/Mods/ModManager.cs @@ -146,6 +146,7 @@ public class ModManager } Collections.RecreateCaches(); + Collections.DefaultCollection.SetFiles(); } public void DeleteMod( DirectoryInfo modFolder ) diff --git a/Penumbra/Penumbra.cs b/Penumbra/Penumbra.cs index cc9cc5e2..a487b7f9 100644 --- a/Penumbra/Penumbra.cs +++ b/Penumbra/Penumbra.cs @@ -34,7 +34,6 @@ public class Penumbra : IDalamudPlugin private const string CommandName = "/penumbra"; public static Configuration Config { get; private set; } = null!; - public static IPlayerWatcher PlayerWatcher { get; private set; } = null!; public static ResidentResourceManager ResidentResources { get; private set; } = null!; public static CharacterUtility CharacterUtility { get; private set; } = null!; @@ -72,10 +71,9 @@ public class Penumbra : IDalamudPlugin MetaDefaults = new MetaDefaults(); ResourceLoader = new ResourceLoader( this ); ResourceLogger = new ResourceLogger( ResourceLoader ); - PlayerWatcher = PlayerWatchFactory.Create( Dalamud.Framework, Dalamud.ClientState, Dalamud.Objects ); ModManager = new ModManager(); ModManager.DiscoverMods(); - ObjectReloader = new ObjectReloader( ModManager, Config.WaitFrames ); + ObjectReloader = new ObjectReloader( ModManager ); PathResolver = new PathResolver( ResourceLoader ); Dalamud.Commands.AddHandler( CommandName, new CommandInfo( OnCommand ) @@ -101,17 +99,6 @@ public class Penumbra : IDalamudPlugin CreateWebServer(); } - if( !Config.EnablePlayerWatch || !Config.EnableMods ) - { - PlayerWatcher.Disable(); - } - - PlayerWatcher.PlayerChanged += p => - { - PluginLog.Debug( "Triggered Redraw of {Player}.", p.Name ); - ObjectReloader.RedrawObject( p, RedrawType.OnlyWithSettings ); - }; - ResourceLoader.EnableHooks(); if( Config.EnableMods ) { @@ -127,17 +114,6 @@ public class Penumbra : IDalamudPlugin { ResourceLoader.EnableFullLogging(); } - - unsafe - { - PluginLog.Information( $"MetaManipulation: {sizeof( MetaManipulation )}" ); - PluginLog.Information( $"EqpManipulation: {sizeof( EqpManipulation )}" ); - PluginLog.Information( $"GmpManipulation: {sizeof( GmpManipulation )}" ); - PluginLog.Information( $"EqdpManipulation: {sizeof( EqdpManipulation )}" ); - PluginLog.Information( $"EstManipulation: {sizeof( EstManipulation )}" ); - PluginLog.Information( $"RspManipulation: {sizeof( RspManipulation )}" ); - PluginLog.Information( $"ImcManipulation: {sizeof( ImcManipulation )}" ); - } } public bool Enable() @@ -150,10 +126,6 @@ public class Penumbra : IDalamudPlugin Config.EnableMods = true; ResourceLoader.EnableReplacements(); ResidentResources.Reload(); - if( Config.EnablePlayerWatch ) - { - PlayerWatcher.SetStatus( true ); - } Config.Save(); ObjectReloader.RedrawAll( RedrawType.WithSettings ); @@ -170,10 +142,6 @@ public class Penumbra : IDalamudPlugin Config.EnableMods = false; ResourceLoader.DisableReplacements(); ResidentResources.Reload(); - if( Config.EnablePlayerWatch ) - { - PlayerWatcher.SetStatus( false ); - } Config.Save(); ObjectReloader.RedrawAll( RedrawType.WithoutSettings ); @@ -232,7 +200,6 @@ public class Penumbra : IDalamudPlugin Api.Dispose(); SettingsInterface.Dispose(); ObjectReloader.Dispose(); - PlayerWatcher.Dispose(); Dalamud.Commands.RemoveHandler( CommandName ); @@ -268,7 +235,7 @@ public class Penumbra : IDalamudPlugin return false; } - ModManager.Collections.SetDefaultCollection( collection ); + ModManager.Collections.SetCollection( collection, CollectionType.Default ); Dalamud.Chat.Print( $"Set {collection.Name} as default collection." ); SettingsInterface.ResetDefaultCollection(); return true; @@ -279,7 +246,7 @@ public class Penumbra : IDalamudPlugin return false; } - ModManager.Collections.SetForcedCollection( collection ); + ModManager.Collections.SetCollection( collection, CollectionType.Forced ); Dalamud.Chat.Print( $"Set {collection.Name} as forced collection." ); SettingsInterface.ResetForcedCollection(); return true; diff --git a/Penumbra/UI/MenuTabs/TabCollections.cs b/Penumbra/UI/MenuTabs/TabCollections.cs index c5ce81a3..2b4fa4d8 100644 --- a/Penumbra/UI/MenuTabs/TabCollections.cs +++ b/Penumbra/UI/MenuTabs/TabCollections.cs @@ -169,7 +169,7 @@ public partial class SettingsInterface return; } - Penumbra.ModManager.Collections.SetCurrentCollection( _collections[ idx + 1 ] ); + Penumbra.ModManager.Collections.SetCollection( _collections[ idx + 1 ], CollectionType.Current ); _currentCollectionIndex = idx; _selector.Cache.TriggerListReset(); if( _selector.Mod != null ) @@ -208,7 +208,7 @@ public partial class SettingsInterface ImGui.SetNextItemWidth( SettingsMenu.InputTextWidth ); if( ImGui.Combo( "##Default Collection", ref index, _collectionNamesWithNone ) && index != _currentDefaultIndex ) { - Penumbra.ModManager.Collections.SetDefaultCollection( _collections[ index ] ); + Penumbra.ModManager.Collections.SetCollection( _collections[ index ], CollectionType.Default ); _currentDefaultIndex = index; } @@ -231,7 +231,7 @@ public partial class SettingsInterface && index != _currentForcedIndex && manager.Collections.CharacterCollection.Count > 0 ) { - manager.Collections.SetForcedCollection( _collections[ index ] ); + manager.Collections.SetCollection( _collections[ index ], CollectionType.Forced ); _currentForcedIndex = index; } @@ -352,7 +352,7 @@ public partial class SettingsInterface ImGui.SetNextItemWidth( SettingsMenu.InputTextWidth ); if( ImGui.Combo( $"##{name}collection", ref tmp, _collectionNamesWithNone ) && idx != tmp ) { - manager.Collections.SetCharacterCollection( name, _collections[ tmp ] ); + manager.Collections.SetCollection( _collections[ tmp ], CollectionType.Character, name ); _currentCharacterIndices[ name ] = tmp; } diff --git a/Penumbra/UI/MenuTabs/TabDebug.cs b/Penumbra/UI/MenuTabs/TabDebug.cs index 72c3e86e..b0281631 100644 --- a/Penumbra/UI/MenuTabs/TabDebug.cs +++ b/Penumbra/UI/MenuTabs/TabDebug.cs @@ -22,104 +22,6 @@ namespace Penumbra.UI; public partial class SettingsInterface { - private static void DrawDebugTabPlayers() - { - if( !ImGui.CollapsingHeader( "Players##Debug" ) ) - { - return; - } - - var players = Penumbra.PlayerWatcher.WatchedPlayers().ToArray(); - var count = players.Sum( s => Math.Max( 1, s.Item2.Length ) ); - if( count == 0 ) - { - return; - } - - if( !ImGui.BeginTable( "##ObjectTable", 13, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.ScrollX, - new Vector2( -1, ImGui.GetTextLineHeightWithSpacing() * 4 * count ) ) ) - { - return; - } - - using var raii = ImGuiRaii.DeferredEnd( ImGui.EndTable ); - - var identifier = GameData.GameData.GetIdentifier(); - - foreach( var (actor, equip) in players.SelectMany( kvp => kvp.Item2.Any() - ? kvp.Item2 - .Select( x => ( $"{kvp.Item1} ({x.Item1})", x.Item2 ) ) - : new[] { ( kvp.Item1, new CharacterEquipment() ) } ) ) - { - // @formatter:off - ImGui.TableNextRow(); - ImGui.TableNextColumn(); - ImGui.Text( actor ); - ImGui.TableNextColumn(); - ImGui.Text( $"{equip.MainHand}" ); - ImGui.TableNextColumn(); - ImGui.Text( $"{equip.Head}" ); - ImGui.TableNextColumn(); - ImGui.Text( $"{equip.Body}" ); - ImGui.TableNextColumn(); - ImGui.Text( $"{equip.Hands}" ); - ImGui.TableNextColumn(); - ImGui.Text( $"{equip.Legs}" ); - ImGui.TableNextColumn(); - ImGui.Text( $"{equip.Feet}" ); - - ImGui.TableNextRow(); - ImGui.TableNextColumn(); - if (equip.IsSet == 0) - { - ImGui.Text( "(not set)" ); - } - ImGui.TableNextColumn(); - ImGui.Text( identifier.Identify( equip.MainHand.Set, equip.MainHand.Type, equip.MainHand.Variant, EquipSlot.MainHand )?.Name.ToString() ?? "Unknown" ); - ImGui.TableNextColumn(); - ImGui.Text( identifier.Identify( equip.Head.Set, 0, equip.Head.Variant, EquipSlot.Head )?.Name.ToString() ?? "Unknown" ); - ImGui.TableNextColumn(); - ImGui.Text( identifier.Identify( equip.Body.Set, 0, equip.Body.Variant, EquipSlot.Body )?.Name.ToString() ?? "Unknown" ); - ImGui.TableNextColumn(); - ImGui.Text( identifier.Identify( equip.Hands.Set, 0, equip.Hands.Variant, EquipSlot.Hands )?.Name.ToString() ?? "Unknown" ); - ImGui.TableNextColumn(); - ImGui.Text( identifier.Identify( equip.Legs.Set, 0, equip.Legs.Variant, EquipSlot.Legs )?.Name.ToString() ?? "Unknown" ); - ImGui.TableNextColumn(); - ImGui.Text( identifier.Identify( equip.Feet.Set, 0, equip.Feet.Variant, EquipSlot.Feet )?.Name.ToString() ?? "Unknown" ); - - ImGui.TableNextRow(); - ImGui.TableNextColumn(); - ImGui.TableNextColumn(); - ImGui.Text( $"{equip.OffHand}" ); - ImGui.TableNextColumn(); - ImGui.Text( $"{equip.Ears}" ); - ImGui.TableNextColumn(); - ImGui.Text( $"{equip.Neck}" ); - ImGui.TableNextColumn(); - ImGui.Text( $"{equip.Wrists}" ); - ImGui.TableNextColumn(); - ImGui.Text( $"{equip.LFinger}" ); - ImGui.TableNextColumn(); - ImGui.Text( $"{equip.RFinger}" ); - - ImGui.TableNextRow(); - ImGui.TableNextColumn(); - ImGui.TableNextColumn(); - ImGui.Text( identifier.Identify( equip.OffHand.Set, equip.OffHand.Type, equip.OffHand.Variant, EquipSlot.OffHand )?.Name.ToString() ?? "Unknown" ); - ImGui.TableNextColumn(); - ImGui.Text( identifier.Identify( equip.Ears.Set, 0, equip.Ears.Variant, EquipSlot.Ears )?.Name.ToString() ?? "Unknown" ); - ImGui.TableNextColumn(); - ImGui.Text( identifier.Identify( equip.Neck.Set, 0, equip.Neck.Variant, EquipSlot.Neck )?.Name.ToString() ?? "Unknown" ); - ImGui.TableNextColumn(); - ImGui.Text( identifier.Identify( equip.Wrists.Set, 0, equip.Wrists.Variant, EquipSlot.Wrists )?.Name.ToString() ?? "Unknown" ); - ImGui.TableNextColumn(); - ImGui.Text( identifier.Identify( equip.LFinger.Set, 0, equip.LFinger.Variant, EquipSlot.LFinger )?.Name.ToString() ?? "Unknown" ); - ImGui.TableNextColumn(); - ImGui.Text( identifier.Identify( equip.RFinger.Set, 0, equip.RFinger.Variant, EquipSlot.LFinger )?.Name.ToString() ?? "Unknown" ); - // @formatter:on - } - } - private static void PrintValue( string name, string value ) { ImGui.TableNextRow(); @@ -431,8 +333,8 @@ public partial class SettingsInterface { var def = ExpandedGmpFile.GetDefault( gmp ); var val = Penumbra.ModManager.Collections.ActiveCollection.Cache?.MetaManipulations.Gmp.File?[ gmp ] ?? def; - ImGui.Text( def.Value.ToString("X") ); - ImGui.Text( val.Value.ToString("X") ); + ImGui.Text( def.Value.ToString( "X" ) ); + ImGui.Text( val.Value.ToString( "X" ) ); } catch { } @@ -557,8 +459,6 @@ public partial class SettingsInterface ImGui.NewLine(); DrawDebugTabRedraw(); ImGui.NewLine(); - DrawDebugTabPlayers(); - ImGui.NewLine(); DrawDebugTabIpc(); ImGui.NewLine(); } diff --git a/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledDetailsManipulations.cs b/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledDetailsManipulations.cs index 3e545e34..a61f6e90 100644 --- a/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledDetailsManipulations.cs +++ b/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledDetailsManipulations.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; -using System.Drawing.Text; +using System.ComponentModel; using System.Linq; using System.Numerics; -using System.Runtime.CompilerServices; using Dalamud.Interface; using ImGuiNET; -using Lumina.Excel.GeneratedSheets; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; using Penumbra.Meta.Files; @@ -77,22 +75,12 @@ public partial class SettingsInterface ( Gender.FemaleNpc.ToName(), Gender.FemaleNpc ), }; - private static readonly (string, ObjectType)[] ObjectTypes = + private static readonly (string, EstManipulation.EstType)[] EstTypes = { - ( "Equipment", ObjectType.Equipment ), - ( "Customization", ObjectType.Character ), - }; - - private static readonly (string, EquipSlot)[] EstEquipSlots = - { - EqpEquipSlots[ 0 ], - EqpEquipSlots[ 1 ], - }; - - private static readonly (string, BodySlot)[] EstBodySlots = - { - ( "Hair", BodySlot.Hair ), - ( "Face", BodySlot.Face ), + ( "Hair", EstManipulation.EstType.Hair ), + ( "Face", EstManipulation.EstType.Face ), + ( "Body", EstManipulation.EstType.Body ), + ( "Head", EstManipulation.EstType.Head ), }; private static readonly (string, SubRace)[] Subraces = @@ -133,9 +121,11 @@ public partial class SettingsInterface ( RspAttribute.FemaleMaxTail.ToFullString(), RspAttribute.FemaleMaxTail ), }; + private static readonly (string, ObjectType)[] ImcObjectType = { - ObjectTypes[ 0 ], + ( "Equipment", ObjectType.Equipment ), + ( "Customization", ObjectType.Character ), ( "Weapon", ObjectType.Weapon ), ( "Demihuman", ObjectType.DemiHuman ), ( "Monster", ObjectType.Monster ), @@ -143,8 +133,8 @@ public partial class SettingsInterface private static readonly (string, BodySlot)[] ImcBodySlots = { - EstBodySlots[ 0 ], - EstBodySlots[ 1 ], + ( "Hair", BodySlot.Hair ), + ( "Face", BodySlot.Face ), ( "Body", BodySlot.Body ), ( "Tail", BodySlot.Tail ), ( "Ears", BodySlot.Zear ), @@ -646,24 +636,26 @@ public partial class SettingsInterface RestrictedInputInt( "Set Id##newManipImc", ref _newManipSetId, 0, ushort.MaxValue ); RestrictedInputInt( "Variant##newManipImc", ref _newManipVariant, 0, byte.MaxValue ); CustomCombo( "Object Type", ImcObjectType, out var objectType, ref _newManipObjectType ); - EquipSlot equipSlot = default; + ImcManipulation imc = new(); switch( objectType ) { case ObjectType.Equipment: - CustomCombo( "Equipment Slot", EqdpEquipSlots, out equipSlot, ref _newManipEquipSlot ); - //newManip = MetaManipulation.Imc( equipSlot, _newManipSetId, _newManipVariant, - // new ImcFile.ImageChangeData() ); + CustomCombo( "Equipment Slot", EqdpEquipSlots, out var equipSlot, ref _newManipEquipSlot ); + imc = new ImcManipulation( equipSlot, _newManipVariant, _newManipSetId, new ImcEntry() ); break; case ObjectType.DemiHuman: case ObjectType.Weapon: case ObjectType.Monster: RestrictedInputInt( "Secondary Id##newManipImc", ref _newManipSecondaryId, 0, ushort.MaxValue ); CustomCombo( "Body Slot", ImcBodySlots, out var bodySlot, ref _newManipBodySlot ); - //newManip = MetaManipulation.Imc( objectType, bodySlot, _newManipSetId, _newManipSecondaryId, - // _newManipVariant, new ImcFile.ImageChangeData() ); + imc = new ImcManipulation( objectType, bodySlot, _newManipSetId, _newManipSecondaryId, + _newManipVariant, new ImcEntry() ); break; } + newManip = new MetaManipulation( new ImcManipulation( imc.ObjectType, imc.BodySlot, imc.PrimaryId, imc.SecondaryId, + imc.Variant, imc.EquipSlot, ImcFile.GetDefault( imc.GamePath(), imc.EquipSlot, imc.Variant ) ) ); + break; } case MetaManipulation.Type.Eqdp: @@ -672,76 +664,50 @@ public partial class SettingsInterface CustomCombo( "Equipment Slot", EqdpEquipSlots, out var equipSlot, ref _newManipEquipSlot ); CustomCombo( "Race", Races, out var race, ref _newManipRace ); CustomCombo( "Gender", Genders, out var gender, ref _newManipGender ); - //newManip = MetaManipulation.Eqdp( equipSlot, Names.CombinedRace( gender, race ), ( ushort )_newManipSetId, - // new EqdpEntry() ); + var eqdp = new EqdpManipulation( new EqdpEntry(), equipSlot, gender, race, _newManipSetId ); + newManip = new MetaManipulation( new EqdpManipulation( ExpandedEqdpFile.GetDefault( eqdp.FileIndex(), eqdp.SetId ), + equipSlot, gender, race, _newManipSetId ) ); break; } case MetaManipulation.Type.Eqp: { RestrictedInputInt( "Set Id##newManipEqp", ref _newManipSetId, 0, ushort.MaxValue ); CustomCombo( "Equipment Slot", EqpEquipSlots, out var equipSlot, ref _newManipEquipSlot ); - //newManip = MetaManipulation.Eqp( equipSlot, ( ushort )_newManipSetId, 0 ); + newManip = new MetaManipulation( new EqpManipulation( ExpandedEqpFile.GetDefault( _newManipSetId ) & Eqp.Mask( equipSlot ), + equipSlot, _newManipSetId ) ); break; } case MetaManipulation.Type.Est: { RestrictedInputInt( "Set Id##newManipEst", ref _newManipSetId, 0, ushort.MaxValue ); - CustomCombo( "Object Type", ObjectTypes, out var objectType, ref _newManipObjectType ); - EquipSlot equipSlot = default; - BodySlot bodySlot = default; - switch( ( ObjectType )_newManipObjectType ) - { - case ObjectType.Equipment: - CustomCombo( "Equipment Slot", EstEquipSlots, out equipSlot, ref _newManipEquipSlot ); - break; - case ObjectType.Character: - CustomCombo( "Body Slot", EstBodySlots, out bodySlot, ref _newManipBodySlot ); - break; - } - + CustomCombo( "Est Type", EstTypes, out var estType, ref _newManipObjectType ); CustomCombo( "Race", Races, out var race, ref _newManipRace ); CustomCombo( "Gender", Genders, out var gender, ref _newManipGender ); - //newManip = MetaManipulation.Est( objectType, equipSlot, Names.CombinedRace( gender, race ), bodySlot, - // ( ushort )_newManipSetId, 0 ); + newManip = new MetaManipulation( new EstManipulation( gender, race, estType, _newManipSetId, + EstFile.GetDefault( estType, Names.CombinedRace( gender, race ), _newManipSetId ) ) ); break; } case MetaManipulation.Type.Gmp: RestrictedInputInt( "Set Id##newManipGmp", ref _newManipSetId, 0, ushort.MaxValue ); - //newManip = MetaManipulation.Gmp( ( ushort )_newManipSetId, new GmpEntry() ); + newManip = new MetaManipulation( new GmpManipulation( ExpandedGmpFile.GetDefault( _newManipSetId ), _newManipSetId ) ); break; case MetaManipulation.Type.Rsp: CustomCombo( "Subrace", Subraces, out var subRace, ref _newManipSubrace ); CustomCombo( "Attribute", RspAttributes, out var rspAttribute, ref _newManipAttribute ); - //newManip = MetaManipulation.Rsp( subRace, rspAttribute, 1f ); + newManip = new MetaManipulation( new RspManipulation( subRace, rspAttribute, + CmpFile.GetDefault( subRace, rspAttribute ) ) ); break; } - //if( ImGui.Button( "Create Manipulation##newManip", Vector2.UnitX * -1 ) - // && newManip != null - // && list.All( m => m.Identifier != newManip.Value.Identifier ) ) - //{ - // var def = Penumbra.MetaDefaults.GetDefaultValue( newManip.Value ); - // if( def != null ) - // { - // var manip = newManip.Value.Type switch - // { - // MetaType.Est => new MetaManipulation( newManip.Value.Identifier, ( ulong )def ), - // MetaType.Eqp => new MetaManipulation( newManip.Value.Identifier, ( ulong )def ), - // MetaType.Eqdp => new MetaManipulation( newManip.Value.Identifier, (ushort) def ), - // MetaType.Gmp => new MetaManipulation( newManip.Value.Identifier, ( ulong )def ), - // MetaType.Imc => new MetaManipulation( newManip.Value.Identifier, - // ( ( ImcFile.ImageChangeData )def ).ToInteger() ), - // MetaType.Rsp => MetaManipulation.Rsp( newManip.Value.RspIdentifier.SubRace, - // newManip.Value.RspIdentifier.Attribute, ( float )def ), - // _ => throw new InvalidEnumArgumentException(), - // }; - // list.Add( manip ); - // change = true; - // ++count; - // } - // - // ImGui.CloseCurrentPopup(); - //} + if( ImGui.Button( "Create Manipulation##newManip", Vector2.UnitX * -1 ) + && newManip != null + && list.All( m => !m.Equals( newManip ) ) ) + { + list.Add( newManip.Value ); + change = true; + ++count; + ImGui.CloseCurrentPopup(); + } return change; } diff --git a/Penumbra/UI/MenuTabs/TabResourceManager.cs b/Penumbra/UI/MenuTabs/TabResourceManager.cs index 507d3fe7..af8f613f 100644 --- a/Penumbra/UI/MenuTabs/TabResourceManager.cs +++ b/Penumbra/UI/MenuTabs/TabResourceManager.cs @@ -87,9 +87,10 @@ public partial class SettingsInterface if( ImGui.IsItemClicked() ) { - var data = ( ( Interop.Structs.ResourceHandle* )r )->GetData(); + var data = Interop.Structs.ResourceHandle.GetData( ( Interop.Structs.ResourceHandle* )r ); + var length = ( int )Interop.Structs.ResourceHandle.GetLength( ( Interop.Structs.ResourceHandle* )r ); ImGui.SetClipboardText( string.Join( " ", - new ReadOnlySpan< byte >( ( byte* )data.Data, data.Length ).ToArray().Select( b => b.ToString( "X2" ) ) ) ); + new ReadOnlySpan< byte >( data, length ).ToArray().Select( b => b.ToString( "X2" ) ) ) ); //ImGuiNative.igSetClipboardText( ( byte* )Structs.ResourceHandle.GetData( ( IntPtr )r ) ); } diff --git a/Penumbra/UI/MenuTabs/TabSettings.cs b/Penumbra/UI/MenuTabs/TabSettings.cs index 9d099eb0..d258231a 100644 --- a/Penumbra/UI/MenuTabs/TabSettings.cs +++ b/Penumbra/UI/MenuTabs/TabSettings.cs @@ -27,10 +27,10 @@ public partial class SettingsInterface public TabSettings( SettingsInterface ui ) { - _base = ui; - _config = Penumbra.Config; - _configChanged = false; - _newModDirectory = _config.ModDirectory; + _base = ui; + _config = Penumbra.Config; + _configChanged = false; + _newModDirectory = _config.ModDirectory; } private static bool DrawPressEnterWarning( string old ) @@ -239,44 +239,6 @@ public partial class SettingsInterface ImGuiComponents.HelpMarker( "Enables other applications, e.g. Anamnesis, to use some Penumbra functions, like requesting redraws." ); } - private void DrawEnabledPlayerWatcher() - { - var enabled = _config.EnablePlayerWatch; - if( ImGui.Checkbox( "Enable Automatic Character Redraws", ref enabled ) ) - { - _config.EnablePlayerWatch = enabled; - _configChanged = true; - Penumbra.PlayerWatcher.SetStatus( enabled ); - } - - ImGui.SameLine(); - ImGuiComponents.HelpMarker( - "If this setting is enabled, Penumbra will keep tabs on characters that have a corresponding character collection setup in the Collections tab.\n" - + "Penumbra will try to automatically redraw those characters using their collection when they first appear in an instance, or when they change their current equip.\n" ); - - if( !_config.EnablePlayerWatch || !_config.ShowAdvanced ) - { - return; - } - - var waitFrames = _config.WaitFrames; - ImGui.SameLine(); - ImGui.SetNextItemWidth( 50 * ImGuiHelpers.GlobalScale ); - if( ImGui.InputInt( "Wait Frames", ref waitFrames, 0, 0 ) - && waitFrames != _config.WaitFrames - && waitFrames is > 0 and < 3000 ) - { - _base._penumbra.ObjectReloader.DefaultWaitFrames = waitFrames; - _config.WaitFrames = waitFrames; - _configChanged = true; - } - - ImGui.SameLine(); - ImGuiComponents.HelpMarker( - "The number of frames penumbra waits after some events (like zone changes) until it starts trying to redraw actors again, in a range of [1, 3001].\n" - + "Keep this as low as possible while producing stable results." ); - } - private static void DrawReloadResourceButton() { if( ImGui.Button( "Reload Resident Resources" ) ) @@ -388,7 +350,6 @@ public partial class SettingsInterface ImGuiCustom.VerticalDistance( DefaultVerticalSpace ); DrawEnabledBox(); - DrawEnabledPlayerWatcher(); ImGuiCustom.VerticalDistance( DefaultVerticalSpace ); DrawScaleModSelectorBox();