Make line endings explicit in editorconfig and share in sub projects, also apply editorconfig everywhere and move some namespaces.

This commit is contained in:
Ottermandias 2023-09-18 16:56:16 +02:00
parent 53adb6fa54
commit 2b4a01df06
155 changed files with 1620 additions and 1614 deletions

View file

@ -80,7 +80,8 @@ public sealed unsafe class LiveColorTablePreviewer : LiveMaterialPreviewerBase
textureSize[0] = TextureWidth;
textureSize[1] = TextureHeight;
using var texture = new SafeTextureHandle(Structs.TextureUtility.Create2D(Device.Instance(), textureSize, 1, 0x2460, 0x80000804, 7), false);
using var texture =
new SafeTextureHandle(Structs.TextureUtility.Create2D(Device.Instance(), textureSize, 1, 0x2460, 0x80000804, 7), false);
if (texture.IsInvalid)
return;

View file

@ -17,7 +17,7 @@ namespace Penumbra.Interop.PathResolving;
public unsafe class AnimationHookService : IDisposable
{
private readonly PerformanceTracker _performance;
private readonly IObjectTable _objects;
private readonly IObjectTable _objects;
private readonly CollectionResolver _collectionResolver;
private readonly DrawObjectState _drawObjectState;
private readonly CollectionResolver _resolver;
@ -34,7 +34,7 @@ public unsafe class AnimationHookService : IDisposable
_collectionResolver = collectionResolver;
_drawObjectState = drawObjectState;
_resolver = resolver;
_conditions = conditions;
_conditions = conditions;
SignatureHelper.Initialise(this);
@ -122,7 +122,7 @@ public unsafe class AnimationHookService : IDisposable
var last = _characterSoundData.Value;
_characterSoundData.Value = _collectionResolver.IdentifyCollection((GameObject*)character, true);
var ret = _loadCharacterSoundHook.Original(character, unk1, unk2, unk3, unk4, unk5, unk6, unk7);
_characterSoundData.Value = last;
_characterSoundData.Value = last;
return ret;
}
@ -140,15 +140,15 @@ public unsafe class AnimationHookService : IDisposable
using var performance = _performance.Measure(PerformanceType.TimelineResources);
// Do not check timeline loading in cutscenes.
if (_conditions[ConditionFlag.OccupiedInCutSceneEvent] || _conditions[ConditionFlag.WatchingCutscene78])
return _loadTimelineResourcesHook.Original(timeline);
return _loadTimelineResourcesHook.Original(timeline);
var last = _animationLoadData.Value;
var last = _animationLoadData.Value;
_animationLoadData.Value = GetDataFromTimeline(timeline);
var ret = _loadTimelineResourcesHook.Original(timeline);
_animationLoadData.Value = last;
return ret;
}
/// <summary>
/// Probably used when the base idle animation gets loaded.
/// Make it aware of the correct collection to load the correct pap files.
@ -297,12 +297,12 @@ public unsafe class AnimationHookService : IDisposable
try
{
if (timeline != IntPtr.Zero)
{
{
var getGameObjectIdx = ((delegate* unmanaged<nint, int>**)timeline)[0][Offsets.GetGameObjectIdxVfunc];
var idx = getGameObjectIdx(timeline);
if (idx >= 0 && idx < _objects.Length)
{
var obj = (GameObject*)_objects.GetObjectAddress(idx);
var obj = (GameObject*)_objects.GetObjectAddress(idx);
return obj != null ? _collectionResolver.IdentifyCollection(obj, true) : ResolveData.Invalid;
}
}
@ -378,17 +378,17 @@ public unsafe class AnimationHookService : IDisposable
if (a6 == nint.Zero)
return _apricotListenerSoundPlayHook!.Original(a1, a2, a3, a4, a5, a6);
var last = _animationLoadData.Value;
// a6 is some instance of Apricot.IInstanceListenner, in some cases we can obtain the associated caster via vfunc 1.
var last = _animationLoadData.Value;
// a6 is some instance of Apricot.IInstanceListenner, in some cases we can obtain the associated caster via vfunc 1.
var gameObject = (*(delegate* unmanaged<nint, GameObject*>**)a6)[1](a6);
if (gameObject != null)
{
_animationLoadData.Value = _collectionResolver.IdentifyCollection(gameObject, true);
}
else
{
// for VfxListenner we can obtain the associated draw object as its first member,
// if the object has different type, drawObject will contain other values or garbage,
{
// for VfxListenner we can obtain the associated draw object as its first member,
// if the object has different type, drawObject will contain other values or garbage,
// but only be used in a dictionary pointer lookup, so this does not hurt.
var drawObject = ((DrawObject**)a6)[1];
if (drawObject != null)

View file

@ -20,7 +20,7 @@ public unsafe class CollectionResolver
private readonly HumanModelList _humanModels;
private readonly IClientState _clientState;
private readonly IGameGui _gameGui;
private readonly IGameGui _gameGui;
private readonly ActorService _actors;
private readonly CutsceneService _cutscenes;

View file

@ -10,7 +10,7 @@ namespace Penumbra.Interop.PathResolving;
public class DrawObjectState : IDisposable, IReadOnlyDictionary<nint, (nint, bool)>
{
private readonly IObjectTable _objects;
private readonly IObjectTable _objects;
private readonly GameEventManager _gameEvents;
private readonly Dictionary<nint, (nint GameObject, bool IsChild)> _drawObjectToGameObject = new();
@ -71,8 +71,8 @@ public class DrawObjectState : IDisposable, IReadOnlyDictionary<nint, (nint, boo
private unsafe void OnWeaponReloaded(nint _, nint gameObject)
{
_lastGameObject.Value!.Dequeue();
IterateDrawObjectTree((Object*) ((GameObject*) gameObject)->DrawObject, gameObject, false, false);
_lastGameObject.Value!.Dequeue();
IterateDrawObjectTree((Object*)((GameObject*)gameObject)->DrawObject, gameObject, false, false);
}
private void OnCharacterBaseDestructor(nint characterBase)

View file

@ -25,8 +25,8 @@ public unsafe class IdentifiedCollectionCache : IDisposable, IEnumerable<(nint A
_events = events;
_communicator.CollectionChange.Subscribe(CollectionChangeClear, CollectionChange.Priority.IdentifiedCollectionCache);
_clientState.TerritoryChanged += TerritoryClear;
_events.CharacterDestructor += OnCharacterDestruct;
_clientState.TerritoryChanged += TerritoryClear;
_events.CharacterDestructor += OnCharacterDestruct;
}
public ResolveData Set(ModCollection collection, ActorIdentifier identifier, GameObject* data)
@ -61,8 +61,8 @@ public unsafe class IdentifiedCollectionCache : IDisposable, IEnumerable<(nint A
public void Dispose()
{
_communicator.CollectionChange.Unsubscribe(CollectionChangeClear);
_clientState.TerritoryChanged -= TerritoryClear;
_events.CharacterDestructor -= OnCharacterDestruct;
_clientState.TerritoryChanged -= TerritoryClear;
_events.CharacterDestructor -= OnCharacterDestruct;
}
public IEnumerator<(nint Address, ActorIdentifier Identifier, ModCollection Collection)> GetEnumerator()

View file

@ -1,5 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using FFXIVClientStructs.FFXIV.Client.System.Resource;
using Penumbra.Api.Enums;
using Penumbra.Collections;
using Penumbra.Collections.Manager;
using Penumbra.GameData.Enums;

View file

@ -1,4 +1,3 @@
using System.Collections.Concurrent;
using Dalamud.Hooking;
using Dalamud.Utility.Signatures;
using Penumbra.Collections;

View file

@ -81,6 +81,6 @@ public unsafe class FileReadService : IDisposable
/// </summary>
private nint GetResourceManager()
=> !_lastFileThreadResourceManager.IsValueCreated || _lastFileThreadResourceManager.Value == IntPtr.Zero
? (nint) _resourceManager.ResourceManager
? (nint)_resourceManager.ResourceManager
: _lastFileThreadResourceManager.Value;
}

View file

@ -37,7 +37,8 @@ public class ResourceNode
Children = new List<ResourceNode>();
}
public ResourceNode(UIData uiData, ResourceType type, nint objectAddress, nint resourceHandle, Utf8GamePath[] possibleGamePaths, FullPath fullPath,
public ResourceNode(UIData uiData, ResourceType type, nint objectAddress, nint resourceHandle, Utf8GamePath[] possibleGamePaths,
FullPath fullPath,
ulong length, bool @internal)
{
Name = uiData.Name;
@ -69,7 +70,7 @@ public class ResourceNode
}
public ResourceNode WithUIData(string? name, ChangedItemIcon icon)
=> string.Equals(Name, name, StringComparison.Ordinal) && Icon == icon ? this : new ResourceNode(new(name, icon), this);
=> string.Equals(Name, name, StringComparison.Ordinal) && Icon == icon ? this : new ResourceNode(new UIData(name, icon), this);
public ResourceNode WithUIData(UIData uiData)
=> string.Equals(Name, uiData.Name, StringComparison.Ordinal) && Icon == uiData.Icon ? this : new ResourceNode(uiData, this);
@ -77,6 +78,6 @@ public class ResourceNode
public readonly record struct UIData(string? Name, ChangedItemIcon Icon)
{
public readonly UIData PrependName(string prefix)
=> Name == null ? this : new(prefix + Name, Icon);
=> Name == null ? this : new UIData(prefix + Name, Icon);
}
}

View file

@ -1,6 +1,6 @@
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
@ -16,7 +16,7 @@ public class ResourceTree
public readonly nint DrawObjectAddress;
public readonly bool PlayerRelated;
public readonly string CollectionName;
public readonly List<ResourceNode> Nodes;
public readonly List<ResourceNode> Nodes;
public readonly HashSet<ResourceNode> FlatNodes;
public int ModelId;
@ -26,11 +26,11 @@ public class ResourceTree
public ResourceTree(string name, nint gameObjectAddress, nint drawObjectAddress, bool playerRelated, string collectionName)
{
Name = name;
GameObjectAddress = gameObjectAddress;
GameObjectAddress = gameObjectAddress;
DrawObjectAddress = drawObjectAddress;
PlayerRelated = playerRelated;
CollectionName = collectionName;
Nodes = new List<ResourceNode>();
Nodes = new List<ResourceNode>();
FlatNodes = new HashSet<ResourceNode>();
}
@ -42,7 +42,7 @@ public class ResourceTree
// var customize = new ReadOnlySpan<byte>( character->CustomizeData, 26 );
ModelId = character->CharacterData.ModelCharaId;
CustomizeData = character->DrawData.CustomizeData;
RaceCode = model->GetModelType() == CharacterBase.ModelType.Human ? (GenderRace) ((Human*)model)->RaceSexId : GenderRace.Unknown;
RaceCode = model->GetModelType() == CharacterBase.ModelType.Human ? (GenderRace)((Human*)model)->RaceSexId : GenderRace.Unknown;
for (var i = 0; i < model->SlotCount; ++i)
{
@ -60,8 +60,8 @@ public class ResourceTree
var mdlNode = context.CreateNodeFromRenderModel(mdl);
if (mdlNode != null)
Nodes.Add(globalContext.WithUiData ? mdlNode.WithUIData(mdlNode.Name ?? $"Model #{i}", mdlNode.Icon) : mdlNode);
}
}
AddSkeleton(Nodes, globalContext.CreateContext(EquipSlot.Unknown, default), model->Skeleton);
if (character->GameObject.GetObjectKind() == (byte)ObjectKind.Pc)
@ -100,8 +100,8 @@ public class ResourceTree
subObjectNodes.Add(globalContext.WithUiData
? mdlNode.WithUIData(mdlNode.Name ?? $"{subObjectNamePrefix} #{subObjectIndex}, Model #{i}", mdlNode.Icon)
: mdlNode);
}
}
AddSkeleton(subObjectNodes, subObjectContext, subObject->Skeleton, $"{subObjectNamePrefix} #{subObjectIndex}, ");
subObject = (CharacterBase*)subObject->DrawObject.Object.NextSiblingObject;
@ -119,19 +119,21 @@ public class ResourceTree
var legacyDecalNode = context.CreateNodeFromTex((TextureResourceHandle*)human->LegacyBodyDecal);
if (legacyDecalNode != null)
Nodes.Add(globalContext.WithUiData ? legacyDecalNode.WithUIData(legacyDecalNode.Name ?? "Legacy Body Decal", legacyDecalNode.Icon) : legacyDecalNode);
}
private unsafe void AddSkeleton(List<ResourceNode> nodes, ResolveContext context, Skeleton* skeleton, string prefix = "")
{
if (skeleton == null)
return;
for (var i = 0; i < skeleton->PartialSkeletonCount; ++i)
{
var sklbNode = context.CreateNodeFromPartialSkeleton(&skeleton->PartialSkeletons[i]);
if (sklbNode != null)
nodes.Add(context.WithUiData ? sklbNode.WithUIData($"{prefix}Skeleton #{i}", sklbNode.Icon) : sklbNode);
}
Nodes.Add(globalContext.WithUiData
? legacyDecalNode.WithUIData(legacyDecalNode.Name ?? "Legacy Body Decal", legacyDecalNode.Icon)
: legacyDecalNode);
}
private unsafe void AddSkeleton(List<ResourceNode> nodes, ResolveContext context, Skeleton* skeleton, string prefix = "")
{
if (skeleton == null)
return;
for (var i = 0; i < skeleton->PartialSkeletonCount; ++i)
{
var sklbNode = context.CreateNodeFromPartialSkeleton(&skeleton->PartialSkeletons[i]);
if (sklbNode != null)
nodes.Add(context.WithUiData ? sklbNode.WithUIData($"{prefix}Skeleton #{i}", sklbNode.Icon) : sklbNode);
}
}
}

View file

@ -4,21 +4,25 @@ namespace Penumbra.Interop.SafeHandles;
public unsafe class SafeResourceHandle : SafeHandle
{
public ResourceHandle* ResourceHandle => (ResourceHandle*)handle;
public ResourceHandle* ResourceHandle
=> (ResourceHandle*)handle;
public override bool IsInvalid => handle == 0;
public override bool IsInvalid
=> handle == 0;
public SafeResourceHandle(ResourceHandle* handle, bool incRef, bool ownsHandle = true) : base(0, ownsHandle)
public SafeResourceHandle(ResourceHandle* handle, bool incRef, bool ownsHandle = true)
: base(0, ownsHandle)
{
if (incRef && !ownsHandle)
throw new ArgumentException("Non-owning SafeResourceHandle with IncRef is unsupported");
if (incRef && handle != null)
handle->IncRef();
SetHandle((nint)handle);
}
public static SafeResourceHandle CreateInvalid()
=> new(null, incRef: false);
=> new(null, false);
protected override bool ReleaseHandle()
{

View file

@ -5,14 +5,18 @@ namespace Penumbra.Interop.SafeHandles;
public unsafe class SafeTextureHandle : SafeHandle
{
public Texture* Texture => (Texture*)handle;
public Texture* Texture
=> (Texture*)handle;
public override bool IsInvalid => handle == 0;
public override bool IsInvalid
=> handle == 0;
public SafeTextureHandle(Texture* handle, bool incRef, bool ownsHandle = true) : base(0, ownsHandle)
public SafeTextureHandle(Texture* handle, bool incRef, bool ownsHandle = true)
: base(0, ownsHandle)
{
if (incRef && !ownsHandle)
throw new ArgumentException("Non-owning SafeTextureHandle with IncRef is unsupported");
if (incRef && handle != null)
TextureUtility.IncRef(handle);
SetHandle((nint)handle);
@ -27,16 +31,17 @@ public unsafe class SafeTextureHandle : SafeHandle
}
public static SafeTextureHandle CreateInvalid()
=> new(null, incRef: false);
=> new(null, false);
protected override bool ReleaseHandle()
{
nint handle;
lock (this)
{
handle = this.handle;
handle = this.handle;
this.handle = 0;
}
if (handle != 0)
TextureUtility.DecRef((Texture*)handle);

View file

@ -14,7 +14,7 @@ public sealed unsafe class DecalReverter : IDisposable
public static readonly Utf8GamePath TransparentPath =
Utf8GamePath.FromSpan("chara/common/texture/transparent.tex"u8, out var p) ? p : Utf8GamePath.Empty;
private readonly CharacterUtility _utility;
private readonly CharacterUtility _utility;
private readonly Structs.TextureResourceHandle* _decal;
private readonly Structs.TextureResourceHandle* _transparent;
@ -22,10 +22,10 @@ public sealed unsafe class DecalReverter : IDisposable
{
_utility = utility;
var ptr = _utility.Address;
_decal = null;
_decal = null;
_transparent = null;
if (!config.EnableMods)
return;
return;
if (doDecal)
{

View file

@ -152,7 +152,7 @@ public unsafe class GameEventManager : IDisposable
{
try
{
((CreatingCharacterBaseEvent)subscriber).Invoke((nint) (&a), b, c);
((CreatingCharacterBaseEvent)subscriber).Invoke((nint)(&a), b, c);
}
catch (Exception ex)
{
@ -265,11 +265,13 @@ public unsafe class GameEventManager : IDisposable
private readonly Hook<TestDelegate>? _testHook = null;
private delegate void TestDelegate(nint a1, int a2);
private void TestDetour(nint a1, int a2)
{
Penumbra.Log.Information($"Test: {a1:X} {a2}");
_testHook!.Original(a1, a2);
}
private void EnableDebugHook()
=> _testHook?.Enable();

View file

@ -100,10 +100,10 @@ public unsafe partial class RedrawService
public sealed unsafe partial class RedrawService : IDisposable
{
private readonly Framework _framework;
private readonly Framework _framework;
private readonly IObjectTable _objects;
private readonly ITargetManager _targets;
private readonly Condition _conditions;
private readonly Condition _conditions;
private readonly List<int> _queue = new(100);
private readonly List<int> _afterGPoseQueue = new(GPoseSlots);
@ -207,7 +207,7 @@ public sealed unsafe partial class RedrawService : IDisposable
return;
_targets.Target = actor;
_target = -1;
_target = -1;
}
private void HandleRedraw()

View file

@ -1,6 +1,6 @@
using Dalamud.Utility.Signatures;
using Penumbra.GameData;
namespace Penumbra.Interop.Services;
public unsafe class ResidentResourceManager
@ -36,4 +36,4 @@ public unsafe class ResidentResourceManager
LoadPlayerResources.Invoke(Address);
}
}
}
}

View file

@ -2,23 +2,23 @@ using Penumbra.GameData.Enums;
namespace Penumbra.Interop.Structs;
[StructLayout( LayoutKind.Explicit )]
[StructLayout(LayoutKind.Explicit)]
public unsafe struct CharacterUtilityData
{
public const int IndexTransparentTex = 72;
public const int IndexDecalTex = 73;
public const int IndexSkinShpk = 76;
public static readonly MetaIndex[] EqdpIndices = Enum.GetNames< MetaIndex >()
.Zip( Enum.GetValues< MetaIndex >() )
.Where( n => n.First.StartsWith( "Eqdp" ) )
.Select( n => n.Second ).ToArray();
public static readonly MetaIndex[] EqdpIndices = Enum.GetNames<MetaIndex>()
.Zip(Enum.GetValues<MetaIndex>())
.Where(n => n.First.StartsWith("Eqdp"))
.Select(n => n.Second).ToArray();
public const int TotalNumResources = 87;
/// <summary> Obtain the index for the eqdp file corresponding to the given race code and accessory. </summary>
public static MetaIndex EqdpIdx( GenderRace raceCode, bool accessory )
=> +( int )raceCode switch
public static MetaIndex EqdpIdx(GenderRace raceCode, bool accessory)
=> +(int)raceCode switch
{
0101 => accessory ? MetaIndex.Eqdp0101Acc : MetaIndex.Eqdp0101,
0201 => accessory ? MetaIndex.Eqdp0201Acc : MetaIndex.Eqdp0201,
@ -48,53 +48,53 @@ public unsafe struct CharacterUtilityData
1404 => accessory ? MetaIndex.Eqdp1404Acc : MetaIndex.Eqdp1404,
9104 => accessory ? MetaIndex.Eqdp9104Acc : MetaIndex.Eqdp9104,
9204 => accessory ? MetaIndex.Eqdp9204Acc : MetaIndex.Eqdp9204,
_ => ( MetaIndex )( -1 ),
_ => (MetaIndex)(-1),
};
[FieldOffset( 0 )]
[FieldOffset(0)]
public void* VTable;
[FieldOffset( 8 )]
[FieldOffset(8)]
public fixed ulong Resources[TotalNumResources];
[FieldOffset( 8 + ( int )MetaIndex.Eqp * 8 )]
[FieldOffset(8 + (int)MetaIndex.Eqp * 8)]
public ResourceHandle* EqpResource;
[FieldOffset( 8 + ( int )MetaIndex.Gmp * 8 )]
[FieldOffset(8 + (int)MetaIndex.Gmp * 8)]
public ResourceHandle* GmpResource;
public ResourceHandle* Resource( int idx )
=> ( ResourceHandle* )Resources[ idx ];
public ResourceHandle* Resource(int idx)
=> (ResourceHandle*)Resources[idx];
public ResourceHandle* Resource( MetaIndex idx )
=> Resource( ( int )idx );
public ResourceHandle* Resource(MetaIndex idx)
=> Resource((int)idx);
public ResourceHandle* EqdpResource( GenderRace raceCode, bool accessory )
=> Resource( ( int )EqdpIdx( raceCode, accessory ) );
public ResourceHandle* EqdpResource(GenderRace raceCode, bool accessory)
=> Resource((int)EqdpIdx(raceCode, accessory));
[FieldOffset( 8 + ( int )MetaIndex.HumanCmp * 8 )]
[FieldOffset(8 + (int)MetaIndex.HumanCmp * 8)]
public ResourceHandle* HumanCmpResource;
[FieldOffset( 8 + ( int )MetaIndex.FaceEst * 8 )]
[FieldOffset(8 + (int)MetaIndex.FaceEst * 8)]
public ResourceHandle* FaceEstResource;
[FieldOffset( 8 + ( int )MetaIndex.HairEst * 8 )]
[FieldOffset(8 + (int)MetaIndex.HairEst * 8)]
public ResourceHandle* HairEstResource;
[FieldOffset( 8 + ( int )MetaIndex.BodyEst * 8 )]
[FieldOffset(8 + (int)MetaIndex.BodyEst * 8)]
public ResourceHandle* BodyEstResource;
[FieldOffset( 8 + ( int )MetaIndex.HeadEst * 8 )]
[FieldOffset(8 + (int)MetaIndex.HeadEst * 8)]
public ResourceHandle* HeadEstResource;
[FieldOffset( 8 + IndexTransparentTex * 8 )]
[FieldOffset(8 + IndexTransparentTex * 8)]
public TextureResourceHandle* TransparentTexResource;
[FieldOffset( 8 + IndexDecalTex * 8 )]
[FieldOffset(8 + IndexDecalTex * 8)]
public TextureResourceHandle* DecalTexResource;
[FieldOffset( 8 + IndexSkinShpk * 8 )]
[FieldOffset(8 + IndexSkinShpk * 8)]
public ResourceHandle* SkinShpkResource;
// not included resources have no known use case.
}
}

View file

@ -1,11 +1,11 @@
namespace Penumbra.Interop.Structs;
[StructLayout( LayoutKind.Explicit )]
[StructLayout(LayoutKind.Explicit)]
public unsafe struct ClipScheduler
{
[FieldOffset( 0 )]
[FieldOffset(0)]
public IntPtr* VTable;
[FieldOffset( 0x38 )]
[FieldOffset(0x38)]
public IntPtr SchedulerTimeline;
}
}

View file

@ -9,4 +9,4 @@ public enum DrawState : uint
MaybeCulled = 0x00_00_04_00,
MaybeHiddenMinion = 0x00_00_80_00,
MaybeHiddenSummon = 0x00_80_00_00,
}
}

View file

@ -8,4 +8,4 @@ public enum FileMode : byte
// Probably debug options only.
LoadIndexResource = 0xA, // load index/index2
LoadSqPackResource = 0xB,
}
}

View file

@ -2,18 +2,18 @@ using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
namespace Penumbra.Interop.Structs;
[StructLayout( LayoutKind.Explicit )]
[StructLayout(LayoutKind.Explicit)]
public unsafe struct HumanExt
{
[FieldOffset( 0x0 )]
[FieldOffset(0x0)]
public Human Human;
[FieldOffset( 0x0 )]
[FieldOffset(0x0)]
public CharacterBaseExt CharacterBase;
[FieldOffset( 0x9E8 )]
[FieldOffset(0x9E8)]
public ResourceHandle* Decal;
[FieldOffset( 0x9F0 )]
[FieldOffset(0x9F0)]
public ResourceHandle* LegacyBodyDecal;
}
}

View file

@ -2,45 +2,46 @@ using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
namespace Penumbra.Interop.Structs;
[StructLayout( LayoutKind.Explicit, Size = 0x40 )]
[StructLayout(LayoutKind.Explicit, Size = 0x40)]
public unsafe struct Material
{
[FieldOffset( 0x10 )]
[FieldOffset(0x10)]
public MtrlResource* ResourceHandle;
[FieldOffset( 0x18 )]
[FieldOffset(0x18)]
public uint ShaderPackageFlags;
[FieldOffset( 0x20 )]
[FieldOffset(0x20)]
public uint* ShaderKeys;
public int ShaderKeyCount
=> (int)((uint*)Textures - ShaderKeys);
[FieldOffset( 0x28 )]
[FieldOffset(0x28)]
public ConstantBuffer* MaterialParameter;
[FieldOffset( 0x30 )]
[FieldOffset(0x30)]
public TextureEntry* Textures;
[FieldOffset( 0x38 )]
[FieldOffset(0x38)]
public ushort TextureCount;
public Texture* Texture( int index ) => Textures[index].ResourceHandle->KernelTexture;
public Texture* Texture(int index)
=> Textures[index].ResourceHandle->KernelTexture;
[StructLayout( LayoutKind.Explicit, Size = 0x18 )]
[StructLayout(LayoutKind.Explicit, Size = 0x18)]
public struct TextureEntry
{
[FieldOffset( 0x00 )]
[FieldOffset(0x00)]
public uint Id;
[FieldOffset( 0x08 )]
[FieldOffset(0x08)]
public TextureResourceHandle* ResourceHandle;
[FieldOffset( 0x10 )]
[FieldOffset(0x10)]
public uint SamplerFlags;
}
public ReadOnlySpan<TextureEntry> TextureSpan
=> new(Textures, TextureCount);
}
=> new(Textures, TextureCount);
}

View file

@ -1,45 +1,45 @@
namespace Penumbra.Interop.Structs;
[StructLayout( LayoutKind.Explicit )]
[StructLayout(LayoutKind.Explicit)]
public unsafe struct MtrlResource
{
[FieldOffset( 0x00 )]
[FieldOffset(0x00)]
public ResourceHandle Handle;
[FieldOffset( 0xC8 )]
[FieldOffset(0xC8)]
public ShaderPackageResourceHandle* ShpkResourceHandle;
[FieldOffset( 0xD0 )]
[FieldOffset(0xD0)]
public TextureEntry* TexSpace; // Contains the offsets for the tex files inside the string list.
[FieldOffset( 0xE0 )]
[FieldOffset(0xE0)]
public byte* StringList;
[FieldOffset( 0xF8 )]
[FieldOffset(0xF8)]
public ushort ShpkOffset;
[FieldOffset( 0xFA )]
[FieldOffset(0xFA)]
public byte NumTex;
public byte* ShpkString
=> StringList + ShpkOffset;
public byte* TexString( int idx )
public byte* TexString(int idx)
=> StringList + TexSpace[idx].PathOffset;
public bool TexIsDX11( int idx )
public bool TexIsDX11(int idx)
=> TexSpace[idx].Flags >= 0x8000;
[StructLayout(LayoutKind.Explicit, Size = 0x10)]
public struct TextureEntry
{
[FieldOffset( 0x00 )]
[FieldOffset(0x00)]
public TextureResourceHandle* ResourceHandle;
[FieldOffset( 0x08 )]
[FieldOffset(0x08)]
public ushort PathOffset;
[FieldOffset( 0x0A )]
[FieldOffset(0x0A)]
public ushort Flags;
}
}
}

View file

@ -2,39 +2,39 @@ using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
namespace Penumbra.Interop.Structs;
[StructLayout( LayoutKind.Explicit )]
[StructLayout(LayoutKind.Explicit)]
public unsafe struct RenderModel
{
[FieldOffset( 0x18 )]
[FieldOffset(0x18)]
public RenderModel* PreviousModel;
[FieldOffset( 0x20 )]
[FieldOffset(0x20)]
public RenderModel* NextModel;
[FieldOffset( 0x30 )]
[FieldOffset(0x30)]
public ResourceHandle* ResourceHandle;
[FieldOffset( 0x40 )]
[FieldOffset(0x40)]
public Skeleton* Skeleton;
[FieldOffset( 0x58 )]
[FieldOffset(0x58)]
public void** BoneList;
[FieldOffset( 0x60 )]
[FieldOffset(0x60)]
public int BoneListCount;
[FieldOffset( 0x70 )]
[FieldOffset(0x70)]
private void* UnkDXBuffer1;
[FieldOffset( 0x78 )]
[FieldOffset(0x78)]
private void* UnkDXBuffer2;
[FieldOffset( 0x80 )]
[FieldOffset(0x80)]
private void* UnkDXBuffer3;
[FieldOffset( 0x98 )]
[FieldOffset(0x98)]
public void** Materials;
[FieldOffset( 0xA0 )]
[FieldOffset(0xA0)]
public int MaterialCount;
}
}

