mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2026-02-22 23:47:45 +01:00
Update automation tab, mod associations panel.
This commit is contained in:
parent
f2ac7e3353
commit
4646fd57ab
14 changed files with 676 additions and 611 deletions
|
|
@ -64,7 +64,10 @@ public sealed class AutomationChanged()
|
||||||
|
|
||||||
public enum Priority
|
public enum Priority
|
||||||
{
|
{
|
||||||
/// <seealso cref="Gui.Tabs.AutomationTab.SetSelector.OnAutomationChange"/>
|
/// <seealso cref="Gui.Tabs.AutomationTab.AutomationSelection.OnAutomationChanged"/>
|
||||||
|
AutomationSelection = 0,
|
||||||
|
|
||||||
|
/// <seealso cref="Gui.Tabs.AutomationTab.SetSelector.Cache.OnAutomationChanged"/>
|
||||||
SetSelector = 0,
|
SetSelector = 0,
|
||||||
|
|
||||||
/// <seealso cref="AutoDesignApplier.OnAutomationChange"/>
|
/// <seealso cref="AutoDesignApplier.OnAutomationChange"/>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ namespace Glamourer.Gui.Tabs.ActorTab;
|
||||||
|
|
||||||
public sealed class ActorSelection(StateManager manager, ActorObjectManager objects, ICondition conditions) : IUiService
|
public sealed class ActorSelection(StateManager manager, ActorObjectManager objects, ICondition conditions) : IUiService
|
||||||
{
|
{
|
||||||
private static readonly StringU8 NoSelection = new("No Selection"u8);
|
private static readonly StringU8 NoSelection = new("No Actor Selected"u8);
|
||||||
|
|
||||||
public ActorIdentifier Identifier { get; private set; }
|
public ActorIdentifier Identifier { get; private set; }
|
||||||
public ActorState? State { get; private set; }
|
public ActorState? State { get; private set; }
|
||||||
|
|
|
||||||
168
Glamourer/Gui/Tabs/AutomationTab/AutomationButtons.cs
Normal file
168
Glamourer/Gui/Tabs/AutomationTab/AutomationButtons.cs
Normal file
|
|
@ -0,0 +1,168 @@
|
||||||
|
using Glamourer.Automation;
|
||||||
|
using ImSharp;
|
||||||
|
using Luna;
|
||||||
|
using Penumbra.GameData.Actors;
|
||||||
|
using Penumbra.GameData.Interop;
|
||||||
|
using Penumbra.GameData.Structs;
|
||||||
|
using Penumbra.String;
|
||||||
|
|
||||||
|
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||||
|
|
||||||
|
public sealed class AutomationButtons : ButtonFooter
|
||||||
|
{
|
||||||
|
public AutomationButtons(Configuration config, AutoDesignManager manager, AutomationSelection selection, ActorObjectManager objects)
|
||||||
|
{
|
||||||
|
Buttons.AddButton(new AddButton(objects, manager), 100);
|
||||||
|
Buttons.AddButton(new DuplicateButton(selection, manager), 90);
|
||||||
|
Buttons.AddButton(new HelpButton(), 80);
|
||||||
|
Buttons.AddButton(new DeleteButton(selection, config, manager), 70);
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class AddButton(ActorObjectManager objects, AutoDesignManager manager) : BaseIconButton<AwesomeIcon>
|
||||||
|
{
|
||||||
|
private ActorIdentifier _identifier;
|
||||||
|
|
||||||
|
public override AwesomeIcon Icon
|
||||||
|
=> LunaStyle.AddObjectIcon;
|
||||||
|
|
||||||
|
public override bool HasTooltip
|
||||||
|
=> true;
|
||||||
|
|
||||||
|
protected override void PreDraw()
|
||||||
|
{
|
||||||
|
_identifier = objects.Actors.GetCurrentPlayer();
|
||||||
|
if (!_identifier.IsValid)
|
||||||
|
_identifier = objects.Actors.CreatePlayer(ByteString.FromSpanUnsafe("New Design"u8, true, false, true), WorldId.AnyWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DrawTooltip()
|
||||||
|
=> Im.Text($"Create a new Automatic Design Set for {_identifier}. The associated player can be changed later.");
|
||||||
|
|
||||||
|
public override bool Enabled
|
||||||
|
=> _identifier.IsValid;
|
||||||
|
|
||||||
|
public override void OnClick()
|
||||||
|
=> manager.AddDesignSet("New Automation Set", _identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class DuplicateButton(AutomationSelection selection, AutoDesignManager manager) : BaseIconButton<AwesomeIcon>
|
||||||
|
{
|
||||||
|
public override AwesomeIcon Icon
|
||||||
|
=> LunaStyle.DuplicateIcon;
|
||||||
|
|
||||||
|
public override bool HasTooltip
|
||||||
|
=> true;
|
||||||
|
|
||||||
|
public override void DrawTooltip()
|
||||||
|
=> Im.Text("Duplicate the current Automatic Design Set."u8);
|
||||||
|
|
||||||
|
public override bool Enabled
|
||||||
|
=> selection.Set is not null;
|
||||||
|
|
||||||
|
public override void OnClick()
|
||||||
|
=> manager.DuplicateDesignSet(selection.Set!);
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class HelpButton : BaseIconButton<AwesomeIcon>
|
||||||
|
{
|
||||||
|
public override AwesomeIcon Icon
|
||||||
|
=> LunaStyle.InfoIcon;
|
||||||
|
|
||||||
|
public override bool HasTooltip
|
||||||
|
=> true;
|
||||||
|
|
||||||
|
public override void DrawTooltip()
|
||||||
|
=> Im.Text("How does Automation work?"u8);
|
||||||
|
|
||||||
|
|
||||||
|
public override void OnClick()
|
||||||
|
=> Im.Popup.Open("Automation Help"u8);
|
||||||
|
|
||||||
|
protected override void PostDraw()
|
||||||
|
{
|
||||||
|
var longestLine =
|
||||||
|
Im.Font.CalculateSize(
|
||||||
|
"A single set can contain multiple automated designs that apply under different conditions and different parts of their design."u8);
|
||||||
|
ImEx.HelpPopup("Automation Help"u8, new Vector2(longestLine.X + 50 * Im.Style.GlobalScale, 33 * Im.Style.TextHeightWithSpacing),
|
||||||
|
DrawHelp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawHelp()
|
||||||
|
{
|
||||||
|
var halfLine = new Vector2(Im.Style.TextHeight / 2);
|
||||||
|
Im.Dummy(halfLine);
|
||||||
|
Im.Text("What is Automation?"u8);
|
||||||
|
Im.BulletText("Automation helps you to automatically apply Designs to specific characters under specific circumstances."u8);
|
||||||
|
Im.Dummy(halfLine);
|
||||||
|
|
||||||
|
Im.Text("Automated Design Sets"u8);
|
||||||
|
Im.BulletText("First, you create automated design sets. An automated design set can be... "u8);
|
||||||
|
using var indent = Im.Indent();
|
||||||
|
Im.BulletText("... enabled, or"u8, ColorId.EnabledAutoSet.Value());
|
||||||
|
Im.BulletText("... disabled."u8, ColorId.DisabledAutoSet.Value());
|
||||||
|
indent.Unindent();
|
||||||
|
Im.BulletText("You can create new, empty automated design sets, or duplicate existing ones."u8);
|
||||||
|
Im.BulletText("You can name automated design sets arbitrarily."u8);
|
||||||
|
Im.BulletText("You can re-order automated design sets via drag & drop in the selector."u8);
|
||||||
|
Im.BulletText("Each automated design set is assigned to exactly one specific character."u8);
|
||||||
|
indent.Indent();
|
||||||
|
Im.BulletText("On creation, it is assigned to your current Player Character."u8);
|
||||||
|
Im.BulletText("You can assign sets to any players, retainers, mannequins and most human NPCs."u8);
|
||||||
|
Im.BulletText("Only one automated design set can be enabled at the same time for each specific character."u8);
|
||||||
|
indent.Indent();
|
||||||
|
Im.BulletText("Enabling another automatically disables the prior one."u8);
|
||||||
|
indent.Unindent();
|
||||||
|
indent.Unindent();
|
||||||
|
|
||||||
|
Im.Dummy(halfLine);
|
||||||
|
Im.Text("Automated Designs"u8);
|
||||||
|
Im.BulletText(
|
||||||
|
"A single set can contain multiple automated designs that apply under different conditions and different parts of their design."u8);
|
||||||
|
Im.BulletText("The order of these automated designs can also be changed via drag & drop, and is relevant for the application."u8);
|
||||||
|
Im.BulletText("Automated designs respect their own, coarse applications rules, and the designs own application rules."u8);
|
||||||
|
Im.BulletText("Automated designs can be configured to be job- or job-group specific and only apply on these jobs, then."u8);
|
||||||
|
Im.BulletText("There is also the special option 'Reset', which can be used to reset remaining slots to the game's values."u8);
|
||||||
|
Im.BulletText("Automated designs apply from top to bottom, either on top of your characters current state, or its game state."u8);
|
||||||
|
Im.BulletText("For a value to apply, it needs to:"u8);
|
||||||
|
indent.Unindent();
|
||||||
|
Im.BulletText("Be configured to apply in the design itself."u8);
|
||||||
|
Im.BulletText("Be configured to apply in the automation rules."u8);
|
||||||
|
Im.BulletText("Fulfill the conditions of the automation rules."u8);
|
||||||
|
Im.BulletText("Be a valid value for the current (on its own application) state of the character."u8);
|
||||||
|
Im.BulletText("Not have had anything applied to the same value before from a different design."u8);
|
||||||
|
indent.Unindent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class DeleteButton(AutomationSelection selection, Configuration config, AutoDesignManager manager)
|
||||||
|
: BaseIconButton<AwesomeIcon>
|
||||||
|
{
|
||||||
|
private bool _enabled;
|
||||||
|
|
||||||
|
public override AwesomeIcon Icon
|
||||||
|
=> LunaStyle.DeleteIcon;
|
||||||
|
|
||||||
|
public override bool HasTooltip
|
||||||
|
=> true;
|
||||||
|
|
||||||
|
public override void DrawTooltip()
|
||||||
|
{
|
||||||
|
if (selection.Set is null)
|
||||||
|
{
|
||||||
|
Im.Text("No Automatic Design Set selected."u8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Im.Text("Delete the currently selected design set."u8);
|
||||||
|
if (!_enabled)
|
||||||
|
Im.Text($"\nHold {config.DeleteDesignModifier} to delete.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Enabled
|
||||||
|
=> (_enabled = config.DeleteDesignModifier.IsActive()) && selection.Set is not null;
|
||||||
|
|
||||||
|
public override void OnClick()
|
||||||
|
=> manager.DeleteDesignSet(selection.Index);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Glamourer/Gui/Tabs/AutomationTab/AutomationCacheItem.cs
Normal file
14
Glamourer/Gui/Tabs/AutomationTab/AutomationCacheItem.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
using Glamourer.Automation;
|
||||||
|
using ImSharp;
|
||||||
|
|
||||||
|
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||||
|
|
||||||
|
public readonly struct AutomationCacheItem(AutoDesignSet set, int index)
|
||||||
|
{
|
||||||
|
public readonly AutoDesignSet Set = set;
|
||||||
|
public readonly int Index = index;
|
||||||
|
public readonly StringPair Name = new(set.Name);
|
||||||
|
public readonly StringPair IdentifierString = new(set.Identifiers.First().ToString());
|
||||||
|
public readonly StringU8 Incognito = new($"Auto Design Set #{index + 1}");
|
||||||
|
public readonly StringU8 IdentifierIncognito = new(set.Identifiers.First().Incognito(null));
|
||||||
|
}
|
||||||
64
Glamourer/Gui/Tabs/AutomationTab/AutomationFilter.cs
Normal file
64
Glamourer/Gui/Tabs/AutomationTab/AutomationFilter.cs
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
using ImSharp;
|
||||||
|
using Luna;
|
||||||
|
|
||||||
|
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||||
|
|
||||||
|
public sealed class AutomationFilter : TextFilterBase<AutomationCacheItem>, IUiService
|
||||||
|
{
|
||||||
|
private bool? _setStateFilter;
|
||||||
|
|
||||||
|
protected override string ToFilterString(in AutomationCacheItem item, int globalIndex)
|
||||||
|
=> item.Name.Utf16;
|
||||||
|
|
||||||
|
public override bool WouldBeVisible(in AutomationCacheItem item, int globalIndex)
|
||||||
|
=> _setStateFilter switch
|
||||||
|
{
|
||||||
|
true => item.Set.Enabled,
|
||||||
|
false => !item.Set.Enabled,
|
||||||
|
null => true,
|
||||||
|
}
|
||||||
|
&& base.WouldBeVisible(in item, globalIndex);
|
||||||
|
|
||||||
|
public override bool DrawFilter(ReadOnlySpan<byte> label, Vector2 availableRegion)
|
||||||
|
{
|
||||||
|
availableRegion.X -= Im.Style.FrameHeight;
|
||||||
|
var ret = base.DrawFilter(label, availableRegion);
|
||||||
|
Im.Line.NoSpacing();
|
||||||
|
using (ImGuiColor.FrameBackground.Push(0x807070FF, _setStateFilter is not null))
|
||||||
|
{
|
||||||
|
if (ImEx.TriStateCheckbox("##state"u8, ref _setStateFilter, Rgba32.Transparent, ColorParameter.Default, ColorParameter.Default))
|
||||||
|
{
|
||||||
|
ret = true;
|
||||||
|
InvokeEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Im.Item.Hovered())
|
||||||
|
{
|
||||||
|
if (Im.Item.RightClicked())
|
||||||
|
{
|
||||||
|
// Ensure that a right-click clears the text filter if it is currently being edited.
|
||||||
|
Im.Id.ClearActive();
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
using var tt = Im.Tooltip.Begin();
|
||||||
|
Im.Text("Filter to only show enabled or disabled sets."u8);
|
||||||
|
if (Text.Length is not 0 || _setStateFilter is not null)
|
||||||
|
Im.Text("\nRight-click to clear all filters, including the text filter."u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
var pos = Im.Item.UpperLeftCorner;
|
||||||
|
pos.X -= Im.Style.GlobalScale;
|
||||||
|
Im.Window.DrawList.Shape.Line(pos, pos with { Y = Im.Item.LowerRightCorner.Y }, ImGuiColor.Border.Get(), Im.Style.GlobalScale);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Clear()
|
||||||
|
{
|
||||||
|
var changes = _setStateFilter is not null;
|
||||||
|
_setStateFilter = null;
|
||||||
|
if (!Set(string.Empty) && changes)
|
||||||
|
InvokeEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Glamourer/Gui/Tabs/AutomationTab/AutomationHeader.cs
Normal file
13
Glamourer/Gui/Tabs/AutomationTab/AutomationHeader.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
using ImSharp;
|
||||||
|
using Luna;
|
||||||
|
|
||||||
|
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||||
|
|
||||||
|
public sealed class AutomationHeader(Configuration config, AutomationSelection selection) : IHeader
|
||||||
|
{
|
||||||
|
public bool Collapsed
|
||||||
|
=> false;
|
||||||
|
|
||||||
|
public void Draw(Vector2 size)
|
||||||
|
=> ImEx.TextFramed(config.Ephemeral.IncognitoMode ? selection.Incognito : selection.Name, size with { Y = Im.Style.FrameHeight });
|
||||||
|
}
|
||||||
61
Glamourer/Gui/Tabs/AutomationTab/AutomationSelection.cs
Normal file
61
Glamourer/Gui/Tabs/AutomationTab/AutomationSelection.cs
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
using Glamourer.Automation;
|
||||||
|
using Glamourer.Events;
|
||||||
|
using ImSharp;
|
||||||
|
using Luna;
|
||||||
|
|
||||||
|
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||||
|
|
||||||
|
public sealed class AutomationSelection : IUiService, IDisposable
|
||||||
|
{
|
||||||
|
public static readonly StringU8 NoSelection = new("No Set Selected"u8);
|
||||||
|
|
||||||
|
private readonly AutomationChanged _automationChanged;
|
||||||
|
|
||||||
|
public int DraggedDesignIndex = -1;
|
||||||
|
|
||||||
|
public AutoDesignSet? Set { get; private set; }
|
||||||
|
public int Index { get; private set; } = -1;
|
||||||
|
public StringU8 Name { get; private set; } = NoSelection;
|
||||||
|
public StringU8 Incognito { get; private set; } = NoSelection;
|
||||||
|
|
||||||
|
public AutomationSelection(AutomationChanged automationChanged)
|
||||||
|
{
|
||||||
|
_automationChanged = automationChanged;
|
||||||
|
_automationChanged.Subscribe(OnAutomationChanged, AutomationChanged.Priority.SetSelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_automationChanged.Unsubscribe(OnAutomationChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAutomationChanged(AutomationChanged.Type type, AutoDesignSet? set, object? data)
|
||||||
|
{
|
||||||
|
if (set != Set)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case AutomationChanged.Type.DeletedSet: Update(null); break;
|
||||||
|
case AutomationChanged.Type.RenamedSet: Name = new StringU8(set!.Name); break;
|
||||||
|
case AutomationChanged.Type.MovedSet: Index = (((int, int))data!).Item2; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(in AutomationCacheItem? item)
|
||||||
|
{
|
||||||
|
Set = item?.Set;
|
||||||
|
if (Set is null)
|
||||||
|
{
|
||||||
|
Index = -1;
|
||||||
|
Name = NoSelection;
|
||||||
|
Incognito = NoSelection;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Index = item!.Value.Index;
|
||||||
|
Name = item!.Value.Name.Utf8;
|
||||||
|
Incognito = item!.Value.Incognito;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,12 +3,27 @@ using Luna;
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.AutomationTab;
|
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||||
|
|
||||||
public class AutomationTab(SetSelector selector, SetPanel panel, Configuration config) : ITab<MainTabType>
|
public class AutomationTab : TwoPanelLayout, ITab<MainTabType>
|
||||||
{
|
{
|
||||||
public bool IsVisible
|
private readonly Configuration _config;
|
||||||
=> config.EnableAutoDesigns;
|
|
||||||
|
|
||||||
public ReadOnlySpan<byte> Label
|
public AutomationTab(AutomationFilter filter, SetSelector selector, SetPanel panel, AutomationButtons buttons, AutomationHeader header,
|
||||||
|
Configuration config)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
LeftHeader = new FilterHeader<AutomationCacheItem>(filter, new StringU8("Filter..."u8));
|
||||||
|
LeftPanel = selector;
|
||||||
|
LeftFooter = buttons;
|
||||||
|
|
||||||
|
RightHeader = header;
|
||||||
|
RightPanel = panel;
|
||||||
|
RightFooter = NopHeaderFooter.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsVisible
|
||||||
|
=> _config.EnableAutoDesigns;
|
||||||
|
|
||||||
|
public override ReadOnlySpan<byte> Label
|
||||||
=> "Automation"u8;
|
=> "Automation"u8;
|
||||||
|
|
||||||
public MainTabType Identifier
|
public MainTabType Identifier
|
||||||
|
|
@ -16,11 +31,6 @@ public class AutomationTab(SetSelector selector, SetPanel panel, Configuration c
|
||||||
|
|
||||||
public void DrawContent()
|
public void DrawContent()
|
||||||
{
|
{
|
||||||
selector.Draw(GetSetSelectorSize());
|
Draw(TwoPanelWidth.IndeterminateRelative);
|
||||||
Im.Line.Same();
|
|
||||||
panel.Draw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public float GetSetSelectorSize()
|
|
||||||
=> 200f * Im.Style.GlobalScale;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
||||||
private readonly Configuration _config;
|
private readonly Configuration _config;
|
||||||
private readonly AutoDesignManager _autoDesignManager;
|
private readonly AutoDesignManager _autoDesignManager;
|
||||||
private readonly RandomDesignCombo _randomDesignCombo;
|
private readonly RandomDesignCombo _randomDesignCombo;
|
||||||
private readonly SetSelector _selector;
|
private readonly AutomationSelection _selection;
|
||||||
private readonly DesignStorage _designs;
|
private readonly DesignStorage _designs;
|
||||||
private readonly DesignFileSystem _designFileSystem;
|
private readonly DesignFileSystem _designFileSystem;
|
||||||
|
|
||||||
|
|
@ -26,13 +26,13 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
||||||
private Design? _newDesign;
|
private Design? _newDesign;
|
||||||
|
|
||||||
public RandomRestrictionDrawer(AutomationChanged automationChanged, Configuration config, AutoDesignManager autoDesignManager,
|
public RandomRestrictionDrawer(AutomationChanged automationChanged, Configuration config, AutoDesignManager autoDesignManager,
|
||||||
RandomDesignCombo randomDesignCombo, SetSelector selector, DesignFileSystem designFileSystem, DesignStorage designs)
|
RandomDesignCombo randomDesignCombo, AutomationSelection selection, DesignFileSystem designFileSystem, DesignStorage designs)
|
||||||
{
|
{
|
||||||
_automationChanged = automationChanged;
|
_automationChanged = automationChanged;
|
||||||
_config = config;
|
_config = config;
|
||||||
_autoDesignManager = autoDesignManager;
|
_autoDesignManager = autoDesignManager;
|
||||||
_randomDesignCombo = randomDesignCombo;
|
_randomDesignCombo = randomDesignCombo;
|
||||||
_selector = selector;
|
_selection = selection;
|
||||||
_designFileSystem = designFileSystem;
|
_designFileSystem = designFileSystem;
|
||||||
_designs = designs;
|
_designs = designs;
|
||||||
_automationChanged.Subscribe(OnAutomationChange, AutomationChanged.Priority.RandomRestrictionDrawer);
|
_automationChanged.Subscribe(OnAutomationChange, AutomationChanged.Priority.RandomRestrictionDrawer);
|
||||||
|
|
@ -87,7 +87,7 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
||||||
if (_set is null || _designIndex < 0 || _designIndex >= _set.Designs.Count)
|
if (_set is null || _designIndex < 0 || _designIndex >= _set.Designs.Count)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_set != _selector.Selection)
|
if (_set != _selection.Set)
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
return;
|
return;
|
||||||
|
|
@ -283,8 +283,10 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
||||||
name = _designFileSystem.TryGetValue(enumerator.Current, out l) ? l.FullName() : enumerator.Current.Name.Text;
|
name = _designFileSystem.TryGetValue(enumerator.Current, out l) ? l.FullName() : enumerator.Current.Name.Text;
|
||||||
Im.BulletText(name);
|
Im.BulletText(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Im.Text("Matches no currently existing designs."u8);
|
Im.Text("Matches no currently existing designs."u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -314,7 +316,8 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
||||||
"Add a new condition that the design must be assigned to the given color."u8, invalid)
|
"Add a new condition that the design must be assigned to the given color."u8, invalid)
|
||||||
&& Add(new RandomPredicate.Exact(RandomPredicate.Exact.Type.Color, _newText));
|
&& Add(new RandomPredicate.Exact(RandomPredicate.Exact.Type.Color, _newText));
|
||||||
|
|
||||||
if (_randomDesignCombo.Draw(StringU8.Empty, _newDesign, out var newDesign, Im.ContentRegion.Available.X - Im.Style.ItemInnerSpacing.X - buttonSize.X))
|
if (_randomDesignCombo.Draw(StringU8.Empty, _newDesign, out var newDesign,
|
||||||
|
Im.ContentRegion.Available.X - Im.Style.ItemInnerSpacing.X - buttonSize.X))
|
||||||
_newDesign = newDesign as Design;
|
_newDesign = newDesign as Design;
|
||||||
Im.Line.SameInner();
|
Im.Line.SameInner();
|
||||||
if (ImEx.Button("Exact Design"u8, buttonSize, "Add a single, specific design."u8, _newDesign is null))
|
if (ImEx.Button("Exact Design"u8, buttonSize, "Add a single, specific design."u8, _newDesign is null))
|
||||||
|
|
@ -346,7 +349,8 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable
|
||||||
var definition = _newDefinition ?? currentDefinition;
|
var definition = _newDefinition ?? currentDefinition;
|
||||||
definition = definition.Replace(";", ";\n\t").Replace("{", "{\n\t").Replace("}", "\n}");
|
definition = definition.Replace(";", ";\n\t").Replace("{", "{\n\t").Replace("}", "\n}");
|
||||||
var lines = definition.Count(c => c is '\n');
|
var lines = definition.Count(c => c is '\n');
|
||||||
if (Im.Input.MultiLine("##definition"u8, ref definition, Im.ContentRegion.Available with { Y = (lines + 1) * Im.Style.TextHeight + Im.Style.FrameHeight },
|
if (Im.Input.MultiLine("##definition"u8, ref definition,
|
||||||
|
Im.ContentRegion.Available with { Y = (lines + 1) * Im.Style.TextHeight + Im.Style.FrameHeight },
|
||||||
InputTextFlags.CtrlEnterForNewLine))
|
InputTextFlags.CtrlEnterForNewLine))
|
||||||
_newDefinition = definition;
|
_newDefinition = definition;
|
||||||
if (Im.Item.DeactivatedAfterEdit && _newDefinition is not null && _newDefinition != currentDefinition)
|
if (Im.Item.DeactivatedAfterEdit && _newDefinition is not null && _newDefinition != currentDefinition)
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,12 @@ using Glamourer.Services;
|
||||||
using Glamourer.Unlocks;
|
using Glamourer.Unlocks;
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using Luna;
|
using Luna;
|
||||||
using OtterGui.Widgets;
|
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
using Action = System.Action;
|
|
||||||
using MouseWheelType = OtterGui.Widgets.MouseWheelType;
|
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.AutomationTab;
|
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||||
|
|
||||||
public class SetPanel(
|
public class SetPanel(
|
||||||
SetSelector selector,
|
|
||||||
AutoDesignManager manager,
|
AutoDesignManager manager,
|
||||||
JobService jobs,
|
JobService jobs,
|
||||||
ItemUnlockManager itemUnlocks,
|
ItemUnlockManager itemUnlocks,
|
||||||
|
|
@ -24,45 +20,34 @@ public class SetPanel(
|
||||||
CustomizeService customizations,
|
CustomizeService customizations,
|
||||||
IdentifierDrawer identifierDrawer,
|
IdentifierDrawer identifierDrawer,
|
||||||
Configuration config,
|
Configuration config,
|
||||||
RandomRestrictionDrawer randomDrawer)
|
RandomRestrictionDrawer randomDrawer,
|
||||||
|
AutomationSelection selection) : IPanel
|
||||||
{
|
{
|
||||||
private readonly JobGroupCombo _jobGroupCombo = new(manager, jobs, Glamourer.Log);
|
private readonly JobGroupCombo _jobGroupCombo = new(manager, jobs);
|
||||||
private readonly HeaderDrawer.Button[] _rightButtons = []; // [new IncognitoButton(config)];
|
|
||||||
private string? _tempName;
|
|
||||||
private int _dragIndex = -1;
|
private int _dragIndex = -1;
|
||||||
|
|
||||||
private Action? _endAction;
|
private Action? _endAction;
|
||||||
|
|
||||||
private AutoDesignSet Selection
|
public ReadOnlySpan<byte> Id
|
||||||
=> selector.Selection!;
|
=> "SetPanel"u8;
|
||||||
|
|
||||||
public void Draw()
|
public void Draw()
|
||||||
{
|
|
||||||
using var group = Im.Group();
|
|
||||||
DrawHeader();
|
|
||||||
DrawPanel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawHeader()
|
|
||||||
=> HeaderDrawer.Draw(selector.SelectionName, 0, ImGuiColor.FrameBackground.Get().Color, [], _rightButtons);
|
|
||||||
|
|
||||||
private void DrawPanel()
|
|
||||||
{
|
{
|
||||||
using var child = Im.Child.Begin("##Panel"u8, Im.ContentRegion.Available, true);
|
using var child = Im.Child.Begin("##Panel"u8, Im.ContentRegion.Available, true);
|
||||||
if (!child || !selector.HasSelection)
|
if (!child || selection.Index < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using (Im.Group())
|
using (Im.Group())
|
||||||
{
|
{
|
||||||
var enabled = Selection.Enabled;
|
var enabled = selection.Set!.Enabled;
|
||||||
if (Im.Checkbox("##Enabled"u8, ref enabled))
|
if (Im.Checkbox("##Enabled"u8, ref enabled))
|
||||||
manager.SetState(selector.SelectionIndex, enabled);
|
manager.SetState(selection.Index, enabled);
|
||||||
LunaStyle.DrawAlignedHelpMarkerLabel("Enabled"u8,
|
LunaStyle.DrawAlignedHelpMarkerLabel("Enabled"u8,
|
||||||
"Whether the designs in this set should be applied at all. Only one set can be enabled for a character at the same time."u8);
|
"Whether the designs in this set should be applied at all. Only one set can be enabled for a character at the same time."u8);
|
||||||
|
|
||||||
var useGame = selector.Selection!.BaseState is AutoDesignSet.Base.Game;
|
var useGame = selection.Set!.BaseState is AutoDesignSet.Base.Game;
|
||||||
if (Im.Checkbox("##gameState"u8, ref useGame))
|
if (Im.Checkbox("##gameState"u8, ref useGame))
|
||||||
manager.ChangeBaseState(selector.SelectionIndex, useGame ? AutoDesignSet.Base.Game : AutoDesignSet.Base.Current);
|
manager.ChangeBaseState(selection.Index, useGame ? AutoDesignSet.Base.Game : AutoDesignSet.Base.Current);
|
||||||
LunaStyle.DrawAlignedHelpMarkerLabel("Use Game State as Base"u8,
|
LunaStyle.DrawAlignedHelpMarkerLabel("Use Game State as Base"u8,
|
||||||
"When this is enabled, the designs matching conditions will be applied successively on top of what your character is supposed to look like for the game. "u8
|
"When this is enabled, the designs matching conditions will be applied successively on top of what your character is supposed to look like for the game. "u8
|
||||||
+ "Otherwise, they will be applied on top of the characters actual current look using Glamourer."u8);
|
+ "Otherwise, they will be applied on top of the characters actual current look using Glamourer."u8);
|
||||||
|
|
@ -81,9 +66,9 @@ public class SetPanel(
|
||||||
LunaStyle.DrawAlignedHelpMarkerLabel("Show Editing"u8,
|
LunaStyle.DrawAlignedHelpMarkerLabel("Show Editing"u8,
|
||||||
"Show options to change the name or the associated character or NPC of this design set."u8);
|
"Show options to change the name or the associated character or NPC of this design set."u8);
|
||||||
|
|
||||||
var resetSettings = selector.Selection!.ResetTemporarySettings;
|
var resetSettings = selection.Set!.ResetTemporarySettings;
|
||||||
if (Im.Checkbox("##resetSettings"u8, ref resetSettings))
|
if (Im.Checkbox("##resetSettings"u8, ref resetSettings))
|
||||||
manager.ChangeResetSettings(selector.SelectionIndex, resetSettings);
|
manager.ChangeResetSettings(selection.Index, resetSettings);
|
||||||
|
|
||||||
LunaStyle.DrawAlignedHelpMarkerLabel("Reset Temporary Settings"u8,
|
LunaStyle.DrawAlignedHelpMarkerLabel("Reset Temporary Settings"u8,
|
||||||
"Always reset all temporary settings applied by Glamourer when this automation set is applied, regardless of active designs."u8);
|
"Always reset all temporary settings applied by Glamourer when this automation set is applied, regardless of active designs."u8);
|
||||||
|
|
@ -95,19 +80,13 @@ public class SetPanel(
|
||||||
Im.Separator();
|
Im.Separator();
|
||||||
Im.Dummy(Vector2.Zero);
|
Im.Dummy(Vector2.Zero);
|
||||||
|
|
||||||
var name = _tempName ?? Selection.Name;
|
|
||||||
var flags = config.Ephemeral.IncognitoMode ? InputTextFlags.ReadOnly | InputTextFlags.Password : InputTextFlags.None;
|
var flags = config.Ephemeral.IncognitoMode ? InputTextFlags.ReadOnly | InputTextFlags.Password : InputTextFlags.None;
|
||||||
Im.Item.SetNextWidthScaled(330);
|
Im.Item.SetNextWidthScaled(330);
|
||||||
if (Im.Input.Text("Rename Set##Name"u8, ref name, StringU8.Empty, flags))
|
if (ImEx.InputOnDeactivation.Text("Rename Set##Name"u8, selection.Name, out string newName, default, flags))
|
||||||
_tempName = name;
|
manager.Rename(selection.Index, newName);
|
||||||
|
|
||||||
if (Im.Item.Deactivated)
|
|
||||||
{
|
|
||||||
manager.Rename(selector.SelectionIndex, name);
|
|
||||||
_tempName = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawIdentifierSelection(selector.SelectionIndex);
|
DrawIdentifierSelection(selection.Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
Im.Dummy(Vector2.Zero);
|
Im.Dummy(Vector2.Zero);
|
||||||
|
|
@ -176,26 +155,26 @@ public class SetPanel(
|
||||||
table.SetupColumn(""u8, TableColumnFlags.WidthFixed, 2 * Im.Style.FrameHeight + 4 * Im.Style.GlobalScale);
|
table.SetupColumn(""u8, TableColumnFlags.WidthFixed, 2 * Im.Style.FrameHeight + 4 * Im.Style.GlobalScale);
|
||||||
|
|
||||||
table.HeaderRow();
|
table.HeaderRow();
|
||||||
foreach (var (idx, design) in Selection.Designs.Index())
|
foreach (var (idx, design) in selection.Set!.Designs.Index())
|
||||||
{
|
{
|
||||||
using var id = Im.Id.Push(idx);
|
using var id = Im.Id.Push(idx);
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
var keyValid = config.DeleteDesignModifier.IsActive();
|
var keyValid = config.DeleteDesignModifier.IsActive();
|
||||||
if (ImEx.Icon.Button(LunaStyle.DeleteIcon, "Remove this design from the set."u8, !keyValid))
|
if (ImEx.Icon.Button(LunaStyle.DeleteIcon, "Remove this design from the set."u8, !keyValid))
|
||||||
_endAction = () => manager.DeleteDesign(Selection, idx);
|
_endAction = () => manager.DeleteDesign(selection.Set!, idx);
|
||||||
if (!keyValid)
|
if (!keyValid)
|
||||||
Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} to remove.");
|
Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} to remove.");
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
DrawSelectable(idx, design.Design);
|
DrawSelectable(idx, design.Design);
|
||||||
|
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
DrawRandomEditing(Selection, design, idx);
|
DrawRandomEditing(selection.Set!, design, idx);
|
||||||
designCombo.Draw(Selection, design, idx);
|
designCombo.Draw(selection.Set!, design, idx);
|
||||||
DrawDragDrop(Selection, idx);
|
DrawDragDrop(selection.Set!, idx);
|
||||||
if (singleRow)
|
if (singleRow)
|
||||||
{
|
{
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
DrawApplicationTypeBoxes(Selection, design, idx, singleRow);
|
DrawApplicationTypeBoxes(selection.Set!, design, idx, singleRow);
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
DrawConditions(design, idx);
|
DrawConditions(design, idx);
|
||||||
}
|
}
|
||||||
|
|
@ -203,7 +182,7 @@ public class SetPanel(
|
||||||
{
|
{
|
||||||
DrawConditions(design, idx);
|
DrawConditions(design, idx);
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
DrawApplicationTypeBoxes(Selection, design, idx, singleRow);
|
DrawApplicationTypeBoxes(selection.Set!, design, idx, singleRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.ShowUnlockedItemWarnings)
|
if (config.ShowUnlockedItemWarnings)
|
||||||
|
|
@ -216,7 +195,7 @@ public class SetPanel(
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
table.DrawFrameColumn("New"u8);
|
table.DrawFrameColumn("New"u8);
|
||||||
table.NextColumn();
|
table.NextColumn();
|
||||||
designCombo.Draw(Selection, null, -1);
|
designCombo.Draw(selection.Set!, null, -1);
|
||||||
table.NextRow();
|
table.NextRow();
|
||||||
|
|
||||||
_endAction?.Invoke();
|
_endAction?.Invoke();
|
||||||
|
|
@ -258,7 +237,7 @@ public class SetPanel(
|
||||||
|
|
||||||
Im.Tooltip.OnHover($"{sb}");
|
Im.Tooltip.OnHover($"{sb}");
|
||||||
|
|
||||||
DrawDragDrop(Selection, idx);
|
DrawDragDrop(selection.Set!, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawConditions(AutoDesign design, int idx)
|
private void DrawConditions(AutoDesign design, int idx)
|
||||||
|
|
@ -267,7 +246,7 @@ public class SetPanel(
|
||||||
if (Im.Button(usingGearset ? "Gearset:##usingGearset"u8 : "Jobs:##usingGearset"u8))
|
if (Im.Button(usingGearset ? "Gearset:##usingGearset"u8 : "Jobs:##usingGearset"u8))
|
||||||
{
|
{
|
||||||
usingGearset = !usingGearset;
|
usingGearset = !usingGearset;
|
||||||
manager.ChangeGearsetCondition(Selection, idx, (short)(usingGearset ? 0 : -1));
|
manager.ChangeGearsetCondition(selection.Set!, idx, (short)(usingGearset ? 0 : -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
Im.Tooltip.OnHover("Click to switch between Job and Gearset restrictions."u8);
|
Im.Tooltip.OnHover("Click to switch between Job and Gearset restrictions."u8);
|
||||||
|
|
@ -277,11 +256,11 @@ public class SetPanel(
|
||||||
{
|
{
|
||||||
Im.Item.SetNextWidthFull();
|
Im.Item.SetNextWidthFull();
|
||||||
if (ImEx.InputOnDeactivation.Scalar("##whichGearset"u8, design.GearsetIndex + 1, out var newIndex))
|
if (ImEx.InputOnDeactivation.Scalar("##whichGearset"u8, design.GearsetIndex + 1, out var newIndex))
|
||||||
manager.ChangeGearsetCondition(Selection, idx, (short)(Math.Clamp(newIndex, 1, 100) - 1));
|
manager.ChangeGearsetCondition(selection.Set!, idx, (short)(Math.Clamp(newIndex, 1, 100) - 1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_jobGroupCombo.Draw(Selection, design, idx);
|
_jobGroupCombo.Draw(selection.Set!, design, idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -398,7 +377,7 @@ public class SetPanel(
|
||||||
if (source.SetPayload("DesignDragDrop"u8))
|
if (source.SetPayload("DesignDragDrop"u8))
|
||||||
{
|
{
|
||||||
_dragIndex = index;
|
_dragIndex = index;
|
||||||
selector.DragDesignIndex = index;
|
selection.DraggedDesignIndex = index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -468,23 +447,24 @@ public class SetPanel(
|
||||||
manager.ChangeIdentifier(setIndex, identifierDrawer.OwnedIdentifier);
|
manager.ChangeIdentifier(setIndex, identifierDrawer.OwnedIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class JobGroupCombo(AutoDesignManager manager, JobService jobs, OtterGui.Log.Logger log)
|
private sealed class JobGroupCombo(AutoDesignManager manager, JobService jobs)
|
||||||
: FilterComboCache<JobGroup>(() => jobs.JobGroups.Values.ToList(), MouseWheelType.None, log)
|
: SimpleFilterCombo<JobGroup>(SimpleFilterType.Partwise)
|
||||||
{
|
{
|
||||||
public void Draw(AutoDesignSet set, AutoDesign design, int autoDesignIndex)
|
public void Draw(AutoDesignSet set, AutoDesign design, int autoDesignIndex)
|
||||||
{
|
{
|
||||||
CurrentSelection = design.Jobs;
|
if (Draw("##jobGroups"u8, design.Jobs, "Select for which job groups this design should be applied.\nControl + Right-Click to set to all classes."u8, Im.ContentRegion.Available.X, out var newGroup))
|
||||||
CurrentSelectionIdx = jobs.JobGroups.Values.IndexOf(j => j.Id == design.Jobs.Id);
|
manager.ChangeJobCondition(set, autoDesignIndex, newGroup);
|
||||||
if (Draw("##JobGroups", design.Jobs.Name.ToString(),
|
|
||||||
"Select for which job groups this design should be applied.\nControl + Right-Click to set to all classes.",
|
|
||||||
Im.ContentRegion.Available.X, Im.Style.TextHeightWithSpacing)
|
|
||||||
&& CurrentSelectionIdx >= 0)
|
|
||||||
manager.ChangeJobCondition(set, autoDesignIndex, CurrentSelection);
|
|
||||||
else if (Im.Io.KeyControl && Im.Item.RightClicked())
|
else if (Im.Io.KeyControl && Im.Item.RightClicked())
|
||||||
manager.ChangeJobCondition(set, autoDesignIndex, jobs.JobGroups[1]);
|
manager.ChangeJobCondition(set, autoDesignIndex, jobs.JobGroups[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string ToString(JobGroup obj)
|
public override StringU8 DisplayString(in JobGroup value)
|
||||||
=> obj.Name.ToString();
|
=> value.Name;
|
||||||
|
|
||||||
|
public override string FilterString(in JobGroup value)
|
||||||
|
=> value.Name.ToString();
|
||||||
|
|
||||||
|
public override IEnumerable<JobGroup> GetBaseItems()
|
||||||
|
=>jobs.JobGroups.Values;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,346 +1,155 @@
|
||||||
using Dalamud.Interface;
|
using Glamourer.Automation;
|
||||||
using Dalamud.Interface.Utility;
|
|
||||||
using Glamourer.Automation;
|
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
using Dalamud.Bindings.ImGui;
|
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using OtterGui;
|
using Luna;
|
||||||
using OtterGui.Classes;
|
|
||||||
using OtterGui.Extensions;
|
|
||||||
using OtterGui.Raii;
|
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
using Penumbra.String;
|
|
||||||
using ImGuiClip = OtterGui.ImGuiClip;
|
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.AutomationTab;
|
namespace Glamourer.Gui.Tabs.AutomationTab;
|
||||||
|
|
||||||
public class SetSelector : IDisposable
|
public sealed class SetSelector(
|
||||||
|
AutomationSelection selection,
|
||||||
|
Configuration config,
|
||||||
|
AutoDesignManager manager,
|
||||||
|
AutomationFilter filter,
|
||||||
|
ActorObjectManager objects,
|
||||||
|
AutomationChanged automationChanged)
|
||||||
|
: IPanel
|
||||||
{
|
{
|
||||||
private readonly Configuration _config;
|
private readonly AutomationFilter _filter = filter;
|
||||||
private readonly AutoDesignManager _manager;
|
private readonly AutoDesignManager _manager = manager;
|
||||||
private readonly AutomationChanged _event;
|
private readonly AutomationChanged _automationChanged = automationChanged;
|
||||||
private readonly ActorObjectManager _objects;
|
|
||||||
private readonly List<(AutoDesignSet, int)> _list = [];
|
|
||||||
|
|
||||||
public AutoDesignSet? Selection { get; private set; }
|
public ReadOnlySpan<byte> Id
|
||||||
public int SelectionIndex { get; private set; } = -1;
|
=> "Automation Selector"u8;
|
||||||
|
|
||||||
private int _dragIndex = -1;
|
public void Draw()
|
||||||
private Action? _endAction;
|
|
||||||
|
|
||||||
internal int DragDesignIndex = -1;
|
|
||||||
|
|
||||||
public SetSelector(AutoDesignManager manager, AutomationChanged @event, Configuration config, ActorObjectManager objects)
|
|
||||||
{
|
{
|
||||||
_manager = manager;
|
Im.Cursor.Y += Im.Style.FramePadding.Y;
|
||||||
_event = @event;
|
var cache = CacheManager.Instance.GetOrCreateCache(Im.Id.Current, () => new Cache(this));
|
||||||
_config = config;
|
using var clip = new Im.ListClipper(cache.Count, cache.SelectableSize.Y);
|
||||||
_objects = objects;
|
foreach (var item in clip.Iterate(cache))
|
||||||
_event.Subscribe(OnAutomationChange, AutomationChanged.Priority.SetSelector);
|
{
|
||||||
|
Im.Cursor.X += Im.Style.FramePadding.X;
|
||||||
|
using var id = Im.Id.Push(item.Index);
|
||||||
|
using var group = Im.Group();
|
||||||
|
DrawSetSelectable(cache, item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
private void DrawSetSelectable(Cache cache, in AutomationCacheItem item)
|
||||||
{
|
{
|
||||||
_event.Unsubscribe(OnAutomationChange);
|
using (ImGuiColor.Text.Push(item.Set.Enabled ? cache.EnabledSet : cache.DisabledSet))
|
||||||
|
{
|
||||||
|
if (Im.Selectable(config.Ephemeral.IncognitoMode ? item.Incognito : item.Name.Utf8, item.Set == selection.Set,
|
||||||
|
SelectableFlags.None, cache.SelectableSize))
|
||||||
|
selection.Update(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string SelectionName
|
var lineEnd = Im.Item.LowerRightCorner;
|
||||||
=> GetSetName(Selection, SelectionIndex);
|
var lineStart = new Vector2(Im.Item.UpperLeftCorner.X, lineEnd.Y);
|
||||||
|
Im.Window.DrawList.Shape.Line(lineStart, lineEnd, cache.LineColor, Im.Style.GlobalScale);
|
||||||
|
|
||||||
public string GetSetName(AutoDesignSet? set, int index)
|
DrawDragDrop(cache, item);
|
||||||
=> set == null ? "No Selection" : _config.Ephemeral.IncognitoMode ? $"Auto Design Set #{index + 1}" : set.Name;
|
|
||||||
|
|
||||||
private void OnAutomationChange(AutomationChanged.Type type, AutoDesignSet? set, object? data)
|
var identifier = config.Ephemeral.IncognitoMode ? item.IdentifierIncognito : item.IdentifierString;
|
||||||
|
var textSize = identifier.CalculateSize();
|
||||||
|
var textColor = item.Set.Identifiers.Any(objects.ContainsKey) ? cache.AutomationAvailable : cache.AutomationUnavailable;
|
||||||
|
Im.Cursor.Position = new Vector2(Im.ContentRegion.Available.X - textSize.X - Im.Style.FramePadding.X, Im.Cursor.Y - Im.Style.TextHeightWithSpacing);
|
||||||
|
Im.Text(identifier, textColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawDragDrop(Cache cache, in AutomationCacheItem item)
|
||||||
|
{
|
||||||
|
using (var target = Im.DragDrop.Target())
|
||||||
|
{
|
||||||
|
if (target.IsDropping("DesignSetDragDrop"u8))
|
||||||
|
{
|
||||||
|
if (cache.SetDragIndex >= 0)
|
||||||
|
{
|
||||||
|
var idx = cache.SetDragIndex;
|
||||||
|
_manager.MoveSet(idx, item.Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.SetDragIndex = -1;
|
||||||
|
}
|
||||||
|
else if (target.IsDropping("DesignDragDrop"u8))
|
||||||
|
{
|
||||||
|
if (selection.DraggedDesignIndex >= 0)
|
||||||
|
{
|
||||||
|
var idx = selection.DraggedDesignIndex;
|
||||||
|
var setTo = item.Set;
|
||||||
|
var setFrom = selection.Set!;
|
||||||
|
_manager.MoveDesignToSet(setFrom, idx, setTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
selection.DraggedDesignIndex = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var source = Im.DragDrop.Source())
|
||||||
|
{
|
||||||
|
if (!source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Im.Text($"Moving design set {item.Name.Utf8} from position {item.Index + 1}...");
|
||||||
|
if (source.SetPayload("DesignSetDragDrop"u8))
|
||||||
|
cache.SetDragIndex = item.Index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private sealed class Cache : BasicFilterCache<AutomationCacheItem>
|
||||||
|
{
|
||||||
|
public Vector2 SelectableSize;
|
||||||
|
public Vector4 EnabledSet;
|
||||||
|
public Vector4 DisabledSet;
|
||||||
|
public Vector4 AutomationAvailable;
|
||||||
|
public Vector4 AutomationUnavailable;
|
||||||
|
public Rgba32 LineColor;
|
||||||
|
|
||||||
|
public int SetDragIndex = -1;
|
||||||
|
private readonly SetSelector _parent;
|
||||||
|
|
||||||
|
public Cache(SetSelector parent)
|
||||||
|
: base(parent._filter)
|
||||||
|
{
|
||||||
|
_parent = parent;
|
||||||
|
_parent._automationChanged.Subscribe(OnAutomationChanged, AutomationChanged.Priority.SetSelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
_parent._automationChanged.Unsubscribe(OnAutomationChanged);
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAutomationChanged(AutomationChanged.Type type, AutoDesignSet? set, object? data)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case AutomationChanged.Type.DeletedSet:
|
case AutomationChanged.Type.DeletedSet:
|
||||||
if (set == Selection)
|
|
||||||
{
|
|
||||||
SelectionIndex = _manager.Count == 0 ? -1 : SelectionIndex == 0 ? 0 : SelectionIndex - 1;
|
|
||||||
Selection = SelectionIndex >= 0 ? _manager[SelectionIndex] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
_dirty = true;
|
|
||||||
break;
|
|
||||||
case AutomationChanged.Type.AddedSet:
|
case AutomationChanged.Type.AddedSet:
|
||||||
SelectionIndex = (((int, string))data!).Item1;
|
|
||||||
Selection = set!;
|
|
||||||
_dirty = true;
|
|
||||||
break;
|
|
||||||
case AutomationChanged.Type.MovedSet:
|
case AutomationChanged.Type.MovedSet:
|
||||||
_dirty = true;
|
|
||||||
var (oldIdx, newIdx) = ((int, int))data!;
|
|
||||||
if (SelectionIndex == oldIdx)
|
|
||||||
SelectionIndex = newIdx;
|
|
||||||
break;
|
|
||||||
case AutomationChanged.Type.RenamedSet:
|
case AutomationChanged.Type.RenamedSet:
|
||||||
case AutomationChanged.Type.ChangeIdentifier:
|
case AutomationChanged.Type.ChangeIdentifier:
|
||||||
case AutomationChanged.Type.ToggleSet:
|
case AutomationChanged.Type.ToggleSet:
|
||||||
_dirty = true;
|
Dirty |= IManagedCache.DirtyFlags.Custom;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private LowerString _filter = LowerString.Empty;
|
protected override IEnumerable<AutomationCacheItem> GetItems()
|
||||||
private uint _enabledFilter;
|
=> _parent._manager.Index().Select(s => new AutomationCacheItem(s.Item, s.Index));
|
||||||
private float _width;
|
|
||||||
private Vector2 _defaultItemSpacing;
|
|
||||||
private Vector2 _selectableSize;
|
|
||||||
private bool _dirty = true;
|
|
||||||
|
|
||||||
private bool CheckFilters(AutoDesignSet set, string identifierString)
|
public override void Update()
|
||||||
{
|
{
|
||||||
if (_enabledFilter switch
|
SelectableSize = new Vector2(0, 2 * Im.Style.TextHeight + Im.Style.ItemSpacing.Y);
|
||||||
{
|
EnabledSet = ColorId.EnabledAutoSet.Value().ToVector();
|
||||||
1 => set.Enabled,
|
DisabledSet = ColorId.DisabledAutoSet.Value().ToVector();
|
||||||
3 => !set.Enabled,
|
AutomationAvailable = ColorId.AutomationActorAvailable.Value().ToVector();
|
||||||
_ => false,
|
AutomationUnavailable = ColorId.AutomationActorUnavailable.Value().ToVector();
|
||||||
})
|
LineColor = ImGuiColor.Border.Get();
|
||||||
return false;
|
base.Update();
|
||||||
|
|
||||||
if (!_filter.IsEmpty && !_filter.IsContained(set.Name) && !_filter.IsContained(identifierString))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateList()
|
|
||||||
{
|
|
||||||
if (!_dirty)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_list.Clear();
|
|
||||||
foreach (var (set, idx) in _manager.WithIndex())
|
|
||||||
{
|
|
||||||
var id = set.Identifiers[0].ToString();
|
|
||||||
if (CheckFilters(set, id))
|
|
||||||
_list.Add((set, idx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HasSelection
|
|
||||||
=> Selection != null;
|
|
||||||
|
|
||||||
public void Draw(float width)
|
|
||||||
{
|
|
||||||
_width = width;
|
|
||||||
using var group = ImRaii.Group();
|
|
||||||
_defaultItemSpacing = Im.Style.ItemSpacing;
|
|
||||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
|
||||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
|
||||||
ImGui.SetNextItemWidth(_width - Im.Style.FrameHeight);
|
|
||||||
if (LowerString.InputWithHint("##filter", "Filter...", ref _filter, 64))
|
|
||||||
_dirty = true;
|
|
||||||
Im.Line.Same();
|
|
||||||
var f = _enabledFilter;
|
|
||||||
|
|
||||||
if (ImGui.CheckboxFlags("##enabledFilter", ref f, 3u))
|
|
||||||
{
|
|
||||||
_enabledFilter = _enabledFilter switch
|
|
||||||
{
|
|
||||||
0 => 3,
|
|
||||||
3 => 1,
|
|
||||||
_ => 0,
|
|
||||||
};
|
|
||||||
_dirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pos = ImGui.GetItemRectMin();
|
|
||||||
pos.X -= Im.Style.GlobalScale;
|
|
||||||
ImGui.GetWindowDrawList().AddLine(pos, pos with { Y = ImGui.GetItemRectMax().Y }, ImGuiColor.Border.Get().Color,
|
|
||||||
Im.Style.GlobalScale);
|
|
||||||
|
|
||||||
ImGuiUtil.HoverTooltip("Filter to show only enabled or disabled sets.");
|
|
||||||
|
|
||||||
DrawSelector();
|
|
||||||
DrawSelectionButtons();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawSelector()
|
|
||||||
{
|
|
||||||
using var child = ImRaii.Child("##Selector", new Vector2(_width, -Im.Style.FrameHeight), true);
|
|
||||||
if (!child)
|
|
||||||
return;
|
|
||||||
|
|
||||||
UpdateList();
|
|
||||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, _defaultItemSpacing);
|
|
||||||
_selectableSize = new Vector2(0, 2 * Im.Style.TextHeight + Im.Style.ItemSpacing.Y);
|
|
||||||
ImGuiClip.ClippedDraw(_list, DrawSetSelectable, _selectableSize.Y + 2 * Im.Style.ItemSpacing.Y);
|
|
||||||
_endAction?.Invoke();
|
|
||||||
_endAction = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawSetSelectable((AutoDesignSet Set, int Index) pair)
|
|
||||||
{
|
|
||||||
using var id = Im.Id.Push(pair.Index);
|
|
||||||
using (ImGuiColor.Text.Push(pair.Set.Enabled ? ColorId.EnabledAutoSet.Value() : ColorId.DisabledAutoSet.Value()))
|
|
||||||
{
|
|
||||||
if (ImGui.Selectable(GetSetName(pair.Set, pair.Index), pair.Set == Selection, ImGuiSelectableFlags.None, _selectableSize))
|
|
||||||
{
|
|
||||||
Selection = pair.Set;
|
|
||||||
SelectionIndex = pair.Index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var lineEnd = ImGui.GetItemRectMax();
|
|
||||||
var lineStart = new Vector2(ImGui.GetItemRectMin().X, lineEnd.Y);
|
|
||||||
ImGui.GetWindowDrawList().AddLine(lineStart, lineEnd, ImGuiColor.Border.Get().Color, Im.Style.GlobalScale);
|
|
||||||
|
|
||||||
DrawDragDrop(pair.Set, pair.Index);
|
|
||||||
|
|
||||||
var text = pair.Set.Identifiers[0].ToString();
|
|
||||||
if (_config.Ephemeral.IncognitoMode)
|
|
||||||
text = pair.Set.Identifiers[0].Incognito(text);
|
|
||||||
var textSize = ImGui.CalcTextSize(text);
|
|
||||||
var textColor = pair.Set.Identifiers.Any(_objects.ContainsKey) ? ColorId.AutomationActorAvailable : ColorId.AutomationActorUnavailable;
|
|
||||||
ImGui.SetCursorPos(new Vector2(Im.ContentRegion.Available.X - textSize.X,
|
|
||||||
ImGui.GetCursorPosY() - Im.Style.TextHeightWithSpacing));
|
|
||||||
Im.Text(text, textColor.Value());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawSelectionButtons()
|
|
||||||
{
|
|
||||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
|
||||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
|
||||||
var buttonWidth = new Vector2(_width / 4, 0);
|
|
||||||
NewSetButton(buttonWidth);
|
|
||||||
Im.Line.Same();
|
|
||||||
DuplicateSetButton(buttonWidth);
|
|
||||||
Im.Line.Same();
|
|
||||||
HelpButton(buttonWidth);
|
|
||||||
Im.Line.Same();
|
|
||||||
DeleteSetButton(buttonWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void HelpButton(Vector2 size)
|
|
||||||
{
|
|
||||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.QuestionCircle.ToIconString(), size, "How does Automation work?", false, true))
|
|
||||||
ImGui.OpenPopup("Automation Help");
|
|
||||||
|
|
||||||
static void HalfLine()
|
|
||||||
=> Im.Dummy(new Vector2(Im.Style.TextHeight / 2));
|
|
||||||
|
|
||||||
const string longestLine =
|
|
||||||
"A single set can contain multiple automated designs that apply under different conditions and different parts of their design.";
|
|
||||||
|
|
||||||
ImGuiUtil.HelpPopup("Automation Help",
|
|
||||||
new Vector2(ImGui.CalcTextSize(longestLine).X + 50 * Im.Style.GlobalScale, 33 * Im.Style.TextHeightWithSpacing), () =>
|
|
||||||
{
|
|
||||||
HalfLine();
|
|
||||||
ImGui.TextUnformatted("What is Automation?");
|
|
||||||
ImGui.BulletText("Automation helps you to automatically apply Designs to specific characters under specific circumstances.");
|
|
||||||
HalfLine();
|
|
||||||
|
|
||||||
ImGui.TextUnformatted("Automated Design Sets");
|
|
||||||
ImGui.BulletText("First, you create automated design sets. An automated design set can be... ");
|
|
||||||
using var indent = ImRaii.PushIndent();
|
|
||||||
Im.BulletText("... enabled, or"u8, ColorId.EnabledAutoSet.Value());
|
|
||||||
Im.BulletText("... disabled."u8, ColorId.DisabledAutoSet.Value());
|
|
||||||
indent.Pop(1);
|
|
||||||
ImGui.BulletText("You can create new, empty automated design sets, or duplicate existing ones.");
|
|
||||||
ImGui.BulletText("You can name automated design sets arbitrarily.");
|
|
||||||
ImGui.BulletText("You can re-order automated design sets via drag & drop in the selector.");
|
|
||||||
ImGui.BulletText("Each automated design set is assigned to exactly one specific character.");
|
|
||||||
indent.Push();
|
|
||||||
ImGui.BulletText("On creation, it is assigned to your current Player Character.");
|
|
||||||
ImGui.BulletText("You can assign sets to any players, retainers, mannequins and most human NPCs.");
|
|
||||||
ImGui.BulletText("Only one automated design set can be enabled at the same time for each specific character.");
|
|
||||||
indent.Push();
|
|
||||||
ImGui.BulletText("Enabling another automatically disables the prior one.");
|
|
||||||
indent.Pop(2);
|
|
||||||
|
|
||||||
HalfLine();
|
|
||||||
ImGui.TextUnformatted("Automated Designs");
|
|
||||||
ImGui.BulletText(longestLine);
|
|
||||||
ImGui.BulletText(
|
|
||||||
"The order of these automated designs can also be changed via drag & drop, and is relevant for the application.");
|
|
||||||
ImGui.BulletText("Automated designs respect their own, coarse applications rules, and the designs own application rules.");
|
|
||||||
ImGui.BulletText("Automated designs can be configured to be job- or job-group specific and only apply on these jobs, then.");
|
|
||||||
ImGui.BulletText("There is also the special option 'Reset', which can be used to reset remaining slots to the game's values.");
|
|
||||||
ImGui.BulletText(
|
|
||||||
"Automated designs apply from top to bottom, either on top of your characters current state, or its game state.");
|
|
||||||
ImGui.BulletText("For a value to apply, it needs to:");
|
|
||||||
indent.Push();
|
|
||||||
ImGui.BulletText("Be configured to apply in the design itself.");
|
|
||||||
ImGui.BulletText("Be configured to apply in the automation rules.");
|
|
||||||
ImGui.BulletText("Fulfill the conditions of the automation rules.");
|
|
||||||
ImGui.BulletText("Be a valid value for the current (on its own application) state of the character.");
|
|
||||||
ImGui.BulletText("Not have had anything applied to the same value before from a different design.");
|
|
||||||
indent.Pop(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void NewSetButton(Vector2 size)
|
|
||||||
{
|
|
||||||
var id = _objects.Actors.GetCurrentPlayer();
|
|
||||||
if (!id.IsValid)
|
|
||||||
id = _objects.Actors.CreatePlayer(ByteString.FromSpanUnsafe("New Design"u8, true, false, true), ushort.MaxValue);
|
|
||||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), size,
|
|
||||||
$"Create a new Automatic Design Set for {id}. The associated player can be changed later.", !id.IsValid, true))
|
|
||||||
_manager.AddDesignSet("New Automation Set", id);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DuplicateSetButton(Vector2 size)
|
|
||||||
{
|
|
||||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Clone.ToIconString(), size, "Duplicate the current Automatic Design Set.",
|
|
||||||
Selection == null, true))
|
|
||||||
_manager.DuplicateDesignSet(Selection!);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void DeleteSetButton(Vector2 size)
|
|
||||||
{
|
|
||||||
var keyValid = _config.DeleteDesignModifier.IsActive();
|
|
||||||
var (disabled, tt) = HasSelection
|
|
||||||
? keyValid
|
|
||||||
? (false, "Delete the currently selected design set.")
|
|
||||||
: (true, $"Delete the currently selected design set.\nHold {_config.DeleteDesignModifier} to delete.")
|
|
||||||
: (true, "No Automatic Design Set selected.");
|
|
||||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), size, tt, disabled, true))
|
|
||||||
_manager.DeleteDesignSet(SelectionIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawDragDrop(AutoDesignSet set, int index)
|
|
||||||
{
|
|
||||||
const string dragDropLabel = "DesignSetDragDrop";
|
|
||||||
using (var target = ImRaii.DragDropTarget())
|
|
||||||
{
|
|
||||||
if (target.Success)
|
|
||||||
{
|
|
||||||
if (ImGuiUtil.IsDropping(dragDropLabel))
|
|
||||||
{
|
|
||||||
if (_dragIndex >= 0)
|
|
||||||
{
|
|
||||||
var idx = _dragIndex;
|
|
||||||
_endAction = () => _manager.MoveSet(idx, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
_dragIndex = -1;
|
|
||||||
}
|
|
||||||
else if (ImGuiUtil.IsDropping("DesignDragDrop"))
|
|
||||||
{
|
|
||||||
if (DragDesignIndex >= 0)
|
|
||||||
{
|
|
||||||
var idx = DragDesignIndex;
|
|
||||||
var setTo = set;
|
|
||||||
var setFrom = Selection!;
|
|
||||||
_endAction = () => _manager.MoveDesignToSet(setFrom, idx, setTo);
|
|
||||||
}
|
|
||||||
|
|
||||||
DragDesignIndex = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var source = ImRaii.DragDropSource())
|
|
||||||
{
|
|
||||||
if (source)
|
|
||||||
{
|
|
||||||
ImGui.TextUnformatted($"Moving design set {GetSetName(set, index)} from position {index + 1}...");
|
|
||||||
if (ImGui.SetDragDropPayload(dragDropLabel, null, 0))
|
|
||||||
_dragIndex = index;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,8 @@
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
|
||||||
using Glamourer.Designs;
|
using Glamourer.Designs;
|
||||||
using Glamourer.Services;
|
using Glamourer.Services;
|
||||||
using Dalamud.Bindings.ImGui;
|
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using Luna;
|
using Luna;
|
||||||
using OtterGui;
|
|
||||||
using OtterGui.Classes;
|
|
||||||
using OtterGui.Raii;
|
|
||||||
using OtterGui.Text;
|
|
||||||
using TagButtons = OtterGui.Widgets.TagButtons;
|
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.DesignTab;
|
namespace Glamourer.Gui.Tabs.DesignTab;
|
||||||
|
|
||||||
|
|
@ -22,15 +15,8 @@ public class DesignDetailTab
|
||||||
private readonly DesignManager _manager;
|
private readonly DesignManager _manager;
|
||||||
private readonly DesignColors _colors;
|
private readonly DesignColors _colors;
|
||||||
private readonly DesignColorCombo _colorCombo;
|
private readonly DesignColorCombo _colorCombo;
|
||||||
private readonly TagButtons _tagButtons = new();
|
|
||||||
|
|
||||||
private string? _newPath;
|
|
||||||
private string? _newDescription;
|
|
||||||
private string? _newName;
|
|
||||||
|
|
||||||
private bool _editDescriptionMode;
|
private bool _editDescriptionMode;
|
||||||
private Design? _changeDesign;
|
|
||||||
private DesignFileSystem.Leaf? _changeLeaf;
|
|
||||||
|
|
||||||
public DesignDetailTab(SaveService saveService, DesignFileSystemSelector selector, DesignManager manager, DesignFileSystem fileSystem,
|
public DesignDetailTab(SaveService saveService, DesignFileSystemSelector selector, DesignManager manager, DesignFileSystem fileSystem,
|
||||||
DesignColors colors, Configuration config)
|
DesignColors colors, Configuration config)
|
||||||
|
|
@ -58,7 +44,7 @@ public class DesignDetailTab
|
||||||
|
|
||||||
private void DrawDesignInfoTable()
|
private void DrawDesignInfoTable()
|
||||||
{
|
{
|
||||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f));
|
using var style = ImStyleDouble.ButtonTextAlign.Push(new Vector2(0, 0.5f));
|
||||||
using var table = Im.Table.Begin("Details"u8, 2);
|
using var table = Im.Table.Begin("Details"u8, 2);
|
||||||
if (!table)
|
if (!table)
|
||||||
return;
|
return;
|
||||||
|
|
@ -66,31 +52,20 @@ public class DesignDetailTab
|
||||||
table.SetupColumn("Type"u8, TableColumnFlags.WidthFixed, Im.Font.CalculateSize("Reset Temporary Settings"u8).X);
|
table.SetupColumn("Type"u8, TableColumnFlags.WidthFixed, Im.Font.CalculateSize("Reset Temporary Settings"u8).X);
|
||||||
table.SetupColumn("Data"u8, TableColumnFlags.WidthStretch);
|
table.SetupColumn("Data"u8, TableColumnFlags.WidthStretch);
|
||||||
|
|
||||||
ImUtf8.DrawFrameColumn("Design Name"u8);
|
table.DrawFrameColumn("Design Name"u8);
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
var width = new Vector2(Im.ContentRegion.Available.X, 0);
|
var width = Im.ContentRegion.Available with { Y = 0 };
|
||||||
var name = _newName ?? _selector.Selected!.Name;
|
Im.Item.SetNextWidth(width.X);
|
||||||
ImGui.SetNextItemWidth(width.X);
|
if (ImEx.InputOnDeactivation.Text("##Name"u8, _selector.Selected!.Name.Text, out string newName))
|
||||||
if (ImUtf8.InputText("##Name"u8, ref name))
|
_manager.Rename(_selector.Selected!, newName);
|
||||||
{
|
|
||||||
_newName = name;
|
|
||||||
_changeDesign = _selector.Selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui.IsItemDeactivatedAfterEdit() && _changeDesign != null)
|
|
||||||
{
|
|
||||||
_manager.Rename(_changeDesign, name);
|
|
||||||
_newName = null;
|
|
||||||
_changeDesign = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var identifier = _selector.Selected!.Identifier.ToString();
|
var identifier = _selector.Selected!.Identifier.ToString();
|
||||||
ImUtf8.DrawFrameColumn("Unique Identifier"u8);
|
table.DrawFrameColumn("Unique Identifier"u8);
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
var fileName = _saveService.FileNames.DesignFile(_selector.Selected!);
|
var fileName = _saveService.FileNames.DesignFile(_selector.Selected!);
|
||||||
using (Im.Font.PushMono())
|
using (Im.Font.PushMono())
|
||||||
{
|
{
|
||||||
if (ImGui.Button(identifier, width))
|
if (Im.Button(identifier, width))
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Process.Start(new ProcessStartInfo(fileName) { UseShellExecute = true });
|
Process.Start(new ProcessStartInfo(fileName) { UseShellExecute = true });
|
||||||
|
|
@ -102,72 +77,60 @@ public class DesignDetailTab
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Im.Item.RightClicked())
|
if (Im.Item.RightClicked())
|
||||||
ImGui.SetClipboardText(identifier);
|
Im.Clipboard.Set(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImUtf8.HoverTooltip(
|
Im.Tooltip.OnHover(
|
||||||
$"Open the file\n\t{fileName}\ncontaining this design in the .json-editor of your choice.\n\nRight-Click to copy identifier to clipboard.");
|
$"Open the file\n\t{fileName}\ncontaining this design in the .json-editor of your choice.\n\nRight-Click to copy identifier to clipboard.");
|
||||||
|
|
||||||
ImUtf8.DrawFrameColumn("Full Selector Path"u8);
|
table.DrawFrameColumn("Full Selector Path"u8);
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
var path = _newPath ?? _selector.SelectedLeaf!.FullName();
|
Im.Item.SetNextWidth(width.X);
|
||||||
ImGui.SetNextItemWidth(width.X);
|
if (ImEx.InputOnDeactivation.Text("##Path"u8, _selector.SelectedLeaf!.FullName(), out string newPath))
|
||||||
if (ImUtf8.InputText("##Path"u8, ref path))
|
|
||||||
{
|
|
||||||
_newPath = path;
|
|
||||||
_changeLeaf = _selector.SelectedLeaf!;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui.IsItemDeactivatedAfterEdit() && _changeLeaf != null)
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_fileSystem.RenameAndMove(_changeLeaf, path);
|
_fileSystem.RenameAndMove(_selector.SelectedLeaf, newPath);
|
||||||
_newPath = null;
|
|
||||||
_changeLeaf = null;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Glamourer.Messager.NotificationMessage(ex, ex.Message, "Could not rename or move design", NotificationType.Error);
|
Glamourer.Messager.NotificationMessage(ex, ex.Message, "Could not rename or move design", NotificationType.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImUtf8.DrawFrameColumn("Quick Design Bar"u8);
|
table.DrawFrameColumn("Quick Design Bar"u8);
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
if (ImUtf8.RadioButton("Display##qdb"u8, _selector.Selected.QuickDesign))
|
if (Im.RadioButton("Display##qdb"u8, _selector.Selected.QuickDesign))
|
||||||
_manager.SetQuickDesign(_selector.Selected!, true);
|
_manager.SetQuickDesign(_selector.Selected!, true);
|
||||||
var hovered = ImGui.IsItemHovered();
|
var hovered = Im.Item.Hovered();
|
||||||
Im.Line.Same();
|
Im.Line.SameInner();
|
||||||
if (ImUtf8.RadioButton("Hide##qdb"u8, !_selector.Selected.QuickDesign))
|
if (Im.RadioButton("Hide##qdb"u8, !_selector.Selected.QuickDesign))
|
||||||
_manager.SetQuickDesign(_selector.Selected!, false);
|
_manager.SetQuickDesign(_selector.Selected!, false);
|
||||||
if (hovered || ImGui.IsItemHovered())
|
if (hovered || Im.Item.Hovered())
|
||||||
{
|
Im.Tooltip.Set("Display or hide this design in your quick design bar."u8);
|
||||||
using var tt = ImUtf8.Tooltip();
|
|
||||||
ImUtf8.Text("Display or hide this design in your quick design bar."u8);
|
|
||||||
}
|
|
||||||
|
|
||||||
var forceRedraw = _selector.Selected!.ForcedRedraw;
|
var forceRedraw = _selector.Selected!.ForcedRedraw;
|
||||||
ImUtf8.DrawFrameColumn("Force Redrawing"u8);
|
table.DrawFrameColumn("Force Redrawing"u8);
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
if (ImUtf8.Checkbox("##ForceRedraw"u8, ref forceRedraw))
|
if (Im.Checkbox("##ForceRedraw"u8, ref forceRedraw))
|
||||||
_manager.ChangeForcedRedraw(_selector.Selected!, forceRedraw);
|
_manager.ChangeForcedRedraw(_selector.Selected!, forceRedraw);
|
||||||
ImUtf8.HoverTooltip("Set this design to always force a redraw when it is applied through any means."u8);
|
Im.Tooltip.OnHover("Set this design to always force a redraw when it is applied through any means."u8);
|
||||||
|
|
||||||
var resetAdvancedDyes = _selector.Selected!.ResetAdvancedDyes;
|
var resetAdvancedDyes = _selector.Selected!.ResetAdvancedDyes;
|
||||||
ImUtf8.DrawFrameColumn("Reset Advanced Dyes"u8);
|
table.DrawFrameColumn("Reset Advanced Dyes"u8);
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
if (ImUtf8.Checkbox("##ResetAdvancedDyes"u8, ref resetAdvancedDyes))
|
if (Im.Checkbox("##ResetAdvancedDyes"u8, ref resetAdvancedDyes))
|
||||||
_manager.ChangeResetAdvancedDyes(_selector.Selected!, resetAdvancedDyes);
|
_manager.ChangeResetAdvancedDyes(_selector.Selected!, resetAdvancedDyes);
|
||||||
ImUtf8.HoverTooltip("Set this design to reset any previously applied advanced dyes when it is applied through any means."u8);
|
Im.Tooltip.OnHover("Set this design to reset any previously applied advanced dyes when it is applied through any means."u8);
|
||||||
|
|
||||||
var resetTemporarySettings = _selector.Selected!.ResetTemporarySettings;
|
var resetTemporarySettings = _selector.Selected!.ResetTemporarySettings;
|
||||||
ImUtf8.DrawFrameColumn("Reset Temporary Settings"u8);
|
table.DrawFrameColumn("Reset Temporary Settings"u8);
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
if (ImUtf8.Checkbox("##ResetTemporarySettings"u8, ref resetTemporarySettings))
|
if (Im.Checkbox("##ResetTemporarySettings"u8, ref resetTemporarySettings))
|
||||||
_manager.ChangeResetTemporarySettings(_selector.Selected!, resetTemporarySettings);
|
_manager.ChangeResetTemporarySettings(_selector.Selected!, resetTemporarySettings);
|
||||||
ImUtf8.HoverTooltip(
|
Im.Tooltip.OnHover(
|
||||||
"Set this design to reset any temporary settings previously applied to the associated collection when it is applied through any means."u8);
|
"Set this design to reset any temporary settings previously applied to the associated collection when it is applied through any means."u8);
|
||||||
|
|
||||||
ImUtf8.DrawFrameColumn("Color"u8);
|
table.DrawFrameColumn("Color"u8);
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
if (_colorCombo.Draw("##colorCombo"u8, _selector.Selected!.Color.Length is 0 ? DesignColors.AutomaticName : _selector.Selected!.Color,
|
if (_colorCombo.Draw("##colorCombo"u8, _selector.Selected!.Color.Length is 0 ? DesignColors.AutomaticName : _selector.Selected!.Color,
|
||||||
"Associate a color with this design.\n"u8
|
"Associate a color with this design.\n"u8
|
||||||
+ "Right-Click to revert to automatic coloring.\n"u8
|
+ "Right-Click to revert to automatic coloring.\n"u8
|
||||||
|
|
@ -191,28 +154,28 @@ public class DesignDetailTab
|
||||||
Im.Tooltip.OnHover("The color associated with this design does not exist."u8);
|
Im.Tooltip.OnHover("The color associated with this design does not exist."u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImUtf8.DrawFrameColumn("Creation Date"u8);
|
table.DrawFrameColumn("Creation Date"u8);
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
ImGuiUtil.DrawTextButton(_selector.Selected!.CreationDate.LocalDateTime.ToString("F"), width, 0);
|
ImEx.TextFramed($"{_selector.Selected!.CreationDate.LocalDateTime:F}", width, 0);
|
||||||
|
|
||||||
ImUtf8.DrawFrameColumn("Last Update Date"u8);
|
table.DrawFrameColumn("Last Update Date"u8);
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
ImGuiUtil.DrawTextButton(_selector.Selected!.LastEdit.LocalDateTime.ToString("F"), width, 0);
|
ImEx.TextFramed($"{_selector.Selected!.LastEdit.LocalDateTime:F}", width, 0);
|
||||||
|
|
||||||
ImUtf8.DrawFrameColumn("Tags"u8);
|
table.DrawFrameColumn("Tags"u8);
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
DrawTags();
|
DrawTags();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawTags()
|
private void DrawTags()
|
||||||
{
|
{
|
||||||
var idx = _tagButtons.Draw(string.Empty, string.Empty, _selector.Selected!.Tags, out var editedTag);
|
var idx = TagButtons.Draw(StringU8.Empty, StringU8.Empty, _selector.Selected!.Tags, out var editedTag);
|
||||||
if (idx < 0)
|
if (idx < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (idx < _selector.Selected!.Tags.Length)
|
if (idx < _selector.Selected!.Tags.Length)
|
||||||
{
|
{
|
||||||
if (editedTag.Length == 0)
|
if (editedTag.Length is 0)
|
||||||
_manager.RemoveTag(_selector.Selected!, idx);
|
_manager.RemoveTag(_selector.Selected!, idx);
|
||||||
else
|
else
|
||||||
_manager.RenameTag(_selector.Selected!, idx, editedTag);
|
_manager.RenameTag(_selector.Selected!, idx, editedTag);
|
||||||
|
|
@ -226,30 +189,24 @@ public class DesignDetailTab
|
||||||
private void DrawDescription()
|
private void DrawDescription()
|
||||||
{
|
{
|
||||||
var desc = _selector.Selected!.Description;
|
var desc = _selector.Selected!.Description;
|
||||||
var size = new Vector2(Im.ContentRegion.Available.X, 12 * Im.Style.TextHeightWithSpacing);
|
var size = Im.ContentRegion.Available with { Y = 12 * Im.Style.TextHeightWithSpacing };
|
||||||
if (!_editDescriptionMode)
|
if (!_editDescriptionMode)
|
||||||
{
|
{
|
||||||
using (var textBox = ImUtf8.ListBox("##desc"u8, size))
|
using (var textBox = Im.ListBox.Begin("##desc"u8, size))
|
||||||
{
|
{
|
||||||
ImUtf8.TextWrapped(desc);
|
if (textBox)
|
||||||
|
Im.TextWrapped(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImUtf8.Button("Edit Description"u8))
|
if (Im.Button("Edit Description"u8))
|
||||||
_editDescriptionMode = true;
|
_editDescriptionMode = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var edit = _newDescription ?? desc;
|
if (ImEx.InputOnDeactivation.MultiLine("##desc"u8, desc, out string newDescription, size))
|
||||||
if (ImUtf8.InputMultiLine("##desc"u8, ref edit, size))
|
_manager.ChangeDescription(_selector.Selected!, newDescription);
|
||||||
_newDescription = edit;
|
|
||||||
|
|
||||||
if (ImGui.IsItemDeactivatedAfterEdit())
|
if (Im.Button("Stop Editing"u8))
|
||||||
{
|
|
||||||
_manager.ChangeDescription(_selector.Selected!, edit);
|
|
||||||
_newDescription = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImUtf8.Button("Stop Editing"u8))
|
|
||||||
_editDescriptionMode = false;
|
_editDescriptionMode = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,9 @@
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
|
||||||
using Dalamud.Interface.Utility;
|
|
||||||
using Dalamud.Utility;
|
|
||||||
using Glamourer.Designs;
|
using Glamourer.Designs;
|
||||||
using Glamourer.Interop.Penumbra;
|
using Glamourer.Interop.Penumbra;
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
using Dalamud.Bindings.ImGui;
|
|
||||||
using ImSharp;
|
using ImSharp;
|
||||||
using Luna;
|
using Luna;
|
||||||
using OtterGui;
|
|
||||||
using OtterGui.Classes;
|
|
||||||
using OtterGui.Extensions;
|
|
||||||
using OtterGui.Raii;
|
|
||||||
using OtterGui.Text;
|
|
||||||
using OtterGui.Text.Widget;
|
|
||||||
|
|
||||||
namespace Glamourer.Gui.Tabs.DesignTab;
|
namespace Glamourer.Gui.Tabs.DesignTab;
|
||||||
|
|
||||||
|
|
@ -28,11 +18,11 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
|
||||||
if (!h.Alive)
|
if (!h.Alive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ImGuiUtil.HoverTooltip(
|
Im.Tooltip.OnHover(
|
||||||
"This tab can store information about specific mods associated with this design.\n\n"
|
"This tab can store information about specific mods associated with this design.\n\n"u8
|
||||||
+ "It does NOT change any mod settings automatically, though there is functionality to apply desired mod settings manually.\n"
|
+ "It does NOT change any mod settings automatically, though there is functionality to apply desired mod settings manually.\n"u8
|
||||||
+ "You can also use it to quickly open the associated mod page in Penumbra.\n\n"
|
+ "You can also use it to quickly open the associated mod page in Penumbra.\n\n"u8
|
||||||
+ "It is not feasible to apply those changes automatically in general cases, since there would be no way to revert those changes, handle multiple designs applying at once, etc.");
|
+ "It is not feasible to apply those changes automatically in general cases, since there would be no way to revert those changes, handle multiple designs applying at once, etc."u8);
|
||||||
if (!h)
|
if (!h)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -44,24 +34,24 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
|
||||||
private void DrawCopyButtons()
|
private void DrawCopyButtons()
|
||||||
{
|
{
|
||||||
var size = new Vector2((Im.ContentRegion.Available.X - 2 * Im.Style.ItemSpacing.X) / 3, 0);
|
var size = new Vector2((Im.ContentRegion.Available.X - 2 * Im.Style.ItemSpacing.X) / 3, 0);
|
||||||
if (ImGui.Button("Copy All to Clipboard", size))
|
if (Im.Button("Copy All to Clipboard"u8, size))
|
||||||
_copy = selector.Selected!.AssociatedMods.Select(kvp => (kvp.Key, kvp.Value)).ToArray();
|
_copy = selector.Selected!.AssociatedMods.Select(kvp => (kvp.Key, kvp.Value)).ToArray();
|
||||||
|
|
||||||
Im.Line.Same();
|
Im.Line.Same();
|
||||||
|
|
||||||
if (ImGuiUtil.DrawDisabledButton("Add from Clipboard", size,
|
if (ImEx.Button("Add from Clipboard"u8, size,
|
||||||
_copy != null
|
_copy is not null
|
||||||
? $"Add {_copy.Length} mod association(s) from clipboard."
|
? $"Add {_copy.Length} mod association(s) from clipboard."
|
||||||
: "Copy some mod associations to the clipboard, first.", _copy == null))
|
: "Copy some mod associations to the clipboard, first."u8, _copy is null))
|
||||||
foreach (var (mod, setting) in _copy!)
|
foreach (var (mod, setting) in _copy!)
|
||||||
manager.UpdateMod(selector.Selected!, mod, setting);
|
manager.UpdateMod(selector.Selected!, mod, setting);
|
||||||
|
|
||||||
Im.Line.Same();
|
Im.Line.Same();
|
||||||
|
|
||||||
if (ImGuiUtil.DrawDisabledButton("Set from Clipboard", size,
|
if (ImEx.Button("Set from Clipboard"u8, size,
|
||||||
_copy != null
|
_copy is not null
|
||||||
? $"Set {_copy.Length} mod association(s) from clipboard and discard existing."
|
? $"Set {_copy.Length} mod association(s) from clipboard and discard existing."
|
||||||
: "Copy some mod associations to the clipboard, first.", _copy == null))
|
: "Copy some mod associations to the clipboard, first."u8, _copy is null))
|
||||||
{
|
{
|
||||||
while (selector.Selected!.AssociatedMods.Count > 0)
|
while (selector.Selected!.AssociatedMods.Count > 0)
|
||||||
manager.RemoveMod(selector.Selected!, selector.Selected!.AssociatedMods.Keys[0]);
|
manager.RemoveMod(selector.Selected!, selector.Selected!.AssociatedMods.Keys[0]);
|
||||||
|
|
@ -75,17 +65,17 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
|
||||||
var (id, name) = penumbra.CurrentCollection;
|
var (id, name) = penumbra.CurrentCollection;
|
||||||
if (config.Ephemeral.IncognitoMode)
|
if (config.Ephemeral.IncognitoMode)
|
||||||
name = id.ShortGuid();
|
name = id.ShortGuid();
|
||||||
if (ImGuiUtil.DrawDisabledButton($"Try Applying All Associated Mods to {name}##applyAll",
|
if (ImEx.Button($"Try Applying All Associated Mods to {name}##applyAll",
|
||||||
new Vector2(Im.ContentRegion.Available.X, 0), string.Empty, id == Guid.Empty))
|
Im.ContentRegion.Available with { Y = 0 }, string.Empty, id == Guid.Empty))
|
||||||
ApplyAll();
|
ApplyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawApplyButton()
|
public void DrawApplyButton()
|
||||||
{
|
{
|
||||||
var (id, name) = penumbra.CurrentCollection;
|
var (id, name) = penumbra.CurrentCollection;
|
||||||
if (ImGuiUtil.DrawDisabledButton("Apply Mod Associations", Vector2.Zero,
|
if (ImEx.Button("Apply Mod Associations"u8, Vector2.Zero,
|
||||||
$"Try to apply all associated mod settings to Penumbras current collection {name}",
|
$"Try to apply all associated mod settings to Penumbras current collection {name}",
|
||||||
selector.Selected!.AssociatedMods.Count == 0 || id == Guid.Empty))
|
selector.Selected!.AssociatedMods.Count is 0 || id == Guid.Empty))
|
||||||
ApplyAll();
|
ApplyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,26 +94,26 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
|
||||||
table.SetupColumn("##Buttons"u8, TableColumnFlags.WidthFixed, Im.Style.FrameHeight * 3 + Im.Style.ItemInnerSpacing.X * 2);
|
table.SetupColumn("##Buttons"u8, TableColumnFlags.WidthFixed, Im.Style.FrameHeight * 3 + Im.Style.ItemInnerSpacing.X * 2);
|
||||||
table.SetupColumn("Mod Name"u8, TableColumnFlags.WidthStretch);
|
table.SetupColumn("Mod Name"u8, TableColumnFlags.WidthStretch);
|
||||||
if (config.UseTemporarySettings)
|
if (config.UseTemporarySettings)
|
||||||
table.SetupColumn("Remove"u8, TableColumnFlags.WidthFixed, ImUtf8.CalcTextSize("Remove"u8).X);
|
table.SetupColumn("Remove"u8, TableColumnFlags.WidthFixed, Im.Font.CalculateSize("Remove"u8).X);
|
||||||
table.SetupColumn("Inherit"u8, TableColumnFlags.WidthFixed, ImUtf8.CalcTextSize("Inherit"u8).X);
|
table.SetupColumn("Inherit"u8, TableColumnFlags.WidthFixed, Im.Font.CalculateSize("Inherit"u8).X);
|
||||||
table.SetupColumn("State"u8, TableColumnFlags.WidthFixed, ImUtf8.CalcTextSize("State"u8).X);
|
table.SetupColumn("State"u8, TableColumnFlags.WidthFixed, Im.Font.CalculateSize("State"u8).X);
|
||||||
table.SetupColumn("Priority"u8, TableColumnFlags.WidthFixed, ImUtf8.CalcTextSize("Priority"u8).X);
|
table.SetupColumn("Priority"u8, TableColumnFlags.WidthFixed, Im.Font.CalculateSize("Priority"u8).X);
|
||||||
table.SetupColumn("##Options"u8, TableColumnFlags.WidthFixed, ImUtf8.CalcTextSize("Applym"u8).X);
|
table.SetupColumn("##Options"u8, TableColumnFlags.WidthFixed, Im.Font.CalculateSize("Applym"u8).X);
|
||||||
table.HeaderRow();
|
table.HeaderRow();
|
||||||
|
|
||||||
Mod? removedMod = null;
|
Mod? removedMod = null;
|
||||||
(Mod mod, ModSettings settings)? updatedMod = null;
|
(Mod mod, ModSettings settings)? updatedMod = null;
|
||||||
foreach (var ((mod, settings), idx) in selector.Selected!.AssociatedMods.WithIndex())
|
foreach (var (idx, (mod, settings)) in selector.Selected!.AssociatedMods.Index())
|
||||||
{
|
{
|
||||||
using var id = Im.Id.Push(idx);
|
using var id = Im.Id.Push(idx);
|
||||||
DrawAssociatedModRow(mod, settings, out var removedModTmp, out var updatedModTmp);
|
DrawAssociatedModRow(table, mod, settings, out var removedModTmp, out var updatedModTmp);
|
||||||
if (removedModTmp.HasValue)
|
if (removedModTmp.HasValue)
|
||||||
removedMod = removedModTmp;
|
removedMod = removedModTmp;
|
||||||
if (updatedModTmp.HasValue)
|
if (updatedModTmp.HasValue)
|
||||||
updatedMod = updatedModTmp;
|
updatedMod = updatedModTmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawNewModRow();
|
DrawNewModRow(table);
|
||||||
|
|
||||||
if (removedMod.HasValue)
|
if (removedMod.HasValue)
|
||||||
manager.RemoveMod(selector.Selected!, removedMod.Value);
|
manager.RemoveMod(selector.Selected!, removedMod.Value);
|
||||||
|
|
@ -132,99 +122,92 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
|
||||||
manager.UpdateMod(selector.Selected!, updatedMod.Value.mod, updatedMod.Value.settings);
|
manager.UpdateMod(selector.Selected!, updatedMod.Value.mod, updatedMod.Value.settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawAssociatedModRow(Mod mod, ModSettings settings, out Mod? removedMod, out (Mod, ModSettings)? updatedMod)
|
private void DrawAssociatedModRow(in Im.TableDisposable table, Mod mod, ModSettings settings, out Mod? removedMod,
|
||||||
|
out (Mod, ModSettings)? updatedMod)
|
||||||
{
|
{
|
||||||
removedMod = null;
|
removedMod = null;
|
||||||
updatedMod = null;
|
updatedMod = null;
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
var canDelete = config.DeleteDesignModifier.IsActive();
|
var canDelete = config.DeleteDesignModifier.IsActive();
|
||||||
if (canDelete)
|
if (ImEx.Icon.Button(LunaStyle.DeleteIcon, "Delete this mod from associations."u8))
|
||||||
{
|
|
||||||
if (ImUtf8.IconButton(FontAwesomeIcon.Trash, "Delete this mod from associations."u8))
|
|
||||||
removedMod = mod;
|
removedMod = mod;
|
||||||
}
|
if (!canDelete)
|
||||||
else
|
Im.Tooltip.OnHover($"\nHold {config.DeleteDesignModifier} to delete.");
|
||||||
{
|
|
||||||
ImUtf8.IconButton(FontAwesomeIcon.Trash, $"Delete this mod from associations.\nHold {config.DeleteDesignModifier} to delete.",
|
|
||||||
disabled: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Im.Line.SameInner();
|
Im.Line.SameInner();
|
||||||
if (ImUtf8.IconButton(FontAwesomeIcon.Clipboard, "Copy this mod setting to clipboard."u8))
|
if (ImEx.Icon.Button(LunaStyle.ToClipboardIcon, "Copy this mod setting to clipboard."u8))
|
||||||
_copy = [(mod, settings)];
|
_copy = [(mod, settings)];
|
||||||
|
|
||||||
Im.Line.SameInner();
|
Im.Line.SameInner();
|
||||||
ImUtf8.IconButton(FontAwesomeIcon.RedoAlt, "Update the settings of this mod association."u8);
|
ImEx.Icon.Button(LunaStyle.RefreshIcon, "Update the settings of this mod association."u8);
|
||||||
if (ImGui.IsItemHovered())
|
if (Im.Item.Hovered())
|
||||||
{
|
{
|
||||||
var newSettings = penumbra.GetModSettings(mod, out var source);
|
var newSettings = penumbra.GetModSettings(mod, out var source);
|
||||||
if (ImGui.IsItemClicked())
|
if (Im.Item.Clicked())
|
||||||
updatedMod = (mod, newSettings);
|
updatedMod = (mod, newSettings);
|
||||||
|
|
||||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.PopupBorderSize, 2 * Im.Style.GlobalScale);
|
using var style = ImStyleSingle.PopupBorderThickness.Push(2 * Im.Style.GlobalScale);
|
||||||
using var tt = ImUtf8.Tooltip();
|
using var tt = Im.Tooltip.Begin();
|
||||||
if (source.Length > 0)
|
if (source.Length > 0)
|
||||||
ImUtf8.Text($"Using temporary settings made by {source}.");
|
Im.Text($"Using temporary settings made by {source}.");
|
||||||
Im.Separator();
|
Im.Separator();
|
||||||
var namesDifferent = mod.Name != mod.DirectoryName;
|
var namesDifferent = mod.Name != mod.DirectoryName;
|
||||||
Im.Dummy(new Vector2(300 * Im.Style.GlobalScale, 0));
|
Im.Dummy(300 * Im.Style.GlobalScale);
|
||||||
using (ImRaii.Group())
|
using (Im.Group())
|
||||||
{
|
{
|
||||||
if (namesDifferent)
|
if (namesDifferent)
|
||||||
ImUtf8.Text("Directory Name"u8);
|
Im.Text("Directory Name"u8);
|
||||||
ImUtf8.Text("Force Inherit"u8);
|
Im.Text("Force Inherit"u8);
|
||||||
ImUtf8.Text("Enabled"u8);
|
Im.Text("Enabled"u8);
|
||||||
ImUtf8.Text("Priority"u8);
|
Im.Text("Priority"u8);
|
||||||
ModCombo.DrawSettingsLeft(newSettings);
|
ModCombo.DrawSettingsLeft(newSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SameLine(Math.Max(ImGui.GetItemRectSize().X + 3 * Im.Style.ItemSpacing.X, 150 * Im.Style.GlobalScale));
|
Im.Line.Same(Math.Max(Im.Item.Size.X + 3 * Im.Style.ItemSpacing.X, 150 * Im.Style.GlobalScale));
|
||||||
using (ImRaii.Group())
|
using (Im.Group())
|
||||||
{
|
{
|
||||||
if (namesDifferent)
|
if (namesDifferent)
|
||||||
ImUtf8.Text(mod.DirectoryName);
|
Im.Text(mod.DirectoryName);
|
||||||
|
|
||||||
ImUtf8.Text(newSettings.ForceInherit.ToString());
|
Im.Text($"{newSettings.ForceInherit}");
|
||||||
ImUtf8.Text(newSettings.Enabled.ToString());
|
Im.Text($"{newSettings.Enabled}");
|
||||||
ImUtf8.Text(newSettings.Priority.ToString());
|
Im.Text($"{newSettings.Priority}");
|
||||||
ModCombo.DrawSettingsRight(newSettings);
|
ModCombo.DrawSettingsRight(newSettings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
|
|
||||||
if (ImUtf8.Selectable($"{mod.Name}##name"))
|
if (Im.Selectable($"{mod.Name}##name"))
|
||||||
penumbra.OpenModPage(mod);
|
penumbra.OpenModPage(mod);
|
||||||
if (ImGui.IsItemHovered())
|
Im.Tooltip.OnHover($"Mod Directory: {mod.DirectoryName}\n\nClick to open mod page in Penumbra.");
|
||||||
ImGui.SetTooltip($"Mod Directory: {mod.DirectoryName}\n\nClick to open mod page in Penumbra.");
|
|
||||||
if (config.UseTemporarySettings)
|
if (config.UseTemporarySettings)
|
||||||
{
|
{
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
var remove = settings.Remove;
|
var remove = settings.Remove;
|
||||||
if (TwoStateCheckbox.Instance.Draw("##Remove"u8, ref remove))
|
if (ImEx.TwoStateCheckbox("##Remove"u8, ref remove))
|
||||||
updatedMod = (mod, settings with { Remove = remove });
|
updatedMod = (mod, settings with { Remove = remove });
|
||||||
ImUtf8.HoverTooltip(
|
Im.Tooltip.OnHover(
|
||||||
"Remove any temporary settings applied by Glamourer instead of applying the configured settings. Only works when using temporary settings, ignored otherwise."u8);
|
"Remove any temporary settings applied by Glamourer instead of applying the configured settings. Only works when using temporary settings, ignored otherwise."u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
var inherit = settings.ForceInherit;
|
var inherit = settings.ForceInherit;
|
||||||
if (TwoStateCheckbox.Instance.Draw("##ForceInherit"u8, ref inherit))
|
if (ImEx.TwoStateCheckbox("##ForceInherit"u8, ref inherit))
|
||||||
updatedMod = (mod, settings with { ForceInherit = inherit });
|
updatedMod = (mod, settings with { ForceInherit = inherit });
|
||||||
ImUtf8.HoverTooltip("Force the mod to inherit its settings from inherited collections."u8);
|
Im.Tooltip.OnHover("Force the mod to inherit its settings from inherited collections."u8);
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
var enabled = settings.Enabled;
|
var enabled = settings.Enabled;
|
||||||
if (TwoStateCheckbox.Instance.Draw("##Enabled"u8, ref enabled))
|
if (ImEx.TwoStateCheckbox("##Enabled"u8, ref enabled))
|
||||||
updatedMod = (mod, settings with { Enabled = enabled });
|
updatedMod = (mod, settings with { Enabled = enabled });
|
||||||
|
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
var priority = settings.Priority;
|
var priority = settings.Priority;
|
||||||
ImGui.SetNextItemWidth(Im.ContentRegion.Available.X);
|
Im.Item.SetNextWidthFull();
|
||||||
if (ImUtf8.InputScalarOnDeactivated("##Priority"u8, ref priority))
|
if (ImEx.InputOnDeactivation.Scalar("##Priority"u8, ref priority))
|
||||||
updatedMod = (mod, settings with { Priority = priority });
|
updatedMod = (mod, settings with { Priority = priority });
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
if (ImGuiUtil.DrawDisabledButton("Apply", new Vector2(Im.ContentRegion.Available.X, 0), string.Empty,
|
if (ImEx.Button("Apply"u8, Im.ContentRegion.Available with { Y = 0 }, StringU8.Empty, !penumbra.Available))
|
||||||
!penumbra.Available))
|
|
||||||
{
|
{
|
||||||
var text = penumbra.SetMod(mod, settings, StateSource.Manual, false);
|
var text = penumbra.SetMod(mod, settings, StateSource.Manual, false);
|
||||||
if (text.Length > 0)
|
if (text.Length > 0)
|
||||||
|
|
@ -236,40 +219,39 @@ public class ModAssociationsTab(PenumbraService penumbra, DesignFileSystemSelect
|
||||||
|
|
||||||
private static void DrawAssociatedModTooltip(ModSettings settings)
|
private static void DrawAssociatedModTooltip(ModSettings settings)
|
||||||
{
|
{
|
||||||
if (settings is not { Enabled: true, Settings.Count: > 0 } || !ImGui.IsItemHovered())
|
if (settings is not { Enabled: true, Settings.Count: > 0 } || !Im.Item.Hovered())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using var t = ImRaii.Tooltip();
|
using var t = Im.Tooltip.Begin();
|
||||||
ImGui.TextUnformatted("This will also try to apply the following settings to the current collection:");
|
Im.Text("This will also try to apply the following settings to the current collection:"u8);
|
||||||
|
|
||||||
Im.Line.New();
|
Im.Line.New();
|
||||||
using (var _ = ImRaii.Group())
|
using (Im.Group())
|
||||||
{
|
{
|
||||||
ModCombo.DrawSettingsLeft(settings);
|
ModCombo.DrawSettingsLeft(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SameLine(Im.ContentRegion.Available.X / 2);
|
Im.Line.Same(Im.ContentRegion.Available.X / 2);
|
||||||
using (var _ = ImRaii.Group())
|
using (Im.Group())
|
||||||
{
|
{
|
||||||
ModCombo.DrawSettingsRight(settings);
|
ModCombo.DrawSettingsRight(settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawNewModRow()
|
private void DrawNewModRow(in Im.TableDisposable table)
|
||||||
{
|
{
|
||||||
var currentName = _modCombo.CurrentSelection.Mod.Name;
|
var currentName = _modCombo.CurrentSelection.Mod.Name;
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
var tt = currentName.IsNullOrEmpty()
|
var tt = string.IsNullOrEmpty(currentName)
|
||||||
? "Please select a mod first."
|
? "Please select a mod first."u8
|
||||||
: selector.Selected!.AssociatedMods.ContainsKey(_modCombo.CurrentSelection.Mod)
|
: selector.Selected!.AssociatedMods.ContainsKey(_modCombo.CurrentSelection.Mod)
|
||||||
? "The design already contains an association with the selected mod."
|
? "The design already contains an association with the selected mod."u8
|
||||||
: string.Empty;
|
: StringU8.Empty;
|
||||||
|
|
||||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), new Vector2(Im.Style.FrameHeight), tt, tt.Length > 0,
|
if (ImEx.Icon.Button(LunaStyle.AddObjectIcon, tt, tt.Length > 0))
|
||||||
true))
|
|
||||||
manager.AddMod(selector.Selected!, _modCombo.CurrentSelection.Mod, _modCombo.CurrentSelection.Settings);
|
manager.AddMod(selector.Selected!, _modCombo.CurrentSelection.Mod, _modCombo.CurrentSelection.Settings);
|
||||||
ImGui.TableNextColumn();
|
table.NextColumn();
|
||||||
_modCombo.Draw("##new", currentName.IsNullOrEmpty() ? "Select new Mod..." : currentName, string.Empty,
|
_modCombo.Draw("##new", string.IsNullOrEmpty(currentName) ? "Select new Mod..." : currentName, string.Empty,
|
||||||
Im.ContentRegion.Available.X, Im.Style.TextHeight);
|
Im.ContentRegion.Available.X, Im.Style.TextHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
Luna
2
Luna
|
|
@ -1 +1 @@
|
||||||
Subproject commit 042b829099c34608782c2a70da3cf189ac5f53be
|
Subproject commit e80bdf5c10c6c30efccdff7d1adcb4a638eba4df
|
||||||
Loading…
Add table
Add a link
Reference in a new issue