diff --git a/Glamourer.GameData/Customization/CustomizeFlag.cs b/Glamourer.GameData/Customization/CustomizeFlag.cs index 54f7f5c..44b6cee 100644 --- a/Glamourer.GameData/Customization/CustomizeFlag.cs +++ b/Glamourer.GameData/Customization/CustomizeFlag.cs @@ -47,9 +47,14 @@ public enum CustomizeFlag : ulong public static class CustomizeFlagExtensions { - public const CustomizeFlag All = (CustomizeFlag)(((ulong)CustomizeFlag.FacePaintColor << 1) - 1ul); - public const CustomizeFlag AllRelevant = All & ~CustomizeFlag.BodyType & ~CustomizeFlag.Race; - public const CustomizeFlag RedrawRequired = CustomizeFlag.Race | CustomizeFlag.Clan | CustomizeFlag.Gender | CustomizeFlag.Face | CustomizeFlag.BodyType; + public const CustomizeFlag All = (CustomizeFlag)(((ulong)CustomizeFlag.FacePaintColor << 1) - 1ul); + public const CustomizeFlag AllRelevant = All & ~CustomizeFlag.BodyType & ~CustomizeFlag.Race; + + public const CustomizeFlag RedrawRequired = + CustomizeFlag.Race | CustomizeFlag.Clan | CustomizeFlag.Gender | CustomizeFlag.Face | CustomizeFlag.BodyType; + + public static CustomizeFlag FixApplication(this CustomizeFlag flag, CustomizationSet set) + => flag & (set.SettingAvailable | CustomizeFlag.Clan | CustomizeFlag.Gender); public static bool RequiresRedraw(this CustomizeFlag flags) => (flags & RedrawRequired) != 0; diff --git a/Glamourer/Designs/Design.cs b/Glamourer/Designs/Design.cs index 9870394..eb2f322 100644 --- a/Glamourer/Designs/Design.cs +++ b/Glamourer/Designs/Design.cs @@ -14,8 +14,8 @@ namespace Glamourer.Designs; public sealed class Design : DesignBase, ISavable { #region Data - internal Design(ItemManager items) - : base(items) + internal Design(CustomizationService customize, ItemManager items) + : base(customize, items) { } internal Design(DesignBase other) @@ -116,7 +116,7 @@ public sealed class Design : DesignBase, ISavable var creationDate = json["CreationDate"]?.ToObject() ?? throw new ArgumentNullException("CreationDate"); - var design = new Design(items) + var design = new Design(customizations, items) { CreationDate = creationDate, Identifier = json["Identifier"]?.ToObject() ?? throw new ArgumentNullException("Identifier"), diff --git a/Glamourer/Designs/DesignBase.cs b/Glamourer/Designs/DesignBase.cs index db923ce..258c765 100644 --- a/Glamourer/Designs/DesignBase.cs +++ b/Glamourer/Designs/DesignBase.cs @@ -16,15 +16,16 @@ public class DesignBase { public const int FileVersion = 1; - internal DesignBase(ItemManager items) + internal DesignBase(CustomizationService customize, ItemManager items) { DesignData.SetDefaultEquipment(items); + FixCustomizeApplication(customize); } internal DesignBase(DesignBase clone) { DesignData = clone.DesignData; - ApplyCustomize = clone.ApplyCustomize & CustomizeFlagExtensions.All; + ApplyCustomize = clone.ApplyCustomize & CustomizeFlagExtensions.AllRelevant; ApplyEquip = clone.ApplyEquip & EquipFlagExtensions.All; _designFlags = clone._designFlags & (DesignFlags)0x0F; } @@ -43,7 +44,7 @@ public class DesignBase WriteProtected = 0x10, } - internal CustomizeFlag ApplyCustomize = CustomizeFlagExtensions.All; + internal CustomizeFlag ApplyCustomize = CustomizeFlagExtensions.AllRelevant; internal EquipFlag ApplyEquip = EquipFlagExtensions.All; private DesignFlags _designFlags = DesignFlags.ApplyHatVisible | DesignFlags.ApplyVisorState | DesignFlags.ApplyWeaponVisible; @@ -151,6 +152,18 @@ public class DesignBase return true; } + public void FixCustomizeApplication(CustomizationService service) + => FixCustomizeApplication(service, ApplyCustomize); + + public void FixCustomizeApplication(CustomizationSet set) + => FixCustomizeApplication(set, ApplyCustomize); + + public void FixCustomizeApplication(CustomizationService service, CustomizeFlag flags) + => FixCustomizeApplication(service.AwaitedService.GetList(DesignData.Customize.Clan, DesignData.Customize.Gender), flags); + + public void FixCustomizeApplication(CustomizationSet set, CustomizeFlag flags) + => ApplyCustomize = flags.FixApplication(set); + #endregion #region Serialization @@ -244,7 +257,7 @@ public class DesignBase private static DesignBase LoadDesignV1Base(CustomizationService customizations, ItemManager items, JObject json) { - var ret = new DesignBase(items); + var ret = new DesignBase(customizations, items); LoadCustomize(customizations, json["Customize"], ret, "Temporary Design", false, true); LoadEquip(items, json["Equipment"], ret, "Temporary Design", true); return ret; @@ -398,7 +411,7 @@ public class DesignBase } } - design.ApplyCustomize &= set.SettingAvailable | CustomizeFlag.Gender | CustomizeFlag.Clan; + design.FixCustomizeApplication(set); } public void MigrateBase64(ItemManager items, HumanModelList humans, string base64) diff --git a/Glamourer/Designs/DesignConverter.cs b/Glamourer/Designs/DesignConverter.cs index 94d7345..09de0cf 100644 --- a/Glamourer/Designs/DesignConverter.cs +++ b/Glamourer/Designs/DesignConverter.cs @@ -60,8 +60,8 @@ public class DesignConverter public DesignBase Convert(ActorState state, EquipFlag equipFlags, CustomizeFlag customizeFlags) { var design = _designs.CreateTemporary(); - design.ApplyEquip = equipFlags & EquipFlagExtensions.All; - design.ApplyCustomize = customizeFlags & CustomizeFlagExtensions.All; + design.ApplyEquip = equipFlags & EquipFlagExtensions.All; + design.FixCustomizeApplication(_customize, customizeFlags); design.SetApplyHatVisible(design.DoApplyEquip(EquipSlot.Head)); design.SetApplyVisorToggle(design.DoApplyEquip(EquipSlot.Head)); design.SetApplyWeaponVisible(design.DoApplyEquip(EquipSlot.MainHand) || design.DoApplyEquip(EquipSlot.OffHand)); @@ -127,6 +127,10 @@ public class DesignConverter ret.ApplyCustomize = 0; ret.SetApplyWetness(false); } + else + { + ret.FixCustomizeApplication(_customize); + } if (!equip) { diff --git a/Glamourer/Designs/DesignManager.cs b/Glamourer/Designs/DesignManager.cs index d70deaf..ca3a605 100644 --- a/Glamourer/Designs/DesignManager.cs +++ b/Glamourer/Designs/DesignManager.cs @@ -85,13 +85,13 @@ public class DesignManager /// Create a new temporary design without adding it to the manager. public DesignBase CreateTemporary() - => new(_items); + => new(_customizations, _items); /// Create a new design of a given name. public Design CreateEmpty(string name, bool handlePath) { var (actualName, path) = ParseName(name, handlePath); - var design = new Design(_items) + var design = new Design(_customizations, _items) { CreationDate = DateTimeOffset.UtcNow, LastEdit = DateTimeOffset.UtcNow, @@ -522,7 +522,7 @@ public class DesignManager try { var actualName = Path.GetFileName(name); - var design = new Design(_items) + var design = new Design(_customizations, _items) { CreationDate = File.GetCreationTimeUtc(_saveService.FileNames.MigrationDesignFile), LastEdit = File.GetLastWriteTimeUtc(_saveService.FileNames.MigrationDesignFile), diff --git a/Glamourer/Gui/Tabs/AutomationTab/DesignCombo.cs b/Glamourer/Gui/Tabs/AutomationTab/DesignCombo.cs index 154a25c..70e94d6 100644 --- a/Glamourer/Gui/Tabs/AutomationTab/DesignCombo.cs +++ b/Glamourer/Gui/Tabs/AutomationTab/DesignCombo.cs @@ -2,6 +2,7 @@ using System.Linq; using Dalamud.Interface; using Glamourer.Automation; +using Glamourer.Customization; using Glamourer.Designs; using Glamourer.Events; using Glamourer.Services; @@ -22,8 +23,8 @@ public sealed class DesignCombo : FilterComboCache<(Design, string)> private float _innerWidth; public DesignCombo(AutoDesignManager manager, DesignManager designs, DesignFileSystem fileSystem, TabSelected tabSelected, - ItemManager items) - : this(manager, designs, fileSystem, tabSelected, CreateRevertDesign(items)) + ItemManager items, CustomizationService customize) + : this(manager, designs, fileSystem, tabSelected, CreateRevertDesign(customize, items)) { } private DesignCombo(AutoDesignManager manager, DesignManager designs, DesignFileSystem fileSystem, TabSelected tabSelected, @@ -97,10 +98,11 @@ public sealed class DesignCombo : FilterComboCache<(Design, string)> return filter.IsContained(path) || design.Name.Lower.Contains(filter.Lower); } - private static Design CreateRevertDesign(ItemManager items) - => new(items) + private static Design CreateRevertDesign(CustomizationService customize, ItemManager items) + => new(customize, items) { Index = RevertDesignIndex, Name = AutoDesign.RevertName, + ApplyCustomize = CustomizeFlagExtensions.AllRelevant, }; } diff --git a/Glamourer/Services/CustomizationService.cs b/Glamourer/Services/CustomizationService.cs index 12b4fa8..630479d 100644 --- a/Glamourer/Services/CustomizationService.cs +++ b/Glamourer/Services/CustomizationService.cs @@ -35,8 +35,9 @@ public sealed class CustomizationService : AsyncServiceWrapper Returns whether a customization value is valid for a given clan/gender set and face. [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - public static bool IsCustomizationValid(CustomizationSet set, CustomizeValue face, CustomizeIndex type, CustomizeValue value, out CustomizeData? data) + public static bool IsCustomizationValid(CustomizationSet set, CustomizeValue face, CustomizeIndex type, CustomizeValue value, + out CustomizeData? data) => set.Validate(type, value, out data, face); /// Returns whether a customization value is valid for a given clan, gender and face.