mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 12:14:17 +01:00
Primary constructor and some null-check cleanup.
This commit is contained in:
parent
e4cfd674ee
commit
70844610d8
1 changed files with 60 additions and 72 deletions
|
|
@ -16,42 +16,35 @@ using ResourceHandle = FFXIVClientStructs.FFXIV.Client.System.Resource.Handle.Re
|
||||||
|
|
||||||
namespace Penumbra.Interop.ResourceTree;
|
namespace Penumbra.Interop.ResourceTree;
|
||||||
|
|
||||||
public class ResourceTree
|
public class ResourceTree(
|
||||||
|
string name,
|
||||||
|
string anonymizedName,
|
||||||
|
int gameObjectIndex,
|
||||||
|
nint gameObjectAddress,
|
||||||
|
nint drawObjectAddress,
|
||||||
|
bool localPlayerRelated,
|
||||||
|
bool playerRelated,
|
||||||
|
bool networked,
|
||||||
|
string collectionName,
|
||||||
|
string anonymizedCollectionName)
|
||||||
{
|
{
|
||||||
public readonly string Name;
|
public readonly string Name = name;
|
||||||
public readonly string AnonymizedName;
|
public readonly string AnonymizedName = anonymizedName;
|
||||||
public readonly int GameObjectIndex;
|
public readonly int GameObjectIndex = gameObjectIndex;
|
||||||
public readonly nint GameObjectAddress;
|
public readonly nint GameObjectAddress = gameObjectAddress;
|
||||||
public readonly nint DrawObjectAddress;
|
public readonly nint DrawObjectAddress = drawObjectAddress;
|
||||||
public readonly bool LocalPlayerRelated;
|
public readonly bool LocalPlayerRelated = localPlayerRelated;
|
||||||
public readonly bool PlayerRelated;
|
public readonly bool PlayerRelated = playerRelated;
|
||||||
public readonly bool Networked;
|
public readonly bool Networked = networked;
|
||||||
public readonly string CollectionName;
|
public readonly string CollectionName = collectionName;
|
||||||
public readonly string AnonymizedCollectionName;
|
public readonly string AnonymizedCollectionName = anonymizedCollectionName;
|
||||||
public readonly List<ResourceNode> Nodes;
|
public readonly List<ResourceNode> Nodes = [];
|
||||||
public readonly HashSet<ResourceNode> FlatNodes;
|
public readonly HashSet<ResourceNode> FlatNodes = [];
|
||||||
|
|
||||||
public int ModelId;
|
public int ModelId;
|
||||||
public CustomizeData CustomizeData;
|
public CustomizeData CustomizeData;
|
||||||
public GenderRace RaceCode;
|
public GenderRace RaceCode;
|
||||||
|
|
||||||
public ResourceTree(string name, string anonymizedName, int gameObjectIndex, nint gameObjectAddress, nint drawObjectAddress,
|
|
||||||
bool localPlayerRelated, bool playerRelated, bool networked, string collectionName, string anonymizedCollectionName)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
AnonymizedName = anonymizedName;
|
|
||||||
GameObjectIndex = gameObjectIndex;
|
|
||||||
GameObjectAddress = gameObjectAddress;
|
|
||||||
DrawObjectAddress = drawObjectAddress;
|
|
||||||
LocalPlayerRelated = localPlayerRelated;
|
|
||||||
Networked = networked;
|
|
||||||
PlayerRelated = playerRelated;
|
|
||||||
CollectionName = collectionName;
|
|
||||||
AnonymizedCollectionName = anonymizedCollectionName;
|
|
||||||
Nodes = [];
|
|
||||||
FlatNodes = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ProcessPostfix(Action<ResourceNode, ResourceNode?> action)
|
public void ProcessPostfix(Action<ResourceNode, ResourceNode?> action)
|
||||||
{
|
{
|
||||||
foreach (var node in Nodes)
|
foreach (var node in Nodes)
|
||||||
|
|
@ -73,13 +66,13 @@ public class ResourceTree
|
||||||
};
|
};
|
||||||
ModelId = character->ModelContainer.ModelCharaId;
|
ModelId = character->ModelContainer.ModelCharaId;
|
||||||
CustomizeData = character->DrawData.CustomizeData;
|
CustomizeData = character->DrawData.CustomizeData;
|
||||||
RaceCode = human != null ? (GenderRace)human->RaceSexId : GenderRace.Unknown;
|
RaceCode = human is not null ? (GenderRace)human->RaceSexId : GenderRace.Unknown;
|
||||||
|
|
||||||
var genericContext = globalContext.CreateContext(model);
|
var genericContext = globalContext.CreateContext(model);
|
||||||
|
|
||||||
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1312)
|
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1312)
|
||||||
var mpapArrayPtr = *(ResourceHandle***)((nint)model + 0x948);
|
var mpapArrayPtr = *(ResourceHandle***)((nint)model + 0x948);
|
||||||
var mpapArray = null != mpapArrayPtr ? new ReadOnlySpan<Pointer<ResourceHandle>>(mpapArrayPtr, model->SlotCount) : [];
|
var mpapArray = mpapArrayPtr is not null ? new ReadOnlySpan<Pointer<ResourceHandle>>(mpapArrayPtr, model->SlotCount) : [];
|
||||||
var decalArray = modelType switch
|
var decalArray = modelType switch
|
||||||
{
|
{
|
||||||
ModelType.Human => human->SlotDecalsSpan,
|
ModelType.Human => human->SlotDecalsSpan,
|
||||||
|
|
@ -105,19 +98,17 @@ public class ResourceTree
|
||||||
: globalContext.CreateContext(model, i),
|
: globalContext.CreateContext(model, i),
|
||||||
};
|
};
|
||||||
|
|
||||||
var imc = (ResourceHandle*)model->IMCArray[i];
|
var imc = (ResourceHandle*)model->IMCArray[i];
|
||||||
var imcNode = slotContext.CreateNodeFromImc(imc);
|
if (slotContext.CreateNodeFromImc(imc) is { } imcNode)
|
||||||
if (imcNode != null)
|
|
||||||
{
|
{
|
||||||
if (globalContext.WithUiData)
|
if (globalContext.WithUiData)
|
||||||
imcNode.FallbackName = $"IMC #{i}";
|
imcNode.FallbackName = $"IMC #{i}";
|
||||||
Nodes.Add(imcNode);
|
Nodes.Add(imcNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
var mdl = model->Models[i];
|
var mdl = model->Models[i];
|
||||||
var mdlNode = slotContext.CreateNodeFromModel(mdl, imc, i < decalArray.Length ? decalArray[(int)i].Value : null,
|
if (slotContext.CreateNodeFromModel(mdl, imc, i < decalArray.Length ? decalArray[(int)i].Value : null,
|
||||||
i < mpapArray.Length ? mpapArray[(int)i].Value : null);
|
i < mpapArray.Length ? mpapArray[(int)i].Value : null) is { } mdlNode)
|
||||||
if (mdlNode != null)
|
|
||||||
{
|
{
|
||||||
if (globalContext.WithUiData)
|
if (globalContext.WithUiData)
|
||||||
mdlNode.FallbackName = $"Model #{i}";
|
mdlNode.FallbackName = $"Model #{i}";
|
||||||
|
|
@ -131,7 +122,7 @@ public class ResourceTree
|
||||||
|
|
||||||
AddWeapons(globalContext, model);
|
AddWeapons(globalContext, model);
|
||||||
|
|
||||||
if (human != null)
|
if (human is not null)
|
||||||
AddHumanResources(globalContext, human);
|
AddHumanResources(globalContext, human);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,12 +132,12 @@ public class ResourceTree
|
||||||
var weaponNodes = new List<ResourceNode>();
|
var weaponNodes = new List<ResourceNode>();
|
||||||
foreach (var baseSubObject in model->DrawObject.Object.ChildObjects)
|
foreach (var baseSubObject in model->DrawObject.Object.ChildObjects)
|
||||||
{
|
{
|
||||||
if (baseSubObject->GetObjectType() != FFXIVClientStructs.FFXIV.Client.Graphics.Scene.ObjectType.CharacterBase)
|
if (baseSubObject->GetObjectType() is not FFXIVClientStructs.FFXIV.Client.Graphics.Scene.ObjectType.CharacterBase)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var subObject = (CharacterBase*)baseSubObject;
|
var subObject = (CharacterBase*)baseSubObject;
|
||||||
|
|
||||||
if (subObject->GetModelType() != ModelType.Weapon)
|
if (subObject->GetModelType() is not ModelType.Weapon)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var weapon = (Weapon*)subObject;
|
var weapon = (Weapon*)subObject;
|
||||||
|
|
@ -160,24 +151,22 @@ public class ResourceTree
|
||||||
|
|
||||||
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1312)
|
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1312)
|
||||||
var mpapArrayPtr = *(ResourceHandle***)((nint)subObject + 0x948);
|
var mpapArrayPtr = *(ResourceHandle***)((nint)subObject + 0x948);
|
||||||
var mpapArray = null != mpapArrayPtr ? new ReadOnlySpan<Pointer<ResourceHandle>>(mpapArrayPtr, subObject->SlotCount) : [];
|
var mpapArray = mpapArrayPtr is not null ? new ReadOnlySpan<Pointer<ResourceHandle>>(mpapArrayPtr, subObject->SlotCount) : [];
|
||||||
|
|
||||||
for (var i = 0; i < subObject->SlotCount; ++i)
|
for (var i = 0; i < subObject->SlotCount; ++i)
|
||||||
{
|
{
|
||||||
var slotContext = globalContext.CreateContext(subObject, (uint)i, slot, equipment, weaponType);
|
var slotContext = globalContext.CreateContext(subObject, (uint)i, slot, equipment, weaponType);
|
||||||
|
|
||||||
var imc = (ResourceHandle*)subObject->IMCArray[i];
|
var imc = (ResourceHandle*)subObject->IMCArray[i];
|
||||||
var imcNode = slotContext.CreateNodeFromImc(imc);
|
if (slotContext.CreateNodeFromImc(imc) is { } imcNode)
|
||||||
if (imcNode != null)
|
|
||||||
{
|
{
|
||||||
if (globalContext.WithUiData)
|
if (globalContext.WithUiData)
|
||||||
imcNode.FallbackName = $"Weapon #{weaponIndex}, IMC #{i}";
|
imcNode.FallbackName = $"Weapon #{weaponIndex}, IMC #{i}";
|
||||||
weaponNodes.Add(imcNode);
|
weaponNodes.Add(imcNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
var mdl = subObject->Models[i];
|
var mdl = subObject->Models[i];
|
||||||
var mdlNode = slotContext.CreateNodeFromModel(mdl, imc, weapon->Decal, i < mpapArray.Length ? mpapArray[i].Value : null);
|
if (slotContext.CreateNodeFromModel(mdl, imc, weapon->Decal, i < mpapArray.Length ? mpapArray[i].Value : null) is { } mdlNode)
|
||||||
if (mdlNode != null)
|
|
||||||
{
|
{
|
||||||
if (globalContext.WithUiData)
|
if (globalContext.WithUiData)
|
||||||
mdlNode.FallbackName = $"Weapon #{weaponIndex}, Model #{i}";
|
mdlNode.FallbackName = $"Weapon #{weaponIndex}, Model #{i}";
|
||||||
|
|
@ -185,9 +174,11 @@ public class ResourceTree
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AddSkeleton(weaponNodes, genericContext, subObject->EID, subObject->Skeleton, subObject->BonePhysicsModule, $"Weapon #{weaponIndex}, ");
|
AddSkeleton(weaponNodes, genericContext, subObject->EID, subObject->Skeleton, subObject->BonePhysicsModule,
|
||||||
|
$"Weapon #{weaponIndex}, ");
|
||||||
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1312)
|
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1312)
|
||||||
AddMaterialAnimationSkeleton(weaponNodes, genericContext, *(SkeletonResourceHandle**)((nint)subObject + 0x940), $"Weapon #{weaponIndex}, ");
|
AddMaterialAnimationSkeleton(weaponNodes, genericContext, *(SkeletonResourceHandle**)((nint)subObject + 0x940),
|
||||||
|
$"Weapon #{weaponIndex}, ");
|
||||||
|
|
||||||
++weaponIndex;
|
++weaponIndex;
|
||||||
}
|
}
|
||||||
|
|
@ -200,28 +191,25 @@ public class ResourceTree
|
||||||
var genericContext = globalContext.CreateContext(&human->CharacterBase);
|
var genericContext = globalContext.CreateContext(&human->CharacterBase);
|
||||||
|
|
||||||
var cache = globalContext.Collection._cache;
|
var cache = globalContext.Collection._cache;
|
||||||
if (cache != null && cache.CustomResources.TryGetValue(PreBoneDeformerReplacer.PreBoneDeformerPath, out var pbdHandle))
|
if (cache is not null
|
||||||
|
&& cache.CustomResources.TryGetValue(PreBoneDeformerReplacer.PreBoneDeformerPath, out var pbdHandle)
|
||||||
|
&& genericContext.CreateNodeFromPbd(pbdHandle.ResourceHandle) is { } pbdNode)
|
||||||
{
|
{
|
||||||
var pbdNode = genericContext.CreateNodeFromPbd(pbdHandle.ResourceHandle);
|
if (globalContext.WithUiData)
|
||||||
if (pbdNode != null)
|
|
||||||
{
|
{
|
||||||
if (globalContext.WithUiData)
|
pbdNode = pbdNode.Clone();
|
||||||
{
|
pbdNode.FallbackName = "Racial Deformer";
|
||||||
pbdNode = pbdNode.Clone();
|
pbdNode.IconFlag = ChangedItemIconFlag.Customization;
|
||||||
pbdNode.FallbackName = "Racial Deformer";
|
|
||||||
pbdNode.IconFlag = ChangedItemIconFlag.Customization;
|
|
||||||
}
|
|
||||||
|
|
||||||
Nodes.Add(pbdNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Nodes.Add(pbdNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
var decalId = (byte)(human->Customize[(int)CustomizeIndex.Facepaint] & 0x7F);
|
var decalId = (byte)(human->Customize[(int)CustomizeIndex.Facepaint] & 0x7F);
|
||||||
var decalPath = decalId != 0
|
var decalPath = decalId is not 0
|
||||||
? GamePaths.Human.Decal.FaceDecalPath(decalId)
|
? GamePaths.Human.Decal.FaceDecalPath(decalId)
|
||||||
: GamePaths.Tex.TransparentPath;
|
: GamePaths.Tex.TransparentPath;
|
||||||
var decalNode = genericContext.CreateNodeFromTex(human->Decal, decalPath);
|
if (genericContext.CreateNodeFromTex(human->Decal, decalPath) is { } decalNode)
|
||||||
if (decalNode != null)
|
|
||||||
{
|
{
|
||||||
if (globalContext.WithUiData)
|
if (globalContext.WithUiData)
|
||||||
{
|
{
|
||||||
|
|
@ -237,8 +225,7 @@ public class ResourceTree
|
||||||
var legacyDecalPath = hasLegacyDecal
|
var legacyDecalPath = hasLegacyDecal
|
||||||
? GamePaths.Human.Decal.LegacyDecalPath
|
? GamePaths.Human.Decal.LegacyDecalPath
|
||||||
: GamePaths.Tex.TransparentPath;
|
: GamePaths.Tex.TransparentPath;
|
||||||
var legacyDecalNode = genericContext.CreateNodeFromTex(human->LegacyBodyDecal, legacyDecalPath);
|
if (genericContext.CreateNodeFromTex(human->LegacyBodyDecal, legacyDecalPath) is { } legacyDecalNode)
|
||||||
if (legacyDecalNode != null)
|
|
||||||
{
|
{
|
||||||
legacyDecalNode.ForceProtected = !hasLegacyDecal;
|
legacyDecalNode.ForceProtected = !hasLegacyDecal;
|
||||||
if (globalContext.WithUiData)
|
if (globalContext.WithUiData)
|
||||||
|
|
@ -252,7 +239,8 @@ public class ResourceTree
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void AddSkeleton(List<ResourceNode> nodes, ResolveContext context, void* eid, Skeleton* skeleton, BonePhysicsModule* physics, string prefix = "")
|
private unsafe void AddSkeleton(List<ResourceNode> nodes, ResolveContext context, void* eid, Skeleton* skeleton, BonePhysicsModule* physics,
|
||||||
|
string prefix = "")
|
||||||
{
|
{
|
||||||
var eidNode = context.CreateNodeFromEid((ResourceHandle*)eid);
|
var eidNode = context.CreateNodeFromEid((ResourceHandle*)eid);
|
||||||
if (eidNode != null)
|
if (eidNode != null)
|
||||||
|
|
@ -269,8 +257,7 @@ public class ResourceTree
|
||||||
{
|
{
|
||||||
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1312)
|
// TODO ClientStructs-ify (aers/FFXIVClientStructs#1312)
|
||||||
var phybHandle = physics != null ? ((ResourceHandle**)((nint)physics + 0x190))[i] : null;
|
var phybHandle = physics != null ? ((ResourceHandle**)((nint)physics + 0x190))[i] : null;
|
||||||
var sklbNode = context.CreateNodeFromPartialSkeleton(&skeleton->PartialSkeletons[i], phybHandle, (uint)i);
|
if (context.CreateNodeFromPartialSkeleton(&skeleton->PartialSkeletons[i], phybHandle, (uint)i) is { } sklbNode)
|
||||||
if (sklbNode != null)
|
|
||||||
{
|
{
|
||||||
if (context.Global.WithUiData)
|
if (context.Global.WithUiData)
|
||||||
sklbNode.FallbackName = $"{prefix}Skeleton #{i}";
|
sklbNode.FallbackName = $"{prefix}Skeleton #{i}";
|
||||||
|
|
@ -279,10 +266,11 @@ public class ResourceTree
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void AddMaterialAnimationSkeleton(List<ResourceNode> nodes, ResolveContext context, SkeletonResourceHandle* sklbHandle, string prefix = "")
|
private unsafe void AddMaterialAnimationSkeleton(List<ResourceNode> nodes, ResolveContext context, SkeletonResourceHandle* sklbHandle,
|
||||||
|
string prefix = "")
|
||||||
{
|
{
|
||||||
var sklbNode = context.CreateNodeFromMaterialSklb(sklbHandle);
|
var sklbNode = context.CreateNodeFromMaterialSklb(sklbHandle);
|
||||||
if (sklbNode == null)
|
if (sklbNode is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (context.Global.WithUiData)
|
if (context.Global.WithUiData)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue