mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
Add UI.
This commit is contained in:
parent
2219d9293f
commit
282d6df165
7 changed files with 190 additions and 75 deletions
|
|
@ -18,6 +18,16 @@ public enum ApplicationType : byte
|
|||
|
||||
public static class ApplicationTypeExtensions
|
||||
{
|
||||
public static readonly IReadOnlyList<(ApplicationType, string)> Types = new[]
|
||||
{
|
||||
(ApplicationType.Customizations,
|
||||
"Apply all customization changes that are enabled in this design and that are valid in a fixed design and for the given race and gender."),
|
||||
(ApplicationType.Armor, "Apply all armor piece changes that are enabled in this design and that are valid in a fixed design."),
|
||||
(ApplicationType.Accessories, "Apply all accessory changes that are enabled in this design and that are valid in a fixed design."),
|
||||
(ApplicationType.GearCustomization, "Apply all dye and crest changes that are enabled in this design."),
|
||||
(ApplicationType.Weapons, "Apply all weapon changes that are enabled in this design and that are valid with the current weapon worn."),
|
||||
};
|
||||
|
||||
public static (EquipFlag Equip, CustomizeFlag Customize, CrestFlag Crest, CustomizeParameterFlag Parameters, MetaFlag Meta) ApplyWhat(
|
||||
this ApplicationType type, DesignBase? design)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,4 +15,5 @@ public enum LinkOrder : byte
|
|||
Self,
|
||||
After,
|
||||
Before,
|
||||
None,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -56,6 +56,17 @@ public sealed class DesignLinkManager : IService, IDisposable
|
|||
_event.Invoke(DesignChanged.Type.ChangedLink, parent, null);
|
||||
}
|
||||
|
||||
public void ChangeApplicationType(Design parent, int idx, LinkOrder order, ApplicationType applicationType)
|
||||
{
|
||||
applicationType &= ApplicationType.All;
|
||||
if (!parent.Links.ChangeApplicationRules(idx, order, applicationType, out var old))
|
||||
return;
|
||||
|
||||
_saveService.QueueSave(parent);
|
||||
Glamourer.Log.Debug($"Changed link application type from {old} to {applicationType} for design link {order} {idx + 1} in design {parent.Identifier}.");
|
||||
_event.Invoke(DesignChanged.Type.ChangedLink, parent, null);
|
||||
}
|
||||
|
||||
private void OnDesignChanged(DesignChanged.Type type, Design deletedDesign, object? _)
|
||||
{
|
||||
if (type is not DesignChanged.Type.Deleted)
|
||||
|
|
@ -63,12 +74,12 @@ public sealed class DesignLinkManager : IService, IDisposable
|
|||
|
||||
foreach (var design in _storage)
|
||||
{
|
||||
if (design.Links.Remove(deletedDesign))
|
||||
{
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
Glamourer.Log.Debug($"Removed {deletedDesign.Identifier} from {design.Identifier} links due to deletion.");
|
||||
_saveService.QueueSave(design);
|
||||
}
|
||||
if (!design.Links.Remove(deletedDesign))
|
||||
continue;
|
||||
|
||||
design.LastEdit = DateTimeOffset.UtcNow;
|
||||
Glamourer.Log.Debug($"Removed {deletedDesign.Identifier} from {design.Identifier} links due to deletion.");
|
||||
_saveService.QueueSave(design);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,29 +57,45 @@ public sealed class LinkContainer : List<DesignLink>
|
|||
return true;
|
||||
}
|
||||
|
||||
public bool ChangeApplicationRules(int idx, LinkOrder order, ApplicationType type, out ApplicationType old)
|
||||
{
|
||||
var list = order switch
|
||||
{
|
||||
LinkOrder.Before => Before,
|
||||
LinkOrder.After => After,
|
||||
_ => throw new ArgumentException("Invalid link order."),
|
||||
};
|
||||
old = list[idx].Type;
|
||||
if (idx < 0 || idx >= list.Count || old == type)
|
||||
return false;
|
||||
|
||||
list[idx] = list[idx] with { Type = type };
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool CanAddLink(Design parent, Design child, LinkOrder order, out string error)
|
||||
{
|
||||
if (parent == child)
|
||||
{
|
||||
error = $"Can not link {parent.Identifier} with itself.";
|
||||
error = $"Can not link {parent.Incognito} with itself.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parent.Links.Contains(child))
|
||||
{
|
||||
error = $"Design {parent.Identifier} already contains a direct link to {child.Identifier}.";
|
||||
error = $"Design {parent.Incognito} already contains a direct link to {child.Incognito}.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetAllLinks(parent).Any(l => l.Link.Link == child && l.Order != order))
|
||||
{
|
||||
error = $"Adding {child.Identifier} to {parent.Identifier}s links would create a circle, the parent already links to the child in the opposite direction.";
|
||||
error = $"Adding {child.Incognito} to {parent.Incognito}s links would create a circle, the parent already links to the child in the opposite direction.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetAllLinks(child).Any(l => l.Link.Link == parent && l.Order == order))
|
||||
{
|
||||
error = $"Adding {child.Identifier} to {parent.Identifier}s links would create a circle, the child already links to the parent in the opposite direction.";
|
||||
error = $"Adding {child.Incognito} to {parent.Incognito}s links would create a circle, the child already links to the parent in the opposite direction.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -161,7 +177,7 @@ public sealed class LinkContainer : List<DesignLink>
|
|||
var after = new JArray();
|
||||
foreach (var link in After)
|
||||
{
|
||||
before.Add(new JObject
|
||||
after.Add(new JObject
|
||||
{
|
||||
["Design"] = link.Link.Identifier,
|
||||
["Type"] = (uint)link.Type,
|
||||
|
|
|
|||
|
|
@ -384,7 +384,7 @@ public class SetPanel(
|
|||
{
|
||||
void Box(int idx)
|
||||
{
|
||||
var (type, description) = Types[idx];
|
||||
var (type, description) = ApplicationTypeExtensions.Types[idx];
|
||||
var value = design.Type.HasFlag(type);
|
||||
if (ImGui.Checkbox($"##{(byte)type}", ref value))
|
||||
newType = value ? newType | type : newType & ~type;
|
||||
|
|
@ -428,40 +428,20 @@ public class SetPanel(
|
|||
_manager.ChangeIdentifier(setIndex, _identifierDrawer.MannequinIdentifier);
|
||||
}
|
||||
|
||||
|
||||
private static readonly IReadOnlyList<(ApplicationType, string)> Types = new[]
|
||||
private sealed class JobGroupCombo(AutoDesignManager manager, JobService jobs, Logger log)
|
||||
: FilterComboCache<JobGroup>(() => jobs.JobGroups.Values.ToList(), log)
|
||||
{
|
||||
(ApplicationType.Customizations,
|
||||
"Apply all customization changes that are enabled in this design and that are valid in a fixed design and for the given race and gender."),
|
||||
(ApplicationType.Armor, "Apply all armor piece changes that are enabled in this design and that are valid in a fixed design."),
|
||||
(ApplicationType.Accessories, "Apply all accessory changes that are enabled in this design and that are valid in a fixed design."),
|
||||
(ApplicationType.GearCustomization, "Apply all dye and crest changes that are enabled in this design."),
|
||||
(ApplicationType.Weapons, "Apply all weapon changes that are enabled in this design and that are valid with the current weapon worn."),
|
||||
};
|
||||
|
||||
private sealed class JobGroupCombo : FilterComboCache<JobGroup>
|
||||
{
|
||||
private readonly AutoDesignManager _manager;
|
||||
private readonly JobService _jobs;
|
||||
|
||||
public JobGroupCombo(AutoDesignManager manager, JobService jobs, Logger log)
|
||||
: base(() => jobs.JobGroups.Values.ToList(), log)
|
||||
{
|
||||
_manager = manager;
|
||||
_jobs = jobs;
|
||||
}
|
||||
|
||||
public void Draw(AutoDesignSet set, AutoDesign design, int autoDesignIndex)
|
||||
{
|
||||
CurrentSelection = design.Jobs;
|
||||
CurrentSelectionIdx = _jobs.JobGroups.Values.IndexOf(j => j.Id == design.Jobs.Id);
|
||||
CurrentSelectionIdx = jobs.JobGroups.Values.IndexOf(j => j.Id == design.Jobs.Id);
|
||||
if (Draw("##JobGroups", design.Jobs.Name,
|
||||
"Select for which job groups this design should be applied.\nControl + Right-Click to set to all classes.",
|
||||
ImGui.GetContentRegionAvail().X, ImGui.GetTextLineHeightWithSpacing())
|
||||
&& CurrentSelectionIdx >= 0)
|
||||
_manager.ChangeJobCondition(set, autoDesignIndex, CurrentSelection);
|
||||
manager.ChangeJobCondition(set, autoDesignIndex, CurrentSelection);
|
||||
else if (ImGui.GetIO().KeyCtrl && ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||
_manager.ChangeJobCondition(set, autoDesignIndex, _jobs.JobGroups[1]);
|
||||
manager.ChangeJobCondition(set, autoDesignIndex, jobs.JobGroups[1]);
|
||||
}
|
||||
|
||||
protected override string ToString(JobGroup obj)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Glamourer.Automation;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Designs.Links;
|
||||
using ImGuiNET;
|
||||
|
|
@ -11,9 +13,9 @@ namespace Glamourer.Gui.Tabs.DesignTab;
|
|||
public class DesignLinkDrawer(DesignLinkManager _linkManager, DesignFileSystemSelector _selector, DesignCombo _combo) : IUiService
|
||||
{
|
||||
private int _dragDropIndex = -1;
|
||||
private LinkOrder _dragDropOrder = LinkOrder.Self;
|
||||
private LinkOrder _dragDropOrder = LinkOrder.None;
|
||||
private int _dragDropTargetIndex = -1;
|
||||
private LinkOrder _dragDropTargetOrder = LinkOrder.Self;
|
||||
private LinkOrder _dragDropTargetOrder = LinkOrder.None;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
|
|
@ -21,30 +23,76 @@ public class DesignLinkDrawer(DesignLinkManager _linkManager, DesignFileSystemSe
|
|||
if (!header)
|
||||
return;
|
||||
|
||||
var width = ImGui.GetContentRegionAvail().X / 2;
|
||||
DrawList(_selector.Selected!.Links.Before, LinkOrder.Before, width);
|
||||
ImGui.SameLine();
|
||||
DrawList(_selector.Selected!.Links.After, LinkOrder.After, width);
|
||||
|
||||
if (_dragDropTargetIndex < 0
|
||||
|| _dragDropIndex < 0)
|
||||
return;
|
||||
|
||||
_linkManager.MoveDesignLink(_selector.Selected!, _dragDropIndex, _dragDropOrder, _dragDropTargetIndex, _dragDropTargetOrder);
|
||||
_dragDropIndex = -1;
|
||||
_dragDropTargetIndex = -1;
|
||||
_dragDropOrder = LinkOrder.Self;
|
||||
_dragDropTargetOrder = LinkOrder.Self;
|
||||
DrawList();
|
||||
}
|
||||
|
||||
private void DrawList(IReadOnlyList<DesignLink> list, LinkOrder order, float width)
|
||||
private void MoveLink()
|
||||
{
|
||||
using var id = ImRaii.PushId((int)order);
|
||||
using var table = ImRaii.Table("table", 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersOuter,
|
||||
new Vector2(width, list.Count * ImGui.GetFrameHeightWithSpacing()));
|
||||
if (_dragDropTargetIndex < 0 || _dragDropIndex < 0)
|
||||
return;
|
||||
|
||||
if (_dragDropOrder is LinkOrder.Self)
|
||||
switch (_dragDropTargetOrder)
|
||||
{
|
||||
case LinkOrder.Before:
|
||||
for (var i = _selector.Selected!.Links.Before.Count - 1; i >= _dragDropTargetIndex; --i)
|
||||
_linkManager.MoveDesignLink(_selector.Selected!, i, LinkOrder.Before, 0, LinkOrder.After);
|
||||
break;
|
||||
case LinkOrder.After:
|
||||
for (var i = 0; i <= _dragDropTargetIndex; ++i)
|
||||
{
|
||||
_linkManager.MoveDesignLink(_selector.Selected!, 0, LinkOrder.After, _selector.Selected!.Links.Before.Count,
|
||||
LinkOrder.Before);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else if (_dragDropTargetOrder is LinkOrder.Self)
|
||||
_linkManager.MoveDesignLink(_selector.Selected!, _dragDropIndex, _dragDropOrder, _selector.Selected!.Links.Before.Count,
|
||||
LinkOrder.Before);
|
||||
else
|
||||
_linkManager.MoveDesignLink(_selector.Selected!, _dragDropIndex, _dragDropOrder, _dragDropTargetIndex, _dragDropTargetOrder);
|
||||
|
||||
_dragDropIndex = -1;
|
||||
_dragDropTargetIndex = -1;
|
||||
_dragDropOrder = LinkOrder.None;
|
||||
_dragDropTargetOrder = LinkOrder.None;
|
||||
}
|
||||
|
||||
private void DrawList()
|
||||
{
|
||||
using var table = ImRaii.Table("table", 3, ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersOuter);
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
ImGui.TableSetupColumn("Del", ImGuiTableColumnFlags.WidthFixed, ImGui.GetFrameHeight());
|
||||
ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableSetupColumn("Detail", ImGuiTableColumnFlags.WidthFixed,
|
||||
6 * ImGui.GetFrameHeight() + 5 * ImGui.GetStyle().ItemInnerSpacing.X);
|
||||
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemInnerSpacing);
|
||||
DrawSubList(_selector.Selected!.Links.Before, LinkOrder.Before);
|
||||
DrawSelf();
|
||||
DrawSubList(_selector.Selected!.Links.After, LinkOrder.After);
|
||||
DrawNew();
|
||||
MoveLink();
|
||||
}
|
||||
|
||||
private void DrawSelf()
|
||||
{
|
||||
using var id = ImRaii.PushId((int)LinkOrder.Self);
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.Selectable(_selector.IncognitoMode ? _selector.Selected!.Incognito : _selector.Selected!.Name.Text);
|
||||
DrawDragDrop(_selector.Selected!, LinkOrder.Self, 0);
|
||||
ImGui.TableNextColumn();
|
||||
}
|
||||
|
||||
private void DrawSubList(IReadOnlyList<DesignLink> list, LinkOrder order)
|
||||
{
|
||||
using var id = ImRaii.PushId((int)order);
|
||||
|
||||
var buttonSize = new Vector2(ImGui.GetFrameHeight());
|
||||
for (var i = 0; i < list.Count; ++i)
|
||||
{
|
||||
|
|
@ -52,11 +100,6 @@ public class DesignLinkDrawer(DesignLinkManager _linkManager, DesignFileSystemSe
|
|||
|
||||
ImGui.TableNextColumn();
|
||||
var delete = ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), buttonSize, "Delete this link.", false, true);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted($"#{i:D2}");
|
||||
|
||||
var (design, flags) = list[i];
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
|
|
@ -66,32 +109,48 @@ public class DesignLinkDrawer(DesignLinkManager _linkManager, DesignFileSystemSe
|
|||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.AlignTextToFramePadding();
|
||||
ImGui.TextUnformatted(flags.ToString());
|
||||
DrawApplicationBoxes(i, order, flags);
|
||||
|
||||
if (delete)
|
||||
_linkManager.RemoveDesignLink(_selector.Selected!, i--, order);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawNew()
|
||||
{
|
||||
var buttonSize = new Vector2(ImGui.GetFrameHeight());
|
||||
ImGui.TableNextColumn();
|
||||
string tt;
|
||||
bool canAdd;
|
||||
ImGui.TableNextColumn();
|
||||
_combo.Draw(ImGui.GetContentRegionAvail().X);
|
||||
ImGui.TableNextColumn();
|
||||
string ttBefore, ttAfter;
|
||||
bool canAddBefore, canAddAfter;
|
||||
if (_combo.Design == null)
|
||||
{
|
||||
tt = "Select a design first.";
|
||||
canAdd = false;
|
||||
ttAfter = ttBefore = "Select a design first.";
|
||||
canAddBefore = canAddAfter = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
canAdd = LinkContainer.CanAddLink(_selector.Selected!, _combo.Design, order, out var error);
|
||||
tt = canAdd ? $"Add a link to {_combo.Design.Name}." : $"Can not add a link to {_combo.Design.Name}: {error}";
|
||||
canAddBefore = LinkContainer.CanAddLink(_selector.Selected!, _combo.Design, LinkOrder.Before, out var error);
|
||||
ttBefore = canAddBefore
|
||||
? $"Add a link at the top of the list to {_combo.Design.Name}."
|
||||
: $"Can not add a link to {_combo.Design.Name}:\n{error}";
|
||||
canAddAfter = LinkContainer.CanAddLink(_selector.Selected!, _combo.Design, LinkOrder.After, out error);
|
||||
ttAfter = canAddAfter
|
||||
? $"Add a link at the bottom of the list to {_combo.Design.Name}."
|
||||
: $"Can not add a link to {_combo.Design.Name}:\n{error}";
|
||||
}
|
||||
|
||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), buttonSize, tt, !canAdd, true))
|
||||
_linkManager.AddDesignLink(_selector.Selected!, _combo.Design!, order);
|
||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.ArrowCircleUp.ToIconString(), buttonSize, ttBefore, !canAddBefore, true))
|
||||
{
|
||||
_linkManager.AddDesignLink(_selector.Selected!, _combo.Design!, LinkOrder.Before);
|
||||
_linkManager.MoveDesignLink(_selector.Selected!, _selector.Selected!.Links.Before.Count - 1, LinkOrder.Before, 0, LinkOrder.Before);
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TableNextColumn();
|
||||
_combo.Draw(200);
|
||||
ImGui.SameLine();
|
||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.ArrowCircleDown.ToIconString(), buttonSize, ttAfter, !canAddAfter, true))
|
||||
_linkManager.AddDesignLink(_selector.Selected!, _combo.Design!, LinkOrder.After);
|
||||
}
|
||||
|
||||
private void DrawDragDrop(Design design, LinkOrder order, int index)
|
||||
|
|
@ -117,4 +176,42 @@ public class DesignLinkDrawer(DesignLinkManager _linkManager, DesignFileSystemSe
|
|||
_dragDropTargetIndex = index;
|
||||
_dragDropTargetOrder = order;
|
||||
}
|
||||
|
||||
private void DrawApplicationBoxes(int idx, LinkOrder order, ApplicationType current)
|
||||
{
|
||||
var newType = current;
|
||||
var newTypeInt = (uint)newType;
|
||||
using (ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, ImGuiHelpers.GlobalScale))
|
||||
{
|
||||
using var _ = ImRaii.PushColor(ImGuiCol.Border, ColorId.FolderLine.Value());
|
||||
if (ImGui.CheckboxFlags("##all", ref newTypeInt, (uint)ApplicationType.All))
|
||||
newType = (ApplicationType)newTypeInt;
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip("Toggle all application modes at once.");
|
||||
|
||||
ImGui.SameLine();
|
||||
Box(0);
|
||||
ImGui.SameLine();
|
||||
Box(1);
|
||||
ImGui.SameLine();
|
||||
|
||||
Box(2);
|
||||
ImGui.SameLine();
|
||||
Box(3);
|
||||
ImGui.SameLine();
|
||||
Box(4);
|
||||
if (newType != current)
|
||||
_linkManager.ChangeApplicationType(_selector.Selected!, idx, order, current);
|
||||
return;
|
||||
|
||||
void Box(int i)
|
||||
{
|
||||
var (applicationType, description) = ApplicationTypeExtensions.Types[i];
|
||||
var value = applicationType.HasFlag(applicationType);
|
||||
if (ImGui.Checkbox($"##{(byte)applicationType}", ref value))
|
||||
newType = value ? newType | applicationType : newType & ~applicationType;
|
||||
ImGuiUtil.HoverTooltip(description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ public class DesignPanel(
|
|||
{
|
||||
var apply = bigChange ? ((MetaFlag)flags).HasFlag(index.ToFlag()) : _selector.Selected!.DoApplyMeta(index);
|
||||
if (ImGui.Checkbox(label, ref apply) || bigChange)
|
||||
_manager.ChangeApplyMeta(_selector.Selected!, MetaIndex.HatState, apply);
|
||||
_manager.ChangeApplyMeta(_selector.Selected!, index, apply);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue