From 68327d3563b6460d263bbceed316f657105d3c9d Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Thu, 16 Nov 2023 17:32:55 +0100 Subject: [PATCH] Do a bunch of refactoring regarding available application options. --- Glamourer/Automation/AutoDesign.cs | 2 +- Glamourer/Automation/AutoDesignApplier.cs | 10 +- Glamourer/Designs/Design.cs | 2 +- Glamourer/Designs/DesignBase.cs | 201 ++++++++++-------- Glamourer/Designs/DesignConverter.cs | 21 +- Glamourer/Designs/DesignManager.cs | 52 +++-- .../CustomizationDrawer.GenderRace.cs | 1 - Glamourer/Gui/Tabs/DebugTab.cs | 2 +- .../DesignTab/DesignFileSystemSelector.cs | 9 +- Glamourer/Gui/Tabs/DesignTab/DesignPanel.cs | 13 +- Glamourer/State/FunModule.cs | 3 +- Glamourer/State/StateManager.cs | 2 +- 12 files changed, 168 insertions(+), 150 deletions(-) diff --git a/Glamourer/Automation/AutoDesign.cs b/Glamourer/Automation/AutoDesign.cs index 2004652..7beda18 100644 --- a/Glamourer/Automation/AutoDesign.cs +++ b/Glamourer/Automation/AutoDesign.cs @@ -31,7 +31,7 @@ public class AutoDesign public string Name(bool incognito) => Revert ? RevertName : incognito ? Design!.Incognito : Design!.Name.Text; - public ref DesignData GetDesignData(ActorState state) + public ref readonly DesignData GetDesignData(ActorState state) => ref Design == null ? ref state.BaseData : ref Design.DesignData; public bool Revert diff --git a/Glamourer/Automation/AutoDesignApplier.cs b/Glamourer/Automation/AutoDesignApplier.cs index f68c3c1..92cd2b0 100644 --- a/Glamourer/Automation/AutoDesignApplier.cs +++ b/Glamourer/Automation/AutoDesignApplier.cs @@ -89,7 +89,8 @@ public class AutoDesignApplier : IDisposable { if (_jobChangeMainhand.TryGetValue(current.Type, out var data)) { - Glamourer.Log.Verbose($"Changing Mainhand from {_jobChangeState.ModelData.Weapon(EquipSlot.MainHand)} | {_jobChangeState.BaseData.Weapon(EquipSlot.MainHand)} to {data.Item1} for 0x{actor.Address:X}."); + Glamourer.Log.Verbose( + $"Changing Mainhand from {_jobChangeState.ModelData.Weapon(EquipSlot.MainHand)} | {_jobChangeState.BaseData.Weapon(EquipSlot.MainHand)} to {data.Item1} for 0x{actor.Address:X}."); _state.ChangeItem(_jobChangeState, EquipSlot.MainHand, data.Item1, data.Item2); weapon.Value = _jobChangeState.ModelData.Weapon(EquipSlot.MainHand); } @@ -98,7 +99,8 @@ public class AutoDesignApplier : IDisposable { if (_jobChangeOffhand.TryGetValue(current.Type, out var data)) { - Glamourer.Log.Verbose($"Changing Offhand from {_jobChangeState.ModelData.Weapon(EquipSlot.OffHand)} | {_jobChangeState.BaseData.Weapon(EquipSlot.OffHand)} to {data.Item1} for 0x{actor.Address:X}."); + Glamourer.Log.Verbose( + $"Changing Offhand from {_jobChangeState.ModelData.Weapon(EquipSlot.OffHand)} | {_jobChangeState.BaseData.Weapon(EquipSlot.OffHand)} to {data.Item1} for 0x{actor.Address:X}."); _state.ChangeItem(_jobChangeState, EquipSlot.OffHand, data.Item1, data.Item2); weapon.Value = _jobChangeState.ModelData.Weapon(EquipSlot.OffHand); } @@ -277,8 +279,8 @@ public class AutoDesignApplier : IDisposable if (design.ApplicationType is 0) continue; - ref var data = ref design.GetDesignData(state); - var source = design.Revert ? StateChanged.Source.Game : StateChanged.Source.Fixed; + ref readonly var data = ref design.GetDesignData(state); + var source = design.Revert ? StateChanged.Source.Game : StateChanged.Source.Fixed; if (!data.IsHuman) continue; diff --git a/Glamourer/Designs/Design.cs b/Glamourer/Designs/Design.cs index e6593a9..9901e81 100644 --- a/Glamourer/Designs/Design.cs +++ b/Glamourer/Designs/Design.cs @@ -15,7 +15,7 @@ public sealed class Design : DesignBase, ISavable { #region Data internal Design(CustomizationService customize, ItemManager items) - : base(items) + : base(customize, items) { } internal Design(DesignBase other) diff --git a/Glamourer/Designs/DesignBase.cs b/Glamourer/Designs/DesignBase.cs index 9fe18ff..cb40279 100644 --- a/Glamourer/Designs/DesignBase.cs +++ b/Glamourer/Designs/DesignBase.cs @@ -16,20 +16,37 @@ public class DesignBase { public const int FileVersion = 1; - internal DesignBase(ItemManager items) + private DesignData _designData = new(); + + /// For read-only information about the actual design. + public ref readonly DesignData DesignData + => ref _designData; + + /// To make it clear that something is edited here. + public ref DesignData GetDesignDataRef() + => ref _designData; + + internal DesignBase(CustomizationService customize, ItemManager items) { - DesignData.SetDefaultEquipment(items); + _designData.SetDefaultEquipment(items); + CustomizationSet = SetCustomizationSet(customize); } internal DesignBase(DesignBase clone) { - DesignData = clone.DesignData; - ApplyCustomize = clone.ApplyCustomize & CustomizeFlagExtensions.AllRelevant; - ApplyEquip = clone.ApplyEquip & EquipFlagExtensions.All; - _designFlags = clone._designFlags & (DesignFlags)0x0F; + _designData = clone._designData; + CustomizationSet = clone.CustomizationSet; + ApplyCustomize = clone.ApplyCustomizeRaw; + ApplyEquip = clone.ApplyEquip & EquipFlagExtensions.All; + _designFlags = clone._designFlags & (DesignFlags)0x0F; } - internal DesignData DesignData = new(); + /// Ensure that the customization set is updated when the design data changes. + internal void SetDesignData(CustomizationService customize, in DesignData other) + { + _designData = other; + CustomizationSet = SetCustomizationSet(customize); + } #region Application Data @@ -43,9 +60,30 @@ public class DesignBase WriteProtected = 0x10, } - internal CustomizeFlag ApplyCustomize = CustomizeFlagExtensions.AllRelevant; - internal EquipFlag ApplyEquip = EquipFlagExtensions.All; - private DesignFlags _designFlags = DesignFlags.ApplyHatVisible | DesignFlags.ApplyVisorState | DesignFlags.ApplyWeaponVisible; + private CustomizeFlag _applyCustomize = CustomizeFlagExtensions.AllRelevant; + public CustomizationSet CustomizationSet { get; private set; } + + internal CustomizeFlag ApplyCustomize + { + get => _applyCustomize.FixApplication(CustomizationSet); + set => _applyCustomize = value & CustomizeFlagExtensions.AllRelevant; + } + + internal CustomizeFlag ApplyCustomizeRaw + => _applyCustomize; + + internal EquipFlag ApplyEquip = EquipFlagExtensions.All; + private DesignFlags _designFlags = DesignFlags.ApplyHatVisible | DesignFlags.ApplyVisorState | DesignFlags.ApplyWeaponVisible; + + public bool SetCustomize(CustomizationService customizationService, Customize customize) + { + if (customize.Equals(_designData.Customize)) + return false; + + _designData.Customize.Load(customize); + CustomizationSet = customizationService.AwaitedService.GetList(customize.Clan, customize.Gender); + return true; + } public bool DoApplyHatVisible() => _designFlags.HasFlag(DesignFlags.ApplyHatVisible); @@ -119,7 +157,7 @@ public class DesignBase => ApplyEquip.HasFlag(slot.ToStainFlag()); public bool DoApplyCustomize(CustomizeIndex idx) - => idx is not CustomizeIndex.Race and not CustomizeIndex.BodyType && ApplyCustomize.HasFlag(idx.ToFlag()); + => ApplyCustomize.HasFlag(idx.ToFlag()); internal bool SetApplyEquip(EquipSlot slot, bool value) { @@ -143,20 +181,14 @@ public class DesignBase internal bool SetApplyCustomize(CustomizeIndex idx, bool value) { - var newValue = value ? ApplyCustomize | idx.ToFlag() : ApplyCustomize & ~idx.ToFlag(); - if (newValue == ApplyCustomize) + var newValue = value ? _applyCustomize | idx.ToFlag() : _applyCustomize & ~idx.ToFlag(); + if (newValue == _applyCustomize) return false; - ApplyCustomize = newValue; + _applyCustomize = newValue; return true; } - 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); - internal FlagRestrictionResetter TemporarilyRestrictApplication(EquipFlag equipFlags, CustomizeFlag customizeFlags) => new(this, equipFlags, customizeFlags); @@ -170,7 +202,7 @@ public class DesignBase { _design = d; _oldEquipFlags = d.ApplyEquip; - _oldCustomizeFlags = d.ApplyCustomize; + _oldCustomizeFlags = d.ApplyCustomizeRaw; d.ApplyEquip &= equipFlags; d.ApplyCustomize &= customizeFlags; } @@ -182,6 +214,11 @@ public class DesignBase } } + private CustomizationSet SetCustomizationSet(CustomizationService customize) + => !_designData.IsHuman + ? customize.AwaitedService.GetList(SubRace.Midlander, Gender.Male) + : customize.AwaitedService.GetList(_designData.Customize.Clan, _designData.Customize.Gender); + #endregion #region Serialization @@ -209,22 +246,22 @@ public class DesignBase }; var ret = new JObject(); - if (DesignData.IsHuman) + if (_designData.IsHuman) { foreach (var slot in EquipSlotExtensions.EqdpSlots.Prepend(EquipSlot.OffHand).Prepend(EquipSlot.MainHand)) { - var item = DesignData.Item(slot); - var stain = DesignData.Stain(slot); + var item = _designData.Item(slot); + var stain = _designData.Stain(slot); ret[slot.ToString()] = Serialize(item.Id, stain, DoApplyEquip(slot), DoApplyStain(slot)); } - 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(), DoApplyHatVisible()).ToJObject("Show", "Apply"); + ret["Visor"] = new QuadBool(_designData.IsVisorToggled(), DoApplyVisorToggle()).ToJObject("IsToggled", "Apply"); + ret["Weapon"] = new QuadBool(_designData.IsWeaponVisible(), DoApplyWeaponVisible()).ToJObject("Show", "Apply"); } else { - ret["Array"] = DesignData.WriteEquipmentBytesBase64(); + ret["Array"] = _designData.WriteEquipmentBytesBase64(); } return ret; @@ -234,17 +271,17 @@ public class DesignBase { var ret = new JObject() { - ["ModelId"] = DesignData.ModelId, + ["ModelId"] = _designData.ModelId, }; - var customize = DesignData.Customize; - if (DesignData.IsHuman) + var customize = _designData.Customize; + if (_designData.IsHuman) foreach (var idx in Enum.GetValues()) { ret[idx.ToString()] = new JObject() { ["Value"] = customize[idx].Value, - ["Apply"] = DoApplyCustomize(idx), + ["Apply"] = ApplyCustomizeRaw.HasFlag(idx.ToFlag()), }; } else @@ -252,7 +289,7 @@ public class DesignBase ret["Wetness"] = new JObject() { - ["Value"] = DesignData.IsWet(), + ["Value"] = _designData.IsWet(), ["Apply"] = DoApplyWetness(), }; @@ -275,7 +312,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; @@ -285,16 +322,16 @@ public class DesignBase { if (equip == null) { - design.DesignData.SetDefaultEquipment(items); + design._designData.SetDefaultEquipment(items); Glamourer.Messager.NotificationMessage("The loaded design does not contain any equipment data, reset to default.", NotificationType.Warning); return; } - if (!design.DesignData.IsHuman) + if (!design._designData.IsHuman) { var textArray = equip["Array"]?.ToObject() ?? string.Empty; - design.DesignData.SetEquipmentBytesFromBase64(textArray); + design._designData.SetEquipmentBytesFromBase64(textArray); return; } @@ -319,8 +356,8 @@ public class DesignBase PrintWarning(items.ValidateItem(slot, id, out var item, allowUnknown)); PrintWarning(items.ValidateStain(stain, out stain, allowUnknown)); - design.DesignData.SetItem(slot, item); - design.DesignData.SetStain(slot, stain); + design._designData.SetItem(slot, item); + design._designData.SetStain(slot, stain); design.SetApplyEquip(slot, apply); design.SetApplyStain(slot, applyStain); } @@ -336,10 +373,10 @@ public class DesignBase PrintWarning(items.ValidateWeapons(id, idOff, out var main, out var off, allowUnknown)); PrintWarning(items.ValidateStain(stain, out stain, allowUnknown)); PrintWarning(items.ValidateStain(stainOff, out stainOff, allowUnknown)); - design.DesignData.SetItem(EquipSlot.MainHand, main); - design.DesignData.SetItem(EquipSlot.OffHand, off); - design.DesignData.SetStain(EquipSlot.MainHand, stain); - design.DesignData.SetStain(EquipSlot.OffHand, stainOff); + design._designData.SetItem(EquipSlot.MainHand, main); + design._designData.SetItem(EquipSlot.OffHand, off); + design._designData.SetStain(EquipSlot.MainHand, stain); + design._designData.SetStain(EquipSlot.OffHand, stainOff); design.SetApplyEquip(EquipSlot.MainHand, apply); design.SetApplyEquip(EquipSlot.OffHand, applyOff); design.SetApplyStain(EquipSlot.MainHand, applyStain); @@ -347,15 +384,15 @@ public class DesignBase } var metaValue = QuadBool.FromJObject(equip["Hat"], "Show", "Apply", QuadBool.NullFalse); design.SetApplyHatVisible(metaValue.Enabled); - design.DesignData.SetHatVisible(metaValue.ForcedValue); + design._designData.SetHatVisible(metaValue.ForcedValue); metaValue = QuadBool.FromJObject(equip["Weapon"], "Show", "Apply", QuadBool.NullFalse); design.SetApplyWeaponVisible(metaValue.Enabled); - design.DesignData.SetWeaponVisible(metaValue.ForcedValue); + design._designData.SetWeaponVisible(metaValue.ForcedValue); metaValue = QuadBool.FromJObject(equip["Visor"], "IsToggled", "Apply", QuadBool.NullFalse); design.SetApplyVisorToggle(metaValue.Enabled); - design.DesignData.SetVisor(metaValue.ForcedValue); + design._designData.SetVisor(metaValue.ForcedValue); } protected static void LoadCustomize(CustomizationService customizations, JToken? json, DesignBase design, string name, bool forbidNonHuman, @@ -363,9 +400,9 @@ public class DesignBase { if (json == null) { - design.DesignData.ModelId = 0; - design.DesignData.IsHuman = true; - design.DesignData.Customize = Customize.Default; + design._designData.ModelId = 0; + design._designData.IsHuman = true; + design.SetCustomize(customizations, Customize.Default); Glamourer.Messager.NotificationMessage("The loaded design does not contain any customization data, reset to default.", NotificationType.Warning); return; @@ -380,21 +417,22 @@ public class DesignBase } var wetness = QuadBool.FromJObject(json["Wetness"], "Value", "Apply", QuadBool.NullFalse); - design.DesignData.SetIsWet(wetness.ForcedValue); + design._designData.SetIsWet(wetness.ForcedValue); design.SetApplyWetness(wetness.Enabled); - design.DesignData.ModelId = json["ModelId"]?.ToObject() ?? 0; - PrintWarning(customizations.ValidateModelId(design.DesignData.ModelId, out design.DesignData.ModelId, out design.DesignData.IsHuman)); - if (design.DesignData.ModelId != 0 && forbidNonHuman) + design._designData.ModelId = json["ModelId"]?.ToObject() ?? 0; + PrintWarning(customizations.ValidateModelId(design._designData.ModelId, out design._designData.ModelId, out design._designData.IsHuman)); + if (design._designData.ModelId != 0 && forbidNonHuman) { PrintWarning("Model IDs different from 0 are not currently allowed, reset model id to 0."); - design.DesignData.ModelId = 0; - design.DesignData.IsHuman = true; + design._designData.ModelId = 0; + design._designData.IsHuman = true; } - else if (!design.DesignData.IsHuman) + else if (!design._designData.IsHuman) { var arrayText = json["Array"]?.ToObject() ?? string.Empty; - design.DesignData.Customize.LoadBase64(arrayText); + design._designData.Customize.LoadBase64(arrayText); + design.CustomizationSet = design.SetCustomizationSet(customizations); return; } @@ -403,42 +441,32 @@ public class DesignBase PrintWarning(customizations.ValidateClan(clan, race, out race, out clan)); var gender = (Gender)((json[CustomizeIndex.Gender.ToString()]?["Value"]?.ToObject() ?? 0) + 1); PrintWarning(customizations.ValidateGender(race, gender, out gender)); - design.DesignData.Customize.Race = race; - design.DesignData.Customize.Clan = clan; - design.DesignData.Customize.Gender = gender; + design._designData.Customize.Race = race; + design._designData.Customize.Clan = clan; + design._designData.Customize.Gender = gender; + design.CustomizationSet = design.SetCustomizationSet(customizations); design.SetApplyCustomize(CustomizeIndex.Race, json[CustomizeIndex.Race.ToString()]?["Apply"]?.ToObject() ?? false); design.SetApplyCustomize(CustomizeIndex.Clan, json[CustomizeIndex.Clan.ToString()]?["Apply"]?.ToObject() ?? false); design.SetApplyCustomize(CustomizeIndex.Gender, json[CustomizeIndex.Gender.ToString()]?["Apply"]?.ToObject() ?? false); - - var set = customizations.AwaitedService.GetList(clan, gender); + var set = design.CustomizationSet; foreach (var idx in CustomizationExtensions.AllBasic) { - if (set.IsAvailable(idx)) - { - var tok = json[idx.ToString()]; - var data = (CustomizeValue)(tok?["Value"]?.ToObject() ?? 0); - PrintWarning(CustomizationService.ValidateCustomizeValue(set, design.DesignData.Customize.Face, idx, data, out data, - allowUnknown)); - var apply = tok?["Apply"]?.ToObject() ?? false; - design.DesignData.Customize[idx] = data; - design.SetApplyCustomize(idx, apply); - } - else - { - design.DesignData.Customize[idx] = CustomizeValue.Zero; - design.SetApplyCustomize(idx, false); - } + var tok = json[idx.ToString()]; + var data = (CustomizeValue)(tok?["Value"]?.ToObject() ?? 0); + PrintWarning(CustomizationService.ValidateCustomizeValue(set, design._designData.Customize.Face, idx, data, out data, + allowUnknown)); + var apply = tok?["Apply"]?.ToObject() ?? false; + design._designData.Customize[idx] = data; + design.SetApplyCustomize(idx, apply); } - - design.FixCustomizeApplication(set, design.ApplyCustomize); } - public void MigrateBase64(ItemManager items, HumanModelList humans, string base64) + public void MigrateBase64(CustomizationService customize, ItemManager items, HumanModelList humans, string base64) { try { - DesignData = DesignBase64Migration.MigrateBase64(items, humans, base64, out var equipFlags, out var customizeFlags, + _designData = DesignBase64Migration.MigrateBase64(items, humans, base64, out var equipFlags, out var customizeFlags, out var writeProtected, out var applyHat, out var applyVisor, out var applyWeapon); ApplyEquip = equipFlags; @@ -448,6 +476,7 @@ public class DesignBase SetApplyVisorToggle(applyVisor); SetApplyWeaponVisible(applyWeapon); SetApplyWetness(true); + CustomizationSet = SetCustomizationSet(customize); } catch (Exception ex) { @@ -455,15 +484,5 @@ public class DesignBase } } - public void RemoveInvalidCustomize(CustomizationService customizations) - { - var set = customizations.AwaitedService.GetList(DesignData.Customize.Clan, DesignData.Customize.Gender); - foreach (var idx in CustomizationExtensions.AllBasic.Where(i => !set.IsAvailable(i))) - { - DesignData.Customize[idx] = CustomizeValue.Zero; - SetApplyCustomize(idx, false); - } - } - #endregion } diff --git a/Glamourer/Designs/DesignConverter.cs b/Glamourer/Designs/DesignConverter.cs index 22bf287..d8f2b0a 100644 --- a/Glamourer/Designs/DesignConverter.cs +++ b/Glamourer/Designs/DesignConverter.cs @@ -60,13 +60,13 @@ public class DesignConverter public DesignBase Convert(ActorState state, EquipFlag equipFlags, CustomizeFlag customizeFlags) { var design = _designs.CreateTemporary(); - design.ApplyEquip = equipFlags & EquipFlagExtensions.All; + design.ApplyEquip = equipFlags & EquipFlagExtensions.All; + design.ApplyCustomize = customizeFlags; design.SetApplyHatVisible(design.DoApplyEquip(EquipSlot.Head)); design.SetApplyVisorToggle(design.DoApplyEquip(EquipSlot.Head)); design.SetApplyWeaponVisible(design.DoApplyEquip(EquipSlot.MainHand) || design.DoApplyEquip(EquipSlot.OffHand)); design.SetApplyWetness(true); - design.DesignData = state.ModelData; - design.FixCustomizeApplication(_customize, customizeFlags); + design.SetDesignData(_customize, state.ModelData); return design; } @@ -90,7 +90,7 @@ public class DesignConverter case 2: case 4: ret = _designs.CreateTemporary(); - ret.MigrateBase64(_items, _humans, base64); + ret.MigrateBase64(_customize, _items, _humans, base64); break; case 3: { @@ -122,15 +122,8 @@ public class DesignConverter return null; } - if (!customize) - { - ret.ApplyCustomize = 0; - ret.SetApplyWetness(false); - } - else - { - ret.FixCustomizeApplication(_customize, ret.ApplyCustomize); - } + ret.SetApplyWetness(customize); + ret.ApplyCustomize = customize ? CustomizeFlagExtensions.AllRelevant : 0; if (!equip) { @@ -152,7 +145,7 @@ public class DesignConverter private static string ShareBackwardCompatible(JObject jObject, DesignBase design) { - var oldBase64 = DesignBase64Migration.CreateOldBase64(design.DesignData, design.ApplyEquip, design.ApplyCustomize, + var oldBase64 = DesignBase64Migration.CreateOldBase64(design.DesignData, design.ApplyEquip, design.ApplyCustomizeRaw, design.DoApplyHatVisible(), design.DoApplyVisorToggle(), design.DoApplyWeaponVisible(), design.WriteProtected(), 1f); var oldBytes = System.Convert.FromBase64String(oldBase64); var json = jObject.ToString(Formatting.None); diff --git a/Glamourer/Designs/DesignManager.cs b/Glamourer/Designs/DesignManager.cs index c67dd88..1084fb0 100644 --- a/Glamourer/Designs/DesignManager.cs +++ b/Glamourer/Designs/DesignManager.cs @@ -90,7 +90,7 @@ 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) @@ -275,6 +275,7 @@ public class DesignManager public void ChangeCustomize(Design design, CustomizeIndex idx, CustomizeValue value) { var oldValue = design.DesignData.Customize[idx]; + switch (idx) { case CustomizeIndex.Race: @@ -282,21 +283,29 @@ public class DesignManager Glamourer.Log.Error("Somehow race or body type was changed in a design. This should not happen."); return; case CustomizeIndex.Clan: - if (_customizations.ChangeClan(ref design.DesignData.Customize, (SubRace)value.Value) == 0) + { + var customize = new Customize(design.DesignData.Customize.Data.Clone()); + if (_customizations.ChangeClan(ref customize, (SubRace)value.Value) == 0) + return; + if (!design.SetCustomize(_customizations, customize)) return; - design.RemoveInvalidCustomize(_customizations); break; + } case CustomizeIndex.Gender: - if (_customizations.ChangeGender(ref design.DesignData.Customize, (Gender)(value.Value + 1)) == 0) + { + var customize = new Customize(design.DesignData.Customize.Data.Clone()); + if (_customizations.ChangeGender(ref customize, (Gender)(value.Value + 1)) == 0) + return; + if (!design.SetCustomize(_customizations, customize)) return; - design.RemoveInvalidCustomize(_customizations); break; + } default: if (!_customizations.IsCustomizationValid(design.DesignData.Customize.Clan, design.DesignData.Customize.Gender, design.DesignData.Customize.Face, idx, value) - || !design.DesignData.Customize.Set(idx, value)) + || !design.GetDesignDataRef().Customize.Set(idx, value)) return; break; @@ -311,8 +320,6 @@ public class DesignManager /// Change whether to apply a specific customize value. public void ChangeApplyCustomize(Design design, CustomizeIndex idx, bool value) { - var set = _customizations.AwaitedService.GetList(design.DesignData.Customize.Clan, design.DesignData.Customize.Gender); - value &= set.IsAvailable(idx) || idx is CustomizeIndex.Clan or CustomizeIndex.Gender; if (!design.SetApplyCustomize(idx, value)) return; @@ -329,7 +336,7 @@ public class DesignManager return; var old = design.DesignData.Item(slot); - if (!design.DesignData.SetItem(slot, item)) + if (!design.GetDesignDataRef().SetItem(slot, item)) return; design.LastEdit = DateTimeOffset.UtcNow; @@ -358,7 +365,8 @@ public class DesignManager return; } - if (!(design.DesignData.SetItem(EquipSlot.MainHand, item) | design.DesignData.SetItem(EquipSlot.OffHand, newOff))) + if (!(design.GetDesignDataRef().SetItem(EquipSlot.MainHand, item) + | design.GetDesignDataRef().SetItem(EquipSlot.OffHand, newOff))) return; design.LastEdit = DateTimeOffset.UtcNow; @@ -372,7 +380,7 @@ public class DesignManager if (!_items.IsOffhandValid(currentOff.Type, item.ItemId, out item)) return; - if (!design.DesignData.SetItem(EquipSlot.OffHand, item)) + if (!design.GetDesignDataRef().SetItem(EquipSlot.OffHand, item)) return; design.LastEdit = DateTimeOffset.UtcNow; @@ -404,7 +412,7 @@ public class DesignManager return; var oldStain = design.DesignData.Stain(slot); - if (!design.DesignData.SetStain(slot, stain)) + if (!design.GetDesignDataRef().SetStain(slot, stain)) return; design.LastEdit = DateTimeOffset.UtcNow; @@ -430,10 +438,10 @@ public class DesignManager { var change = metaIndex switch { - ActorState.MetaIndex.Wetness => design.DesignData.SetIsWet(value), - ActorState.MetaIndex.HatState => design.DesignData.SetHatVisible(value), - ActorState.MetaIndex.VisorState => design.DesignData.SetVisor(value), - ActorState.MetaIndex.WeaponState => design.DesignData.SetWeaponVisible(value), + ActorState.MetaIndex.Wetness => design.GetDesignDataRef().SetIsWet(value), + ActorState.MetaIndex.HatState => design.GetDesignDataRef().SetHatVisible(value), + ActorState.MetaIndex.VisorState => design.GetDesignDataRef().SetVisor(value), + ActorState.MetaIndex.WeaponState => design.GetDesignDataRef().SetWeaponVisible(value), _ => throw new ArgumentOutOfRangeException(nameof(metaIndex), metaIndex, null), }; if (!change) @@ -470,13 +478,13 @@ public class DesignManager { _undoStore[design.Identifier] = design.DesignData; if (other.DoApplyWetness()) - design.DesignData.SetIsWet(other.DesignData.IsWet()); + design.GetDesignDataRef().SetIsWet(other.DesignData.IsWet()); if (other.DoApplyHatVisible()) - design.DesignData.SetHatVisible(other.DesignData.IsHatVisible()); + design.GetDesignDataRef().SetHatVisible(other.DesignData.IsHatVisible()); if (other.DoApplyVisorToggle()) - design.DesignData.SetVisor(other.DesignData.IsVisorToggled()); + design.GetDesignDataRef().SetVisor(other.DesignData.IsVisorToggled()); if (other.DoApplyWeaponVisible()) - design.DesignData.SetWeaponVisible(other.DesignData.IsWeaponVisible()); + design.GetDesignDataRef().SetWeaponVisible(other.DesignData.IsWeaponVisible()); if (design.DesignData.IsHuman) { @@ -515,7 +523,7 @@ public class DesignManager return; var other = CreateTemporary(); - other.DesignData = otherData; + other.SetDesignData(_customizations, otherData); ApplyDesign(design, other); } @@ -545,7 +553,7 @@ public class DesignManager Identifier = CreateNewGuid(), Name = actualName, }; - design.MigrateBase64(_items, _humans, base64); + design.MigrateBase64(_customizations, _items, _humans, base64); if (!oldDesigns.Any(d => d.Name == design.Name && d.CreationDate == design.CreationDate)) { Add(design, $"Migrated old design to {design.Identifier}."); diff --git a/Glamourer/Gui/Customization/CustomizationDrawer.GenderRace.cs b/Glamourer/Gui/Customization/CustomizationDrawer.GenderRace.cs index 9cfe301..5528f44 100644 --- a/Glamourer/Gui/Customization/CustomizationDrawer.GenderRace.cs +++ b/Glamourer/Gui/Customization/CustomizationDrawer.GenderRace.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Specialized; using System.Linq; using Dalamud.Interface; using Glamourer.Customization; diff --git a/Glamourer/Gui/Tabs/DebugTab.cs b/Glamourer/Gui/Tabs/DebugTab.cs index 482a7ab..3b07b33 100644 --- a/Glamourer/Gui/Tabs/DebugTab.cs +++ b/Glamourer/Gui/Tabs/DebugTab.cs @@ -962,7 +962,7 @@ public unsafe class DebugTab : ITab continue; DrawDesign(design); - var base64 = DesignBase64Migration.CreateOldBase64(design.DesignData, design.ApplyEquip, design.ApplyCustomize, + var base64 = DesignBase64Migration.CreateOldBase64(design.DesignData, design.ApplyEquip, design.ApplyCustomizeRaw, design.DoApplyHatVisible(), design.DoApplyVisorToggle(), design.DoApplyWeaponVisible(), design.WriteProtected()); using var font = ImRaii.PushFont(UiBuilder.MonoFont); diff --git a/Glamourer/Gui/Tabs/DesignTab/DesignFileSystemSelector.cs b/Glamourer/Gui/Tabs/DesignTab/DesignFileSystemSelector.cs index 05e7bf3..0127cdb 100644 --- a/Glamourer/Gui/Tabs/DesignTab/DesignFileSystemSelector.cs +++ b/Glamourer/Gui/Tabs/DesignTab/DesignFileSystemSelector.cs @@ -4,7 +4,6 @@ using System.Numerics; using Dalamud.Interface; using Dalamud.Interface.Internal.Notifications; using Dalamud.Plugin.Services; -using Glamourer.Customization; using Glamourer.Designs; using Glamourer.Events; using Glamourer.Services; @@ -119,6 +118,9 @@ public sealed class DesignFileSystemSelector : FileSystemSelector Combined wrapper for handling all filters and setting state. private bool ApplyFiltersAndState(DesignFileSystem.Leaf leaf, out DesignState state) { - var applyEquip = leaf.Value.ApplyEquip != 0; - var list = _customizationService.AwaitedService.GetList(leaf.Value.DesignData.Customize.Clan, leaf.Value.DesignData.Customize.Gender); - var applyCustomize = leaf.Value.ApplyCustomize.FixApplication(list) != 0; + var applyEquip = leaf.Value.ApplyEquip != 0; + var applyCustomize = leaf.Value.ApplyCustomize != 0; state.Color = (applyEquip, applyCustomize) switch { diff --git a/Glamourer/Gui/Tabs/DesignTab/DesignPanel.cs b/Glamourer/Gui/Tabs/DesignTab/DesignPanel.cs index 3bc73af..64324d2 100644 --- a/Glamourer/Gui/Tabs/DesignTab/DesignPanel.cs +++ b/Glamourer/Gui/Tabs/DesignTab/DesignPanel.cs @@ -193,7 +193,7 @@ public class DesignPanel if (!ImGui.CollapsingHeader(header)) return; - if (_customizationDrawer.Draw(_selector.Selected!.DesignData.Customize, _selector.Selected.ApplyCustomize, + if (_customizationDrawer.Draw(_selector.Selected!.DesignData.Customize, _selector.Selected.ApplyCustomizeRaw, _selector.Selected!.WriteProtected(), false)) foreach (var idx in Enum.GetValues()) { @@ -217,18 +217,15 @@ public class DesignPanel using (var group1 = ImRaii.Group()) { - var set = _customizationService.AwaitedService.GetList(_selector.Selected!.DesignData.Customize.Clan, - _selector.Selected!.DesignData.Customize.Gender); - var all = CustomizationExtensions.All.Where(set.IsAvailable).Select(c => c.ToFlag()).Aggregate((a, b) => a | b) - | CustomizeFlag.Clan - | CustomizeFlag.Gender; - var flags = (_selector.Selected!.ApplyCustomize & all) == 0 ? 0 : (_selector.Selected!.ApplyCustomize & all) == all ? 3 : 1; + var set = _selector.Selected!.CustomizationSet; + var available = set.SettingAvailable | CustomizeFlag.Clan | CustomizeFlag.Gender; + var flags = _selector.Selected!.ApplyCustomize == 0 ? 0 : (_selector.Selected!.ApplyCustomize & available) == available ? 3 : 1; if (ImGui.CheckboxFlags("Apply All Customizations", ref flags, 3)) { var newFlags = flags == 3; _manager.ChangeApplyCustomize(_selector.Selected!, CustomizeIndex.Clan, newFlags); _manager.ChangeApplyCustomize(_selector.Selected!, CustomizeIndex.Gender, newFlags); - foreach (var index in CustomizationExtensions.AllBasic.Where(set.IsAvailable)) + foreach (var index in CustomizationExtensions.AllBasic) _manager.ChangeApplyCustomize(_selector.Selected!, index, newFlags); } diff --git a/Glamourer/State/FunModule.cs b/Glamourer/State/FunModule.cs index 77a990f..b570d45 100644 --- a/Glamourer/State/FunModule.cs +++ b/Glamourer/State/FunModule.cs @@ -249,8 +249,7 @@ public unsafe class FunModule : IDisposable try { var tmp = _designManager.CreateTemporary(); - tmp.DesignData = _stateManager.FromActor(actor, true, true); - tmp.FixCustomizeApplication(_customizations, CustomizeFlagExtensions.AllRelevant); + tmp.SetDesignData(_customizations, _stateManager.FromActor(actor, true, true)); var data = _designConverter.ShareBase64(tmp); ImGui.SetClipboardText(data); Glamourer.Messager.NotificationMessage($"Copied current actual design of {actor.Utf8Name} to clipboard.", NotificationType.Info, diff --git a/Glamourer/State/StateManager.cs b/Glamourer/State/StateManager.cs index 4a85112..5157c60 100644 --- a/Glamourer/State/StateManager.cs +++ b/Glamourer/State/StateManager.cs @@ -368,7 +368,7 @@ public class StateManager : IReadOnlyDictionary }; } - if (!_editor.ChangeModelId(state, design.DesignData.ModelId, design.DesignData.Customize, design.DesignData.GetEquipmentPtr(), source, + if (!_editor.ChangeModelId(state, design.DesignData.ModelId, design.DesignData.Customize, design.GetDesignDataRef().GetEquipmentPtr(), source, out var oldModelId, key)) return;