Material editor: live-preview changes

This commit is contained in:
Exter-N 2023-08-19 05:42:26 +02:00
parent ccca2f1434
commit f64fdd2b26
14 changed files with 1067 additions and 110 deletions

View file

@ -65,26 +65,34 @@ internal record class ResolveContext(Configuration Config, IObjectIdentifier Ide
private ResourceNode CreateNodeFromGamePath(ResourceType type, nint sourceAddress, Utf8GamePath gamePath, bool @internal)
=> new(null, type, sourceAddress, gamePath, FilterFullPath(Collection.ResolvePath(gamePath) ?? new FullPath(gamePath)), @internal);
private unsafe ResourceNode? CreateNodeFromResourceHandle(ResourceType type, nint sourceAddress, ResourceHandle* handle, bool @internal,
bool withName)
public static unsafe FullPath GetResourceHandlePath(ResourceHandle* handle)
{
if (handle == null)
return null;
var name = handle->FileName();
if (name.IsEmpty)
return null;
return FullPath.Empty;
if (name[0] == (byte)'|')
{
var pos = name.IndexOf((byte)'|', 1);
if (pos < 0)
return null;
return FullPath.Empty;
name = name.Substring(pos + 1);
}
var fullPath = new FullPath(Utf8GamePath.FromByteString(name, out var p) ? p : Utf8GamePath.Empty);
return new FullPath(Utf8GamePath.FromByteString(name, out var p) ? p : Utf8GamePath.Empty);
}
private unsafe ResourceNode? CreateNodeFromResourceHandle(ResourceType type, nint sourceAddress, ResourceHandle* handle, bool @internal,
bool withName)
{
if (handle == null)
return null;
var fullPath = GetResourceHandlePath(handle);
if (fullPath.InternalName.IsEmpty)
return null;
var gamePaths = Collection.ReverseResolvePath(fullPath).ToList();
fullPath = FilterFullPath(fullPath);
@ -161,7 +169,7 @@ internal record class ResolveContext(Configuration Config, IObjectIdentifier Ide
if (mtrl == null)
return null;
var resource = (MtrlResource*)mtrl->ResourceHandle;
var resource = mtrl->ResourceHandle;
var node = CreateNodeFromResourceHandle(ResourceType.Mtrl, (nint) mtrl, &resource->Handle, false, WithNames);
if (node == null)
return null;

View file

@ -0,0 +1,31 @@
using System;
using System.Runtime.InteropServices;
namespace Penumbra.Interop.Structs;
[StructLayout(LayoutKind.Explicit, Size = 0x70)]
public unsafe struct ConstantBuffer
{
[FieldOffset(0x20)]
public int Size;
[FieldOffset(0x24)]
public int Flags;
[FieldOffset(0x28)]
private void* _maybeSourcePointer;
public bool TryGetBuffer(out Span<float> buffer)
{
if ((Flags & 0x4003) == 0 && _maybeSourcePointer != null)
{
buffer = new Span<float>(_maybeSourcePointer, Size >> 2);
return true;
}
else
{
buffer = null;
return false;
}
}
}

View file

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

View file

@ -8,8 +8,11 @@ public unsafe struct MtrlResource
[FieldOffset( 0x00 )]
public ResourceHandle Handle;
[FieldOffset( 0xC8 )]
public ShaderPackageResourceHandle* ShpkResourceHandle;
[FieldOffset( 0xD0 )]
public ushort* TexSpace; // Contains the offsets for the tex files inside the string list.
public TextureEntry* TexSpace; // Contains the offsets for the tex files inside the string list.
[FieldOffset( 0xE0 )]
public byte* StringList;
@ -24,8 +27,21 @@ public unsafe struct MtrlResource
=> StringList + ShpkOffset;
public byte* TexString( int idx )
=> StringList + *( TexSpace + 4 + idx * 8 );
=> StringList + TexSpace[idx].PathOffset;
public bool TexIsDX11( int idx )
=> *(TexSpace + 5 + idx * 8) >= 0x8000;
=> TexSpace[idx].Flags >= 0x8000;
[StructLayout(LayoutKind.Explicit, Size = 0x10)]
public struct TextureEntry
{
[FieldOffset( 0x00 )]
public TextureResourceHandle* ResourceHandle;
[FieldOffset( 0x08 )]
public ushort PathOffset;
[FieldOffset( 0x0A )]
public ushort Flags;
}
}

View file

@ -1,5 +1,7 @@
using System;
using System.Runtime.InteropServices;
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
using FFXIVClientStructs.FFXIV.Client.System.Resource;
using Penumbra.GameData;
using Penumbra.GameData.Enums;
@ -18,12 +20,22 @@ public unsafe struct TextureResourceHandle
public IntPtr Unk;
[FieldOffset( 0x118 )]
public IntPtr KernelTexture;
public Texture* KernelTexture;
[FieldOffset( 0x20 )]
public IntPtr NewKernelTexture;
}
[StructLayout(LayoutKind.Explicit)]
public unsafe struct ShaderPackageResourceHandle
{
[FieldOffset( 0x0 )]
public ResourceHandle Handle;
[FieldOffset( 0xB0 )]
public ShaderPackage* ShaderPackage;
}
[StructLayout( LayoutKind.Explicit )]
public unsafe struct ResourceHandle
{

View file

@ -0,0 +1,19 @@
using System.Runtime.InteropServices;
namespace Penumbra.Interop.Structs;
public static class ShaderPackageUtility
{
[StructLayout(LayoutKind.Explicit, Size = 0xC)]
public unsafe struct Sampler
{
[FieldOffset(0x0)]
public uint Crc;
[FieldOffset(0x4)]
public uint Id;
[FieldOffset(0xA)]
public ushort Slot;
}
}

View file

@ -0,0 +1,36 @@
using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
namespace Penumbra.Interop.Structs;
public unsafe static 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);
public static bool InitializeContents(Texture* texture, void* contents)
=> ((delegate* unmanaged<Texture*, void*, bool>)Funcs.TextureInitializeContents)(texture, contents);
public static void IncRef(Texture* texture)
=> ((delegate* unmanaged<Texture*, void>)(*(void***)texture)[2])(texture);
public static void DecRef(Texture* texture)
=> ((delegate* unmanaged<Texture*, void>)(*(void***)texture)[3])(texture);
private sealed class Functions
{
[Signature("E8 ?? ?? ?? ?? 8B 0F 48 8D 54 24")]
public nint TextureCreate2D = nint.Zero;
[Signature("E9 ?? ?? ?? ?? 8B 02 25")]
public nint TextureInitializeContents = nint.Zero;
public Functions()
{
SignatureHelper.Initialise(this);
}
}
}