Current State.

This commit is contained in:
Ottermandias 2024-12-29 00:05:36 +01:00
parent 282189ef6d
commit 5f9cbe9ab1
14 changed files with 381 additions and 213 deletions

View file

@ -56,12 +56,24 @@ public static class Colors
{
var tintValue = ImGui.ColorConvertU32ToFloat4(tint.Value());
var value = ImGui.ColorConvertU32ToFloat4(color.Value());
var negAlpha = 1 - tintValue.W;
var newAlpha = negAlpha * value.W + tintValue.W;
var newR = (negAlpha * value.W * value.X + tintValue.W * tintValue.X) / newAlpha;
var newG = (negAlpha * value.W * value.Y + tintValue.W * tintValue.Y) / newAlpha;
var newB = (negAlpha * value.W * value.Z + tintValue.W * tintValue.Z) / newAlpha;
return ImGui.ColorConvertFloat4ToU32(new Vector4(newR, newG, newB, newAlpha));
return ImGui.ColorConvertFloat4ToU32(TintColor(value, tintValue));
}
public static unsafe uint Tinted(this ImGuiCol color, ColorId tint)
{
var tintValue = ImGui.ColorConvertU32ToFloat4(tint.Value());
ref var value = ref *ImGui.GetStyleColorVec4(color);
return ImGui.ColorConvertFloat4ToU32(TintColor(value, tintValue));
}
private static unsafe Vector4 TintColor(in Vector4 color, in Vector4 tint)
{
var negAlpha = 1 - tint.W;
var newAlpha = negAlpha * color.W + tint.W;
var newR = (negAlpha * color.W * color.X + tint.W * tint.X) / newAlpha;
var newG = (negAlpha * color.W * color.Y + tint.W * tint.Y) / newAlpha;
var newB = (negAlpha * color.W * color.Z + tint.W * tint.Z) / newAlpha;
return new Vector4(newR, newG, newB, newAlpha);
}
public static (uint DefaultColor, string Name, string Description) Data(this ColorId color)

View file

@ -3,6 +3,7 @@ using ImGuiNET;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Services;
using OtterGui.Text;
using OtterGui.Widgets;
using Penumbra.Collections;
using Penumbra.Collections.Manager;
@ -16,13 +17,19 @@ namespace Penumbra.UI.ModsTab.Groups;
public sealed class ModGroupDrawer(Configuration config, CollectionManager collectionManager) : IUiService
{
private readonly List<(IModGroup, int)> _blockGroupCache = [];
private bool _temporary;
private bool _locked;
private TemporaryModSettings? _tempSettings;
public void Draw(Mod mod, ModSettings settings)
public void Draw(Mod mod, ModSettings settings, TemporaryModSettings? tempSettings)
{
if (mod.Groups.Count <= 0)
return;
_blockGroupCache.Clear();
_tempSettings = tempSettings;
_temporary = tempSettings != null;
_locked = (tempSettings?.Lock ?? 0) != 0;
var useDummy = true;
foreach (var (group, idx) in mod.Groups.WithIndex())
{
@ -63,22 +70,23 @@ public sealed class ModGroupDrawer(Configuration config, CollectionManager colle
/// </summary>
private void DrawSingleGroupCombo(IModGroup group, int groupIdx, Setting setting)
{
using var id = ImRaii.PushId(groupIdx);
var selectedOption = setting.AsIndex;
using var id = ImUtf8.PushId(groupIdx);
var selectedOption = setting.AsIndex;
using var disabled = ImRaii.Disabled(_locked);
ImGui.SetNextItemWidth(UiHelpers.InputTextWidth.X * 3 / 4);
var options = group.Options;
using (var combo = ImRaii.Combo(string.Empty, options[selectedOption].Name))
using (var combo = ImUtf8.Combo(""u8, 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))
if (ImUtf8.Selectable(option.Name, idx2 == selectedOption))
SetModSetting(group, groupIdx, Setting.Single(idx2));
if (option.Description.Length > 0)
ImGuiUtil.SelectableHelpMarker(option.Description);
ImUtf8.SelectableHelpMarker(option.Description);
id.Pop();
}
@ -86,9 +94,9 @@ public sealed class ModGroupDrawer(Configuration config, CollectionManager colle
ImGui.SameLine();
if (group.Description.Length > 0)
ImGuiUtil.LabeledHelpMarker(group.Name, group.Description);
ImUtf8.LabeledHelpMarker(group.Name, group.Description);
else
ImGui.TextUnformatted(group.Name);
ImUtf8.Text(group.Name);
}
/// <summary>
@ -97,10 +105,10 @@ public sealed class ModGroupDrawer(Configuration config, CollectionManager colle
/// </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;
using var id = ImUtf8.PushId(groupIdx);
var selectedOption = setting.AsIndex;
var minWidth = Widget.BeginFramedGroup(group.Name, group.Description);
var options = group.Options;
DrawCollapseHandling(options, minWidth, DrawOptions);
Widget.EndFramedGroup();
@ -108,11 +116,12 @@ public sealed class ModGroupDrawer(Configuration config, CollectionManager colle
void DrawOptions()
{
using var disabled = ImRaii.Disabled(_locked);
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))
using var i = ImUtf8.PushId(idx);
var option = options[idx];
if (ImUtf8.RadioButton(option.Name, selectedOption == idx))
SetModSetting(group, groupIdx, Setting.Single(idx));
if (option.Description.Length <= 0)
@ -130,28 +139,29 @@ public sealed class ModGroupDrawer(Configuration config, CollectionManager colle
/// </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;
using var id = ImUtf8.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}");
ImUtf8.OpenPopup($"##multi{groupIdx}");
DrawMultiPopup(group, groupIdx, label);
return;
void DrawOptions()
{
using var disabled = ImRaii.Disabled(_locked);
for (var idx = 0; idx < options.Count; ++idx)
{
using var i = ImRaii.PushId(idx);
var option = options[idx];
var enabled = setting.HasFlag(idx);
using var i = ImUtf8.PushId(idx);
var option = options[idx];
var enabled = setting.HasFlag(idx);
if (ImGui.Checkbox(option.Name, ref enabled))
if (ImUtf8.Checkbox(option.Name, ref enabled))
SetModSetting(group, groupIdx, setting.SetBit(idx, enabled));
if (option.Description.Length > 0)
@ -171,11 +181,12 @@ public sealed class ModGroupDrawer(Configuration config, CollectionManager colle
return;
ImGui.TextUnformatted(group.Name);
using var disabled = ImRaii.Disabled(_locked);
ImGui.Separator();
if (ImGui.Selectable("Enable All"))
if (ImUtf8.Selectable("Enable All"u8))
SetModSetting(group, groupIdx, Setting.AllBits(group.Options.Count));
if (ImGui.Selectable("Disable All"))
if (ImUtf8.Selectable("Disable All"u8))
SetModSetting(group, groupIdx, Setting.Zero);
}
@ -187,11 +198,11 @@ public sealed class ModGroupDrawer(Configuration config, CollectionManager colle
}
else
{
var collapseId = ImGui.GetID("Collapse");
var shown = ImGui.GetStateStorage().GetBool(collapseId, true);
var collapseId = ImUtf8.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)
var buttonWidth = Math.Max(ImUtf8.CalcTextSize(buttonTextShow).X, ImUtf8.CalcTextSize(buttonTextHide).X)
+ 2 * ImGui.GetStyle().FramePadding.X;
minWidth = Math.Max(buttonWidth, minWidth);
if (shown)
@ -204,22 +215,22 @@ public sealed class ModGroupDrawer(Configuration config, CollectionManager colle
}
var width = Math.Max(ImGui.GetItemRectSize().X, minWidth);
var width = Math.Max(ImGui.GetItemRectSize().X, minWidth);
var endPos = ImGui.GetCursorPos();
ImGui.SetCursorPos(pos);
if (ImGui.Button(buttonTextHide, new Vector2(width, 0)))
if (ImUtf8.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)
var optionWidth = options.Max(o => ImUtf8.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)))
if (ImUtf8.Button(buttonTextShow, new Vector2(width, 0)))
ImGui.GetStateStorage().SetBool(collapseId, !shown);
}
}
@ -228,6 +239,18 @@ public sealed class ModGroupDrawer(Configuration config, CollectionManager colle
private ModCollection Current
=> collectionManager.Active.Current;
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private void SetModSetting(IModGroup group, int groupIdx, Setting setting)
=> collectionManager.Editor.SetModSetting(Current, group.Mod, groupIdx, setting);
{
if (_temporary)
{
_tempSettings!.ForceInherit = false;
_tempSettings!.Settings[groupIdx] = setting;
collectionManager.Editor.SetTemporarySettings(Current, group.Mod, _tempSettings);
}
else
{
collectionManager.Editor.SetModSetting(Current, group.Mod, groupIdx, setting);
}
}
}

View file

@ -1,6 +1,5 @@
using ImGuiNET;
using OtterGui.Raii;
using OtterGui;
using OtterGui.Services;
using OtterGui.Text;
using OtterGui.Widgets;
@ -24,6 +23,8 @@ public class ModPanelSettingsTab(
: ITab, IUiService
{
private bool _inherited;
private bool _temporary;
private bool _locked;
private int? _currentPriority;
public ReadOnlySpan<byte> Label
@ -37,11 +38,14 @@ public class ModPanelSettingsTab(
public void DrawContent()
{
using var child = ImRaii.Child("##settings");
using var child = ImUtf8.Child("##settings"u8, default);
if (!child)
return;
_inherited = selection.Collection != collectionManager.Active.Current;
_inherited = selection.Collection != collectionManager.Active.Current;
_temporary = selection.TemporarySettings != null;
_locked = (selection.TemporarySettings?.Lock ?? 0) != 0;
DrawTemporaryWarning();
DrawInheritedWarning();
UiHelpers.DefaultLineSpace();
communicator.PreSettingsPanelDraw.Invoke(selection.Mod!.Identifier);
@ -54,11 +58,27 @@ public class ModPanelSettingsTab(
communicator.PostEnabledDraw.Invoke(selection.Mod!.Identifier);
modGroupDrawer.Draw(selection.Mod!, selection.Settings);
modGroupDrawer.Draw(selection.Mod!, selection.Settings, selection.TemporarySettings);
UiHelpers.DefaultLineSpace();
communicator.PostSettingsPanelDraw.Invoke(selection.Mod!.Identifier);
}
/// <summary> Draw a big tinted bar if the current setting is temporary. </summary>
private void DrawTemporaryWarning()
{
if (!_temporary)
return;
using var color = ImRaii.PushColor(ImGuiCol.Button, ImGuiCol.Button.Tinted(ColorId.TemporaryModSettingsTint));
var width = new Vector2(ImGui.GetContentRegionAvail().X, 0);
if (ImUtf8.ButtonEx($"These settings are temporary from {selection.TemporarySettings!.Source}{(_locked ? " and locked." : ".")}", width,
_locked))
collectionManager.Editor.SetTemporarySettings(collectionManager.Active.Current, selection.Mod!, null);
ImUtf8.HoverTooltip("Changing settings in temporary settings will not save them across sessions.\n"u8
+ "You can click this button to remove the temporary settings and return to your normal settings."u8);
}
/// <summary> Draw a big red bar if the current setting is inherited. </summary>
private void DrawInheritedWarning()
{
@ -67,22 +87,42 @@ public class ModPanelSettingsTab(
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 {selection.Collection.Identity.Name}.", width))
collectionManager.Editor.SetModInheritance(collectionManager.Active.Current, selection.Mod!, false);
if (ImUtf8.ButtonEx($"These settings are inherited from {selection.Collection.Identity.Name}.", width, _locked))
{
if (_temporary)
{
selection.TemporarySettings!.ForceInherit = false;
collectionManager.Editor.SetTemporarySettings(collectionManager.Active.Current, selection.Mod!, selection.TemporarySettings);
}
else
{
collectionManager.Editor.SetModInheritance(collectionManager.Active.Current, selection.Mod!, 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.");
ImUtf8.HoverTooltip("You can click this button to copy the current settings to the current selection.\n"u8
+ "You can also just change any setting, which will copy the settings with the single setting changed to the current selection."u8);
}
/// <summary> Draw a checkbox for the enabled status of the mod. </summary>
private void DrawEnabledInput()
{
var enabled = selection.Settings.Enabled;
if (!ImGui.Checkbox("Enabled", ref enabled))
var enabled = selection.Settings.Enabled;
using var disabled = ImRaii.Disabled(_locked);
if (!ImUtf8.Checkbox("Enabled"u8, ref enabled))
return;
modManager.SetKnown(selection.Mod!);
collectionManager.Editor.SetModState(collectionManager.Active.Current, selection.Mod!, enabled);
if (_temporary)
{
selection.TemporarySettings!.ForceInherit = false;
selection.TemporarySettings!.Enabled = enabled;
collectionManager.Editor.SetTemporarySettings(collectionManager.Active.Current, selection.Mod!, selection.TemporarySettings);
}
else
{
collectionManager.Editor.SetModState(collectionManager.Active.Current, selection.Mod!, enabled);
}
}
/// <summary>
@ -91,45 +131,66 @@ public class ModPanelSettingsTab(
/// </summary>
private void DrawPriorityInput()
{
using var group = ImRaii.Group();
using var group = ImUtf8.Group();
var settings = selection.Settings;
var priority = _currentPriority ?? settings.Priority.Value;
ImGui.SetNextItemWidth(50 * UiHelpers.Scale);
if (ImGui.InputInt("##Priority", ref priority, 0, 0))
using var disabled = ImRaii.Disabled(_locked);
if (ImUtf8.InputScalar("##Priority"u8, ref priority))
_currentPriority = priority;
if (new ModPriority(priority).IsHidden)
ImUtf8.HoverTooltip($"This priority is special-cased to hide this mod in conflict tabs ({ModPriority.HiddenMin}, {ModPriority.HiddenMax}).");
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled,
$"This priority is special-cased to hide this mod in conflict tabs ({ModPriority.HiddenMin}, {ModPriority.HiddenMax}).");
if (ImGui.IsItemDeactivatedAfterEdit() && _currentPriority.HasValue)
{
if (_currentPriority != settings.Priority.Value)
collectionManager.Editor.SetModPriority(collectionManager.Active.Current, selection.Mod!,
new ModPriority(_currentPriority.Value));
{
if (_temporary)
{
selection.TemporarySettings!.ForceInherit = false;
selection.TemporarySettings!.Priority = new ModPriority(_currentPriority.Value);
collectionManager.Editor.SetTemporarySettings(collectionManager.Active.Current, selection.Mod!,
selection.TemporarySettings);
}
else
{
collectionManager.Editor.SetModPriority(collectionManager.Active.Current, selection.Mod!,
new ModPriority(_currentPriority.Value));
}
}
_currentPriority = null;
}
ImGuiUtil.LabeledHelpMarker("Priority", "Mods with a higher number here take precedence before Mods with a lower number.\n"
+ "That means, if Mod A should overwrite changes from Mod B, Mod A should have a higher priority number than Mod B.");
ImUtf8.LabeledHelpMarker("Priority"u8, "Mods with a higher number here take precedence before Mods with a lower number.\n"u8
+ "That means, if Mod A should overwrite changes from Mod B, Mod A should have a higher priority number than Mod B."u8);
}
/// <summary>
/// Draw a button to remove the current settings and inherit them instead
/// on the top-right corner of the window/tab.
/// in the top-right corner of the window/tab.
/// </summary>
private void DrawRemoveSettings()
{
const string text = "Inherit Settings";
if (_inherited || selection.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, selection.Mod!, true);
ImGui.SameLine(ImGui.GetWindowWidth() - ImUtf8.CalcTextSize("Inherit Settings"u8).X - ImGui.GetStyle().FramePadding.X * 2 - scroll);
if (!ImUtf8.ButtonEx("Inherit Settings"u8, "Remove current settings from this collection so that it can inherit them.\n"u8
+ "If no inherited collection has settings for this mod, it will be disabled."u8, default, _locked))
return;
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 (_temporary)
{
selection.TemporarySettings!.ForceInherit = true;
collectionManager.Editor.SetTemporarySettings(collectionManager.Active.Current, selection.Mod!, selection.TemporarySettings);
}
else
{
collectionManager.Editor.SetModInheritance(collectionManager.Active.Current, selection.Mod!, true);
}
}
}

View file

@ -791,19 +791,25 @@ public class DebugTab : Window, ITab, IUiService
ImGuiClip.DrawEndDummy(dummy, ImGui.GetTextLineHeightWithSpacing());
}
private string _tmbKeyFilter = string.Empty;
private CiByteString _tmbKeyFilterU8 = CiByteString.Empty;
private void DrawActionTmbs()
{
using var mainTree = TreeNode("Action TMBs");
if (!mainTree)
return;
if (ImGui.InputText("Key", ref _tmbKeyFilter, 256))
_tmbKeyFilterU8 = CiByteString.FromString(_tmbKeyFilter, out var r, MetaDataComputation.All) ? r : CiByteString.Empty;
using var table = Table("##table", 2, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY | ImGuiTableFlags.SizingFixedFit,
new Vector2(-1, 12 * ImGui.GetTextLineHeightWithSpacing()));
if (!table)
return;
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeightWithSpacing());
var dummy = ImGuiClip.ClippedDraw(_schedulerService.ActionTmbs.OrderBy(r => r.Value), skips,
var dummy = ImGuiClip.FilteredClippedDraw(_schedulerService.ActionTmbs.OrderBy(r => r.Value), skips,
kvp => kvp.Key.Contains(_tmbKeyFilterU8),
p =>
{
ImUtf8.DrawTableColumn($"{p.Value}");