mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-19 23:24:22 +01:00
Fix a bunch of issues.
This commit is contained in:
parent
9084b43e3e
commit
36fc251d5b
14 changed files with 513 additions and 266 deletions
|
|
@ -1 +1 @@
|
||||||
Subproject commit 1b0b5469f792999e5b412d4f0c3ed77d9994d7b7
|
Subproject commit 595ac5722c9c400bea36110503ed2ae7b02d1489
|
||||||
|
|
@ -12,16 +12,23 @@ public interface ITexToolsGroup
|
||||||
public IReadOnlyList<OptionSubMod> OptionData { get; }
|
public IReadOnlyList<OptionSubMod> OptionData { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum GroupDrawBehaviour
|
||||||
|
{
|
||||||
|
SingleSelection,
|
||||||
|
MultiSelection,
|
||||||
|
}
|
||||||
|
|
||||||
public interface IModGroup
|
public interface IModGroup
|
||||||
{
|
{
|
||||||
public const int MaxMultiOptions = 63;
|
public const int MaxMultiOptions = 63;
|
||||||
|
|
||||||
public Mod Mod { get; }
|
public Mod Mod { get; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
public GroupType Type { get; }
|
public GroupType Type { get; }
|
||||||
public ModPriority Priority { get; set; }
|
public GroupDrawBehaviour Behaviour { get; }
|
||||||
public Setting DefaultSettings { get; set; }
|
public ModPriority Priority { get; set; }
|
||||||
|
public Setting DefaultSettings { get; set; }
|
||||||
|
|
||||||
public FullPath? FindBestMatch(Utf8GamePath gamePath);
|
public FullPath? FindBestMatch(Utf8GamePath gamePath);
|
||||||
public IModOption? AddOption(string name, string description = "");
|
public IModOption? AddOption(string name, string description = "");
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,9 @@ public class ImcModGroup(Mod mod) : IModGroup
|
||||||
public GroupType Type
|
public GroupType Type
|
||||||
=> GroupType.Imc;
|
=> GroupType.Imc;
|
||||||
|
|
||||||
|
public GroupDrawBehaviour Behaviour
|
||||||
|
=> GroupDrawBehaviour.MultiSelection;
|
||||||
|
|
||||||
public ModPriority Priority { get; set; } = ModPriority.Default;
|
public ModPriority Priority { get; set; } = ModPriority.Default;
|
||||||
public Setting DefaultSettings { get; set; } = Setting.Zero;
|
public Setting DefaultSettings { get; set; } = Setting.Zero;
|
||||||
|
|
||||||
|
|
@ -150,7 +153,6 @@ public class ImcModGroup(Mod mod) : IModGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
jWriter.WriteEndArray();
|
jWriter.WriteEndArray();
|
||||||
jWriter.WriteEndObject();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public (int Redirections, int Swaps, int Manips) GetCounts()
|
public (int Redirections, int Swaps, int Manips) GetCounts()
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,10 @@ public readonly struct ModSaveGroup : ISavable
|
||||||
{
|
{
|
||||||
_basePath = (container.Mod as Mod)?.ModPath
|
_basePath = (container.Mod as Mod)?.ModPath
|
||||||
?? throw new Exception("Invalid save group from default data container without base path."); // Should not happen.
|
?? throw new Exception("Invalid save group from default data container without base path."); // Should not happen.
|
||||||
_defaultMod = null;
|
_defaultMod = container as DefaultSubMod;
|
||||||
_onlyAscii = onlyAscii;
|
_onlyAscii = onlyAscii;
|
||||||
_group = container.Group!;
|
_group = container.Group;
|
||||||
_groupIdx = _group.GetIndex();
|
_groupIdx = _group?.GetIndex() ?? -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ToFilename(FilenameService fileNames)
|
public string ToFilename(FilenameService fileNames)
|
||||||
|
|
@ -80,7 +80,6 @@ public readonly struct ModSaveGroup : ISavable
|
||||||
|
|
||||||
public static void WriteJsonBase(JsonTextWriter jWriter, IModGroup group)
|
public static void WriteJsonBase(JsonTextWriter jWriter, IModGroup group)
|
||||||
{
|
{
|
||||||
jWriter.WriteStartObject();
|
|
||||||
jWriter.WritePropertyName(nameof(group.Name));
|
jWriter.WritePropertyName(nameof(group.Name));
|
||||||
jWriter.WriteValue(group.Name);
|
jWriter.WriteValue(group.Name);
|
||||||
jWriter.WritePropertyName(nameof(group.Description));
|
jWriter.WritePropertyName(nameof(group.Description));
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,9 @@ public sealed class MultiModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
||||||
public GroupType Type
|
public GroupType Type
|
||||||
=> GroupType.Multi;
|
=> GroupType.Multi;
|
||||||
|
|
||||||
|
public GroupDrawBehaviour Behaviour
|
||||||
|
=> GroupDrawBehaviour.MultiSelection;
|
||||||
|
|
||||||
public Mod Mod { get; } = mod;
|
public Mod Mod { get; } = mod;
|
||||||
public string Name { get; set; } = "Group";
|
public string Name { get; set; } = "Group";
|
||||||
public string Description { get; set; } = "A non-exclusive group of settings.";
|
public string Description { get; set; } = "A non-exclusive group of settings.";
|
||||||
|
|
@ -127,7 +130,6 @@ public sealed class MultiModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
jWriter.WriteEndArray();
|
jWriter.WriteEndArray();
|
||||||
jWriter.WriteEndObject();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public (int Redirections, int Swaps, int Manips) GetCounts()
|
public (int Redirections, int Swaps, int Manips) GetCounts()
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,10 @@ public sealed class SingleModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
||||||
public GroupType Type
|
public GroupType Type
|
||||||
=> GroupType.Single;
|
=> GroupType.Single;
|
||||||
|
|
||||||
public Mod Mod { get; } = mod;
|
public GroupDrawBehaviour Behaviour
|
||||||
|
=> GroupDrawBehaviour.SingleSelection;
|
||||||
|
|
||||||
|
public Mod Mod { get; } = mod;
|
||||||
public string Name { get; set; } = "Option";
|
public string Name { get; set; } = "Option";
|
||||||
public string Description { get; set; } = "A mutually exclusive group of settings.";
|
public string Description { get; set; } = "A mutually exclusive group of settings.";
|
||||||
public ModPriority Priority { get; set; }
|
public ModPriority Priority { get; set; }
|
||||||
|
|
@ -89,7 +92,12 @@ public sealed class SingleModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
||||||
=> ModGroup.GetIndex(this);
|
=> ModGroup.GetIndex(this);
|
||||||
|
|
||||||
public void AddData(Setting setting, Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
public void AddData(Setting setting, Dictionary<Utf8GamePath, FullPath> redirections, HashSet<MetaManipulation> manipulations)
|
||||||
=> OptionData[setting.AsIndex].AddDataTo(redirections, manipulations);
|
{
|
||||||
|
if (!IsOption)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OptionData[setting.AsIndex].AddDataTo(redirections, manipulations);
|
||||||
|
}
|
||||||
|
|
||||||
public Setting FixSetting(Setting setting)
|
public Setting FixSetting(Setting setting)
|
||||||
=> OptionData.Count == 0 ? Setting.Zero : new Setting(Math.Min(setting.Value, (ulong)(OptionData.Count - 1)));
|
=> OptionData.Count == 0 ? Setting.Zero : new Setting(Math.Min(setting.Value, (ulong)(OptionData.Count - 1)));
|
||||||
|
|
@ -111,7 +119,6 @@ public sealed class SingleModGroup(Mod mod) : IModGroup, ITexToolsGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
jWriter.WriteEndArray();
|
jWriter.WriteEndArray();
|
||||||
jWriter.WriteEndObject();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Create a group without a mod only for saving it in the creator. </summary>
|
/// <summary> Create a group without a mod only for saving it in the creator. </summary>
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ public sealed class MultiModGroupEditor(CommunicatorService communicator, SaveSe
|
||||||
var idx = group.GetIndex();
|
var idx = group.GetIndex();
|
||||||
var singleGroup = group.ConvertToSingle();
|
var singleGroup = group.ConvertToSingle();
|
||||||
group.Mod.Groups[idx] = singleGroup;
|
group.Mod.Groups[idx] = singleGroup;
|
||||||
SaveService.QueueSave(new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport));
|
SaveService.QueueSave(new ModSaveGroup(singleGroup, Config.ReplaceNonAsciiOnImport));
|
||||||
Communicator.ModOptionChanged.Invoke(ModOptionChangeType.GroupTypeChanged, group.Mod, group, null, null, -1);
|
Communicator.ModOptionChanged.Invoke(ModOptionChangeType.GroupTypeChanged, singleGroup.Mod, singleGroup, null, null, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Change the internal priority of the given option. </summary>
|
/// <summary> Change the internal priority of the given option. </summary>
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ public sealed class SingleModGroupEditor(CommunicatorService communicator, SaveS
|
||||||
var idx = group.GetIndex();
|
var idx = group.GetIndex();
|
||||||
var multiGroup = group.ConvertToMulti();
|
var multiGroup = group.ConvertToMulti();
|
||||||
group.Mod.Groups[idx] = multiGroup;
|
group.Mod.Groups[idx] = multiGroup;
|
||||||
SaveService.QueueSave(new ModSaveGroup(group, Config.ReplaceNonAsciiOnImport));
|
SaveService.QueueSave(new ModSaveGroup(multiGroup, Config.ReplaceNonAsciiOnImport));
|
||||||
Communicator.ModOptionChanged.Invoke(ModOptionChangeType.GroupTypeChanged, group.Mod, multiGroup, null, null, -1);
|
Communicator.ModOptionChanged.Invoke(ModOptionChangeType.GroupTypeChanged, multiGroup.Mod, multiGroup, null, null, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override SingleModGroup CreateGroup(Mod mod, string newName, ModPriority priority, SaveType saveType = SaveType.ImmediateSync)
|
protected override SingleModGroup CreateGroup(Mod mod, string newName, ModPriority priority, SaveType saveType = SaveType.ImmediateSync)
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,6 @@ public static class SubMod
|
||||||
j.WriteEndObject();
|
j.WriteEndObject();
|
||||||
j.WritePropertyName(nameof(data.Manipulations));
|
j.WritePropertyName(nameof(data.Manipulations));
|
||||||
serializer.Serialize(j, data.Manipulations);
|
serializer.Serialize(j, data.Manipulations);
|
||||||
j.WriteEndObject();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Write the data for a selectable mod option on a JsonWriter. </summary>
|
/// <summary> Write the data for a selectable mod option on a JsonWriter. </summary>
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ public class BackupService : IAsyncService
|
||||||
list.Add(new FileInfo(fileNames.ConfigFile));
|
list.Add(new FileInfo(fileNames.ConfigFile));
|
||||||
list.Add(new FileInfo(fileNames.FilesystemFile));
|
list.Add(new FileInfo(fileNames.FilesystemFile));
|
||||||
list.Add(new FileInfo(fileNames.ActiveCollectionsFile));
|
list.Add(new FileInfo(fileNames.ActiveCollectionsFile));
|
||||||
|
list.Add(new FileInfo(fileNames.PredefinedTagFile));
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,6 @@ public static class StaticServiceManager
|
||||||
.AddSingleton<CollectionSelectHeader>()
|
.AddSingleton<CollectionSelectHeader>()
|
||||||
.AddSingleton<ImportPopup>()
|
.AddSingleton<ImportPopup>()
|
||||||
.AddSingleton<ModPanelDescriptionTab>()
|
.AddSingleton<ModPanelDescriptionTab>()
|
||||||
.AddSingleton<ModPanelSettingsTab>()
|
|
||||||
.AddSingleton<ModPanelEditTab>()
|
.AddSingleton<ModPanelEditTab>()
|
||||||
.AddSingleton<ModPanelChangedItemsTab>()
|
.AddSingleton<ModPanelChangedItemsTab>()
|
||||||
.AddSingleton<ModPanelConflictsTab>()
|
.AddSingleton<ModPanelConflictsTab>()
|
||||||
|
|
|
||||||
233
Penumbra/UI/ModsTab/ModGroupDrawer.cs
Normal file
233
Penumbra/UI/ModsTab/ModGroupDrawer.cs
Normal file
|
|
@ -0,0 +1,233 @@
|
||||||
|
using Dalamud.Interface.Components;
|
||||||
|
using ImGuiNET;
|
||||||
|
using OtterGui;
|
||||||
|
using OtterGui.Raii;
|
||||||
|
using OtterGui.Services;
|
||||||
|
using OtterGui.Widgets;
|
||||||
|
using Penumbra.Collections;
|
||||||
|
using Penumbra.Collections.Manager;
|
||||||
|
using Penumbra.Mods;
|
||||||
|
using Penumbra.Mods.Groups;
|
||||||
|
using Penumbra.Mods.Settings;
|
||||||
|
using Penumbra.Mods.SubMods;
|
||||||
|
|
||||||
|
namespace Penumbra.UI.ModsTab;
|
||||||
|
|
||||||
|
public sealed class ModGroupDrawer(Configuration config, CollectionManager collectionManager) : IUiService
|
||||||
|
{
|
||||||
|
private readonly List<(IModGroup, int)> _blockGroupCache = [];
|
||||||
|
|
||||||
|
public void Draw(Mod mod, ModSettings settings)
|
||||||
|
{
|
||||||
|
if (mod.Groups.Count <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_blockGroupCache.Clear();
|
||||||
|
var useDummy = true;
|
||||||
|
foreach (var (group, idx) in mod.Groups.WithIndex())
|
||||||
|
{
|
||||||
|
if (!group.IsOption)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (group.Behaviour)
|
||||||
|
{
|
||||||
|
case GroupDrawBehaviour.SingleSelection when group.Options.Count <= config.SingleGroupRadioMax:
|
||||||
|
case GroupDrawBehaviour.MultiSelection:
|
||||||
|
_blockGroupCache.Add((group, idx));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GroupDrawBehaviour.SingleSelection:
|
||||||
|
ImGuiUtil.Dummy(UiHelpers.DefaultSpace, useDummy);
|
||||||
|
useDummy = false;
|
||||||
|
DrawSingleGroupCombo(group, idx, settings == ModSettings.Empty ? group.DefaultSettings : settings.Settings[idx]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useDummy = true;
|
||||||
|
foreach (var (group, idx) in _blockGroupCache)
|
||||||
|
{
|
||||||
|
ImGuiUtil.Dummy(UiHelpers.DefaultSpace, useDummy);
|
||||||
|
useDummy = false;
|
||||||
|
var option = settings == ModSettings.Empty ? group.DefaultSettings : settings.Settings[idx];
|
||||||
|
if (group.Behaviour is GroupDrawBehaviour.MultiSelection)
|
||||||
|
DrawMultiGroup(group, idx, option);
|
||||||
|
else
|
||||||
|
DrawSingleGroupRadio(group, idx, option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draw a single group selector as a combo box.
|
||||||
|
/// If a description is provided, add a help marker besides it.
|
||||||
|
/// </summary>
|
||||||
|
private void DrawSingleGroupCombo(IModGroup group, int groupIdx, Setting setting)
|
||||||
|
{
|
||||||
|
using var id = ImRaii.PushId(groupIdx);
|
||||||
|
var selectedOption = setting.AsIndex;
|
||||||
|
ImGui.SetNextItemWidth(UiHelpers.InputTextWidth.X * 3 / 4);
|
||||||
|
var options = group.Options;
|
||||||
|
using (var combo = ImRaii.Combo(string.Empty, options[selectedOption].Name))
|
||||||
|
{
|
||||||
|
if (combo)
|
||||||
|
for (var idx2 = 0; idx2 < options.Count; ++idx2)
|
||||||
|
{
|
||||||
|
id.Push(idx2);
|
||||||
|
var option = options[idx2];
|
||||||
|
if (ImGui.Selectable(option.Name, idx2 == selectedOption))
|
||||||
|
SetModSetting(group, groupIdx, Setting.Single(idx2));
|
||||||
|
|
||||||
|
if (option.Description.Length > 0)
|
||||||
|
ImGuiUtil.SelectableHelpMarker(option.Description);
|
||||||
|
|
||||||
|
id.Pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
if (group.Description.Length > 0)
|
||||||
|
ImGuiUtil.LabeledHelpMarker(group.Name, group.Description);
|
||||||
|
else
|
||||||
|
ImGui.TextUnformatted(group.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draw a single group selector as a set of radio buttons.
|
||||||
|
/// If a description is provided, add a help marker besides it.
|
||||||
|
/// </summary>
|
||||||
|
private void DrawSingleGroupRadio(IModGroup group, int groupIdx, Setting setting)
|
||||||
|
{
|
||||||
|
using var id = ImRaii.PushId(groupIdx);
|
||||||
|
var selectedOption = setting.AsIndex;
|
||||||
|
var minWidth = Widget.BeginFramedGroup(group.Name, group.Description);
|
||||||
|
var options = group.Options;
|
||||||
|
DrawCollapseHandling(options, minWidth, DrawOptions);
|
||||||
|
|
||||||
|
Widget.EndFramedGroup();
|
||||||
|
return;
|
||||||
|
|
||||||
|
void DrawOptions()
|
||||||
|
{
|
||||||
|
for (var idx = 0; idx < group.Options.Count; ++idx)
|
||||||
|
{
|
||||||
|
using var i = ImRaii.PushId(idx);
|
||||||
|
var option = options[idx];
|
||||||
|
if (ImGui.RadioButton(option.Name, selectedOption == idx))
|
||||||
|
SetModSetting(group, groupIdx, Setting.Single(idx));
|
||||||
|
|
||||||
|
if (option.Description.Length <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGuiComponents.HelpMarker(option.Description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draw a multi group selector as a bordered set of checkboxes.
|
||||||
|
/// If a description is provided, add a help marker in the title.
|
||||||
|
/// </summary>
|
||||||
|
private void DrawMultiGroup(IModGroup group, int groupIdx, Setting setting)
|
||||||
|
{
|
||||||
|
using var id = ImRaii.PushId(groupIdx);
|
||||||
|
var minWidth = Widget.BeginFramedGroup(group.Name, group.Description);
|
||||||
|
var options = group.Options;
|
||||||
|
DrawCollapseHandling(options, minWidth, DrawOptions);
|
||||||
|
|
||||||
|
Widget.EndFramedGroup();
|
||||||
|
var label = $"##multi{groupIdx}";
|
||||||
|
if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||||
|
ImGui.OpenPopup($"##multi{groupIdx}");
|
||||||
|
|
||||||
|
DrawMultiPopup(group, groupIdx, label);
|
||||||
|
return;
|
||||||
|
|
||||||
|
void DrawOptions()
|
||||||
|
{
|
||||||
|
for (var idx = 0; idx < options.Count; ++idx)
|
||||||
|
{
|
||||||
|
using var i = ImRaii.PushId(idx);
|
||||||
|
var option = options[idx];
|
||||||
|
var enabled = setting.HasFlag(idx);
|
||||||
|
|
||||||
|
if (ImGui.Checkbox(option.Name, ref enabled))
|
||||||
|
SetModSetting(group, groupIdx, setting.SetBit(idx, enabled));
|
||||||
|
|
||||||
|
if (option.Description.Length > 0)
|
||||||
|
{
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGuiComponents.HelpMarker(option.Description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawMultiPopup(IModGroup group, int groupIdx, string label)
|
||||||
|
{
|
||||||
|
using var style = ImRaii.PushStyle(ImGuiStyleVar.PopupBorderSize, 1);
|
||||||
|
using var popup = ImRaii.Popup(label);
|
||||||
|
if (!popup)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImGui.TextUnformatted(group.Name);
|
||||||
|
ImGui.Separator();
|
||||||
|
if (ImGui.Selectable("Enable All"))
|
||||||
|
SetModSetting(group, groupIdx, Setting.AllBits(group.Options.Count));
|
||||||
|
|
||||||
|
if (ImGui.Selectable("Disable All"))
|
||||||
|
SetModSetting(group, groupIdx, Setting.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawCollapseHandling(IReadOnlyList<IModOption> options, float minWidth, Action draw)
|
||||||
|
{
|
||||||
|
if (options.Count <= config.OptionGroupCollapsibleMin)
|
||||||
|
{
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var collapseId = ImGui.GetID("Collapse");
|
||||||
|
var shown = ImGui.GetStateStorage().GetBool(collapseId, true);
|
||||||
|
var buttonTextShow = $"Show {options.Count} Options";
|
||||||
|
var buttonTextHide = $"Hide {options.Count} Options";
|
||||||
|
var buttonWidth = Math.Max(ImGui.CalcTextSize(buttonTextShow).X, ImGui.CalcTextSize(buttonTextHide).X)
|
||||||
|
+ 2 * ImGui.GetStyle().FramePadding.X;
|
||||||
|
minWidth = Math.Max(buttonWidth, minWidth);
|
||||||
|
if (shown)
|
||||||
|
{
|
||||||
|
var pos = ImGui.GetCursorPos();
|
||||||
|
ImGui.Dummy(UiHelpers.IconButtonSize);
|
||||||
|
using (var _ = ImRaii.Group())
|
||||||
|
{
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var width = Math.Max(ImGui.GetItemRectSize().X, minWidth);
|
||||||
|
var endPos = ImGui.GetCursorPos();
|
||||||
|
ImGui.SetCursorPos(pos);
|
||||||
|
if (ImGui.Button(buttonTextHide, new Vector2(width, 0)))
|
||||||
|
ImGui.GetStateStorage().SetBool(collapseId, !shown);
|
||||||
|
|
||||||
|
ImGui.SetCursorPos(endPos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var optionWidth = options.Max(o => ImGui.CalcTextSize(o.Name).X)
|
||||||
|
+ ImGui.GetStyle().ItemInnerSpacing.X
|
||||||
|
+ ImGui.GetFrameHeight()
|
||||||
|
+ ImGui.GetStyle().FramePadding.X;
|
||||||
|
var width = Math.Max(optionWidth, minWidth);
|
||||||
|
if (ImGui.Button(buttonTextShow, new Vector2(width, 0)))
|
||||||
|
ImGui.GetStateStorage().SetBool(collapseId, !shown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModCollection Current
|
||||||
|
=> collectionManager.Active.Current;
|
||||||
|
|
||||||
|
private void SetModSetting(IModGroup group, int groupIdx, Setting setting)
|
||||||
|
=> collectionManager.Editor.SetModSetting(Current, group.Mod, groupIdx, setting);
|
||||||
|
}
|
||||||
214
Penumbra/UI/ModsTab/ModGroupEditDrawer.cs
Normal file
214
Penumbra/UI/ModsTab/ModGroupEditDrawer.cs
Normal file
|
|
@ -0,0 +1,214 @@
|
||||||
|
using Dalamud.Interface;
|
||||||
|
using Dalamud.Interface.Internal.Notifications;
|
||||||
|
using Dalamud.Interface.Utility;
|
||||||
|
using ImGuiNET;
|
||||||
|
using OtterGui;
|
||||||
|
using OtterGui.Classes;
|
||||||
|
using OtterGui.Raii;
|
||||||
|
using OtterGui.Services;
|
||||||
|
using Penumbra.Mods;
|
||||||
|
using Penumbra.Mods.Groups;
|
||||||
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Manager.OptionEditor;
|
||||||
|
using Penumbra.Mods.Settings;
|
||||||
|
using Penumbra.Mods.SubMods;
|
||||||
|
using Penumbra.Services;
|
||||||
|
using Penumbra.UI.Classes;
|
||||||
|
|
||||||
|
namespace Penumbra.UI.ModsTab;
|
||||||
|
|
||||||
|
public sealed class ModGroupEditDrawer(ModManager modManager, Configuration config, FilenameService filenames) : IUiService
|
||||||
|
{
|
||||||
|
private Vector2 _buttonSize;
|
||||||
|
private float _priorityWidth;
|
||||||
|
private float _groupNameWidth;
|
||||||
|
private float _spacing;
|
||||||
|
|
||||||
|
private string? _currentGroupName;
|
||||||
|
private ModPriority? _currentGroupPriority;
|
||||||
|
private IModGroup? _currentGroupEdited;
|
||||||
|
private bool _isGroupNameValid;
|
||||||
|
private IModGroup? _deleteGroup;
|
||||||
|
private IModGroup? _moveGroup;
|
||||||
|
private int _moveTo;
|
||||||
|
|
||||||
|
private string? _currentOptionName;
|
||||||
|
private ModPriority? _currentOptionPriority;
|
||||||
|
private IModOption? _currentOptionEdited;
|
||||||
|
private IModOption? _deleteOption;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private void SameLine()
|
||||||
|
=> ImGui.SameLine(0, _spacing);
|
||||||
|
|
||||||
|
public void Draw(Mod mod)
|
||||||
|
{
|
||||||
|
_buttonSize = new Vector2(ImGui.GetFrameHeight());
|
||||||
|
_priorityWidth = 50 * ImGuiHelpers.GlobalScale;
|
||||||
|
_groupNameWidth = 350f * ImGuiHelpers.GlobalScale;
|
||||||
|
_spacing = ImGui.GetStyle().ItemInnerSpacing.X;
|
||||||
|
|
||||||
|
|
||||||
|
FinishGroupCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FinishGroupCleanup()
|
||||||
|
{
|
||||||
|
if (_deleteGroup != null)
|
||||||
|
{
|
||||||
|
modManager.OptionEditor.DeleteModGroup(_deleteGroup);
|
||||||
|
_deleteGroup = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_deleteOption != null)
|
||||||
|
{
|
||||||
|
modManager.OptionEditor.DeleteOption(_deleteOption);
|
||||||
|
_deleteOption = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_moveGroup != null)
|
||||||
|
{
|
||||||
|
modManager.OptionEditor.MoveModGroup(_moveGroup, _moveTo);
|
||||||
|
_moveGroup = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawGroup(IModGroup group, int idx)
|
||||||
|
{
|
||||||
|
using var id = ImRaii.PushId(idx);
|
||||||
|
using var frame = ImRaii.FramedGroup($"Group #{idx + 1}");
|
||||||
|
DrawGroupNameRow(group);
|
||||||
|
switch (group)
|
||||||
|
{
|
||||||
|
case SingleModGroup s:
|
||||||
|
DrawSingleGroup(s, idx);
|
||||||
|
break;
|
||||||
|
case MultiModGroup m:
|
||||||
|
DrawMultiGroup(m, idx);
|
||||||
|
break;
|
||||||
|
case ImcModGroup i:
|
||||||
|
DrawImcGroup(i, idx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawGroupNameRow(IModGroup group)
|
||||||
|
{
|
||||||
|
DrawGroupName(group);
|
||||||
|
SameLine();
|
||||||
|
DrawGroupDelete(group);
|
||||||
|
SameLine();
|
||||||
|
DrawGroupPriority(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawGroupName(IModGroup group)
|
||||||
|
{
|
||||||
|
var text = _currentGroupEdited == group ? _currentGroupName ?? group.Name : group.Name;
|
||||||
|
ImGui.SetNextItemWidth(_groupNameWidth);
|
||||||
|
using var border = ImRaii.PushFrameBorder(UiHelpers.ScaleX2, Colors.RegexWarningBorder, !_isGroupNameValid);
|
||||||
|
if (ImGui.InputText("##GroupName", ref text, 256))
|
||||||
|
{
|
||||||
|
_currentGroupEdited = group;
|
||||||
|
_currentGroupName = text;
|
||||||
|
_isGroupNameValid = ModGroupEditor.VerifyFileName(group.Mod, group, text, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.IsItemDeactivated())
|
||||||
|
{
|
||||||
|
if (_currentGroupName != null && _isGroupNameValid)
|
||||||
|
modManager.OptionEditor.RenameModGroup(group, _currentGroupName);
|
||||||
|
_currentGroupName = null;
|
||||||
|
_currentGroupEdited = null;
|
||||||
|
_isGroupNameValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tt = _isGroupNameValid
|
||||||
|
? "Group Name"
|
||||||
|
: "Current name can not be used for this group.";
|
||||||
|
ImGuiUtil.HoverTooltip(tt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawGroupDelete(IModGroup group)
|
||||||
|
{
|
||||||
|
var enabled = config.DeleteModModifier.IsActive();
|
||||||
|
var tt = enabled
|
||||||
|
? "Delete this option group."
|
||||||
|
: $"Delete this option group.\nHold {config.DeleteModModifier} while clicking to delete.";
|
||||||
|
|
||||||
|
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), _buttonSize, tt, !enabled, true))
|
||||||
|
_deleteGroup = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawGroupPriority(IModGroup group)
|
||||||
|
{
|
||||||
|
var priority = _currentGroupEdited == group
|
||||||
|
? (_currentGroupPriority ?? group.Priority).Value
|
||||||
|
: group.Priority.Value;
|
||||||
|
ImGui.SetNextItemWidth(_priorityWidth);
|
||||||
|
if (ImGui.InputInt("##GroupPriority", ref priority, 0, 0))
|
||||||
|
{
|
||||||
|
_currentGroupEdited = group;
|
||||||
|
_currentGroupPriority = new ModPriority(priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.IsItemDeactivated())
|
||||||
|
{
|
||||||
|
if (_currentGroupPriority.HasValue)
|
||||||
|
modManager.OptionEditor.ChangeGroupPriority(group, _currentGroupPriority.Value);
|
||||||
|
_currentGroupEdited = null;
|
||||||
|
_currentGroupPriority = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGuiUtil.HoverTooltip("Group Priority");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawGroupMoveButtons(IModGroup group, int idx)
|
||||||
|
{
|
||||||
|
var isFirst = idx == 0;
|
||||||
|
var tt = isFirst ? "Can not move this group further upwards." : $"Move this group up to group {idx}.";
|
||||||
|
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.ArrowUp.ToIconString(), UiHelpers.IconButtonSize, tt, isFirst, true))
|
||||||
|
{
|
||||||
|
_moveGroup = group;
|
||||||
|
_moveTo = idx - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SameLine();
|
||||||
|
var isLast = idx == group.Mod.Groups.Count - 1;
|
||||||
|
tt = isLast
|
||||||
|
? "Can not move this group further downwards."
|
||||||
|
: $"Move this group down to group {idx + 2}.";
|
||||||
|
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.ArrowDown.ToIconString(), UiHelpers.IconButtonSize, tt, isLast, true))
|
||||||
|
{
|
||||||
|
_moveGroup = group;
|
||||||
|
_moveTo = idx + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawGroupOpenFile(IModGroup group, int idx)
|
||||||
|
{
|
||||||
|
var fileName = filenames.OptionGroupFile(group.Mod, idx, config.ReplaceNonAsciiOnImport);
|
||||||
|
var fileExists = File.Exists(fileName);
|
||||||
|
var tt = fileExists
|
||||||
|
? $"Open the {group.Name} json file in the text editor of your choice."
|
||||||
|
: $"The {group.Name} json file does not exist.";
|
||||||
|
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.FileExport.ToIconString(), UiHelpers.IconButtonSize, tt, !fileExists, true))
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Process.Start(new ProcessStartInfo(fileName) { UseShellExecute = true });
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Penumbra.Messager.NotificationMessage(e, "Could not open editor.", NotificationType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void DrawSingleGroup(SingleModGroup group, int idx)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
private void DrawMultiGroup(MultiModGroup group, int idx)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
private void DrawImcGroup(ImcModGroup group, int idx)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
@ -1,51 +1,37 @@
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
|
using OtterGui.Services;
|
||||||
|
using OtterGui.Text;
|
||||||
using OtterGui.Widgets;
|
using OtterGui.Widgets;
|
||||||
using Penumbra.Api.Enums;
|
|
||||||
using Penumbra.Collections;
|
using Penumbra.Collections;
|
||||||
using Penumbra.UI.Classes;
|
using Penumbra.UI.Classes;
|
||||||
using Dalamud.Interface.Components;
|
|
||||||
using Penumbra.Collections.Manager;
|
using Penumbra.Collections.Manager;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.Mods.SubMods;
|
|
||||||
using Penumbra.Mods.Groups;
|
|
||||||
using Penumbra.Mods.Settings;
|
using Penumbra.Mods.Settings;
|
||||||
|
|
||||||
namespace Penumbra.UI.ModsTab;
|
namespace Penumbra.UI.ModsTab;
|
||||||
|
|
||||||
public class ModPanelSettingsTab : ITab
|
public class ModPanelSettingsTab(
|
||||||
|
CollectionManager collectionManager,
|
||||||
|
ModManager modManager,
|
||||||
|
ModFileSystemSelector selector,
|
||||||
|
TutorialService tutorial,
|
||||||
|
CommunicatorService communicator,
|
||||||
|
ModGroupDrawer modGroupDrawer)
|
||||||
|
: ITab, IUiService
|
||||||
{
|
{
|
||||||
private readonly Configuration _config;
|
|
||||||
private readonly CommunicatorService _communicator;
|
|
||||||
private readonly CollectionManager _collectionManager;
|
|
||||||
private readonly ModFileSystemSelector _selector;
|
|
||||||
private readonly TutorialService _tutorial;
|
|
||||||
private readonly ModManager _modManager;
|
|
||||||
|
|
||||||
private bool _inherited;
|
private bool _inherited;
|
||||||
private ModSettings _settings = null!;
|
private ModSettings _settings = null!;
|
||||||
private ModCollection _collection = null!;
|
private ModCollection _collection = null!;
|
||||||
private bool _empty;
|
|
||||||
private int? _currentPriority;
|
private int? _currentPriority;
|
||||||
|
|
||||||
public ModPanelSettingsTab(CollectionManager collectionManager, ModManager modManager, ModFileSystemSelector selector,
|
|
||||||
TutorialService tutorial, CommunicatorService communicator, Configuration config)
|
|
||||||
{
|
|
||||||
_collectionManager = collectionManager;
|
|
||||||
_communicator = communicator;
|
|
||||||
_modManager = modManager;
|
|
||||||
_selector = selector;
|
|
||||||
_tutorial = tutorial;
|
|
||||||
_config = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReadOnlySpan<byte> Label
|
public ReadOnlySpan<byte> Label
|
||||||
=> "Settings"u8;
|
=> "Settings"u8;
|
||||||
|
|
||||||
public void DrawHeader()
|
public void DrawHeader()
|
||||||
=> _tutorial.OpenTutorial(BasicTutorialSteps.ModOptions);
|
=> tutorial.OpenTutorial(BasicTutorialSteps.ModOptions);
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
=> _currentPriority = null;
|
=> _currentPriority = null;
|
||||||
|
|
@ -56,53 +42,24 @@ public class ModPanelSettingsTab : ITab
|
||||||
if (!child)
|
if (!child)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_settings = _selector.SelectedSettings;
|
_settings = selector.SelectedSettings;
|
||||||
_collection = _selector.SelectedSettingCollection;
|
_collection = selector.SelectedSettingCollection;
|
||||||
_inherited = _collection != _collectionManager.Active.Current;
|
_inherited = _collection != collectionManager.Active.Current;
|
||||||
_empty = _settings == ModSettings.Empty;
|
|
||||||
|
|
||||||
DrawInheritedWarning();
|
DrawInheritedWarning();
|
||||||
UiHelpers.DefaultLineSpace();
|
UiHelpers.DefaultLineSpace();
|
||||||
_communicator.PreSettingsPanelDraw.Invoke(_selector.Selected!.Identifier);
|
communicator.PreSettingsPanelDraw.Invoke(selector.Selected!.Identifier);
|
||||||
DrawEnabledInput();
|
DrawEnabledInput();
|
||||||
_tutorial.OpenTutorial(BasicTutorialSteps.EnablingMods);
|
tutorial.OpenTutorial(BasicTutorialSteps.EnablingMods);
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
DrawPriorityInput();
|
DrawPriorityInput();
|
||||||
_tutorial.OpenTutorial(BasicTutorialSteps.Priority);
|
tutorial.OpenTutorial(BasicTutorialSteps.Priority);
|
||||||
DrawRemoveSettings();
|
DrawRemoveSettings();
|
||||||
|
|
||||||
_communicator.PostEnabledDraw.Invoke(_selector.Selected!.Identifier);
|
communicator.PostEnabledDraw.Invoke(selector.Selected!.Identifier);
|
||||||
|
|
||||||
if (_selector.Selected!.Groups.Count > 0)
|
|
||||||
{
|
|
||||||
var useDummy = true;
|
|
||||||
foreach (var (group, idx) in _selector.Selected!.Groups.WithIndex()
|
|
||||||
.Where(g => g.Value.Type == GroupType.Single && g.Value.Options.Count > _config.SingleGroupRadioMax))
|
|
||||||
{
|
|
||||||
ImGuiUtil.Dummy(UiHelpers.DefaultSpace, useDummy);
|
|
||||||
useDummy = false;
|
|
||||||
DrawSingleGroupCombo(group, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
useDummy = true;
|
|
||||||
foreach (var (group, idx) in _selector.Selected!.Groups.WithIndex().Where(g => g.Value.IsOption))
|
|
||||||
{
|
|
||||||
ImGuiUtil.Dummy(UiHelpers.DefaultSpace, useDummy);
|
|
||||||
useDummy = false;
|
|
||||||
switch (group.Type)
|
|
||||||
{
|
|
||||||
case GroupType.Multi:
|
|
||||||
DrawMultiGroup(group, idx);
|
|
||||||
break;
|
|
||||||
case GroupType.Single when group.Options.Count <= _config.SingleGroupRadioMax:
|
|
||||||
DrawSingleGroupRadio(group, idx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
modGroupDrawer.Draw(selector.Selected!, _settings);
|
||||||
UiHelpers.DefaultLineSpace();
|
UiHelpers.DefaultLineSpace();
|
||||||
_communicator.PostSettingsPanelDraw.Invoke(_selector.Selected!.Identifier);
|
communicator.PostSettingsPanelDraw.Invoke(selector.Selected!.Identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Draw a big red bar if the current setting is inherited. </summary>
|
/// <summary> Draw a big red bar if the current setting is inherited. </summary>
|
||||||
|
|
@ -113,8 +70,8 @@ public class ModPanelSettingsTab : ITab
|
||||||
|
|
||||||
using var color = ImRaii.PushColor(ImGuiCol.Button, Colors.PressEnterWarningBg);
|
using var color = ImRaii.PushColor(ImGuiCol.Button, Colors.PressEnterWarningBg);
|
||||||
var width = new Vector2(ImGui.GetContentRegionAvail().X, 0);
|
var width = new Vector2(ImGui.GetContentRegionAvail().X, 0);
|
||||||
if (ImGui.Button($"These settings are inherited from {_collection.Name}.", width))
|
if (ImUtf8.Button($"These settings are inherited from {_collection.Name}.", width))
|
||||||
_collectionManager.Editor.SetModInheritance(_collectionManager.Active.Current, _selector.Selected!, false);
|
collectionManager.Editor.SetModInheritance(collectionManager.Active.Current, selector.Selected!, false);
|
||||||
|
|
||||||
ImGuiUtil.HoverTooltip("You can click this button to copy the current settings to the current selection.\n"
|
ImGuiUtil.HoverTooltip("You can click this button to copy the current settings to the current selection.\n"
|
||||||
+ "You can also just change any setting, which will copy the settings with the single setting changed to the current selection.");
|
+ "You can also just change any setting, which will copy the settings with the single setting changed to the current selection.");
|
||||||
|
|
@ -127,8 +84,8 @@ public class ModPanelSettingsTab : ITab
|
||||||
if (!ImGui.Checkbox("Enabled", ref enabled))
|
if (!ImGui.Checkbox("Enabled", ref enabled))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_modManager.SetKnown(_selector.Selected!);
|
modManager.SetKnown(selector.Selected!);
|
||||||
_collectionManager.Editor.SetModState(_collectionManager.Active.Current, _selector.Selected!, enabled);
|
collectionManager.Editor.SetModState(collectionManager.Active.Current, selector.Selected!, enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -146,7 +103,8 @@ public class ModPanelSettingsTab : ITab
|
||||||
if (ImGui.IsItemDeactivatedAfterEdit() && _currentPriority.HasValue)
|
if (ImGui.IsItemDeactivatedAfterEdit() && _currentPriority.HasValue)
|
||||||
{
|
{
|
||||||
if (_currentPriority != _settings.Priority.Value)
|
if (_currentPriority != _settings.Priority.Value)
|
||||||
_collectionManager.Editor.SetModPriority(_collectionManager.Active.Current, _selector.Selected!, new ModPriority(_currentPriority.Value));
|
collectionManager.Editor.SetModPriority(collectionManager.Active.Current, selector.Selected!,
|
||||||
|
new ModPriority(_currentPriority.Value));
|
||||||
|
|
||||||
_currentPriority = null;
|
_currentPriority = null;
|
||||||
}
|
}
|
||||||
|
|
@ -162,189 +120,15 @@ public class ModPanelSettingsTab : ITab
|
||||||
private void DrawRemoveSettings()
|
private void DrawRemoveSettings()
|
||||||
{
|
{
|
||||||
const string text = "Inherit Settings";
|
const string text = "Inherit Settings";
|
||||||
if (_inherited || _empty)
|
if (_inherited || _settings == ModSettings.Empty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var scroll = ImGui.GetScrollMaxY() > 0 ? ImGui.GetStyle().ScrollbarSize : 0;
|
var scroll = ImGui.GetScrollMaxY() > 0 ? ImGui.GetStyle().ScrollbarSize : 0;
|
||||||
ImGui.SameLine(ImGui.GetWindowWidth() - ImGui.CalcTextSize(text).X - ImGui.GetStyle().FramePadding.X * 2 - scroll);
|
ImGui.SameLine(ImGui.GetWindowWidth() - ImGui.CalcTextSize(text).X - ImGui.GetStyle().FramePadding.X * 2 - scroll);
|
||||||
if (ImGui.Button(text))
|
if (ImGui.Button(text))
|
||||||
_collectionManager.Editor.SetModInheritance(_collectionManager.Active.Current, _selector.Selected!, true);
|
collectionManager.Editor.SetModInheritance(collectionManager.Active.Current, selector.Selected!, true);
|
||||||
|
|
||||||
ImGuiUtil.HoverTooltip("Remove current settings from this collection so that it can inherit them.\n"
|
ImGuiUtil.HoverTooltip("Remove current settings from this collection so that it can inherit them.\n"
|
||||||
+ "If no inherited collection has settings for this mod, it will be disabled.");
|
+ "If no inherited collection has settings for this mod, it will be disabled.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draw a single group selector as a combo box.
|
|
||||||
/// If a description is provided, add a help marker besides it.
|
|
||||||
/// </summary>
|
|
||||||
private void DrawSingleGroupCombo(IModGroup group, int groupIdx)
|
|
||||||
{
|
|
||||||
using var id = ImRaii.PushId(groupIdx);
|
|
||||||
var selectedOption = _empty ? group.DefaultSettings.AsIndex : _settings.Settings[groupIdx].AsIndex;
|
|
||||||
ImGui.SetNextItemWidth(UiHelpers.InputTextWidth.X * 3 / 4);
|
|
||||||
var options = group.Options;
|
|
||||||
using (var combo = ImRaii.Combo(string.Empty, options[selectedOption].Name))
|
|
||||||
{
|
|
||||||
if (combo)
|
|
||||||
for (var idx2 = 0; idx2 < options.Count; ++idx2)
|
|
||||||
{
|
|
||||||
id.Push(idx2);
|
|
||||||
var option = options[idx2];
|
|
||||||
if (ImGui.Selectable(option.Name, idx2 == selectedOption))
|
|
||||||
_collectionManager.Editor.SetModSetting(_collectionManager.Active.Current, _selector.Selected!, groupIdx,
|
|
||||||
Setting.Single(idx2));
|
|
||||||
|
|
||||||
if (option.Description.Length > 0)
|
|
||||||
ImGuiUtil.SelectableHelpMarker(option.Description);
|
|
||||||
|
|
||||||
id.Pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.SameLine();
|
|
||||||
if (group.Description.Length > 0)
|
|
||||||
ImGuiUtil.LabeledHelpMarker(group.Name, group.Description);
|
|
||||||
else
|
|
||||||
ImGui.TextUnformatted(group.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw a single group selector as a set of radio buttons.
|
|
||||||
// If a description is provided, add a help marker besides it.
|
|
||||||
private void DrawSingleGroupRadio(IModGroup group, int groupIdx)
|
|
||||||
{
|
|
||||||
using var id = ImRaii.PushId(groupIdx);
|
|
||||||
var selectedOption = _empty ? group.DefaultSettings.AsIndex : _settings.Settings[groupIdx].AsIndex;
|
|
||||||
var minWidth = Widget.BeginFramedGroup(group.Name, group.Description);
|
|
||||||
var options = group.Options;
|
|
||||||
DrawCollapseHandling(options, minWidth, DrawOptions);
|
|
||||||
|
|
||||||
Widget.EndFramedGroup();
|
|
||||||
return;
|
|
||||||
|
|
||||||
void DrawOptions()
|
|
||||||
{
|
|
||||||
for (var idx = 0; idx < group.Options.Count; ++idx)
|
|
||||||
{
|
|
||||||
using var i = ImRaii.PushId(idx);
|
|
||||||
var option = options[idx];
|
|
||||||
if (ImGui.RadioButton(option.Name, selectedOption == idx))
|
|
||||||
_collectionManager.Editor.SetModSetting(_collectionManager.Active.Current, _selector.Selected!, groupIdx,
|
|
||||||
Setting.Single(idx));
|
|
||||||
|
|
||||||
if (option.Description.Length <= 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ImGui.SameLine();
|
|
||||||
ImGuiComponents.HelpMarker(option.Description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void DrawCollapseHandling(IReadOnlyList<IModOption> options, float minWidth, Action draw)
|
|
||||||
{
|
|
||||||
if (options.Count <= _config.OptionGroupCollapsibleMin)
|
|
||||||
{
|
|
||||||
draw();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var collapseId = ImGui.GetID("Collapse");
|
|
||||||
var shown = ImGui.GetStateStorage().GetBool(collapseId, true);
|
|
||||||
var buttonTextShow = $"Show {options.Count} Options";
|
|
||||||
var buttonTextHide = $"Hide {options.Count} Options";
|
|
||||||
var buttonWidth = Math.Max(ImGui.CalcTextSize(buttonTextShow).X, ImGui.CalcTextSize(buttonTextHide).X)
|
|
||||||
+ 2 * ImGui.GetStyle().FramePadding.X;
|
|
||||||
minWidth = Math.Max(buttonWidth, minWidth);
|
|
||||||
if (shown)
|
|
||||||
{
|
|
||||||
var pos = ImGui.GetCursorPos();
|
|
||||||
ImGui.Dummy(UiHelpers.IconButtonSize);
|
|
||||||
using (var _ = ImRaii.Group())
|
|
||||||
{
|
|
||||||
draw();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var width = Math.Max(ImGui.GetItemRectSize().X, minWidth);
|
|
||||||
var endPos = ImGui.GetCursorPos();
|
|
||||||
ImGui.SetCursorPos(pos);
|
|
||||||
if (ImGui.Button(buttonTextHide, new Vector2(width, 0)))
|
|
||||||
ImGui.GetStateStorage().SetBool(collapseId, !shown);
|
|
||||||
|
|
||||||
ImGui.SetCursorPos(endPos);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var optionWidth = options.Max(o => ImGui.CalcTextSize(o.Name).X)
|
|
||||||
+ ImGui.GetStyle().ItemInnerSpacing.X
|
|
||||||
+ ImGui.GetFrameHeight()
|
|
||||||
+ ImGui.GetStyle().FramePadding.X;
|
|
||||||
var width = Math.Max(optionWidth, minWidth);
|
|
||||||
if (ImGui.Button(buttonTextShow, new Vector2(width, 0)))
|
|
||||||
ImGui.GetStateStorage().SetBool(collapseId, !shown);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draw a multi group selector as a bordered set of checkboxes.
|
|
||||||
/// If a description is provided, add a help marker in the title.
|
|
||||||
/// </summary>
|
|
||||||
private void DrawMultiGroup(IModGroup group, int groupIdx)
|
|
||||||
{
|
|
||||||
using var id = ImRaii.PushId(groupIdx);
|
|
||||||
var flags = _empty ? group.DefaultSettings : _settings.Settings[groupIdx];
|
|
||||||
var minWidth = Widget.BeginFramedGroup(group.Name, group.Description);
|
|
||||||
var options = group.Options;
|
|
||||||
DrawCollapseHandling(options, minWidth, DrawOptions);
|
|
||||||
|
|
||||||
Widget.EndFramedGroup();
|
|
||||||
var label = $"##multi{groupIdx}";
|
|
||||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
|
||||||
ImGui.OpenPopup($"##multi{groupIdx}");
|
|
||||||
|
|
||||||
DrawMultiPopup(group, groupIdx, label);
|
|
||||||
return;
|
|
||||||
|
|
||||||
void DrawOptions()
|
|
||||||
{
|
|
||||||
for (var idx = 0; idx < options.Count; ++idx)
|
|
||||||
{
|
|
||||||
using var i = ImRaii.PushId(idx);
|
|
||||||
var option = options[idx];
|
|
||||||
var setting = flags.HasFlag(idx);
|
|
||||||
|
|
||||||
if (ImGui.Checkbox(option.Name, ref setting))
|
|
||||||
{
|
|
||||||
flags = flags.SetBit(idx, setting);
|
|
||||||
_collectionManager.Editor.SetModSetting(_collectionManager.Active.Current, _selector.Selected!, groupIdx, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (option.Description.Length > 0)
|
|
||||||
{
|
|
||||||
ImGui.SameLine();
|
|
||||||
ImGuiComponents.HelpMarker(option.Description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawMultiPopup(IModGroup group, int groupIdx, string label)
|
|
||||||
{
|
|
||||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.PopupBorderSize, 1);
|
|
||||||
using var popup = ImRaii.Popup(label);
|
|
||||||
if (!popup)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImGui.TextUnformatted(group.Name);
|
|
||||||
ImGui.Separator();
|
|
||||||
if (ImGui.Selectable("Enable All"))
|
|
||||||
_collectionManager.Editor.SetModSetting(_collectionManager.Active.Current, _selector.Selected!, groupIdx,
|
|
||||||
Setting.AllBits(group.Options.Count));
|
|
||||||
|
|
||||||
if (ImGui.Selectable("Disable All"))
|
|
||||||
_collectionManager.Editor.SetModSetting(_collectionManager.Active.Current, _selector.Selected!, groupIdx, Setting.Zero);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue