From 4f9e2244944802f3b5b6c0106e02aeb330ed5c8e Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Mon, 22 Jan 2024 23:49:56 +0100 Subject: [PATCH] Move MetaIndex to its first class enum. --- Glamourer/Designs/DesignBase.cs | 111 +++++------------- Glamourer/Designs/DesignBase64Migration.cs | 16 +-- Glamourer/Designs/DesignData.cs | 20 ++++ Glamourer/Designs/Links/DesignMerger.cs | 61 +++------- Glamourer/Designs/Links/MergedDesign.cs | 36 +++++- Glamourer/Designs/MetaIndex.cs | 39 ++++++ .../Interop/PalettePlus/PaletteImport.cs | 1 - Glamourer/State/StateEditor.cs | 1 + Glamourer/State/StateListener.cs | 1 + Glamourer/State/StateSource.cs | 9 -- 10 files changed, 147 insertions(+), 148 deletions(-) create mode 100644 Glamourer/Designs/MetaIndex.cs diff --git a/Glamourer/Designs/DesignBase.cs b/Glamourer/Designs/DesignBase.cs index 2363060..a533bc4 100644 --- a/Glamourer/Designs/DesignBase.cs +++ b/Glamourer/Designs/DesignBase.cs @@ -1,6 +1,7 @@ using Dalamud.Interface.Internal.Notifications; using Glamourer.GameData; using Glamourer.Services; +using Glamourer.State; using Newtonsoft.Json.Linq; using OtterGui.Classes; using Penumbra.GameData.Enums; @@ -34,7 +35,7 @@ public class DesignBase _designData = designData; ApplyCustomize = customizeFlags & CustomizeFlagExtensions.AllRelevant; ApplyEquip = equipFlags & EquipFlagExtensions.All; - _designFlags = 0; + ApplyMeta = 0; CustomizeSet = SetCustomizationSet(customize); } @@ -45,7 +46,7 @@ public class DesignBase ApplyCustomize = clone.ApplyCustomizeRaw; ApplyEquip = clone.ApplyEquip & EquipFlagExtensions.All; ApplyParameters = clone.ApplyParameters & CustomizeParameterExtensions.All; - _designFlags = clone._designFlags & (DesignFlags)0x0F; + ApplyMeta = clone.ApplyMeta & MetaExtensions.All; } /// Ensure that the customization set is updated when the design data changes. @@ -57,16 +58,6 @@ public class DesignBase #region Application Data - [Flags] - private enum DesignFlags : byte - { - ApplyHatVisible = 0x01, - ApplyVisorState = 0x02, - ApplyWeaponVisible = 0x04, - ApplyWetness = 0x08, - WriteProtected = 0x10, - } - private CustomizeFlag _applyCustomize = CustomizeFlagExtensions.AllRelevant; public CustomizeSet CustomizeSet { get; private set; } @@ -84,9 +75,10 @@ public class DesignBase internal CustomizeFlag ApplyCustomizeRaw => _applyCustomize; - internal EquipFlag ApplyEquip = EquipFlagExtensions.All; - internal CrestFlag ApplyCrest = CrestExtensions.AllRelevant; - private DesignFlags _designFlags = DesignFlags.ApplyHatVisible | DesignFlags.ApplyVisorState | DesignFlags.ApplyWeaponVisible; + internal EquipFlag ApplyEquip = EquipFlagExtensions.All; + internal CrestFlag ApplyCrest = CrestExtensions.AllRelevant; + internal MetaFlag ApplyMeta = MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.WeaponState; + private bool _writeProtected; public bool SetCustomize(CustomizeService customizeService, CustomizeArray customize) { @@ -98,69 +90,30 @@ public class DesignBase return true; } - public bool DoApplyHatVisible() - => _designFlags.HasFlag(DesignFlags.ApplyHatVisible); - - public bool DoApplyVisorToggle() - => _designFlags.HasFlag(DesignFlags.ApplyVisorState); - - public bool DoApplyWeaponVisible() - => _designFlags.HasFlag(DesignFlags.ApplyWeaponVisible); - - public bool DoApplyWetness() - => _designFlags.HasFlag(DesignFlags.ApplyWetness); + public bool DoApplyMeta(MetaIndex index) + => ApplyMeta.HasFlag(index.ToFlag()); public bool WriteProtected() - => _designFlags.HasFlag(DesignFlags.WriteProtected); + => _writeProtected; - public bool SetApplyHatVisible(bool value) + public bool SetApplyMeta(MetaIndex index, bool value) { - var newFlag = value ? _designFlags | DesignFlags.ApplyHatVisible : _designFlags & ~DesignFlags.ApplyHatVisible; - if (newFlag == _designFlags) + var newFlag = value ? ApplyMeta | index.ToFlag() : ApplyMeta & ~index.ToFlag(); + if (newFlag == ApplyMeta) return false; - _designFlags = newFlag; - return true; - } - - public bool SetApplyVisorToggle(bool value) - { - var newFlag = value ? _designFlags | DesignFlags.ApplyVisorState : _designFlags & ~DesignFlags.ApplyVisorState; - if (newFlag == _designFlags) - return false; - - _designFlags = newFlag; - return true; - } - - public bool SetApplyWeaponVisible(bool value) - { - var newFlag = value ? _designFlags | DesignFlags.ApplyWeaponVisible : _designFlags & ~DesignFlags.ApplyWeaponVisible; - if (newFlag == _designFlags) - return false; - - _designFlags = newFlag; - return true; - } - - public bool SetApplyWetness(bool value) - { - var newFlag = value ? _designFlags | DesignFlags.ApplyWetness : _designFlags & ~DesignFlags.ApplyWetness; - if (newFlag == _designFlags) - return false; - - _designFlags = newFlag; + ApplyMeta = newFlag; return true; } public bool SetWriteProtected(bool value) { - var newFlag = value ? _designFlags | DesignFlags.WriteProtected : _designFlags & ~DesignFlags.WriteProtected; - if (newFlag == _designFlags) + if (value == _writeProtected) return false; - _designFlags = newFlag; + _writeProtected = value; return true; + } public bool DoApplyEquip(EquipSlot slot) @@ -298,9 +251,9 @@ public class DesignBase ret[slot.ToString()] = Serialize(item.Id, stain, crest, DoApplyEquip(slot), DoApplyStain(slot), DoApplyCrest(crestSlot)); } - ret["Hat"] = new QuadBool(_designData.IsHatVisible(), DoApplyHatVisible()).ToJObject("Show", "Apply"); - ret["Visor"] = new QuadBool(_designData.IsVisorToggled(), DoApplyVisorToggle()).ToJObject("IsToggled", "Apply"); - ret["Weapon"] = new QuadBool(_designData.IsWeaponVisible(), DoApplyWeaponVisible()).ToJObject("Show", "Apply"); + ret["Hat"] = new QuadBool(_designData.IsHatVisible(), DoApplyMeta(MetaIndex.HatState)).ToJObject("Show", "Apply"); + ret["Visor"] = new QuadBool(_designData.IsVisorToggled(), DoApplyMeta(MetaIndex.VisorState)).ToJObject("IsToggled", "Apply"); + ret["Weapon"] = new QuadBool(_designData.IsWeaponVisible(), DoApplyMeta(MetaIndex.WeaponState)).ToJObject("Show", "Apply"); } else { @@ -344,7 +297,7 @@ public class DesignBase ret["Wetness"] = new JObject() { ["Value"] = _designData.IsWet(), - ["Apply"] = DoApplyWetness(), + ["Apply"] = DoApplyMeta(MetaIndex.Wetness), }; return ret; @@ -478,7 +431,7 @@ public class DesignBase // Load the token and set application. bool TryGetToken(CustomizeParameterFlag flag, [NotNullWhen(true)] out JToken? token) { - token = parameters![flag.ToString()]; + token = parameters[flag.ToString()]; if (token != null) { var apply = token["Apply"]?.ToObject() ?? false; @@ -493,8 +446,8 @@ public class DesignBase void MigrateLipOpacity() { - var token = parameters!["LipOpacity"]?["Percentage"]?.ToObject(); - var actualToken = parameters![CustomizeParameterFlag.LipDiffuse.ToString()]?["Alpha"]; + var token = parameters["LipOpacity"]?["Percentage"]?.ToObject(); + var actualToken = parameters[CustomizeParameterFlag.LipDiffuse.ToString()]?["Alpha"]; if (token != null && actualToken == null) design.GetDesignDataRef().Parameters.LipDiffuse.W = token.Value; } @@ -575,15 +528,15 @@ public class DesignBase design.SetApplyCrest(CrestFlag.OffHand, applyCrestOff); } var metaValue = QuadBool.FromJObject(equip["Hat"], "Show", "Apply", QuadBool.NullFalse); - design.SetApplyHatVisible(metaValue.Enabled); + design.SetApplyMeta(MetaIndex.HatState, metaValue.Enabled); design._designData.SetHatVisible(metaValue.ForcedValue); metaValue = QuadBool.FromJObject(equip["Weapon"], "Show", "Apply", QuadBool.NullFalse); - design.SetApplyWeaponVisible(metaValue.Enabled); + design.SetApplyMeta(MetaIndex.WeaponState, metaValue.Enabled); design._designData.SetWeaponVisible(metaValue.ForcedValue); metaValue = QuadBool.FromJObject(equip["Visor"], "IsToggled", "Apply", QuadBool.NullFalse); - design.SetApplyVisorToggle(metaValue.Enabled); + design.SetApplyMeta(MetaIndex.VisorState, metaValue.Enabled); design._designData.SetVisor(metaValue.ForcedValue); } @@ -610,7 +563,7 @@ public class DesignBase var wetness = QuadBool.FromJObject(json["Wetness"], "Value", "Apply", QuadBool.NullFalse); design._designData.SetIsWet(wetness.ForcedValue); - design.SetApplyWetness(wetness.Enabled); + design.SetApplyMeta(MetaIndex.Wetness, wetness.Enabled); design._designData.ModelId = json["ModelId"]?.ToObject() ?? 0; PrintWarning(customizations.ValidateModelId(design._designData.ModelId, out design._designData.ModelId, @@ -664,17 +617,13 @@ public class DesignBase try { _designData = DesignBase64Migration.MigrateBase64(items, humans, base64, out var equipFlags, out var customizeFlags, - out var writeProtected, - out var applyHat, out var applyVisor, out var applyWeapon); + out var writeProtected, out var applyMeta); ApplyEquip = equipFlags; ApplyCustomize = customizeFlags; ApplyParameters = 0; ApplyCrest = 0; + ApplyMeta = applyMeta; SetWriteProtected(writeProtected); - SetApplyHatVisible(applyHat); - SetApplyVisorToggle(applyVisor); - SetApplyWeaponVisible(applyWeapon); - SetApplyWetness(true); CustomizeSet = SetCustomizationSet(customize); } catch (Exception ex) diff --git a/Glamourer/Designs/DesignBase64Migration.cs b/Glamourer/Designs/DesignBase64Migration.cs index 2d85924..ec4beb1 100644 --- a/Glamourer/Designs/DesignBase64Migration.cs +++ b/Glamourer/Designs/DesignBase64Migration.cs @@ -1,4 +1,5 @@ using Glamourer.Services; +using Glamourer.State; using OtterGui; using Penumbra.GameData.DataContainers; using Penumbra.GameData.Enums; @@ -13,7 +14,7 @@ public class DesignBase64Migration public const int Base64SizeV4 = 95; public static unsafe DesignData MigrateBase64(ItemManager items, HumanModelList humans, string base64, out EquipFlag equipFlags, - out CustomizeFlag customizeFlags, out bool writeProtected, out bool applyHat, out bool applyVisor, out bool applyWeapon) + out CustomizeFlag customizeFlags, out bool writeProtected, out MetaFlag metaFlags) { static void CheckSize(int length, int requiredLength) { @@ -25,9 +26,7 @@ public class DesignBase64Migration byte applicationFlags; ushort equipFlagsS; var bytes = Convert.FromBase64String(base64); - applyHat = false; - applyVisor = false; - applyWeapon = false; + metaFlags = MetaFlag.Wetness; var data = new DesignData(); switch (bytes[0]) { @@ -77,9 +76,12 @@ public class DesignBase64Migration customizeFlags = (applicationFlags & 0x01) != 0 ? CustomizeFlagExtensions.All : 0; data.SetIsWet((applicationFlags & 0x02) != 0); - applyHat = (applicationFlags & 0x04) != 0; - applyWeapon = (applicationFlags & 0x08) != 0; - applyVisor = (applicationFlags & 0x10) != 0; + if ((applicationFlags & 0x04) != 0) + metaFlags |= MetaFlag.HatState; + if ((applicationFlags & 0x08) != 0) + metaFlags |= MetaFlag.WeaponState; + if ((applicationFlags & 0x10) != 0) + metaFlags |= MetaFlag.VisorState; writeProtected = (applicationFlags & 0x20) != 0; equipFlags = 0; diff --git a/Glamourer/Designs/DesignData.cs b/Glamourer/Designs/DesignData.cs index edc35e1..5b573d3 100644 --- a/Glamourer/Designs/DesignData.cs +++ b/Glamourer/Designs/DesignData.cs @@ -186,6 +186,26 @@ public unsafe struct DesignData return true; } + public readonly bool GetMeta(MetaIndex index) + => index switch + { + MetaIndex.Wetness => IsWet(), + MetaIndex.HatState => IsHatVisible(), + MetaIndex.VisorState => IsVisorToggled(), + MetaIndex.WeaponState => IsWeaponVisible(), + _ => false, + }; + + public bool SetMeta(MetaIndex index, bool value) + => index switch + { + MetaIndex.Wetness => SetIsWet(value), + MetaIndex.HatState => SetHatVisible(value), + MetaIndex.VisorState => SetVisor(value), + MetaIndex.WeaponState => SetWeaponVisible(value), + _ => false, + }; + public readonly bool IsWet() => (_states & 0x01) == 0x01; diff --git a/Glamourer/Designs/Links/DesignMerger.cs b/Glamourer/Designs/Links/DesignMerger.cs index abf1163..2aef9bc 100644 --- a/Glamourer/Designs/Links/DesignMerger.cs +++ b/Glamourer/Designs/Links/DesignMerger.cs @@ -6,50 +6,9 @@ using Glamourer.State; using Glamourer.Unlocks; using OtterGui.Services; using Penumbra.GameData.Enums; -using Penumbra.GameData.Structs; namespace Glamourer.Designs.Links; -using WeaponDict = Dictionary; - -public sealed class MergedDesign -{ - public MergedDesign(DesignManager designManager) - { - Design = designManager.CreateTemporary(); - Design.ApplyEquip = 0; - Design.ApplyCustomize = 0; - Design.ApplyCrest = 0; - Design.ApplyParameters = 0; - Design.SetApplyWetness(false); - Design.SetApplyVisorToggle(false); - Design.SetApplyWeaponVisible(false); - Design.SetApplyHatVisible(false); - } - - public readonly DesignBase Design; - public readonly WeaponDict Weapons = new(4); - public readonly StateSource Source = new(); - - public StateChanged.Source GetSource(EquipSlot slot, bool stain, StateChanged.Source actualSource) - => GetSource(Source[slot, stain], actualSource); - - public StateChanged.Source GetSource(CrestFlag slot, StateChanged.Source actualSource) - => GetSource(Source[slot], actualSource); - - public StateChanged.Source GetSource(CustomizeIndex type, StateChanged.Source actualSource) - => GetSource(Source[type], actualSource); - - public StateChanged.Source GetSource(MetaIndex index, StateChanged.Source actualSource) - => GetSource(Source[index], actualSource); - - public StateChanged.Source GetSource(CustomizeParameterFlag flag, StateChanged.Source actualSource) - => GetSource(Source[flag], actualSource); - - public static StateChanged.Source GetSource(StateChanged.Source given, StateChanged.Source actualSource) - => given is StateChanged.Source.Game ? StateChanged.Source.Game : actualSource; -} - public class DesignMerger( DesignManager designManager, CustomizeService _customize, @@ -57,7 +16,8 @@ public class DesignMerger( ItemUnlockManager _itemUnlocks, CustomizeUnlockManager _customizeUnlocks) : IService { - public MergedDesign Merge(IEnumerable<(DesignBase?, ApplicationType)> designs, in DesignData baseRef, bool respectOwnership) + public MergedDesign Merge(IEnumerable<(DesignBase?, ApplicationType)> designs, in DesignData baseRef, bool respectOwnership, + bool modAssociations) { var ret = new MergedDesign(designManager); CustomizeFlag fixFlags = 0; @@ -81,6 +41,7 @@ public class DesignMerger( ReduceOffhands(data, equipFlags, ret, source, respectOwnership); ReduceCrests(data, crestFlags, ret, source); ReduceParameters(data, parameterFlags, ret, source); + ReduceMods(design as Design, ret, modAssociations); } ApplyFixFlags(ret, fixFlags); @@ -88,6 +49,15 @@ public class DesignMerger( } + private static void ReduceMods(Design? design, MergedDesign ret, bool modAssociations) + { + if (design == null || !modAssociations) + return; + + foreach (var (mod, settings) in design.AssociatedMods) + ret.AssociatedMods.TryAdd(mod, settings); + } + private static void ReduceMeta(in DesignData design, bool applyHat, bool applyVisor, bool applyWeapon, bool applyWet, MergedDesign ret, StateChanged.Source source) { @@ -196,7 +166,8 @@ public class DesignMerger( } } - private void ReduceMainhands(in DesignData design, EquipFlag equipFlags, MergedDesign ret, StateChanged.Source source, bool respectOwnership) + private void ReduceMainhands(in DesignData design, EquipFlag equipFlags, MergedDesign ret, StateChanged.Source source, + bool respectOwnership) { if (!equipFlags.HasFlag(EquipFlag.Mainhand)) return; @@ -271,7 +242,7 @@ public class DesignMerger( ret.Source[CustomizeIndex.Face] = source; } - var set = _customize.Manager.GetSet(customize.Clan, customize.Gender); + var set = ret.Design.CustomizeSet; var face = customize.Face; foreach (var index in Enum.GetValues()) { @@ -291,6 +262,8 @@ public class DesignMerger( ret.Source[index] = source; fixFlags &= ~flag; } + + ret.Design.SetCustomize(_customize, customize); } private static void ApplyFixFlags(MergedDesign ret, CustomizeFlag fixFlags) diff --git a/Glamourer/Designs/Links/MergedDesign.cs b/Glamourer/Designs/Links/MergedDesign.cs index eccc46f..d4b3cab 100644 --- a/Glamourer/Designs/Links/MergedDesign.cs +++ b/Glamourer/Designs/Links/MergedDesign.cs @@ -1,5 +1,6 @@ using Glamourer.Events; using Glamourer.GameData; +using Glamourer.Interop.Penumbra; using Glamourer.State; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; @@ -15,15 +16,38 @@ public sealed class MergedDesign Design.ApplyCustomize = 0; Design.ApplyCrest = 0; Design.ApplyParameters = 0; - Design.SetApplyWetness(false); - Design.SetApplyVisorToggle(false); - Design.SetApplyWeaponVisible(false); - Design.SetApplyHatVisible(false); + Design.ApplyMeta = 0; + } + + public MergedDesign(DesignBase design) + { + Design = design; + if (design.DoApplyEquip(EquipSlot.MainHand)) + { + var weapon = design.DesignData.Item(EquipSlot.MainHand); + if (weapon.Valid) + Weapons.TryAdd(weapon.Type, (weapon, StateChanged.Source.Manual)); + } + + if (design.DoApplyEquip(EquipSlot.OffHand)) + { + var weapon = design.DesignData.Item(EquipSlot.OffHand); + if (weapon.Valid) + Weapons.TryAdd(weapon.Type, (weapon, StateChanged.Source.Manual)); + } + } + + public MergedDesign(Design design) + : this((DesignBase)design) + { + foreach (var (mod, settings) in design.AssociatedMods) + AssociatedMods[mod] = settings; } public readonly DesignBase Design; - public readonly Dictionary Weapons = new(4); - public readonly StateSource Source = new(); + public readonly Dictionary Weapons = new(4); + public readonly StateSource Source = new(); + public readonly SortedList AssociatedMods = []; public StateChanged.Source GetSource(EquipSlot slot, bool stain, StateChanged.Source actualSource) => GetSource(Source[slot, stain], actualSource); diff --git a/Glamourer/Designs/MetaIndex.cs b/Glamourer/Designs/MetaIndex.cs new file mode 100644 index 0000000..4fac98d --- /dev/null +++ b/Glamourer/Designs/MetaIndex.cs @@ -0,0 +1,39 @@ +using Penumbra.GameData.Enums; + +namespace Glamourer.State; + +public enum MetaIndex +{ + Wetness = EquipFlagExtensions.NumEquipFlags + CustomizationExtensions.NumIndices, + HatState, + VisorState, + WeaponState, + ModelId, +} + +[Flags] +public enum MetaFlag : byte +{ + Wetness = 0x01, + HatState = 0x02, + VisorState = 0x04, + WeaponState = 0x08, +} + +public static class MetaExtensions +{ + public static readonly IReadOnlyList AllRelevant = + [MetaIndex.Wetness, MetaIndex.HatState, MetaIndex.VisorState, MetaIndex.WeaponState]; + + public const MetaFlag All = MetaFlag.Wetness | MetaFlag.HatState | MetaFlag.VisorState | MetaFlag.WeaponState; + + public static MetaFlag ToFlag(this MetaIndex index) + => index switch + { + MetaIndex.Wetness => MetaFlag.Wetness, + MetaIndex.HatState => MetaFlag.HatState, + MetaIndex.VisorState => MetaFlag.VisorState, + MetaIndex.WeaponState => MetaFlag.WeaponState, + _ => (MetaFlag) byte.MaxValue, + }; +} diff --git a/Glamourer/Interop/PalettePlus/PaletteImport.cs b/Glamourer/Interop/PalettePlus/PaletteImport.cs index b26f8f9..8513036 100644 --- a/Glamourer/Interop/PalettePlus/PaletteImport.cs +++ b/Glamourer/Interop/PalettePlus/PaletteImport.cs @@ -1,7 +1,6 @@ using Dalamud.Plugin; using Glamourer.Designs; using Glamourer.GameData; -using Glamourer.State; using Newtonsoft.Json.Linq; using OtterGui.Services; diff --git a/Glamourer/State/StateEditor.cs b/Glamourer/State/StateEditor.cs index 1d23cff..abb3716 100644 --- a/Glamourer/State/StateEditor.cs +++ b/Glamourer/State/StateEditor.cs @@ -1,4 +1,5 @@ using Dalamud.Plugin.Services; +using Glamourer.Designs; using Glamourer.Events; using Glamourer.GameData; using Glamourer.Services; diff --git a/Glamourer/State/StateListener.cs b/Glamourer/State/StateListener.cs index d529206..a8c8dd5 100644 --- a/Glamourer/State/StateListener.cs +++ b/Glamourer/State/StateListener.cs @@ -11,6 +11,7 @@ using Dalamud.Game.ClientState.Conditions; using Dalamud.Plugin.Services; using Glamourer.GameData; using Penumbra.GameData.DataContainers; +using Glamourer.Designs; namespace Glamourer.State; diff --git a/Glamourer/State/StateSource.cs b/Glamourer/State/StateSource.cs index 04c934d..80899d2 100644 --- a/Glamourer/State/StateSource.cs +++ b/Glamourer/State/StateSource.cs @@ -4,15 +4,6 @@ using static Glamourer.Events.StateChanged; namespace Glamourer.State; -public enum MetaIndex -{ - Wetness = EquipFlagExtensions.NumEquipFlags + CustomizationExtensions.NumIndices, - HatState, - VisorState, - WeaponState, - ModelId, -} - public readonly struct StateSource { public static readonly int Size = EquipFlagExtensions.NumEquipFlags