diff --git a/Glamourer/Designs/Design.cs b/Glamourer/Designs/Design.cs index 14a3c0e..f09e7bc 100644 --- a/Glamourer/Designs/Design.cs +++ b/Glamourer/Designs/Design.cs @@ -43,6 +43,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn public string Description { get; internal set; } = string.Empty; public string[] Tags { get; internal set; } = []; public int Index { get; internal set; } + public bool ForcedRedraw { get; internal set; } public bool QuickDesign { get; internal set; } = true; public string Color { get; internal set; } = string.Empty; public SortedList AssociatedMods { get; private set; } = []; @@ -99,6 +100,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn ["LastEdit"] = LastEdit, ["Name"] = Name.Text, ["Description"] = Description, + ["ForcedRedraw"] = ForcedRedraw, ["Color"] = Color, ["QuickDesign"] = QuickDesign, ["Tags"] = JArray.FromObject(Tags), @@ -173,7 +175,8 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn LoadParameters(json["Parameters"], design, design.Name); LoadMaterials(json["Materials"], design, design.Name); LoadLinks(linkLoader, json["Links"], design); - design.Color = json["Color"]?.ToObject() ?? string.Empty; + design.Color = json["Color"]?.ToObject() ?? string.Empty; + design.ForcedRedraw = json["ForcedRedraw"]?.ToObject() ?? false; return design; static string[] ParseTags(JObject json) diff --git a/Glamourer/Designs/DesignManager.cs b/Glamourer/Designs/DesignManager.cs index 03f0590..7bd949c 100644 --- a/Glamourer/Designs/DesignManager.cs +++ b/Glamourer/Designs/DesignManager.cs @@ -193,6 +193,7 @@ public sealed class DesignManager : DesignEditor DesignChanged.Invoke(DesignChanged.Type.ChangedDescription, design, oldDescription); } + /// Change the associated color of a design. public void ChangeColor(Design design, string newColor) { var oldColor = design.Color; @@ -311,6 +312,17 @@ public sealed class DesignManager : DesignEditor #region Edit Application Rules + public void ChangeForcedRedraw(Design design, bool forcedRedraw) + { + if (design.ForcedRedraw == forcedRedraw) + return; + + design.ForcedRedraw = forcedRedraw; + SaveService.QueueSave(design); + Glamourer.Log.Debug($"Set {design.Identifier} to {(forcedRedraw ? "not" : string.Empty)} force redraws."); + DesignChanged.Invoke(DesignChanged.Type.ForceRedraw, design, null); + } + /// Change whether to apply a specific customize value. public void ChangeApplyCustomize(Design design, CustomizeIndex idx, bool value) { diff --git a/Glamourer/Designs/IDesignStandIn.cs b/Glamourer/Designs/IDesignStandIn.cs index 4865068..492bc6b 100644 --- a/Glamourer/Designs/IDesignStandIn.cs +++ b/Glamourer/Designs/IDesignStandIn.cs @@ -23,4 +23,6 @@ public interface IDesignStandIn : IEquatable public void ParseData(JObject jObj); public bool ChangeData(object data); + + public bool ForcedRedraw { get; } } diff --git a/Glamourer/Designs/Links/DesignMerger.cs b/Glamourer/Designs/Links/DesignMerger.cs index 44f4db9..558377a 100644 --- a/Glamourer/Designs/Links/DesignMerger.cs +++ b/Glamourer/Designs/Links/DesignMerger.cs @@ -19,9 +19,11 @@ public class DesignMerger( { public MergedDesign Merge(LinkContainer designs, in CustomizeArray currentCustomize, in DesignData baseRef, bool respectOwnership, bool modAssociations) - => Merge(designs.Select(d => ((IDesignStandIn)d.Link, d.Type, JobFlag.All)), currentCustomize, baseRef, respectOwnership, modAssociations); + => Merge(designs.Select(d => ((IDesignStandIn)d.Link, d.Type, JobFlag.All)), currentCustomize, baseRef, respectOwnership, + modAssociations); - public MergedDesign Merge(IEnumerable<(IDesignStandIn, ApplicationType, JobFlag)> designs, in CustomizeArray currentCustomize, in DesignData baseRef, + public MergedDesign Merge(IEnumerable<(IDesignStandIn, ApplicationType, JobFlag)> designs, in CustomizeArray currentCustomize, + in DesignData baseRef, bool respectOwnership, bool modAssociations) { var ret = new MergedDesign(designManager); @@ -51,6 +53,8 @@ public class DesignMerger( ReduceMods(design as Design, ret, modAssociations); if (type.HasFlag(ApplicationType.GearCustomization)) ReduceMaterials(design, ret); + if (design.ForcedRedraw) + ret.ForcedRedraw = true; } ApplyFixFlags(ret, fixFlags); @@ -189,7 +193,8 @@ public class DesignMerger( ret.Weapons.TryAdd(weapon.Type, weapon, source, allowedJobs); } - private void ReduceOffhands(in DesignData design, JobFlag allowedJobs, EquipFlag equipFlags, MergedDesign ret, StateSource source, bool respectOwnership) + private void ReduceOffhands(in DesignData design, JobFlag allowedJobs, EquipFlag equipFlags, MergedDesign ret, StateSource source, + bool respectOwnership) { if (!equipFlags.HasFlag(EquipFlag.Offhand)) return; diff --git a/Glamourer/Designs/Links/MergedDesign.cs b/Glamourer/Designs/Links/MergedDesign.cs index 131b074..d3c7664 100644 --- a/Glamourer/Designs/Links/MergedDesign.cs +++ b/Glamourer/Designs/Links/MergedDesign.cs @@ -88,6 +88,8 @@ public sealed class MergedDesign if (weapon.Valid) Weapons.TryAdd(weapon.Type, weapon, StateSource.Manual, JobFlag.All); } + + ForcedRedraw = design is IDesignStandIn { ForcedRedraw: true }; } public MergedDesign(Design design) @@ -101,4 +103,5 @@ public sealed class MergedDesign public readonly WeaponList Weapons = new(); public readonly SortedList AssociatedMods = []; public StateSources Sources = new(); + public bool ForcedRedraw; } diff --git a/Glamourer/Designs/Special/QuickSelectedDesign.cs b/Glamourer/Designs/Special/QuickSelectedDesign.cs index f347085..c506f0a 100644 --- a/Glamourer/Designs/Special/QuickSelectedDesign.cs +++ b/Glamourer/Designs/Special/QuickSelectedDesign.cs @@ -50,4 +50,7 @@ public class QuickSelectedDesign(QuickDesignCombo combo) : IDesignStandIn, IServ public bool ChangeData(object data) => false; + + public bool ForcedRedraw + => combo.Design?.ForcedRedraw ?? false; } diff --git a/Glamourer/Designs/Special/RandomDesign.cs b/Glamourer/Designs/Special/RandomDesign.cs index c09fd2b..5fac61b 100644 --- a/Glamourer/Designs/Special/RandomDesign.cs +++ b/Glamourer/Designs/Special/RandomDesign.cs @@ -78,4 +78,7 @@ public class RandomDesign(RandomDesignGenerator rng) : IDesignStandIn Predicates = predicates; return true; } + + public bool ForcedRedraw + => false; } diff --git a/Glamourer/Designs/Special/RevertDesign.cs b/Glamourer/Designs/Special/RevertDesign.cs index e450ff1..023d5eb 100644 --- a/Glamourer/Designs/Special/RevertDesign.cs +++ b/Glamourer/Designs/Special/RevertDesign.cs @@ -42,4 +42,7 @@ public class RevertDesign : IDesignStandIn public bool ChangeData(object data) => false; + + public bool ForcedRedraw + => false; } diff --git a/Glamourer/Events/DesignChanged.cs b/Glamourer/Events/DesignChanged.cs index cd51f6d..1837aad 100644 --- a/Glamourer/Events/DesignChanged.cs +++ b/Glamourer/Events/DesignChanged.cs @@ -80,6 +80,9 @@ public sealed class DesignChanged() /// An existing design had an advanced dye rows Revert state changed. Data is the index [MaterialValueIndex]. MaterialRevert, + /// An existing design had changed whether it always forces a redraw or not. + ForceRedraw, + /// An existing design changed whether a specific customization is applied. Data is the type of customization [CustomizeIndex]. ApplyCustomize, diff --git a/Glamourer/Gui/Tabs/DesignTab/DesignDetailTab.cs b/Glamourer/Gui/Tabs/DesignTab/DesignDetailTab.cs index e56ec00..ecac046 100644 --- a/Glamourer/Gui/Tabs/DesignTab/DesignDetailTab.cs +++ b/Glamourer/Gui/Tabs/DesignTab/DesignDetailTab.cs @@ -136,6 +136,13 @@ public class DesignDetailTab if (hovered || ImGui.IsItemHovered()) ImGui.SetTooltip("Display or hide this design in your quick design bar."); + var forceRedraw = _selector.Selected!.ForcedRedraw; + ImGuiUtil.DrawFrameColumn("Force Redrawing"); + ImGui.TableNextColumn(); + if (ImGui.Checkbox("##ForceRedraw", ref forceRedraw)) + _manager.ChangeForcedRedraw(_selector.Selected!, forceRedraw); + ImGuiUtil.HoverTooltip("Set this design to always force a redraw when it is applied through any means."); + ImGuiUtil.DrawFrameColumn("Color"); var colorName = _selector.Selected!.Color.Length == 0 ? DesignColors.AutomaticName : _selector.Selected!.Color; ImGui.TableNextColumn(); diff --git a/Glamourer/State/StateEditor.cs b/Glamourer/State/StateEditor.cs index 30a61ce..bd5d1e0 100644 --- a/Glamourer/State/StateEditor.cs +++ b/Glamourer/State/StateEditor.cs @@ -212,7 +212,9 @@ public class StateEditor( mergedDesign.Design.GetDesignDataRef().GetEquipmentPtr(), settings.Source, out var oldModelId, settings.Key)) return; - var requiresRedraw = oldModelId != mergedDesign.Design.DesignData.ModelId || !mergedDesign.Design.DesignData.IsHuman; + var requiresRedraw = mergedDesign.ForcedRedraw + || oldModelId != mergedDesign.Design.DesignData.ModelId + || !mergedDesign.Design.DesignData.IsHuman; if (state.ModelData.IsHuman) { @@ -402,6 +404,6 @@ public class StateEditor( if (mh is { Type: FullEquipType.Fists } && Items.ItemData.Tertiary.TryGetValue(mh.ItemId, out var gauntlets)) ChangeEquip(state, EquipSlot.Hands, newMainhand != null ? gauntlets : state.ModelData.Item(EquipSlot.Hands), - stain, settings); + stain, settings); } }