diff --git a/Penumbra/Mods/Editor/ModEditor.cs b/Penumbra/Mods/Editor/ModEditor.cs index 0b41d7c3..6ab0da69 100644 --- a/Penumbra/Mods/Editor/ModEditor.cs +++ b/Penumbra/Mods/Editor/ModEditor.cs @@ -42,7 +42,7 @@ public class ModEditor : IDisposable LoadOption(groupIdx, optionIdx, true); Files.UpdateAll(mod, Option!); SwapEditor.Revert(Option!); - MetaEditor.Load(Option!); + MetaEditor.Load(Mod!, Option!); Duplicates.Clear(); } @@ -51,7 +51,7 @@ public class ModEditor : IDisposable LoadOption(groupIdx, optionIdx, true); SwapEditor.Revert(Option!); Files.UpdatePaths(Mod!, Option!); - MetaEditor.Load(Option!); + MetaEditor.Load(Mod!, Option!); FileEditor.Clear(); Duplicates.Clear(); } diff --git a/Penumbra/Mods/Editor/ModMetaEditor.cs b/Penumbra/Mods/Editor/ModMetaEditor.cs index dbd42aa3..4d845a7c 100644 --- a/Penumbra/Mods/Editor/ModMetaEditor.cs +++ b/Penumbra/Mods/Editor/ModMetaEditor.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using Penumbra.Meta.Manipulations; @@ -16,6 +17,14 @@ public class ModMetaEditor private readonly HashSet _est = new(); private readonly HashSet _rsp = new(); + public int OtherImcCount { get; private set; } + public int OtherEqpCount { get; private set; } + public int OtherEqdpCount { get; private set; } + public int OtherGmpCount { get; private set; } + public int OtherEstCount { get; private set; } + public int OtherRspCount { get; private set; } + + public ModMetaEditor(ModManager modManager) => _modManager = modManager; @@ -102,8 +111,46 @@ public class ModMetaEditor Changes = true; } - public void Load(ISubMod mod) - => Split(mod.Manipulations); + public void Load(Mod mod, ISubMod currentOption) + { + OtherImcCount = 0; + OtherEqpCount = 0; + OtherEqdpCount = 0; + OtherGmpCount = 0; + OtherEstCount = 0; + OtherRspCount = 0; + foreach (var option in mod.AllSubMods) + { + if (option == currentOption) + continue; + + foreach (var manip in option.Manipulations) + { + switch (manip.ManipulationType) + { + case MetaManipulation.Type.Imc: + ++OtherImcCount; + break; + case MetaManipulation.Type.Eqdp: + ++OtherEqdpCount; + break; + case MetaManipulation.Type.Eqp: + ++OtherEqpCount; + break; + case MetaManipulation.Type.Est: + ++OtherEstCount; + break; + case MetaManipulation.Type.Gmp: + ++OtherGmpCount; + break; + case MetaManipulation.Type.Rsp: + ++OtherRspCount; + break; + } + } + } + Split(currentOption.Manipulations); + } public void Apply(Mod mod, int groupIdx, int optionIdx) { diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs index 709b6cf5..e6d8d40c 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Meta.cs @@ -53,7 +53,7 @@ public partial class ModEditWindow ImGui.SameLine(); tt = setsEqual ? "No changes staged." : "Revert all currently staged changes."; if (ImGuiUtil.DrawDisabledButton("Revert Changes", Vector2.Zero, tt, setsEqual)) - _editor.MetaEditor.Load(_editor.Option!); + _editor.MetaEditor.Load(_editor.Mod!, _editor.Option!); ImGui.SameLine(); AddFromClipboardButton(); @@ -69,21 +69,33 @@ public partial class ModEditWindow if (!child) return; - DrawEditHeader(_editor.MetaEditor.Eqp, "Equipment Parameter Edits (EQP)###EQP", 5, EqpRow.Draw, EqpRow.DrawNew); - DrawEditHeader(_editor.MetaEditor.Eqdp, "Racial Model Edits (EQDP)###EQDP", 7, EqdpRow.Draw, EqdpRow.DrawNew); - DrawEditHeader(_editor.MetaEditor.Imc, "Variant Edits (IMC)###IMC", 10, ImcRow.Draw, ImcRow.DrawNew); - DrawEditHeader(_editor.MetaEditor.Est, "Extra Skeleton Parameters (EST)###EST", 7, EstRow.Draw, EstRow.DrawNew); - DrawEditHeader(_editor.MetaEditor.Gmp, "Visor/Gimmick Edits (GMP)###GMP", 7, GmpRow.Draw, GmpRow.DrawNew); - DrawEditHeader(_editor.MetaEditor.Rsp, "Racial Scaling Edits (RSP)###RSP", 5, RspRow.Draw, RspRow.DrawNew); + DrawEditHeader(_editor.MetaEditor.Eqp, "Equipment Parameter Edits (EQP)###EQP", 5, EqpRow.Draw, EqpRow.DrawNew , _editor.MetaEditor.OtherEqpCount); + DrawEditHeader(_editor.MetaEditor.Eqdp, "Racial Model Edits (EQDP)###EQDP", 7, EqdpRow.Draw, EqdpRow.DrawNew, _editor.MetaEditor.OtherEqdpCount); + DrawEditHeader(_editor.MetaEditor.Imc, "Variant Edits (IMC)###IMC", 10, ImcRow.Draw, ImcRow.DrawNew , _editor.MetaEditor.OtherImcCount); + DrawEditHeader(_editor.MetaEditor.Est, "Extra Skeleton Parameters (EST)###EST", 7, EstRow.Draw, EstRow.DrawNew , _editor.MetaEditor.OtherEstCount); + DrawEditHeader(_editor.MetaEditor.Gmp, "Visor/Gimmick Edits (GMP)###GMP", 7, GmpRow.Draw, GmpRow.DrawNew , _editor.MetaEditor.OtherGmpCount); + DrawEditHeader(_editor.MetaEditor.Rsp, "Racial Scaling Edits (RSP)###RSP", 5, RspRow.Draw, RspRow.DrawNew , _editor.MetaEditor.OtherRspCount); } /// The headers for the different meta changes all have basically the same structure for different types. private void DrawEditHeader(IReadOnlyCollection items, string label, int numColumns, Action draw, - Action drawNew) - { - const ImGuiTableFlags flags = ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.BordersInnerV; - if (!ImGui.CollapsingHeader($"{items.Count} {label}")) + Action drawNew, int otherCount) + { + const ImGuiTableFlags flags = ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.BordersInnerV; + + var oldPos = ImGui.GetCursorPosY(); + var header = ImGui.CollapsingHeader($"{items.Count} {label}"); + var newPos = ImGui.GetCursorPos(); + if (otherCount > 0) + { + var text = $"{otherCount} Edits in other Options"; + var size = ImGui.CalcTextSize(text).X; + ImGui.SetCursorPos(new Vector2(ImGui.GetContentRegionAvail().X - size, oldPos + ImGui.GetStyle().FramePadding.Y)); + ImGuiUtil.TextColored(ColorId.RedundantAssignment.Value() | 0xFF000000, text); + ImGui.SetCursorPos(newPos); + } + if (!header) return; using (var table = ImRaii.Table(label, numColumns, flags)) diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs index b8a2590c..22fb385e 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs @@ -367,9 +367,9 @@ public partial class ModEditWindow : Window, IDisposable { const string defaultOption = "Default Option"; using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero).Push(ImGuiStyleVar.FrameRounding, 0); - var width = new Vector2(ImGui.GetWindowWidth() / 3, 0); + var width = new Vector2(ImGui.GetContentRegionAvail().X / 3, 0); if (ImGuiUtil.DrawDisabledButton(defaultOption, width, "Switch to the default option for the mod.\nThis resets unsaved changes.", - _editor!.Option!.IsDefault)) + _editor.Option!.IsDefault)) _editor.LoadOption(-1, 0); ImGui.SameLine(); @@ -377,12 +377,14 @@ public partial class ModEditWindow : Window, IDisposable _editor.LoadMod(_editor.Mod!, _editor.GroupIdx, _editor.OptionIdx); ImGui.SameLine(); - - using var combo = ImRaii.Combo("##optionSelector", _editor.Option.FullName, ImGuiComboFlags.NoArrowButton); + ImGui.SetNextItemWidth(width.X); + style.Push(ImGuiStyleVar.FrameBorderSize, ImGuiHelpers.GlobalScale); + using var color = ImRaii.PushColor(ImGuiCol.Border, ColorId.FolderLine.Value()); + using var combo = ImRaii.Combo("##optionSelector", _editor.Option.FullName); if (!combo) return; - foreach (var option in _mod!.AllSubMods.Cast()) + foreach (var option in _mod!.AllSubMods) { if (ImGui.Selectable(option.FullName, option == _editor.Option)) _editor.LoadOption(option.GroupIdx, option.OptionIdx); @@ -411,6 +413,13 @@ public partial class ModEditWindow : Window, IDisposable if (ImGuiUtil.DrawDisabledButton("Revert Changes", Vector2.Zero, tt, setsEqual)) _editor.SwapEditor.Revert(_editor.Option!); + var otherSwaps = _editor.Mod!.TotalSwapCount - _editor.SwapEditor.Swaps.Count; + if (otherSwaps > 0) + { + ImGui.SameLine(); + ImGuiUtil.DrawTextButton($"There are {otherSwaps} file swaps configured in other options.", Vector2.Zero, ColorId.RedundantAssignment.Value()); + } + using var child = ImRaii.Child("##swaps", -Vector2.One, true); if (!child) return; @@ -434,18 +443,18 @@ public partial class ModEditWindow : Window, IDisposable _editor.SwapEditor.Remove(gamePath); ImGui.TableNextColumn(); - var tmp = gamePath.Path.ToString(); + var tmp = file.FullName; + ImGui.SetNextItemWidth(-1); + if (ImGui.InputText("##value", ref tmp, Utf8GamePath.MaxGamePathLength) && tmp.Length > 0) + _editor.SwapEditor.Change(gamePath, new FullPath(tmp)); + + ImGui.TableNextColumn(); + tmp = gamePath.Path.ToString(); ImGui.SetNextItemWidth(-1); if (ImGui.InputText("##key", ref tmp, Utf8GamePath.MaxGamePathLength) && Utf8GamePath.FromString(tmp, out var path) && !_editor.SwapEditor.Swaps.ContainsKey(path)) _editor.SwapEditor.Change(gamePath, path); - - ImGui.TableNextColumn(); - tmp = file.FullName; - ImGui.SetNextItemWidth(-1); - if (ImGui.InputText("##value", ref tmp, Utf8GamePath.MaxGamePathLength) && tmp.Length > 0) - _editor.SwapEditor.Change(gamePath, new FullPath(tmp)); } ImGui.TableNextColumn();