mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Merge remote-tracking branch 'Exter-N/human-skin-materials'
This commit is contained in:
commit
692beacc2e
4 changed files with 81 additions and 54 deletions
|
|
@ -35,6 +35,7 @@ public sealed unsafe class ResolvePathHooksBase : IDisposable
|
|||
private readonly Hook<MPapResolveDelegate> _resolveMPapPathHook;
|
||||
private readonly Hook<PerSlotResolveDelegate> _resolveMdlPathHook;
|
||||
private readonly Hook<NamedResolveDelegate> _resolveMtrlPathHook;
|
||||
private readonly Hook<PerSlotResolveDelegate> _resolveSkinMtrlPathHook;
|
||||
private readonly Hook<NamedResolveDelegate> _resolvePapPathHook;
|
||||
private readonly Hook<PerSlotResolveDelegate> _resolveKdbPathHook;
|
||||
private readonly Hook<PerSlotResolveDelegate> _resolvePhybPathHook;
|
||||
|
|
@ -52,22 +53,23 @@ public sealed unsafe class ResolvePathHooksBase : IDisposable
|
|||
{
|
||||
_parent = parent;
|
||||
// @formatter:off
|
||||
_resolveSklbPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolveSklb)}", hooks, vTable[76], type, ResolveSklb, ResolveSklbHuman);
|
||||
_resolveMdlPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolveMdl)}", hooks, vTable[77], type, ResolveMdl, ResolveMdlHuman);
|
||||
_resolveSkpPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolveSkp)}", hooks, vTable[78], type, ResolveSkp, ResolveSkpHuman);
|
||||
_resolvePhybPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolvePhyb)}", hooks, vTable[79], type, ResolvePhyb, ResolvePhybHuman);
|
||||
_resolveKdbPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolveKdb)}", hooks, vTable[80], type, ResolveKdb, ResolveKdbHuman);
|
||||
_vFunc81Hook = Create<SkeletonVFuncDelegate>( $"{name}.{nameof(VFunc81)}", hooks, vTable[81], type, null, VFunc81);
|
||||
_resolveBnmbPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolveBnmb)}", hooks, vTable[82], type, ResolveBnmb, ResolveBnmbHuman);
|
||||
_vFunc83Hook = Create<SkeletonVFuncDelegate>( $"{name}.{nameof(VFunc83)}", hooks, vTable[83], type, null, VFunc83);
|
||||
_resolvePapPathHook = Create<NamedResolveDelegate>( $"{name}.{nameof(ResolvePap)}", hooks, vTable[84], type, ResolvePap, ResolvePapHuman);
|
||||
_resolveTmbPathHook = Create<TmbResolveDelegate>( $"{name}.{nameof(ResolveTmb)}", hooks, vTable[85], ResolveTmb);
|
||||
_resolveMPapPathHook = Create<MPapResolveDelegate>( $"{name}.{nameof(ResolveMPap)}", hooks, vTable[87], ResolveMPap);
|
||||
_resolveImcPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolveImc)}", hooks, vTable[89], ResolveImc);
|
||||
_resolveMtrlPathHook = Create<NamedResolveDelegate>( $"{name}.{nameof(ResolveMtrl)}", hooks, vTable[90], ResolveMtrl);
|
||||
_resolveDecalPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolveDecal)}", hooks, vTable[92], ResolveDecal);
|
||||
_resolveVfxPathHook = Create<VfxResolveDelegate>( $"{name}.{nameof(ResolveVfx)}", hooks, vTable[93], type, ResolveVfx, ResolveVfxHuman);
|
||||
_resolveEidPathHook = Create<SingleResolveDelegate>( $"{name}.{nameof(ResolveEid)}", hooks, vTable[94], ResolveEid);
|
||||
_resolveSklbPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolveSklb)}", hooks, vTable[76], type, ResolveSklb, ResolveSklbHuman);
|
||||
_resolveMdlPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolveMdl)}", hooks, vTable[77], type, ResolveMdl, ResolveMdlHuman);
|
||||
_resolveSkpPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolveSkp)}", hooks, vTable[78], type, ResolveSkp, ResolveSkpHuman);
|
||||
_resolvePhybPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolvePhyb)}", hooks, vTable[79], type, ResolvePhyb, ResolvePhybHuman);
|
||||
_resolveKdbPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolveKdb)}", hooks, vTable[80], type, ResolveKdb, ResolveKdbHuman);
|
||||
_vFunc81Hook = Create<SkeletonVFuncDelegate>( $"{name}.{nameof(VFunc81)}", hooks, vTable[81], type, null, VFunc81);
|
||||
_resolveBnmbPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolveBnmb)}", hooks, vTable[82], type, ResolveBnmb, ResolveBnmbHuman);
|
||||
_vFunc83Hook = Create<SkeletonVFuncDelegate>( $"{name}.{nameof(VFunc83)}", hooks, vTable[83], type, null, VFunc83);
|
||||
_resolvePapPathHook = Create<NamedResolveDelegate>( $"{name}.{nameof(ResolvePap)}", hooks, vTable[84], type, ResolvePap, ResolvePapHuman);
|
||||
_resolveTmbPathHook = Create<TmbResolveDelegate>( $"{name}.{nameof(ResolveTmb)}", hooks, vTable[85], ResolveTmb);
|
||||
_resolveMPapPathHook = Create<MPapResolveDelegate>( $"{name}.{nameof(ResolveMPap)}", hooks, vTable[87], ResolveMPap);
|
||||
_resolveImcPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolveImc)}", hooks, vTable[89], ResolveImc);
|
||||
_resolveMtrlPathHook = Create<NamedResolveDelegate>( $"{name}.{nameof(ResolveMtrl)}", hooks, vTable[90], ResolveMtrl);
|
||||
_resolveSkinMtrlPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolveSkinMtrl)}", hooks, vTable[91], ResolveSkinMtrl);
|
||||
_resolveDecalPathHook = Create<PerSlotResolveDelegate>($"{name}.{nameof(ResolveDecal)}", hooks, vTable[92], ResolveDecal);
|
||||
_resolveVfxPathHook = Create<VfxResolveDelegate>( $"{name}.{nameof(ResolveVfx)}", hooks, vTable[93], type, ResolveVfx, ResolveVfxHuman);
|
||||
_resolveEidPathHook = Create<SingleResolveDelegate>( $"{name}.{nameof(ResolveEid)}", hooks, vTable[94], ResolveEid);
|
||||
|
||||
|
||||
// @formatter:on
|
||||
|
|
@ -83,6 +85,7 @@ public sealed unsafe class ResolvePathHooksBase : IDisposable
|
|||
_resolveMPapPathHook.Enable();
|
||||
_resolveMdlPathHook.Enable();
|
||||
_resolveMtrlPathHook.Enable();
|
||||
_resolveSkinMtrlPathHook.Enable();
|
||||
_resolvePapPathHook.Enable();
|
||||
_resolveKdbPathHook.Enable();
|
||||
_resolvePhybPathHook.Enable();
|
||||
|
|
@ -103,6 +106,7 @@ public sealed unsafe class ResolvePathHooksBase : IDisposable
|
|||
_resolveMPapPathHook.Disable();
|
||||
_resolveMdlPathHook.Disable();
|
||||
_resolveMtrlPathHook.Disable();
|
||||
_resolveSkinMtrlPathHook.Disable();
|
||||
_resolvePapPathHook.Disable();
|
||||
_resolveKdbPathHook.Disable();
|
||||
_resolvePhybPathHook.Disable();
|
||||
|
|
@ -123,6 +127,7 @@ public sealed unsafe class ResolvePathHooksBase : IDisposable
|
|||
_resolveMPapPathHook.Dispose();
|
||||
_resolveMdlPathHook.Dispose();
|
||||
_resolveMtrlPathHook.Dispose();
|
||||
_resolveSkinMtrlPathHook.Dispose();
|
||||
_resolvePapPathHook.Dispose();
|
||||
_resolveKdbPathHook.Dispose();
|
||||
_resolvePhybPathHook.Dispose();
|
||||
|
|
@ -153,6 +158,9 @@ public sealed unsafe class ResolvePathHooksBase : IDisposable
|
|||
private nint ResolveMtrl(nint drawObject, nint pathBuffer, nint pathBufferSize, uint slotIndex, nint mtrlFileName)
|
||||
=> ResolvePath(drawObject, _resolveMtrlPathHook.Original(drawObject, pathBuffer, pathBufferSize, slotIndex, mtrlFileName));
|
||||
|
||||
private nint ResolveSkinMtrl(nint drawObject, nint pathBuffer, nint pathBufferSize, uint slotIndex)
|
||||
=> ResolvePath(drawObject, _resolveSkinMtrlPathHook.Original(drawObject, pathBuffer, pathBufferSize, slotIndex));
|
||||
|
||||
private nint ResolvePap(nint drawObject, nint pathBuffer, nint pathBufferSize, uint unkAnimationIndex, nint animationName)
|
||||
=> ResolvePath(drawObject, _resolvePapPathHook.Original(drawObject, pathBuffer, pathBufferSize, unkAnimationIndex, animationName));
|
||||
|
||||
|
|
|
|||
|
|
@ -188,7 +188,8 @@ internal unsafe partial record ResolveContext(
|
|||
return GetOrCreateNode(ResourceType.Tex, (nint)tex->Texture, &tex->ResourceHandle, gamePath);
|
||||
}
|
||||
|
||||
public ResourceNode? CreateNodeFromModel(Model* mdl, ResourceHandle* imc, TextureResourceHandle* decalHandle, ResourceHandle* mpapHandle)
|
||||
public ResourceNode? CreateNodeFromModel(Model* mdl, ResourceHandle* imc, TextureResourceHandle* decalHandle,
|
||||
MaterialResourceHandle* skinMtrlHandle, ResourceHandle* mpapHandle)
|
||||
{
|
||||
if (mdl is null || mdl->ModelResourceHandle is null)
|
||||
return null;
|
||||
|
|
@ -218,6 +219,12 @@ internal unsafe partial record ResolveContext(
|
|||
}
|
||||
}
|
||||
|
||||
if (skinMtrlHandle is not null
|
||||
&& Utf8GamePath.FromByteString(CharacterBase->ResolveSkinMtrlPathAsByteString(SlotIndex), out var skinMtrlPath)
|
||||
&& CreateNodeFromMaterial(skinMtrlHandle->Material, skinMtrlPath) is
|
||||
{ } skinMaaterialNode)
|
||||
node.Children.Add(skinMaaterialNode);
|
||||
|
||||
if (CreateNodeFromDecal(decalHandle, imc) is { } decalNode)
|
||||
node.Children.Add(decalNode);
|
||||
|
||||
|
|
|
|||
|
|
@ -70,9 +70,14 @@ public class ResourceTree(
|
|||
|
||||
var genericContext = globalContext.CreateContext(model);
|
||||
|
||||
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1312)
|
||||
var mpapArrayPtr = *(ResourceHandle***)((nint)model + 0x948);
|
||||
var mpapArrayPtr = model->MaterialAnimationPacks;
|
||||
var mpapArray = mpapArrayPtr is not null ? new ReadOnlySpan<Pointer<ResourceHandle>>(mpapArrayPtr, model->SlotCount) : [];
|
||||
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1474)
|
||||
var skinMtrlArray = modelType switch
|
||||
{
|
||||
ModelType.Human => new ReadOnlySpan<Pointer<MaterialResourceHandle>>((MaterialResourceHandle**)((nint)model + 0xB48), 5),
|
||||
_ => [],
|
||||
};
|
||||
var decalArray = modelType switch
|
||||
{
|
||||
ModelType.Human => human->SlotDecalsSpan,
|
||||
|
|
@ -108,7 +113,8 @@ public class ResourceTree(
|
|||
|
||||
var mdl = model->Models[i];
|
||||
if (slotContext.CreateNodeFromModel(mdl, imc, i < decalArray.Length ? decalArray[(int)i].Value : null,
|
||||
i < mpapArray.Length ? mpapArray[(int)i].Value : null) is { } mdlNode)
|
||||
i < skinMtrlArray.Length ? skinMtrlArray[(int)i].Value : null, i < mpapArray.Length ? mpapArray[(int)i].Value : null) is
|
||||
{ } mdlNode)
|
||||
{
|
||||
if (globalContext.WithUiData)
|
||||
mdlNode.FallbackName = $"Model #{i}";
|
||||
|
|
@ -117,8 +123,7 @@ public class ResourceTree(
|
|||
}
|
||||
|
||||
AddSkeleton(Nodes, genericContext, model->EID, model->Skeleton, model->BonePhysicsModule);
|
||||
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1312)
|
||||
AddMaterialAnimationSkeleton(Nodes, genericContext, *(SkeletonResourceHandle**)((nint)model + 0x940));
|
||||
AddMaterialAnimationSkeleton(Nodes, genericContext, model->MaterialAnimationSkeleton);
|
||||
|
||||
AddWeapons(globalContext, model);
|
||||
|
||||
|
|
@ -149,8 +154,7 @@ public class ResourceTree(
|
|||
|
||||
var genericContext = globalContext.CreateContext(subObject, 0xFFFFFFFFu, slot, equipment, weaponType);
|
||||
|
||||
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1312)
|
||||
var mpapArrayPtr = *(ResourceHandle***)((nint)subObject + 0x948);
|
||||
var mpapArrayPtr = subObject->MaterialAnimationPacks;
|
||||
var mpapArray = mpapArrayPtr is not null ? new ReadOnlySpan<Pointer<ResourceHandle>>(mpapArrayPtr, subObject->SlotCount) : [];
|
||||
|
||||
for (var i = 0; i < subObject->SlotCount; ++i)
|
||||
|
|
@ -166,7 +170,8 @@ public class ResourceTree(
|
|||
}
|
||||
|
||||
var mdl = subObject->Models[i];
|
||||
if (slotContext.CreateNodeFromModel(mdl, imc, weapon->Decal, i < mpapArray.Length ? mpapArray[i].Value : null) is { } mdlNode)
|
||||
if (slotContext.CreateNodeFromModel(mdl, imc, weapon->Decal, null, i < mpapArray.Length ? mpapArray[i].Value : null) is
|
||||
{ } mdlNode)
|
||||
{
|
||||
if (globalContext.WithUiData)
|
||||
mdlNode.FallbackName = $"Weapon #{weaponIndex}, Model #{i}";
|
||||
|
|
@ -176,8 +181,7 @@ public class ResourceTree(
|
|||
|
||||
AddSkeleton(weaponNodes, genericContext, subObject->EID, subObject->Skeleton, subObject->BonePhysicsModule,
|
||||
$"Weapon #{weaponIndex}, ");
|
||||
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1312)
|
||||
AddMaterialAnimationSkeleton(weaponNodes, genericContext, *(SkeletonResourceHandle**)((nint)subObject + 0x940),
|
||||
AddMaterialAnimationSkeleton(weaponNodes, genericContext, subObject->MaterialAnimationSkeleton,
|
||||
$"Weapon #{weaponIndex}, ");
|
||||
|
||||
++weaponIndex;
|
||||
|
|
@ -255,7 +259,7 @@ public class ResourceTree(
|
|||
|
||||
for (var i = 0; i < skeleton->PartialSkeletonCount; ++i)
|
||||
{
|
||||
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1312)
|
||||
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1475)
|
||||
var phybHandle = physics != null ? ((ResourceHandle**)((nint)physics + 0x190))[i] : null;
|
||||
if (context.CreateNodeFromPartialSkeleton(&skeleton->PartialSkeletons[i], phybHandle, (uint)i) is { } sklbNode)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,28 +10,36 @@ internal static class StructExtensions
|
|||
public static CiByteString AsByteString(in this StdString str)
|
||||
=> CiByteString.FromSpanUnsafe(str.AsSpan(), true);
|
||||
|
||||
public static CiByteString ResolveEidPathAsByteString(ref this CharacterBase character)
|
||||
{
|
||||
Span<byte> pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveEidPath(pathBuffer));
|
||||
}
|
||||
|
||||
public static CiByteString ResolveImcPathAsByteString(ref this CharacterBase character, uint slotIndex)
|
||||
{
|
||||
Span<byte> pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveImcPath(pathBuffer, slotIndex));
|
||||
public static CiByteString ResolveEidPathAsByteString(ref this CharacterBase character)
|
||||
{
|
||||
Span<byte> pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveEidPath(pathBuffer));
|
||||
}
|
||||
|
||||
public static CiByteString ResolveMdlPathAsByteString(ref this CharacterBase character, uint slotIndex)
|
||||
{
|
||||
Span<byte> pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveMdlPath(pathBuffer, slotIndex));
|
||||
public static CiByteString ResolveImcPathAsByteString(ref this CharacterBase character, uint slotIndex)
|
||||
{
|
||||
Span<byte> pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveImcPath(pathBuffer, slotIndex));
|
||||
}
|
||||
|
||||
public static unsafe CiByteString ResolveMtrlPathAsByteString(ref this CharacterBase character, uint slotIndex, byte* mtrlFileName)
|
||||
{
|
||||
var pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveMtrlPath(pathBuffer, CharacterBase.PathBufferSize, slotIndex, mtrlFileName));
|
||||
public static CiByteString ResolveMdlPathAsByteString(ref this CharacterBase character, uint slotIndex)
|
||||
{
|
||||
Span<byte> pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveMdlPath(pathBuffer, slotIndex));
|
||||
}
|
||||
|
||||
public static unsafe CiByteString ResolveMtrlPathAsByteString(ref this CharacterBase character, uint slotIndex, byte* mtrlFileName)
|
||||
{
|
||||
var pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveMtrlPath(pathBuffer, CharacterBase.PathBufferSize, slotIndex, mtrlFileName));
|
||||
}
|
||||
|
||||
public static unsafe CiByteString ResolveSkinMtrlPathAsByteString(ref this CharacterBase character, uint slotIndex)
|
||||
{
|
||||
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1474)
|
||||
var vf91 = (delegate* unmanaged<CharacterBase*, byte*, nuint, uint, byte*>)((nint*)character.VirtualTable)[91];
|
||||
var pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(vf91((CharacterBase*)Unsafe.AsPointer(ref character), pathBuffer, CharacterBase.PathBufferSize, slotIndex));
|
||||
}
|
||||
|
||||
public static CiByteString ResolveMaterialPapPathAsByteString(ref this CharacterBase character, uint slotIndex, uint unkSId)
|
||||
|
|
@ -40,16 +48,16 @@ internal static class StructExtensions
|
|||
return ToOwnedByteString(character.ResolveMaterialPapPath(pathBuffer, slotIndex, unkSId));
|
||||
}
|
||||
|
||||
public static CiByteString ResolveSklbPathAsByteString(ref this CharacterBase character, uint partialSkeletonIndex)
|
||||
{
|
||||
Span<byte> pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveSklbPath(pathBuffer, partialSkeletonIndex));
|
||||
public static CiByteString ResolveSklbPathAsByteString(ref this CharacterBase character, uint partialSkeletonIndex)
|
||||
{
|
||||
Span<byte> pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveSklbPath(pathBuffer, partialSkeletonIndex));
|
||||
}
|
||||
|
||||
public static CiByteString ResolveSkpPathAsByteString(ref this CharacterBase character, uint partialSkeletonIndex)
|
||||
{
|
||||
Span<byte> pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveSkpPath(pathBuffer, partialSkeletonIndex));
|
||||
public static CiByteString ResolveSkpPathAsByteString(ref this CharacterBase character, uint partialSkeletonIndex)
|
||||
{
|
||||
Span<byte> pathBuffer = stackalloc byte[CharacterBase.PathBufferSize];
|
||||
return ToOwnedByteString(character.ResolveSkpPath(pathBuffer, partialSkeletonIndex));
|
||||
}
|
||||
|
||||
public static CiByteString ResolvePhybPathAsByteString(ref this CharacterBase character, uint partialSkeletonIndex)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue