Fix a bunch of issues.

This commit is contained in:
Ottermandias 2024-05-03 18:52:52 +02:00
parent 9084b43e3e
commit 36fc251d5b
14 changed files with 513 additions and 266 deletions

View 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);
}

View 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)
{ }
}

View file

@ -1,51 +1,37 @@
using ImGuiNET;
using OtterGui.Raii;
using OtterGui;
using OtterGui.Services;
using OtterGui.Text;
using OtterGui.Widgets;
using Penumbra.Api.Enums;
using Penumbra.Collections;
using Penumbra.UI.Classes;
using Dalamud.Interface.Components;
using Penumbra.Collections.Manager;
using Penumbra.Mods.Manager;
using Penumbra.Services;
using Penumbra.Mods.SubMods;
using Penumbra.Mods.Groups;
using Penumbra.Mods.Settings;
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 ModSettings _settings = null!;
private ModCollection _collection = null!;
private bool _empty;
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
=> "Settings"u8;
public void DrawHeader()
=> _tutorial.OpenTutorial(BasicTutorialSteps.ModOptions);
=> tutorial.OpenTutorial(BasicTutorialSteps.ModOptions);
public void Reset()
=> _currentPriority = null;
@ -56,53 +42,24 @@ public class ModPanelSettingsTab : ITab
if (!child)
return;
_settings = _selector.SelectedSettings;
_collection = _selector.SelectedSettingCollection;
_inherited = _collection != _collectionManager.Active.Current;
_empty = _settings == ModSettings.Empty;
_settings = selector.SelectedSettings;
_collection = selector.SelectedSettingCollection;
_inherited = _collection != collectionManager.Active.Current;
DrawInheritedWarning();
UiHelpers.DefaultLineSpace();
_communicator.PreSettingsPanelDraw.Invoke(_selector.Selected!.Identifier);
communicator.PreSettingsPanelDraw.Invoke(selector.Selected!.Identifier);
DrawEnabledInput();
_tutorial.OpenTutorial(BasicTutorialSteps.EnablingMods);
tutorial.OpenTutorial(BasicTutorialSteps.EnablingMods);
ImGui.SameLine();
DrawPriorityInput();
_tutorial.OpenTutorial(BasicTutorialSteps.Priority);
tutorial.OpenTutorial(BasicTutorialSteps.Priority);
DrawRemoveSettings();
_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;
}
}
}
communicator.PostEnabledDraw.Invoke(selector.Selected!.Identifier);
modGroupDrawer.Draw(selector.Selected!, _settings);
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>
@ -113,8 +70,8 @@ public class ModPanelSettingsTab : ITab
using var color = ImRaii.PushColor(ImGuiCol.Button, Colors.PressEnterWarningBg);
var width = new Vector2(ImGui.GetContentRegionAvail().X, 0);
if (ImGui.Button($"These settings are inherited from {_collection.Name}.", width))
_collectionManager.Editor.SetModInheritance(_collectionManager.Active.Current, _selector.Selected!, false);
if (ImUtf8.Button($"These settings are inherited from {_collection.Name}.", width))
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"
+ "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))
return;
_modManager.SetKnown(_selector.Selected!);
_collectionManager.Editor.SetModState(_collectionManager.Active.Current, _selector.Selected!, enabled);
modManager.SetKnown(selector.Selected!);
collectionManager.Editor.SetModState(collectionManager.Active.Current, selector.Selected!, enabled);
}
/// <summary>
@ -146,7 +103,8 @@ public class ModPanelSettingsTab : ITab
if (ImGui.IsItemDeactivatedAfterEdit() && _currentPriority.HasValue)
{
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;
}
@ -162,189 +120,15 @@ public class ModPanelSettingsTab : ITab
private void DrawRemoveSettings()
{
const string text = "Inherit Settings";
if (_inherited || _empty)
if (_inherited || _settings == ModSettings.Empty)
return;
var scroll = ImGui.GetScrollMaxY() > 0 ? ImGui.GetStyle().ScrollbarSize : 0;
ImGui.SameLine(ImGui.GetWindowWidth() - ImGui.CalcTextSize(text).X - ImGui.GetStyle().FramePadding.X * 2 - scroll);
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"
+ "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);
}
}