View file

@ -3,15 +3,15 @@ namespace Penumbra.Interop.Structs;
[StructLayout(LayoutKind.Explicit)]
public unsafe struct ResidentResourceManager
{
[FieldOffset( 0x00 )]
[FieldOffset(0x00)]
public void** VTable;
[FieldOffset( 0x08 )]
[FieldOffset(0x08)]
public void** ResourceListVTable;
[FieldOffset( 0x14 )]
[FieldOffset(0x14)]
public uint NumResources;
[FieldOffset( 0x18 )]
[FieldOffset(0x18)]
public ResourceHandle** ResourceList;
}
}

View file

@ -8,45 +8,45 @@ using Penumbra.String.Classes;
namespace Penumbra.Interop.Structs;
[StructLayout( LayoutKind.Explicit )]
[StructLayout(LayoutKind.Explicit)]
public unsafe struct TextureResourceHandle
{
[FieldOffset( 0x0 )]
[FieldOffset(0x0)]
public ResourceHandle Handle;
[FieldOffset( 0x38 )]
[FieldOffset(0x38)]
public IntPtr Unk;
[FieldOffset( 0x118 )]
[FieldOffset(0x118)]
public Texture* KernelTexture;
[FieldOffset( 0x20 )]
[FieldOffset(0x20)]
public IntPtr NewKernelTexture;
}
[StructLayout(LayoutKind.Explicit)]
public unsafe struct ShaderPackageResourceHandle
{
[FieldOffset( 0x0 )]
[FieldOffset(0x0)]
public ResourceHandle Handle;
[FieldOffset( 0xB0 )]
[FieldOffset(0xB0)]
public ShaderPackage* ShaderPackage;
}
[StructLayout( LayoutKind.Explicit )]
[StructLayout(LayoutKind.Explicit)]
public unsafe struct ResourceHandle
{
[StructLayout( LayoutKind.Explicit )]
[StructLayout(LayoutKind.Explicit)]
public struct DataIndirection
{
[FieldOffset( 0x00 )]
[FieldOffset(0x00)]
public void** VTable;
[FieldOffset( 0x10 )]
[FieldOffset(0x10)]
public byte* DataPtr;
[FieldOffset( 0x28 )]
[FieldOffset(0x28)]
public ulong DataLength;
}
@ -54,87 +54,83 @@ public unsafe struct ResourceHandle
public byte* FileNamePtr()
{
if( FileNameLength > SsoSize )
{
if (FileNameLength > SsoSize)
return FileNameData;
}
fixed( byte** name = &FileNameData )
fixed (byte** name = &FileNameData)
{
return ( byte* )name;
return (byte*)name;
}
}
public ByteString FileName()
=> ByteString.FromByteStringUnsafe( FileNamePtr(), FileNameLength, true );
=> ByteString.FromByteStringUnsafe(FileNamePtr(), FileNameLength, true);
public ReadOnlySpan< byte > FileNameAsSpan()
=> new( FileNamePtr(), FileNameLength );
public ReadOnlySpan<byte> FileNameAsSpan()
=> new(FileNamePtr(), FileNameLength);
public bool GamePath( out Utf8GamePath path )
=> Utf8GamePath.FromSpan( FileNameAsSpan(), out path );
public bool GamePath(out Utf8GamePath path)
=> Utf8GamePath.FromSpan(FileNameAsSpan(), out path);
[FieldOffset( 0x00 )]
[FieldOffset(0x00)]
public void** VTable;
[FieldOffset( 0x08 )]
[FieldOffset(0x08)]
public ResourceCategory Category;
[FieldOffset( 0x0C )]
[FieldOffset(0x0C)]
public ResourceType FileType;
[FieldOffset( 0x10 )]
[FieldOffset(0x10)]
public uint Id;
[FieldOffset( 0x28 )]
[FieldOffset(0x28)]
public uint FileSize;
[FieldOffset( 0x2C )]
[FieldOffset(0x2C)]
public uint FileSize2;
[FieldOffset( 0x34 )]
[FieldOffset(0x34)]
public uint FileSize3;
[FieldOffset( 0x48 )]
[FieldOffset(0x48)]
public byte* FileNameData;
[FieldOffset( 0x58 )]
[FieldOffset(0x58)]
public int FileNameLength;
[FieldOffset( 0xAC )]
[FieldOffset(0xAC)]
public uint RefCount;
// May return null.
public static byte* GetData( ResourceHandle* handle )
=> ( ( delegate* unmanaged< ResourceHandle*, byte* > )handle->VTable[ Offsets.ResourceHandleGetDataVfunc ] )( handle );
public static byte* GetData(ResourceHandle* handle)
=> ((delegate* unmanaged< ResourceHandle*, byte* >)handle->VTable[Offsets.ResourceHandleGetDataVfunc])(handle);
public static ulong GetLength( ResourceHandle* handle )
=> ( ( delegate* unmanaged< ResourceHandle*, ulong > )handle->VTable[ Offsets.ResourceHandleGetLengthVfunc ] )( handle );
public static ulong GetLength(ResourceHandle* handle)
=> ((delegate* unmanaged< ResourceHandle*, ulong >)handle->VTable[Offsets.ResourceHandleGetLengthVfunc])(handle);
// Only use these if you know what you are doing.
// Those are actually only sure to be accessible for DefaultResourceHandles.
[FieldOffset( 0xB0 )]
[FieldOffset(0xB0)]
public DataIndirection* Data;
[FieldOffset( 0xB8 )]
[FieldOffset(0xB8)]
public uint DataLength;
public (IntPtr Data, int Length) GetData()
=> Data != null
? ( ( IntPtr )Data->DataPtr, ( int )Data->DataLength )
: ( IntPtr.Zero, 0 );
? ((IntPtr)Data->DataPtr, (int)Data->DataLength)
: (IntPtr.Zero, 0);
public bool SetData( IntPtr data, int length )
public bool SetData(IntPtr data, int length)
{
if( Data == null )
{
if (Data == null)
return false;
}
Data->DataPtr = length != 0 ? ( byte* )data : null;
Data->DataLength = ( ulong )length;
DataLength = ( uint )length;
Data->DataPtr = length != 0 ? (byte*)data : null;
Data->DataLength = (ulong)length;
DataLength = (uint)length;
return true;
}
}
}

View file

@ -1,18 +1,17 @@
namespace Penumbra.Interop.Structs;
[StructLayout( LayoutKind.Explicit )]
[StructLayout(LayoutKind.Explicit)]
public unsafe struct SeFileDescriptor
{
[FieldOffset( 0x00 )]
[FieldOffset(0x00)]
public FileMode FileMode;
[FieldOffset( 0x30 )]
public void* FileDescriptor; //
[FieldOffset(0x30)]
public void* FileDescriptor;
[FieldOffset( 0x50 )]
public ResourceHandle* ResourceHandle; //
[FieldOffset(0x50)]
public ResourceHandle* ResourceHandle;
[FieldOffset( 0x70 )]
public char Utf16FileName; //
}
[FieldOffset(0x70)]
public char Utf16FileName;
}

View file

@ -4,12 +4,13 @@ using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
namespace Penumbra.Interop.Structs;
public unsafe static class TextureUtility
public static unsafe class TextureUtility
{
private static readonly Functions Funcs = new();
public static Texture* Create2D(Device* device, int* size, byte mipLevel, uint textureFormat, uint flags, uint unk)
=> ((delegate* unmanaged<Device*, int*, byte, uint, uint, uint, Texture*>)Funcs.TextureCreate2D)(device, size, mipLevel, textureFormat, flags, unk);
=> ((delegate* unmanaged<Device*, int*, byte, uint, uint, uint, Texture*>)Funcs.TextureCreate2D)(device, size, mipLevel, textureFormat,
flags, unk);
public static bool InitializeContents(Texture* texture, void* contents)
=> ((delegate* unmanaged<Texture*, void*, bool>)Funcs.TextureInitializeContents)(texture, contents);

View file

@ -1,17 +1,17 @@
namespace Penumbra.Interop.Structs;
[StructLayout( LayoutKind.Explicit )]
[StructLayout(LayoutKind.Explicit)]
public unsafe struct VfxParams
{
[FieldOffset( 0x118 )]
[FieldOffset(0x118)]
public uint GameObjectId;
[FieldOffset( 0x11C )]
[FieldOffset(0x11C)]
public byte GameObjectType;
[FieldOffset( 0xD0 )]
[FieldOffset(0xD0)]
public ushort TargetCount;
[FieldOffset( 0x120 )]
[FieldOffset(0x120)]
public fixed ulong Target[16];
}
}