diff --git a/Penumbra/Meta/Files/ImcFile.cs b/Penumbra/Meta/Files/ImcFile.cs index 1c23dd32..d7eaaa80 100644 --- a/Penumbra/Meta/Files/ImcFile.cs +++ b/Penumbra/Meta/Files/ImcFile.cs @@ -2,6 +2,7 @@ using System; using System.Numerics; using Dalamud.Logging; using Dalamud.Memory; +using Newtonsoft.Json; using Penumbra.GameData.ByteString; using Penumbra.GameData.Enums; using Penumbra.GameData.Util; @@ -18,10 +19,16 @@ public readonly struct ImcEntry : IEquatable< ImcEntry > public readonly byte MaterialAnimationId; public ushort AttributeMask - => ( ushort )( _attributeAndSound & 0x3FF ); + { + get => ( ushort )( _attributeAndSound & 0x3FF ); + init => _attributeAndSound = ( ushort )( ( _attributeAndSound & ~0x3FF ) | ( value & 0x3FF ) ); + } public byte SoundId - => ( byte )( _attributeAndSound >> 10 ); + { + get => ( byte )( _attributeAndSound >> 10 ); + init => _attributeAndSound = ( ushort )( AttributeMask | ( value << 10 ) ); + } public bool Equals( ImcEntry other ) => MaterialId == other.MaterialId @@ -35,6 +42,18 @@ public readonly struct ImcEntry : IEquatable< ImcEntry > public override int GetHashCode() => 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 @@ -118,7 +137,7 @@ public unsafe class ImcFile : MetaBaseFile } PluginLog.Verbose( "Expanded imc from {Count} to {NewCount} variants.", Count, numVariants ); - *( ushort* )Count = ( ushort )numVariants; + *( ushort* )Data = ( ushort )numVariants; return true; } diff --git a/Penumbra/Meta/Manipulations/EqdpManipulation.cs b/Penumbra/Meta/Manipulations/EqdpManipulation.cs index c7fdd553..9abcd47b 100644 --- a/Penumbra/Meta/Manipulations/EqdpManipulation.cs +++ b/Penumbra/Meta/Manipulations/EqdpManipulation.cs @@ -1,4 +1,7 @@ using System; +using System.Runtime.InteropServices; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; using Penumbra.Interop.Structs; @@ -6,12 +9,16 @@ using Penumbra.Meta.Files; 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; + [JsonConverter( typeof( StringEnumConverter ) )] public readonly Gender Gender; + [JsonConverter( typeof( StringEnumConverter ) )] public readonly ModelRace Race; public readonly ushort SetId; + [JsonConverter( typeof( StringEnumConverter ) )] public readonly EquipSlot Slot; 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() => 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() => CharacterUtility.EqdpIdx( Names.CombinedRace( Gender, Race ), Slot.IsAccessory() ); diff --git a/Penumbra/Meta/Manipulations/EqpManipulation.cs b/Penumbra/Meta/Manipulations/EqpManipulation.cs index eab5b864..430dbb9f 100644 --- a/Penumbra/Meta/Manipulations/EqpManipulation.cs +++ b/Penumbra/Meta/Manipulations/EqpManipulation.cs @@ -1,4 +1,7 @@ using System; +using System.Runtime.InteropServices; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; using Penumbra.Interop.Structs; @@ -6,10 +9,12 @@ using Penumbra.Meta.Files; 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 ushort SetId; + [JsonConverter( typeof( StringEnumConverter ) )] public readonly EquipSlot Slot; public EqpManipulation( EqpEntry entry, EquipSlot slot, ushort setId ) @@ -32,6 +37,12 @@ public readonly struct EqpManipulation : IEquatable< EqpManipulation > public override int GetHashCode() => 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() => CharacterUtility.EqpIdx; diff --git a/Penumbra/Meta/Manipulations/EstManipulation.cs b/Penumbra/Meta/Manipulations/EstManipulation.cs index 985f9a65..613ef965 100644 --- a/Penumbra/Meta/Manipulations/EstManipulation.cs +++ b/Penumbra/Meta/Manipulations/EstManipulation.cs @@ -1,11 +1,15 @@ using System; +using System.Runtime.InteropServices; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using Penumbra.GameData.Enums; using Penumbra.Interop.Structs; using Penumbra.Meta.Files; 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 { @@ -16,10 +20,13 @@ public readonly struct EstManipulation : IEquatable< EstManipulation > } public readonly ushort SkeletonIdx; + [JsonConverter( typeof( StringEnumConverter ) )] public readonly Gender Gender; + [JsonConverter( typeof( StringEnumConverter ) )] public readonly ModelRace Race; 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 ) { @@ -27,27 +34,45 @@ public readonly struct EstManipulation : IEquatable< EstManipulation > Gender = gender; Race = race; SetId = setId; - Type = estType; + Slot = estType; } public override string ToString() - => $"Est - {SetId} - {Type} - {Race.ToName()} {Gender.ToName()}"; + => $"Est - {SetId} - {Slot} - {Race.ToName()} {Gender.ToName()}"; public bool Equals( EstManipulation other ) => Gender == other.Gender && Race == other.Race && SetId == other.SetId - && Type == other.Type; + && Slot == other.Slot; public override bool Equals( object? obj ) => obj is EstManipulation other && Equals( other ); 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() - => ( int )Type; + => ( int )Slot; public bool Apply( EstFile file ) { diff --git a/Penumbra/Meta/Manipulations/GmpManipulation.cs b/Penumbra/Meta/Manipulations/GmpManipulation.cs index 2af52dfb..edae0b72 100644 --- a/Penumbra/Meta/Manipulations/GmpManipulation.cs +++ b/Penumbra/Meta/Manipulations/GmpManipulation.cs @@ -1,11 +1,13 @@ using System; +using System.Runtime.InteropServices; using Penumbra.GameData.Structs; using Penumbra.Interop.Structs; using Penumbra.Meta.Files; 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 ushort SetId; @@ -28,6 +30,9 @@ public readonly struct GmpManipulation : IEquatable< GmpManipulation > public override int GetHashCode() => SetId.GetHashCode(); + public int CompareTo( GmpManipulation other ) + => SetId.CompareTo( other.SetId ); + public int FileIndex() => CharacterUtility.GmpIdx; diff --git a/Penumbra/Meta/Manipulations/ImcManipulation.cs b/Penumbra/Meta/Manipulations/ImcManipulation.cs index 42a19a22..f00aaffc 100644 --- a/Penumbra/Meta/Manipulations/ImcManipulation.cs +++ b/Penumbra/Meta/Manipulations/ImcManipulation.cs @@ -1,21 +1,29 @@ using System; using System.Runtime.InteropServices; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using Penumbra.GameData.ByteString; using Penumbra.GameData.Enums; using Penumbra.Meta.Files; namespace Penumbra.Meta.Manipulations; -[StructLayout( LayoutKind.Sequential )] -public readonly struct ImcManipulation : IEquatable< ImcManipulation > +[StructLayout( LayoutKind.Sequential, Pack = 1 )] +public readonly struct ImcManipulation : IMetaManipulation< ImcManipulation > { - public readonly ImcEntry Entry; - public readonly ushort PrimaryId; - public readonly ushort Variant; - public readonly ushort SecondaryId; + public readonly ImcEntry Entry; + public readonly ushort PrimaryId; + public readonly ushort Variant; + public readonly ushort SecondaryId; + + [JsonConverter( typeof( StringEnumConverter ) )] 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 ) { @@ -40,6 +48,19 @@ public readonly struct ImcManipulation : IEquatable< ImcManipulation > 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() => ObjectType is ObjectType.Equipment or ObjectType.Accessory ? $"Imc - {PrimaryId} - {EquipSlot} - {Variant}" @@ -59,6 +80,39 @@ public readonly struct ImcManipulation : IEquatable< ImcManipulation > public override int GetHashCode() => 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() { return ObjectType switch diff --git a/Penumbra/Meta/Manipulations/MetaManipulation.cs b/Penumbra/Meta/Manipulations/MetaManipulation.cs index af07d17b..92caaa23 100644 --- a/Penumbra/Meta/Manipulations/MetaManipulation.cs +++ b/Penumbra/Meta/Manipulations/MetaManipulation.cs @@ -1,60 +1,225 @@ using System; +using System.Collections.Generic; using System.Runtime.InteropServices; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using Penumbra.GameData.Util; 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 )] -public readonly struct MetaManipulation : IEquatable< MetaManipulation >, IComparable +public readonly struct MetaManipulation : IEquatable< MetaManipulation >, IComparable< MetaManipulation > { public enum Type : byte { - Eqp, - Gmp, - Eqdp, - Est, - Rsp, - Imc, + Unknown = 0, + Imc = 1, + Eqdp = 2, + Eqp = 3, + Est = 4, + Gmp = 5, + Rsp = 6, } [FieldOffset( 0 )] + [JsonIgnore] public readonly EqpManipulation Eqp = default; [FieldOffset( 0 )] + [JsonIgnore] public readonly GmpManipulation Gmp = default; [FieldOffset( 0 )] + [JsonIgnore] public readonly EqdpManipulation Eqdp = default; [FieldOffset( 0 )] + [JsonIgnore] public readonly EstManipulation Est = default; [FieldOffset( 0 )] + [JsonIgnore] public readonly RspManipulation Rsp = default; [FieldOffset( 0 )] + [JsonIgnore] public readonly ImcManipulation Imc = default; [FieldOffset( 15 )] + [JsonConverter( typeof( StringEnumConverter ) )] + [JsonProperty("Type")] 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 ) - => ( ManipulationType, Eqp ) = ( Type.Eqp, eqp ); + { + Eqp = eqp; + ManipulationType = Type.Eqp; + } public MetaManipulation( GmpManipulation gmp ) - => ( ManipulationType, Gmp ) = ( Type.Gmp, gmp ); + { + Gmp = gmp; + ManipulationType = Type.Gmp; + } public MetaManipulation( EqdpManipulation eqdp ) - => ( ManipulationType, Eqdp ) = ( Type.Eqdp, eqdp ); + { + Eqdp = eqdp; + ManipulationType = Type.Eqdp; + } public MetaManipulation( EstManipulation est ) - => ( ManipulationType, Est ) = ( Type.Est, est ); + { + Est = est; + ManipulationType = Type.Est; + } public MetaManipulation( RspManipulation rsp ) - => ( ManipulationType, Rsp ) = ( Type.Rsp, rsp ); + { + Rsp = rsp; + ManipulationType = Type.Rsp; + } public MetaManipulation( ImcManipulation imc ) - => ( ManipulationType, Imc ) = ( Type.Imc, imc ); + { + Imc = imc; + ManipulationType = Type.Imc; + } public static implicit operator MetaManipulation( EqpManipulation eqp ) => new(eqp); @@ -110,7 +275,9 @@ public readonly struct MetaManipulation : IEquatable< MetaManipulation >, ICompa public unsafe int CompareTo( MetaManipulation other ) { - fixed(MetaManipulation* lhs = &this) - return Functions.MemCmpUnchecked(lhs, &other, sizeof(MetaManipulation)); + fixed( MetaManipulation* lhs = &this ) + { + return Functions.MemCmpUnchecked( lhs, &other, sizeof( MetaManipulation ) ); + } } } \ No newline at end of file diff --git a/Penumbra/Meta/Manipulations/RspManipulation.cs b/Penumbra/Meta/Manipulations/RspManipulation.cs index 0ad017cd..d25b695f 100644 --- a/Penumbra/Meta/Manipulations/RspManipulation.cs +++ b/Penumbra/Meta/Manipulations/RspManipulation.cs @@ -1,14 +1,22 @@ using System; +using System.Runtime.InteropServices; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using Penumbra.GameData.Enums; using Penumbra.Interop.Structs; using Penumbra.Meta.Files; 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 SubRace SubRace; + public readonly float Entry; + + [JsonConverter( typeof( StringEnumConverter ) )] + public readonly SubRace SubRace; + + [JsonConverter( typeof( StringEnumConverter ) )] public readonly RspAttribute Attribute; public RspManipulation( SubRace subRace, RspAttribute attribute, float entry ) @@ -31,6 +39,12 @@ public readonly struct RspManipulation : IEquatable< RspManipulation > public override int GetHashCode() => 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() => CharacterUtility.HumanCmpIdx; diff --git a/Penumbra/Meta/MetaManager.cs b/Penumbra/Meta/MetaManager.cs index d9519863..f733b6ee 100644 --- a/Penumbra/Meta/MetaManager.cs +++ b/Penumbra/Meta/MetaManager.cs @@ -243,7 +243,7 @@ public class MetaManager2 : IDisposable return false; } - var file = m.Type switch + var file = m.Slot switch { EstManipulation.EstType.Hair => HairEstFile ??= new EstFile( EstManipulation.EstType.Hair ), EstManipulation.EstType.Face => FaceEstFile ??= new EstFile( EstManipulation.EstType.Face ), diff --git a/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledDetailsManipulations.cs b/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledDetailsManipulations.cs index ffe45792..cca21491 100644 --- a/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledDetailsManipulations.cs +++ b/Penumbra/UI/MenuTabs/TabInstalled/TabInstalledDetailsManipulations.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Drawing.Text; +using System.Linq; using System.Numerics; using Dalamud.Interface; using ImGuiNET; @@ -484,39 +486,39 @@ namespace Penumbra.UI private bool DrawRspRow( int manipIdx, IList< MetaManipulation > list ) { var ret = false; - //var id = list[ manipIdx ].RspIdentifier; - //var val = list[ manipIdx ].RspValue; - // - //if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) ) - //{ - // using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup ); - // if( DefaultButton( - // $"{( _editMode ? "Set to " : "" )}Default: {defaults:F3}##scaleManip", ref val, defaults ) - // && _editMode ) - // { - // list[ manipIdx ] = MetaManipulation.Rsp( id.SubRace, id.Attribute, defaults ); - // ret = true; - // } - // - // ImGui.SetNextItemWidth( 50 * ImGuiHelpers.GlobalScale ); - // if( ImGui.InputFloat( "Scale###manip", ref val, 0, 0, "%.3f", - // _editMode ? ImGuiInputTextFlags.EnterReturnsTrue : ImGuiInputTextFlags.ReadOnly ) - // && val >= 0 - // && val <= 5 - // && _editMode ) - // { - // list[ manipIdx ] = MetaManipulation.Rsp( id.SubRace, id.Attribute, val ); - // ret = true; - // } - //} - // - //ImGui.Text( id.Attribute.ToUngenderedString() ); - //ImGui.TableNextColumn(); - //ImGui.TableNextColumn(); - //ImGui.TableNextColumn(); - //ImGui.Text( id.SubRace.ToString() ); - //ImGui.TableNextColumn(); - //ImGui.Text( id.Attribute.ToGender().ToString() ); + var id = list[ manipIdx ].RspIdentifier; + var val = list[ manipIdx ].RspValue; + + if( ImGui.BeginPopup( $"##MetaPopup{manipIdx}" ) ) + { + using var raii = ImGuiRaii.DeferredEnd( ImGui.EndPopup ); + if( DefaultButton( + $"{( _editMode ? "Set to " : "" )}Default: {defaults:F3}##scaleManip", ref val, defaults ) + && _editMode ) + { + list[ manipIdx ] = MetaManipulation.Rsp( id.SubRace, id.Attribute, defaults ); + ret = true; + } + + ImGui.SetNextItemWidth( 50 * ImGuiHelpers.GlobalScale ); + if( ImGui.InputFloat( "Scale###manip", ref val, 0, 0, "%.3f", + _editMode ? ImGuiInputTextFlags.EnterReturnsTrue : ImGuiInputTextFlags.ReadOnly ) + && val >= 0 + && val <= 5 + && _editMode ) + { + list[ manipIdx ] = MetaManipulation.Rsp( id.SubRace, id.Attribute, val ); + ret = true; + } + } + + ImGui.Text( id.Attribute.ToUngenderedString() ); + ImGui.TableNextColumn(); + ImGui.TableNextColumn(); + ImGui.TableNextColumn(); + ImGui.Text( id.SubRace.ToString() ); + ImGui.TableNextColumn(); + ImGui.Text( id.Attribute.ToGender().ToString() ); return ret; } @@ -543,35 +545,35 @@ namespace Penumbra.UI ImGui.TableNextColumn(); var changes = false; - //switch( type ) - //{ - // case MetaType.Eqp: - // changes = DrawEqpRow( manipIdx, list ); - // break; - // case MetaType.Gmp: - // changes = DrawGmpRow( manipIdx, list ); - // break; - // case MetaType.Eqdp: - // changes = DrawEqdpRow( manipIdx, list ); - // break; - // case MetaType.Est: - // changes = DrawEstRow( manipIdx, list ); - // break; - // case MetaType.Imc: - // changes = DrawImcRow( manipIdx, list ); - // break; - // case MetaType.Rsp: - // changes = DrawRspRow( manipIdx, list ); - // break; - //} - // - //ImGui.TableSetColumnIndex( 9 ); - //if( ImGui.Selectable( $"{list[ manipIdx ].Value:X}##{manipIdx}" ) ) - //{ - // ImGui.OpenPopup( $"##MetaPopup{manipIdx}" ); - //} - // - //ImGui.TableNextRow(); + switch( type ) + { + case MetaManipulation.Type.Eqp: + changes = DrawEqpRow( manipIdx, list ); + break; + case MetaManipulation.Type.Gmp: + changes = DrawGmpRow( manipIdx, list ); + break; + case MetaManipulation.Type.Eqdp: + changes = DrawEqdpRow( manipIdx, list ); + break; + case MetaManipulation.Type.Est: + changes = DrawEstRow( manipIdx, list ); + break; + case MetaManipulation.Type.Imc: + changes = DrawImcRow( manipIdx, list ); + break; + case MetaManipulation.Type.Rsp: + changes = DrawRspRow( manipIdx, list ); + break; + } + + ImGui.TableSetColumnIndex( 9 ); + if( ImGui.Selectable( $"{manipIdx}##{manipIdx}" ) ) + { + ImGui.OpenPopup( $"##MetaPopup{manipIdx}" ); + } + + ImGui.TableNextRow(); return changes; } @@ -714,6 +716,8 @@ namespace Penumbra.UI { var numRows = _editMode ? 11 : 10; var changes = false; + + if( list.Count > 0 && ImGui.BeginTable( label, numRows, ImGuiTableFlags.BordersInner | ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit ) )