mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
tmp2
This commit is contained in:
parent
de082439a4
commit
707570615c
10 changed files with 426 additions and 102 deletions
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Logging;
|
||||||
using Dalamud.Memory;
|
using Dalamud.Memory;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Penumbra.GameData.ByteString;
|
using Penumbra.GameData.ByteString;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Util;
|
using Penumbra.GameData.Util;
|
||||||
|
|
@ -18,10 +19,16 @@ public readonly struct ImcEntry : IEquatable< ImcEntry >
|
||||||
public readonly byte MaterialAnimationId;
|
public readonly byte MaterialAnimationId;
|
||||||
|
|
||||||
public ushort AttributeMask
|
public ushort AttributeMask
|
||||||
=> ( ushort )( _attributeAndSound & 0x3FF );
|
{
|
||||||
|
get => ( ushort )( _attributeAndSound & 0x3FF );
|
||||||
|
init => _attributeAndSound = ( ushort )( ( _attributeAndSound & ~0x3FF ) | ( value & 0x3FF ) );
|
||||||
|
}
|
||||||
|
|
||||||
public byte SoundId
|
public byte SoundId
|
||||||
=> ( byte )( _attributeAndSound >> 10 );
|
{
|
||||||
|
get => ( byte )( _attributeAndSound >> 10 );
|
||||||
|
init => _attributeAndSound = ( ushort )( AttributeMask | ( value << 10 ) );
|
||||||
|
}
|
||||||
|
|
||||||
public bool Equals( ImcEntry other )
|
public bool Equals( ImcEntry other )
|
||||||
=> MaterialId == other.MaterialId
|
=> MaterialId == other.MaterialId
|
||||||
|
|
@ -35,6 +42,18 @@ public readonly struct ImcEntry : IEquatable< ImcEntry >
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
=> HashCode.Combine( MaterialId, DecalId, _attributeAndSound, VfxId, MaterialAnimationId );
|
=> HashCode.Combine( MaterialId, DecalId, _attributeAndSound, VfxId, MaterialAnimationId );
|
||||||
|
|
||||||
|
[JsonConstructor]
|
||||||
|
public ImcEntry( byte materialId, byte decalId, ushort attributeMask, byte soundId, byte vfxId, byte materialAnimationId )
|
||||||
|
{
|
||||||
|
MaterialId = materialId;
|
||||||
|
DecalId = decalId;
|
||||||
|
_attributeAndSound = 0;
|
||||||
|
VfxId = vfxId;
|
||||||
|
MaterialAnimationId = materialAnimationId;
|
||||||
|
AttributeMask = attributeMask;
|
||||||
|
SoundId = soundId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe class ImcFile : MetaBaseFile
|
public unsafe class ImcFile : MetaBaseFile
|
||||||
|
|
@ -118,7 +137,7 @@ public unsafe class ImcFile : MetaBaseFile
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginLog.Verbose( "Expanded imc from {Count} to {NewCount} variants.", Count, numVariants );
|
PluginLog.Verbose( "Expanded imc from {Count} to {NewCount} variants.", Count, numVariants );
|
||||||
*( ushort* )Count = ( ushort )numVariants;
|
*( ushort* )Data = ( ushort )numVariants;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
using Penumbra.Interop.Structs;
|
using Penumbra.Interop.Structs;
|
||||||
|
|
@ -6,12 +9,16 @@ using Penumbra.Meta.Files;
|
||||||
|
|
||||||
namespace Penumbra.Meta.Manipulations;
|
namespace Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
public readonly struct EqdpManipulation : IEquatable< EqdpManipulation >
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||||
|
public readonly struct EqdpManipulation : IMetaManipulation< EqdpManipulation >
|
||||||
{
|
{
|
||||||
public readonly EqdpEntry Entry;
|
public readonly EqdpEntry Entry;
|
||||||
|
[JsonConverter( typeof( StringEnumConverter ) )]
|
||||||
public readonly Gender Gender;
|
public readonly Gender Gender;
|
||||||
|
[JsonConverter( typeof( StringEnumConverter ) )]
|
||||||
public readonly ModelRace Race;
|
public readonly ModelRace Race;
|
||||||
public readonly ushort SetId;
|
public readonly ushort SetId;
|
||||||
|
[JsonConverter( typeof( StringEnumConverter ) )]
|
||||||
public readonly EquipSlot Slot;
|
public readonly EquipSlot Slot;
|
||||||
|
|
||||||
public EqdpManipulation( EqdpEntry entry, EquipSlot slot, Gender gender, ModelRace race, ushort setId )
|
public EqdpManipulation( EqdpEntry entry, EquipSlot slot, Gender gender, ModelRace race, ushort setId )
|
||||||
|
|
@ -38,6 +45,24 @@ public readonly struct EqdpManipulation : IEquatable< EqdpManipulation >
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
=> HashCode.Combine( ( int )Gender, ( int )Race, SetId, ( int )Slot );
|
=> HashCode.Combine( ( int )Gender, ( int )Race, SetId, ( int )Slot );
|
||||||
|
|
||||||
|
public int CompareTo( EqdpManipulation other )
|
||||||
|
{
|
||||||
|
var r = Race.CompareTo( other.Race );
|
||||||
|
if( r != 0 )
|
||||||
|
{
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
var g = Gender.CompareTo( other.Gender );
|
||||||
|
if( g != 0 )
|
||||||
|
{
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
var set = SetId.CompareTo( other.SetId );
|
||||||
|
return set != 0 ? set : Slot.CompareTo( other.Slot );
|
||||||
|
}
|
||||||
|
|
||||||
public int FileIndex()
|
public int FileIndex()
|
||||||
=> CharacterUtility.EqdpIdx( Names.CombinedRace( Gender, Race ), Slot.IsAccessory() );
|
=> CharacterUtility.EqdpIdx( Names.CombinedRace( Gender, Race ), Slot.IsAccessory() );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
using Penumbra.Interop.Structs;
|
using Penumbra.Interop.Structs;
|
||||||
|
|
@ -6,10 +9,12 @@ using Penumbra.Meta.Files;
|
||||||
|
|
||||||
namespace Penumbra.Meta.Manipulations;
|
namespace Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
public readonly struct EqpManipulation : IEquatable< EqpManipulation >
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||||
|
public readonly struct EqpManipulation : IMetaManipulation< EqpManipulation >
|
||||||
{
|
{
|
||||||
public readonly EqpEntry Entry;
|
public readonly EqpEntry Entry;
|
||||||
public readonly ushort SetId;
|
public readonly ushort SetId;
|
||||||
|
[JsonConverter( typeof( StringEnumConverter ) )]
|
||||||
public readonly EquipSlot Slot;
|
public readonly EquipSlot Slot;
|
||||||
|
|
||||||
public EqpManipulation( EqpEntry entry, EquipSlot slot, ushort setId )
|
public EqpManipulation( EqpEntry entry, EquipSlot slot, ushort setId )
|
||||||
|
|
@ -32,6 +37,12 @@ public readonly struct EqpManipulation : IEquatable< EqpManipulation >
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
=> HashCode.Combine( ( int )Slot, SetId );
|
=> HashCode.Combine( ( int )Slot, SetId );
|
||||||
|
|
||||||
|
public int CompareTo( EqpManipulation other )
|
||||||
|
{
|
||||||
|
var set = SetId.CompareTo( other.SetId );
|
||||||
|
return set != 0 ? set : Slot.CompareTo( other.Slot );
|
||||||
|
}
|
||||||
|
|
||||||
public int FileIndex()
|
public int FileIndex()
|
||||||
=> CharacterUtility.EqpIdx;
|
=> CharacterUtility.EqpIdx;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.Interop.Structs;
|
using Penumbra.Interop.Structs;
|
||||||
using Penumbra.Meta.Files;
|
using Penumbra.Meta.Files;
|
||||||
|
|
||||||
namespace Penumbra.Meta.Manipulations;
|
namespace Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
public readonly struct EstManipulation : IEquatable< EstManipulation >
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||||
|
public readonly struct EstManipulation : IMetaManipulation< EstManipulation >
|
||||||
{
|
{
|
||||||
public enum EstType : byte
|
public enum EstType : byte
|
||||||
{
|
{
|
||||||
|
|
@ -16,10 +20,13 @@ public readonly struct EstManipulation : IEquatable< EstManipulation >
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly ushort SkeletonIdx;
|
public readonly ushort SkeletonIdx;
|
||||||
|
[JsonConverter( typeof( StringEnumConverter ) )]
|
||||||
public readonly Gender Gender;
|
public readonly Gender Gender;
|
||||||
|
[JsonConverter( typeof( StringEnumConverter ) )]
|
||||||
public readonly ModelRace Race;
|
public readonly ModelRace Race;
|
||||||
public readonly ushort SetId;
|
public readonly ushort SetId;
|
||||||
public readonly EstType Type;
|
[JsonConverter( typeof( StringEnumConverter ) )]
|
||||||
|
public readonly EstType Slot;
|
||||||
|
|
||||||
public EstManipulation( Gender gender, ModelRace race, EstType estType, ushort setId, ushort skeletonIdx )
|
public EstManipulation( Gender gender, ModelRace race, EstType estType, ushort setId, ushort skeletonIdx )
|
||||||
{
|
{
|
||||||
|
|
@ -27,27 +34,45 @@ public readonly struct EstManipulation : IEquatable< EstManipulation >
|
||||||
Gender = gender;
|
Gender = gender;
|
||||||
Race = race;
|
Race = race;
|
||||||
SetId = setId;
|
SetId = setId;
|
||||||
Type = estType;
|
Slot = estType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
=> $"Est - {SetId} - {Type} - {Race.ToName()} {Gender.ToName()}";
|
=> $"Est - {SetId} - {Slot} - {Race.ToName()} {Gender.ToName()}";
|
||||||
|
|
||||||
public bool Equals( EstManipulation other )
|
public bool Equals( EstManipulation other )
|
||||||
=> Gender == other.Gender
|
=> Gender == other.Gender
|
||||||
&& Race == other.Race
|
&& Race == other.Race
|
||||||
&& SetId == other.SetId
|
&& SetId == other.SetId
|
||||||
&& Type == other.Type;
|
&& Slot == other.Slot;
|
||||||
|
|
||||||
public override bool Equals( object? obj )
|
public override bool Equals( object? obj )
|
||||||
=> obj is EstManipulation other && Equals( other );
|
=> obj is EstManipulation other && Equals( other );
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
=> HashCode.Combine( ( int )Gender, ( int )Race, SetId, ( int )Type );
|
=> HashCode.Combine( ( int )Gender, ( int )Race, SetId, ( int )Slot );
|
||||||
|
|
||||||
|
public int CompareTo( EstManipulation other )
|
||||||
|
{
|
||||||
|
var r = Race.CompareTo( other.Race );
|
||||||
|
if( r != 0 )
|
||||||
|
{
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
var g = Gender.CompareTo( other.Gender );
|
||||||
|
if( g != 0 )
|
||||||
|
{
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
var s = Slot.CompareTo( other.Slot );
|
||||||
|
return s != 0 ? s : SetId.CompareTo( other.SetId );
|
||||||
|
}
|
||||||
|
|
||||||
public int FileIndex()
|
public int FileIndex()
|
||||||
=> ( int )Type;
|
=> ( int )Slot;
|
||||||
|
|
||||||
public bool Apply( EstFile file )
|
public bool Apply( EstFile file )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
using Penumbra.Interop.Structs;
|
using Penumbra.Interop.Structs;
|
||||||
using Penumbra.Meta.Files;
|
using Penumbra.Meta.Files;
|
||||||
|
|
||||||
namespace Penumbra.Meta.Manipulations;
|
namespace Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
public readonly struct GmpManipulation : IEquatable< GmpManipulation >
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||||
|
public readonly struct GmpManipulation : IMetaManipulation< GmpManipulation >
|
||||||
{
|
{
|
||||||
public readonly GmpEntry Entry;
|
public readonly GmpEntry Entry;
|
||||||
public readonly ushort SetId;
|
public readonly ushort SetId;
|
||||||
|
|
@ -28,6 +30,9 @@ public readonly struct GmpManipulation : IEquatable< GmpManipulation >
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
=> SetId.GetHashCode();
|
=> SetId.GetHashCode();
|
||||||
|
|
||||||
|
public int CompareTo( GmpManipulation other )
|
||||||
|
=> SetId.CompareTo( other.SetId );
|
||||||
|
|
||||||
public int FileIndex()
|
public int FileIndex()
|
||||||
=> CharacterUtility.GmpIdx;
|
=> CharacterUtility.GmpIdx;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,29 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
using Penumbra.GameData.ByteString;
|
using Penumbra.GameData.ByteString;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.Meta.Files;
|
using Penumbra.Meta.Files;
|
||||||
|
|
||||||
namespace Penumbra.Meta.Manipulations;
|
namespace Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
[StructLayout( LayoutKind.Sequential )]
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||||
public readonly struct ImcManipulation : IEquatable< ImcManipulation >
|
public readonly struct ImcManipulation : IMetaManipulation< ImcManipulation >
|
||||||
{
|
{
|
||||||
public readonly ImcEntry Entry;
|
public readonly ImcEntry Entry;
|
||||||
public readonly ushort PrimaryId;
|
public readonly ushort PrimaryId;
|
||||||
public readonly ushort Variant;
|
public readonly ushort Variant;
|
||||||
public readonly ushort SecondaryId;
|
public readonly ushort SecondaryId;
|
||||||
|
|
||||||
|
[JsonConverter( typeof( StringEnumConverter ) )]
|
||||||
public readonly ObjectType ObjectType;
|
public readonly ObjectType ObjectType;
|
||||||
public readonly EquipSlot EquipSlot;
|
|
||||||
public readonly BodySlot BodySlot;
|
[JsonConverter( typeof( StringEnumConverter ) )]
|
||||||
|
public readonly EquipSlot EquipSlot;
|
||||||
|
|
||||||
|
[JsonConverter( typeof( StringEnumConverter ) )]
|
||||||
|
public readonly BodySlot BodySlot;
|
||||||
|
|
||||||
public ImcManipulation( EquipSlot equipSlot, ushort variant, ushort primaryId, ImcEntry entry )
|
public ImcManipulation( EquipSlot equipSlot, ushort variant, ushort primaryId, ImcEntry entry )
|
||||||
{
|
{
|
||||||
|
|
@ -40,6 +48,19 @@ public readonly struct ImcManipulation : IEquatable< ImcManipulation >
|
||||||
EquipSlot = EquipSlot.Unknown;
|
EquipSlot = EquipSlot.Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonConstructor]
|
||||||
|
internal ImcManipulation( ObjectType objectType, BodySlot bodySlot, ushort primaryId, ushort secondaryId, ushort variant,
|
||||||
|
EquipSlot equipSlot, ImcEntry entry )
|
||||||
|
{
|
||||||
|
Entry = entry;
|
||||||
|
ObjectType = objectType;
|
||||||
|
BodySlot = bodySlot;
|
||||||
|
PrimaryId = primaryId;
|
||||||
|
SecondaryId = secondaryId;
|
||||||
|
Variant = variant;
|
||||||
|
EquipSlot = equipSlot;
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
=> ObjectType is ObjectType.Equipment or ObjectType.Accessory
|
=> ObjectType is ObjectType.Equipment or ObjectType.Accessory
|
||||||
? $"Imc - {PrimaryId} - {EquipSlot} - {Variant}"
|
? $"Imc - {PrimaryId} - {EquipSlot} - {Variant}"
|
||||||
|
|
@ -59,6 +80,39 @@ public readonly struct ImcManipulation : IEquatable< ImcManipulation >
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
=> HashCode.Combine( PrimaryId, Variant, SecondaryId, ( int )ObjectType, ( int )EquipSlot, ( int )BodySlot );
|
=> HashCode.Combine( PrimaryId, Variant, SecondaryId, ( int )ObjectType, ( int )EquipSlot, ( int )BodySlot );
|
||||||
|
|
||||||
|
public int CompareTo( ImcManipulation other )
|
||||||
|
{
|
||||||
|
var o = ObjectType.CompareTo( other.ObjectType );
|
||||||
|
if( o != 0 )
|
||||||
|
{
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
var i = PrimaryId.CompareTo( other.PrimaryId );
|
||||||
|
if( i != 0 )
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ObjectType is ObjectType.Equipment or ObjectType.Accessory )
|
||||||
|
{
|
||||||
|
var e = EquipSlot.CompareTo( other.EquipSlot );
|
||||||
|
return e != 0 ? e : Variant.CompareTo( other.Variant );
|
||||||
|
}
|
||||||
|
|
||||||
|
var s = SecondaryId.CompareTo( other.SecondaryId );
|
||||||
|
if( s != 0 )
|
||||||
|
{
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
var b = BodySlot.CompareTo( other.BodySlot );
|
||||||
|
return b != 0 ? b : Variant.CompareTo( other.Variant );
|
||||||
|
}
|
||||||
|
|
||||||
|
public int FileIndex()
|
||||||
|
=> -1;
|
||||||
|
|
||||||
public Utf8GamePath GamePath()
|
public Utf8GamePath GamePath()
|
||||||
{
|
{
|
||||||
return ObjectType switch
|
return ObjectType switch
|
||||||
|
|
|
||||||
|
|
@ -1,60 +1,225 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
using Penumbra.GameData.Util;
|
using Penumbra.GameData.Util;
|
||||||
|
|
||||||
namespace Penumbra.Meta.Manipulations;
|
namespace Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
|
public interface IMetaManipulation
|
||||||
|
{
|
||||||
|
public int FileIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IMetaManipulation< T > : IMetaManipulation, IComparable< T >, IEquatable< T > where T : struct
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public struct ManipulationSet< T > where T : struct, IMetaManipulation< T >
|
||||||
|
{
|
||||||
|
private List< T >? _data = null;
|
||||||
|
|
||||||
|
public IReadOnlyList< T > Data
|
||||||
|
=> ( IReadOnlyList< T >? )_data ?? Array.Empty< T >();
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
=> _data?.Count ?? 0;
|
||||||
|
|
||||||
|
public ManipulationSet( int count = 0 )
|
||||||
|
{
|
||||||
|
if( count > 0 )
|
||||||
|
{
|
||||||
|
_data = new List< T >( count );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryAdd( T manip )
|
||||||
|
{
|
||||||
|
if( _data == null )
|
||||||
|
{
|
||||||
|
_data = new List< T > { manip };
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var idx = _data.BinarySearch( manip );
|
||||||
|
if( idx >= 0 )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_data.Insert( ~idx, manip );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Set( T manip )
|
||||||
|
{
|
||||||
|
if( _data == null )
|
||||||
|
{
|
||||||
|
_data = new List< T > { manip };
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var idx = _data.BinarySearch( manip );
|
||||||
|
if( idx >= 0 )
|
||||||
|
{
|
||||||
|
_data[ idx ] = manip;
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
idx = ~idx;
|
||||||
|
_data.Insert( idx, manip );
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGet( T manip, out T value )
|
||||||
|
{
|
||||||
|
var idx = _data?.BinarySearch( manip ) ?? -1;
|
||||||
|
if( idx < 0 )
|
||||||
|
{
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = _data![ idx ];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove( T manip )
|
||||||
|
{
|
||||||
|
var idx = _data?.BinarySearch( manip ) ?? -1;
|
||||||
|
if( idx < 0 )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_data!.RemoveAt( idx );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[StructLayout( LayoutKind.Explicit, Pack = 1, Size = 16 )]
|
[StructLayout( LayoutKind.Explicit, Pack = 1, Size = 16 )]
|
||||||
public readonly struct MetaManipulation : IEquatable< MetaManipulation >, IComparable<MetaManipulation>
|
public readonly struct MetaManipulation : IEquatable< MetaManipulation >, IComparable< MetaManipulation >
|
||||||
{
|
{
|
||||||
public enum Type : byte
|
public enum Type : byte
|
||||||
{
|
{
|
||||||
Eqp,
|
Unknown = 0,
|
||||||
Gmp,
|
Imc = 1,
|
||||||
Eqdp,
|
Eqdp = 2,
|
||||||
Est,
|
Eqp = 3,
|
||||||
Rsp,
|
Est = 4,
|
||||||
Imc,
|
Gmp = 5,
|
||||||
|
Rsp = 6,
|
||||||
}
|
}
|
||||||
|
|
||||||
[FieldOffset( 0 )]
|
[FieldOffset( 0 )]
|
||||||
|
[JsonIgnore]
|
||||||
public readonly EqpManipulation Eqp = default;
|
public readonly EqpManipulation Eqp = default;
|
||||||
|
|
||||||
[FieldOffset( 0 )]
|
[FieldOffset( 0 )]
|
||||||
|
[JsonIgnore]
|
||||||
public readonly GmpManipulation Gmp = default;
|
public readonly GmpManipulation Gmp = default;
|
||||||
|
|
||||||
[FieldOffset( 0 )]
|
[FieldOffset( 0 )]
|
||||||
|
[JsonIgnore]
|
||||||
public readonly EqdpManipulation Eqdp = default;
|
public readonly EqdpManipulation Eqdp = default;
|
||||||
|
|
||||||
[FieldOffset( 0 )]
|
[FieldOffset( 0 )]
|
||||||
|
[JsonIgnore]
|
||||||
public readonly EstManipulation Est = default;
|
public readonly EstManipulation Est = default;
|
||||||
|
|
||||||
[FieldOffset( 0 )]
|
[FieldOffset( 0 )]
|
||||||
|
[JsonIgnore]
|
||||||
public readonly RspManipulation Rsp = default;
|
public readonly RspManipulation Rsp = default;
|
||||||
|
|
||||||
[FieldOffset( 0 )]
|
[FieldOffset( 0 )]
|
||||||
|
[JsonIgnore]
|
||||||
public readonly ImcManipulation Imc = default;
|
public readonly ImcManipulation Imc = default;
|
||||||
|
|
||||||
[FieldOffset( 15 )]
|
[FieldOffset( 15 )]
|
||||||
|
[JsonConverter( typeof( StringEnumConverter ) )]
|
||||||
|
[JsonProperty("Type")]
|
||||||
public readonly Type ManipulationType;
|
public readonly Type ManipulationType;
|
||||||
|
|
||||||
|
public object? Manipulation
|
||||||
|
{
|
||||||
|
get => ManipulationType switch
|
||||||
|
{
|
||||||
|
Type.Unknown => null,
|
||||||
|
Type.Imc => Imc,
|
||||||
|
Type.Eqdp => Eqdp,
|
||||||
|
Type.Eqp => Eqp,
|
||||||
|
Type.Est => Est,
|
||||||
|
Type.Gmp => Gmp,
|
||||||
|
Type.Rsp => Rsp,
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
|
init
|
||||||
|
{
|
||||||
|
switch( value )
|
||||||
|
{
|
||||||
|
case EqpManipulation m:
|
||||||
|
Eqp = m;
|
||||||
|
ManipulationType = Type.Eqp;
|
||||||
|
return;
|
||||||
|
case EqdpManipulation m:
|
||||||
|
Eqdp = m;
|
||||||
|
ManipulationType = Type.Eqdp;
|
||||||
|
return;
|
||||||
|
case GmpManipulation m:
|
||||||
|
Gmp = m;
|
||||||
|
ManipulationType = Type.Gmp;
|
||||||
|
return;
|
||||||
|
case EstManipulation m:
|
||||||
|
Est = m;
|
||||||
|
ManipulationType = Type.Est;
|
||||||
|
return;
|
||||||
|
case RspManipulation m:
|
||||||
|
Rsp = m;
|
||||||
|
ManipulationType = Type.Rsp;
|
||||||
|
return;
|
||||||
|
case ImcManipulation m:
|
||||||
|
Imc = m;
|
||||||
|
ManipulationType = Type.Imc;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public MetaManipulation( EqpManipulation eqp )
|
public MetaManipulation( EqpManipulation eqp )
|
||||||
=> ( ManipulationType, Eqp ) = ( Type.Eqp, eqp );
|
{
|
||||||
|
Eqp = eqp;
|
||||||
|
ManipulationType = Type.Eqp;
|
||||||
|
}
|
||||||
|
|
||||||
public MetaManipulation( GmpManipulation gmp )
|
public MetaManipulation( GmpManipulation gmp )
|
||||||
=> ( ManipulationType, Gmp ) = ( Type.Gmp, gmp );
|
{
|
||||||
|
Gmp = gmp;
|
||||||
|
ManipulationType = Type.Gmp;
|
||||||
|
}
|
||||||
|
|
||||||
public MetaManipulation( EqdpManipulation eqdp )
|
public MetaManipulation( EqdpManipulation eqdp )
|
||||||
=> ( ManipulationType, Eqdp ) = ( Type.Eqdp, eqdp );
|
{
|
||||||
|
Eqdp = eqdp;
|
||||||
|
ManipulationType = Type.Eqdp;
|
||||||
|
}
|
||||||
|
|
||||||
public MetaManipulation( EstManipulation est )
|
public MetaManipulation( EstManipulation est )
|
||||||
=> ( ManipulationType, Est ) = ( Type.Est, est );
|
{
|
||||||
|
Est = est;
|
||||||
|
ManipulationType = Type.Est;
|
||||||
|
}
|
||||||
|
|
||||||
public MetaManipulation( RspManipulation rsp )
|
public MetaManipulation( RspManipulation rsp )
|
||||||
=> ( ManipulationType, Rsp ) = ( Type.Rsp, rsp );
|
{
|
||||||
|
Rsp = rsp;
|
||||||
|
ManipulationType = Type.Rsp;
|
||||||
|
}
|
||||||
|
|
||||||
public MetaManipulation( ImcManipulation imc )
|
public MetaManipulation( ImcManipulation imc )
|
||||||
=> ( ManipulationType, Imc ) = ( Type.Imc, imc );
|
{
|
||||||
|
Imc = imc;
|
||||||
|
ManipulationType = Type.Imc;
|
||||||
|
}
|
||||||
|
|
||||||
public static implicit operator MetaManipulation( EqpManipulation eqp )
|
public static implicit operator MetaManipulation( EqpManipulation eqp )
|
||||||
=> new(eqp);
|
=> new(eqp);
|
||||||
|
|
@ -110,7 +275,9 @@ public readonly struct MetaManipulation : IEquatable< MetaManipulation >, ICompa
|
||||||
|
|
||||||
public unsafe int CompareTo( MetaManipulation other )
|
public unsafe int CompareTo( MetaManipulation other )
|
||||||
{
|
{
|
||||||
fixed(MetaManipulation* lhs = &this)
|
fixed( MetaManipulation* lhs = &this )
|
||||||
return Functions.MemCmpUnchecked(lhs, &other, sizeof(MetaManipulation));
|
{
|
||||||
|
return Functions.MemCmpUnchecked( lhs, &other, sizeof( MetaManipulation ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,14 +1,22 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.Interop.Structs;
|
using Penumbra.Interop.Structs;
|
||||||
using Penumbra.Meta.Files;
|
using Penumbra.Meta.Files;
|
||||||
|
|
||||||
namespace Penumbra.Meta.Manipulations;
|
namespace Penumbra.Meta.Manipulations;
|
||||||
|
|
||||||
public readonly struct RspManipulation : IEquatable< RspManipulation >
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||||
|
public readonly struct RspManipulation : IMetaManipulation< RspManipulation >
|
||||||
{
|
{
|
||||||
public readonly float Entry;
|
public readonly float Entry;
|
||||||
public readonly SubRace SubRace;
|
|
||||||
|
[JsonConverter( typeof( StringEnumConverter ) )]
|
||||||
|
public readonly SubRace SubRace;
|
||||||
|
|
||||||
|
[JsonConverter( typeof( StringEnumConverter ) )]
|
||||||
public readonly RspAttribute Attribute;
|
public readonly RspAttribute Attribute;
|
||||||
|
|
||||||
public RspManipulation( SubRace subRace, RspAttribute attribute, float entry )
|
public RspManipulation( SubRace subRace, RspAttribute attribute, float entry )
|
||||||
|
|
@ -31,6 +39,12 @@ public readonly struct RspManipulation : IEquatable< RspManipulation >
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
=> HashCode.Combine( ( int )SubRace, ( int )Attribute );
|
=> HashCode.Combine( ( int )SubRace, ( int )Attribute );
|
||||||
|
|
||||||
|
public int CompareTo( RspManipulation other )
|
||||||
|
{
|
||||||
|
var s = SubRace.CompareTo( other.SubRace );
|
||||||
|
return s != 0 ? s : Attribute.CompareTo( other.Attribute );
|
||||||
|
}
|
||||||
|
|
||||||
public int FileIndex()
|
public int FileIndex()
|
||||||
=> CharacterUtility.HumanCmpIdx;
|
=> CharacterUtility.HumanCmpIdx;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -243,7 +243,7 @@ public class MetaManager2 : IDisposable
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var file = m.Type switch
|
var file = m.Slot switch
|
||||||
{
|
{
|
||||||
EstManipulation.EstType.Hair => HairEstFile ??= new EstFile( EstManipulation.EstType.Hair ),
|
EstManipulation.EstType.Hair => HairEstFile ??= new EstFile( EstManipulation.EstType.Hair ),
|
||||||
EstManipulation.EstType.Face => FaceEstFile ??= new EstFile( EstManipulation.EstType.Face ),
|
EstManipulation.EstType.Face => FaceEstFile ??= new EstFile( EstManipulation.EstType.Face ),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing.Text;
|
||||||
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
|
@ -484,39 +486,39 @@ namespace Penumbra.UI
|
||||||
private bool DrawRspRow( int manipIdx, IList< MetaManipulation > list )
|
private bool DrawRspRow( int manipIdx, IList< MetaManipulation > list )
|
||||||
{
|
{
|
||||||
var ret = false;
|
var ret = false;
|
||||||
//var id = list[ manipIdx ].RspIdentifier;
|
var id = list[ manipIdx ].RspIdentifier;
|
||||||
//var val = list[ manipIdx ].RspValue;
|
var val = list[ manipIdx ].RspValue;
|
||||||
//
|
|
||||||
//if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) )
|
if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) )
|
||||||
//{
|
{
|
||||||
// using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
|
using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup );
|
||||||
// if( DefaultButton(
|
if( DefaultButton(
|
||||||
// $"{( _editMode ? "Set to " : "" )}Default: {defaults:F3}##scaleManip", ref val, defaults )
|
$"{( _editMode ? "Set to " : "" )}Default: {defaults:F3}##scaleManip", ref val, defaults )
|
||||||
// && _editMode )
|
&& _editMode )
|
||||||
// {
|
{
|
||||||
// list[ manipIdx ] = MetaManipulation.Rsp( id.SubRace, id.Attribute, defaults );
|
list[ manipIdx ] = MetaManipulation.Rsp( id.SubRace, id.Attribute, defaults );
|
||||||
// ret = true;
|
ret = true;
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// ImGui.SetNextItemWidth( 50 * ImGuiHelpers.GlobalScale );
|
ImGui.SetNextItemWidth( 50 * ImGuiHelpers.GlobalScale );
|
||||||
// if( ImGui.InputFloat( "Scale###manip", ref val, 0, 0, "%.3f",
|
if( ImGui.InputFloat( "Scale###manip", ref val, 0, 0, "%.3f",
|
||||||
// _editMode ? ImGuiInputTextFlags.EnterReturnsTrue : ImGuiInputTextFlags.ReadOnly )
|
_editMode ? ImGuiInputTextFlags.EnterReturnsTrue : ImGuiInputTextFlags.ReadOnly )
|
||||||
// && val >= 0
|
&& val >= 0
|
||||||
// && val <= 5
|
&& val <= 5
|
||||||
// && _editMode )
|
&& _editMode )
|
||||||
// {
|
{
|
||||||
// list[ manipIdx ] = MetaManipulation.Rsp( id.SubRace, id.Attribute, val );
|
list[ manipIdx ] = MetaManipulation.Rsp( id.SubRace, id.Attribute, val );
|
||||||
// ret = true;
|
ret = true;
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//ImGui.Text( id.Attribute.ToUngenderedString() );
|
ImGui.Text( id.Attribute.ToUngenderedString() );
|
||||||
//ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
//ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
//ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
//ImGui.Text( id.SubRace.ToString() );
|
ImGui.Text( id.SubRace.ToString() );
|
||||||
//ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
//ImGui.Text( id.Attribute.ToGender().ToString() );
|
ImGui.Text( id.Attribute.ToGender().ToString() );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -543,35 +545,35 @@ namespace Penumbra.UI
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
|
|
||||||
var changes = false;
|
var changes = false;
|
||||||
//switch( type )
|
switch( type )
|
||||||
//{
|
{
|
||||||
// case MetaType.Eqp:
|
case MetaManipulation.Type.Eqp:
|
||||||
// changes = DrawEqpRow( manipIdx, list );
|
changes = DrawEqpRow( manipIdx, list );
|
||||||
// break;
|
break;
|
||||||
// case MetaType.Gmp:
|
case MetaManipulation.Type.Gmp:
|
||||||
// changes = DrawGmpRow( manipIdx, list );
|
changes = DrawGmpRow( manipIdx, list );
|
||||||
// break;
|
break;
|
||||||
// case MetaType.Eqdp:
|
case MetaManipulation.Type.Eqdp:
|
||||||
// changes = DrawEqdpRow( manipIdx, list );
|
changes = DrawEqdpRow( manipIdx, list );
|
||||||
// break;
|
break;
|
||||||
// case MetaType.Est:
|
case MetaManipulation.Type.Est:
|
||||||
// changes = DrawEstRow( manipIdx, list );
|
changes = DrawEstRow( manipIdx, list );
|
||||||
// break;
|
break;
|
||||||
// case MetaType.Imc:
|
case MetaManipulation.Type.Imc:
|
||||||
// changes = DrawImcRow( manipIdx, list );
|
changes = DrawImcRow( manipIdx, list );
|
||||||
// break;
|
break;
|
||||||
// case MetaType.Rsp:
|
case MetaManipulation.Type.Rsp:
|
||||||
// changes = DrawRspRow( manipIdx, list );
|
changes = DrawRspRow( manipIdx, list );
|
||||||
// break;
|
break;
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//ImGui.TableSetColumnIndex( 9 );
|
ImGui.TableSetColumnIndex( 9 );
|
||||||
//if( ImGui.Selectable( $"{list[ manipIdx ].Value:X}##{manipIdx}" ) )
|
if( ImGui.Selectable( $"{manipIdx}##{manipIdx}" ) )
|
||||||
//{
|
{
|
||||||
// ImGui.OpenPopup( $"##MetaPopup{manipIdx}" );
|
ImGui.OpenPopup( $"##MetaPopup{manipIdx}" );
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//ImGui.TableNextRow();
|
ImGui.TableNextRow();
|
||||||
return changes;
|
return changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -714,6 +716,8 @@ namespace Penumbra.UI
|
||||||
{
|
{
|
||||||
var numRows = _editMode ? 11 : 10;
|
var numRows = _editMode ? 11 : 10;
|
||||||
var changes = false;
|
var changes = false;
|
||||||
|
|
||||||
|
|
||||||
if( list.Count > 0
|
if( list.Count > 0
|
||||||
&& ImGui.BeginTable( label, numRows,
|
&& ImGui.BeginTable( label, numRows,
|
||||||
ImGuiTableFlags.BordersInner | ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit ) )
|
ImGuiTableFlags.BordersInner | ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit ) )
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue