From 6e7805d58f5e1a842311d7c6f051ddba0fd2bf14 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Thu, 6 Jul 2023 00:51:08 +0200 Subject: [PATCH] Fix handling of decals overall. --- Penumbra/Interop/PathResolving/MetaState.cs | 12 +++++----- .../Interop/ResourceLoading/ResourceLoader.cs | 23 ++++++++++++++++--- .../ResourceLoading/ResourceService.cs | 4 +++- Penumbra/Interop/Services/DecalReverter.cs | 8 +++---- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/Penumbra/Interop/PathResolving/MetaState.cs b/Penumbra/Interop/PathResolving/MetaState.cs index bac81c89..4d95b94a 100644 --- a/Penumbra/Interop/PathResolving/MetaState.cs +++ b/Penumbra/Interop/PathResolving/MetaState.cs @@ -49,7 +49,7 @@ public unsafe class MetaState : IDisposable private readonly CommunicatorService _communicator; private readonly PerformanceTracker _performance; private readonly CollectionResolver _collectionResolver; - private readonly ResourceService _resources; + private readonly ResourceLoader _resources; private readonly GameEventManager _gameEventManager; private readonly CharacterUtility _characterUtility; @@ -57,7 +57,7 @@ public unsafe class MetaState : IDisposable private DisposableContainer _characterBaseCreateMetaChanges = DisposableContainer.Empty; public MetaState(PerformanceTracker performance, CommunicatorService communicator, CollectionResolver collectionResolver, - ResourceService resources, GameEventManager gameEventManager, CharacterUtility characterUtility, Configuration config) + ResourceLoader resources, GameEventManager gameEventManager, CharacterUtility characterUtility, Configuration config) { _performance = performance; _communicator = communicator; @@ -129,7 +129,7 @@ public unsafe class MetaState : IDisposable _communicator.CreatingCharacterBase.Invoke(_lastCreatedCollection.AssociatedGameObject, _lastCreatedCollection.ModCollection.Name, (nint)(&modelCharaId), customize, equipData); - var decal = new DecalReverter(_config, _characterUtility, _resources, _lastCreatedCollection.ModCollection, UsesDecal(modelCharaId, customize)); + var decal = new DecalReverter(_config, _characterUtility, _resources, _lastCreatedCollection, UsesDecal(modelCharaId, customize)); var cmp = _lastCreatedCollection.ModCollection.TemporarilySetCmpFile(_characterUtility); _characterBaseCreateMetaChanges.Dispose(); // Should always be empty. _characterBaseCreateMetaChanges = new DisposableContainer(decal, cmp); @@ -255,9 +255,9 @@ public unsafe class MetaState : IDisposable _inChangeCustomize = true; var resolveData = _collectionResolver.IdentifyCollection((DrawObject*)human, true); using var cmp = resolveData.ModCollection.TemporarilySetCmpFile(_characterUtility); - using var decals = - new DecalReverter(_config, _characterUtility, _resources, resolveData.ModCollection, UsesDecal(0, data)); - var ret = _changeCustomize.Original(human, data, skipEquipment); + using var decals = new DecalReverter(_config, _characterUtility, _resources, resolveData, true); + using var decal2 = new DecalReverter(_config, _characterUtility, _resources, resolveData, false); + var ret = _changeCustomize.Original(human, data, skipEquipment); _inChangeCustomize = false; return ret; } diff --git a/Penumbra/Interop/ResourceLoading/ResourceLoader.cs b/Penumbra/Interop/ResourceLoading/ResourceLoader.cs index 5d7ba16a..f96ad99b 100644 --- a/Penumbra/Interop/ResourceLoading/ResourceLoader.cs +++ b/Penumbra/Interop/ResourceLoading/ResourceLoader.cs @@ -16,6 +16,8 @@ public unsafe class ResourceLoader : IDisposable private readonly FileReadService _fileReadService; private readonly TexMdlService _texMdlService; + private ResolveData _resolvedData = ResolveData.Invalid; + public ResourceLoader(ResourceService resources, FileReadService fileReadService, TexMdlService texMdlService, CreateFileWHook _) { @@ -30,6 +32,15 @@ public unsafe class ResourceLoader : IDisposable _fileReadService.ReadSqPack += ReadSqPackDetour; } + /// Load a resource for a given path and a specific collection. + public ResourceHandle* LoadResolvedResource(ResourceCategory category, ResourceType type, ByteString path, ResolveData resolveData) + { + _resolvedData = resolveData; + var ret = _resources.GetResource(category, type, path); + _resolvedData = ResolveData.Invalid; + return ret; + } + /// The function to use to resolve a given path. public Func ResolvePath = null!; @@ -66,7 +77,8 @@ public unsafe class ResourceLoader : IDisposable _fileReadService.ReadSqPack -= ReadSqPackDetour; } - private void ResourceHandler(ref ResourceCategory category, ref ResourceType type, ref int hash, ref Utf8GamePath path, Utf8GamePath original, + private void ResourceHandler(ref ResourceCategory category, ref ResourceType type, ref int hash, ref Utf8GamePath path, + Utf8GamePath original, GetResourceParameters* parameters, ref bool sync, ref ResourceHandle* returnValue) { if (returnValue != null) @@ -75,7 +87,12 @@ public unsafe class ResourceLoader : IDisposable CompareHash(ComputeHash(path.Path, parameters), hash, path); // If no replacements are being made, we still want to be able to trigger the event. - var (resolvedPath, data) = _incMode.Value ? (null, ResolveData.Invalid) : ResolvePath(path, category, type); + var (resolvedPath, data) = _incMode.Value + ? (null, ResolveData.Invalid) + : _resolvedData.Valid + ? (_resolvedData.ModCollection.ResolvePath(path), _resolvedData) + : ResolvePath(path, category, type); + if (resolvedPath == null || !Utf8GamePath.FromByteString(resolvedPath.Value.InternalName, out var p)) { returnValue = _resources.GetOriginalResource(sync, category, type, hash, path.Path, parameters); @@ -85,7 +102,7 @@ public unsafe class ResourceLoader : IDisposable _texMdlService.AddCrc(type, resolvedPath); // Replace the hash and path with the correct one for the replacement. - hash = ComputeHash(resolvedPath.Value.InternalName, parameters); + hash = ComputeHash(resolvedPath.Value.InternalName, parameters); var oldPath = path; path = p; returnValue = _resources.GetOriginalResource(sync, category, type, hash, path.Path, parameters); diff --git a/Penumbra/Interop/ResourceLoading/ResourceService.cs b/Penumbra/Interop/ResourceLoading/ResourceService.cs index bced539c..645596a3 100644 --- a/Penumbra/Interop/ResourceLoading/ResourceService.cs +++ b/Penumbra/Interop/ResourceLoading/ResourceService.cs @@ -2,6 +2,7 @@ using System; using Dalamud.Hooking; using Dalamud.Utility.Signatures; using FFXIVClientStructs.FFXIV.Client.System.Resource; +using Penumbra.Collections; using Penumbra.GameData; using Penumbra.GameData.Enums; using Penumbra.Interop.Structs; @@ -60,7 +61,8 @@ public unsafe class ResourceService : IDisposable /// Mainly used for SCD streaming, can be null. /// Whether to request the resource synchronously or asynchronously. /// The returned resource handle. If this is not null, calling original will be skipped. - public delegate void GetResourcePreDelegate(ref ResourceCategory category, ref ResourceType type, ref int hash, ref Utf8GamePath path, Utf8GamePath original, + public delegate void GetResourcePreDelegate(ref ResourceCategory category, ref ResourceType type, ref int hash, ref Utf8GamePath path, + Utf8GamePath original, GetResourceParameters* parameters, ref bool sync, ref ResourceHandle* returnValue); /// diff --git a/Penumbra/Interop/Services/DecalReverter.cs b/Penumbra/Interop/Services/DecalReverter.cs index a0a8c84d..a8aa3fa2 100644 --- a/Penumbra/Interop/Services/DecalReverter.cs +++ b/Penumbra/Interop/Services/DecalReverter.cs @@ -19,7 +19,7 @@ public sealed unsafe class DecalReverter : IDisposable private readonly Structs.TextureResourceHandle* _decal; private readonly Structs.TextureResourceHandle* _transparent; - public DecalReverter(Configuration config, CharacterUtility utility, ResourceService resources, ModCollection? collection, bool doDecal) + public DecalReverter(Configuration config, CharacterUtility utility, ResourceLoader resources, ResolveData resolveData, bool doDecal) { _utility = utility; var ptr = _utility.Address; @@ -30,16 +30,14 @@ public sealed unsafe class DecalReverter : IDisposable if (doDecal) { - var decalPath = collection?.ResolvePath(DecalPath)?.InternalName ?? DecalPath.Path; - var decalHandle = resources.GetResource(ResourceCategory.Chara, ResourceType.Tex, decalPath); + var decalHandle = resources.LoadResolvedResource(ResourceCategory.Chara, ResourceType.Tex, DecalPath.Path, resolveData); _decal = (Structs.TextureResourceHandle*)decalHandle; if (_decal != null) ptr->DecalTexResource = _decal; } else { - var transparentPath = collection?.ResolvePath(TransparentPath)?.InternalName ?? TransparentPath.Path; - var transparentHandle = resources.GetResource(ResourceCategory.Chara, ResourceType.Tex, transparentPath); + var transparentHandle = resources.LoadResolvedResource(ResourceCategory.Chara, ResourceType.Tex, TransparentPath.Path, resolveData); _transparent = (Structs.TextureResourceHandle*)transparentHandle; if (_transparent != null) ptr->TransparentTexResource = _transparent;