Improve Path preprocessing.

This commit is contained in:
Ottermandias 2024-06-18 18:33:37 +02:00
parent f9c45a2f3f
commit cf1dcfcb7c
14 changed files with 209 additions and 246 deletions

View file

@ -46,9 +46,6 @@ public unsafe class CharacterUtility : IDisposable
private readonly MetaList[] _lists;
public IReadOnlyList<MetaList> Lists
=> _lists;
public (nint Address, int Size) DefaultResource(InternalIndex idx)
=> _lists[idx.Value].DefaultResource;
@ -58,7 +55,7 @@ public unsafe class CharacterUtility : IDisposable
{
interop.InitializeFromAttributes(this);
_lists = Enumerable.Range(0, RelevantIndices.Length)
.Select(idx => new MetaList(this, new InternalIndex(idx)))
.Select(idx => new MetaList(new InternalIndex(idx)))
.ToArray();
_framework = framework;
LoadingFinished += () => Penumbra.Log.Debug("Loading of CharacterUtility finished.");
@ -124,9 +121,6 @@ public unsafe class CharacterUtility : IDisposable
if (!Ready)
return;
foreach (var list in _lists)
list.Dispose();
Address->HumanPbdResource = (ResourceHandle*)DefaultHumanPbdResource;
Address->TransparentTexResource = (TextureResourceHandle*)DefaultTransparentResource;
Address->DecalTexResource = (TextureResourceHandle*)DefaultDecalResource;

View file

@ -2,26 +2,14 @@ using Penumbra.Interop.Structs;
namespace Penumbra.Interop.Services;
public unsafe class MetaList : IDisposable
public class MetaList(CharacterUtility.InternalIndex index)
{
private readonly CharacterUtility _utility;
private readonly LinkedList<MetaReverter> _entries = new();
public readonly CharacterUtility.InternalIndex Index;
public readonly MetaIndex GlobalMetaIndex;
public IReadOnlyCollection<MetaReverter> Entries
=> _entries;
public readonly CharacterUtility.InternalIndex Index = index;
public readonly MetaIndex GlobalMetaIndex = CharacterUtility.RelevantIndices[index.Value];
private nint _defaultResourceData = nint.Zero;
private int _defaultResourceSize = 0;
public bool Ready { get; private set; } = false;
public MetaList(CharacterUtility utility, CharacterUtility.InternalIndex index)
{
_utility = utility;
Index = index;
GlobalMetaIndex = CharacterUtility.RelevantIndices[index.Value];
}
private int _defaultResourceSize;
public bool Ready { get; private set; }
public void SetDefaultResource(nint data, int size)
{
@ -31,116 +19,8 @@ public unsafe class MetaList : IDisposable
_defaultResourceData = data;
_defaultResourceSize = size;
Ready = _defaultResourceData != nint.Zero && size != 0;
if (_entries.Count <= 0)
return;
var first = _entries.First!.Value;
SetResource(first.Data, first.Length);
}
public (nint Address, int Size) DefaultResource
=> (_defaultResourceData, _defaultResourceSize);
public MetaReverter TemporarilySetResource(nint data, int length)
{
Penumbra.Log.Excessive($"Temporarily set resource {GlobalMetaIndex} to 0x{(ulong)data:X} ({length} bytes).");
var reverter = new MetaReverter(this, data, length);
_entries.AddFirst(reverter);
SetResourceInternal(data, length);
return reverter;
}
public MetaReverter TemporarilyResetResource()
{
Penumbra.Log.Excessive(
$"Temporarily reset resource {GlobalMetaIndex} to default at 0x{_defaultResourceData:X} ({_defaultResourceSize} bytes).");
var reverter = new MetaReverter(this);
_entries.AddFirst(reverter);
ResetResourceInternal();
return reverter;
}
public void SetResource(nint data, int length)
{
Penumbra.Log.Excessive($"Set resource {GlobalMetaIndex} to 0x{(ulong)data:X} ({length} bytes).");
SetResourceInternal(data, length);
}
public void ResetResource()
{
Penumbra.Log.Excessive($"Reset resource {GlobalMetaIndex} to default at 0x{_defaultResourceData:X} ({_defaultResourceSize} bytes).");
ResetResourceInternal();
}
/// <summary> Set the currently stored data of this resource to new values. </summary>
private void SetResourceInternal(nint data, int length)
{
if (!Ready)
return;
var resource = _utility.Address->Resource(GlobalMetaIndex);
resource->SetData(data, length);
}
/// <summary> Reset the currently stored data of this resource to its default values. </summary>
private void ResetResourceInternal()
=> SetResourceInternal(_defaultResourceData, _defaultResourceSize);
private void SetResourceToDefaultCollection()
{}
public void Dispose()
{
if (_entries.Count > 0)
{
foreach (var entry in _entries)
entry.Disposed = true;
_entries.Clear();
}
ResetResourceInternal();
}
public sealed class MetaReverter(MetaList metaList, nint data, int length) : IDisposable
{
public static readonly MetaReverter Disabled = new(null!) { Disposed = true };
public readonly MetaList MetaList = metaList;
public readonly nint Data = data;
public readonly int Length = length;
public readonly bool Resetter;
public bool Disposed;
public MetaReverter(MetaList metaList)
: this(metaList, nint.Zero, 0)
=> Resetter = true;
public void Dispose()
{
if (Disposed)
return;
var list = MetaList._entries;
var wasCurrent = ReferenceEquals(this, list.First?.Value);
list.Remove(this);
if (!wasCurrent)
return;
if (list.Count == 0)
{
MetaList.SetResourceToDefaultCollection();
}
else
{
var next = list.First!.Value;
if (next.Resetter)
MetaList.ResetResourceInternal();
else
MetaList.SetResourceInternal(next.Data, next.Length);
}
Disposed = true;
}
}
}