Current design state.

This commit is contained in:
Ottermandias 2026-02-16 14:50:25 +01:00
parent 4646fd57ab
commit 6f219b0929
7 changed files with 524 additions and 507 deletions

View file

@ -18,7 +18,7 @@ using Luna;
namespace Glamourer.Gui.Tabs.DesignTab; namespace Glamourer.Gui.Tabs.DesignTab;
public sealed class DesignFileSystemSelector : FileSystemSelector<Design, DesignFileSystemSelector.DesignState> public sealed class DesignFileSystemSelector : FileSystemSelector<Design, DesignFileSystemSelector.DesignState>, IPanel
{ {
private readonly DesignManager _designManager; private readonly DesignManager _designManager;
private readonly DesignChanged _event; private readonly DesignChanged _event;
@ -399,4 +399,7 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
} }
#endregion #endregion
public ReadOnlySpan<byte> Id
=> "DesignSelector"u8;
} }

View file

@ -0,0 +1,21 @@
using Luna;
namespace Glamourer.Gui.Tabs.DesignTab;
public sealed class DesignHeader : SplitButtonHeader
{
public DesignHeader(DesignSelection selection, IncognitoButton incognito)
{
RightButtons.AddButton(incognito, 50);
RightButtons.AddButton(new LockedButton(selection), 100);
}
private sealed class LockedButton(DesignSelection selection) : BaseIconButton<AwesomeIcon>
{
public override bool IsVisible
=> selection.Design is not null;
public override AwesomeIcon Icon
=> selection.Design!.WriteProtected() ? LunaStyle.LockedIcon : LunaStyle.UnlockedIcon;
}
}

View file

@ -24,10 +24,10 @@ using static Glamourer.Gui.Tabs.HeaderDrawer;
namespace Glamourer.Gui.Tabs.DesignTab; namespace Glamourer.Gui.Tabs.DesignTab;
public class DesignPanel public class DesignPanel : IPanel
{ {
private readonly FileDialogManager _fileDialog = new(); private readonly FileDialogManager _fileDialog = new();
private readonly DesignFileSystemSelector _selector; private readonly DesignSelection _selection;
private readonly CustomizationDrawer _customizationDrawer; private readonly CustomizationDrawer _customizationDrawer;
private readonly DesignManager _manager; private readonly DesignManager _manager;
private readonly ActorObjectManager _objects; private readonly ActorObjectManager _objects;
@ -47,8 +47,7 @@ public class DesignPanel
private readonly Button[] _rightButtons; private readonly Button[] _rightButtons;
public DesignPanel(DesignFileSystemSelector selector, public DesignPanel(CustomizationDrawer customizationDrawer,
CustomizationDrawer customizationDrawer,
DesignManager manager, DesignManager manager,
ActorObjectManager objects, ActorObjectManager objects,
StateManager state, StateManager state,
@ -62,9 +61,8 @@ public class DesignPanel
CustomizeParameterDrawer parameterDrawer, CustomizeParameterDrawer parameterDrawer,
DesignLinkDrawer designLinkDrawer, DesignLinkDrawer designLinkDrawer,
MaterialDrawer materials, MaterialDrawer materials,
EditorHistory history) EditorHistory history, DesignSelection selection)
{ {
_selector = selector;
_customizationDrawer = customizationDrawer; _customizationDrawer = customizationDrawer;
_manager = manager; _manager = manager;
_objects = objects; _objects = objects;
@ -80,6 +78,7 @@ public class DesignPanel
_designLinkDrawer = designLinkDrawer; _designLinkDrawer = designLinkDrawer;
_materials = materials; _materials = materials;
_history = history; _history = history;
_selection = selection;
_leftButtons = _leftButtons =
[ [
new SetFromClipboardButton(this), new SetFromClipboardButton(this),
@ -99,7 +98,7 @@ public class DesignPanel
=> HeaderDrawer.Draw(SelectionName, 0, ImGuiColor.FrameBackground.Get().Color, _leftButtons, _rightButtons); => HeaderDrawer.Draw(SelectionName, 0, ImGuiColor.FrameBackground.Get().Color, _leftButtons, _rightButtons);
private string SelectionName private string SelectionName
=> _selector.Selected == null ? "No Selection" : _config.Ephemeral.IncognitoMode ? _selector.Selected.Incognito : _selector.Selected.Name.Text; => _selection.Design == null ? "No Selection" : _config.Ephemeral.IncognitoMode ? _selection.Design.Incognito : _selection.Design.Name.Text;
private void DrawEquipment() private void DrawEquipment()
{ {
@ -109,22 +108,22 @@ public class DesignPanel
_equipmentDrawer.Prepare(); _equipmentDrawer.Prepare();
var usedAllStain = _equipmentDrawer.DrawAllStain(out var newAllStain, _selector.Selected!.WriteProtected()); var usedAllStain = _equipmentDrawer.DrawAllStain(out var newAllStain, _selection.Design!.WriteProtected());
foreach (var slot in EquipSlotExtensions.EqdpSlots) foreach (var slot in EquipSlotExtensions.EqdpSlots)
{ {
var data = EquipDrawData.FromDesign(_manager, _selector.Selected!, slot); var data = EquipDrawData.FromDesign(_manager, _selection.Design!, slot);
_equipmentDrawer.DrawEquip(data); _equipmentDrawer.DrawEquip(data);
if (usedAllStain) if (usedAllStain)
_manager.ChangeStains(_selector.Selected, slot, newAllStain); _manager.ChangeStains(_selection.Design, slot, newAllStain);
} }
var mainhand = EquipDrawData.FromDesign(_manager, _selector.Selected!, EquipSlot.MainHand); var mainhand = EquipDrawData.FromDesign(_manager, _selection.Design!, EquipSlot.MainHand);
var offhand = EquipDrawData.FromDesign(_manager, _selector.Selected!, EquipSlot.OffHand); var offhand = EquipDrawData.FromDesign(_manager, _selection.Design!, EquipSlot.OffHand);
_equipmentDrawer.DrawWeapons(mainhand, offhand, true); _equipmentDrawer.DrawWeapons(mainhand, offhand, true);
foreach (var slot in BonusExtensions.AllFlags) foreach (var slot in BonusExtensions.AllFlags)
{ {
var data = BonusDrawData.FromDesign(_manager, _selector.Selected!, slot); var data = BonusDrawData.FromDesign(_manager, _selection.Design!, slot);
_equipmentDrawer.DrawBonusItem(data); _equipmentDrawer.DrawBonusItem(data);
} }
@ -138,28 +137,28 @@ public class DesignPanel
{ {
using (var _ = ImRaii.Group()) using (var _ = ImRaii.Group())
{ {
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.HatState, _manager, _selector.Selected!)); EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.HatState, _manager, _selection.Design!));
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.CrestFromDesign(CrestFlag.Head, _manager, _selector.Selected!)); EquipmentDrawer.DrawMetaToggle(ToggleDrawData.CrestFromDesign(CrestFlag.Head, _manager, _selection.Design!));
} }
Im.Line.Same(); Im.Line.Same();
using (var _ = ImRaii.Group()) using (var _ = ImRaii.Group())
{ {
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.VisorState, _manager, _selector.Selected!)); EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.VisorState, _manager, _selection.Design!));
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.CrestFromDesign(CrestFlag.Body, _manager, _selector.Selected!)); EquipmentDrawer.DrawMetaToggle(ToggleDrawData.CrestFromDesign(CrestFlag.Body, _manager, _selection.Design!));
} }
Im.Line.Same(); Im.Line.Same();
using (var _ = ImRaii.Group()) using (var _ = ImRaii.Group())
{ {
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.WeaponState, _manager, _selector.Selected!)); EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.WeaponState, _manager, _selection.Design!));
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.CrestFromDesign(CrestFlag.OffHand, _manager, _selector.Selected!)); EquipmentDrawer.DrawMetaToggle(ToggleDrawData.CrestFromDesign(CrestFlag.OffHand, _manager, _selection.Design!));
} }
Im.Line.Same(); Im.Line.Same();
using (var _ = ImRaii.Group()) using (var _ = ImRaii.Group())
{ {
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.EarState, _manager, _selector.Selected!)); EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.EarState, _manager, _selection.Design!));
} }
} }
@ -169,25 +168,25 @@ public class DesignPanel
return; return;
var expand = _config.AutoExpandDesignPanel.HasFlag(DesignPanelFlag.Customization); var expand = _config.AutoExpandDesignPanel.HasFlag(DesignPanelFlag.Customization);
using var h = Im.Tree.HeaderId(_selector.Selected!.DesignData.ModelId is 0 using var h = Im.Tree.HeaderId(_selection.Design!.DesignData.ModelId is 0
? "Customization" ? "Customization"
: $"Customization (Model Id #{_selector.Selected!.DesignData.ModelId})###Customization", : $"Customization (Model Id #{_selection.Design!.DesignData.ModelId})###Customization",
expand ? TreeNodeFlags.DefaultOpen : TreeNodeFlags.None); expand ? TreeNodeFlags.DefaultOpen : TreeNodeFlags.None);
if (!h) if (!h)
return; return;
if (_customizationDrawer.Draw(_selector.Selected!.DesignData.Customize, _selector.Selected.Application.Customize, if (_customizationDrawer.Draw(_selection.Design!.DesignData.Customize, _selection.Design.Application.Customize,
_selector.Selected!.WriteProtected(), false)) _selection.Design!.WriteProtected(), false))
foreach (var idx in CustomizeIndex.Values) foreach (var idx in CustomizeIndex.Values)
{ {
var flag = idx.ToFlag(); var flag = idx.ToFlag();
var newValue = _customizationDrawer.ChangeApply.HasFlag(flag); var newValue = _customizationDrawer.ChangeApply.HasFlag(flag);
_manager.ChangeApplyCustomize(_selector.Selected, idx, newValue); _manager.ChangeApplyCustomize(_selection.Design, idx, newValue);
if (_customizationDrawer.Changed.HasFlag(flag)) if (_customizationDrawer.Changed.HasFlag(flag))
_manager.ChangeCustomize(_selector.Selected, idx, _customizationDrawer.Customize[idx]); _manager.ChangeCustomize(_selection.Design, idx, _customizationDrawer.Customize[idx]);
} }
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.Wetness, _manager, _selector.Selected!)); EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.Wetness, _manager, _selection.Design!));
Im.Dummy(new Vector2(Im.Style.TextHeight / 2)); Im.Dummy(new Vector2(Im.Style.TextHeight / 2));
} }
@ -197,7 +196,7 @@ public class DesignPanel
if (!h) if (!h)
return; return;
_parameterDrawer.Draw(_manager, _selector.Selected!); _parameterDrawer.Draw(_manager, _selection.Design!);
} }
private void DrawMaterialValues() private void DrawMaterialValues()
@ -206,52 +205,52 @@ public class DesignPanel
if (!h) if (!h)
return; return;
_materials.Draw(_selector.Selected!); _materials.Draw(_selection.Design!);
} }
private void DrawCustomizeApplication() private void DrawCustomizeApplication()
{ {
using var id = ImUtf8.PushId("Customizations"u8); using var id = ImUtf8.PushId("Customizations"u8);
var set = _selector.Selected!.CustomizeSet; var set = _selection.Design!.CustomizeSet;
var available = set.SettingAvailable | CustomizeFlag.Clan | CustomizeFlag.Gender | CustomizeFlag.BodyType; var available = set.SettingAvailable | CustomizeFlag.Clan | CustomizeFlag.Gender | CustomizeFlag.BodyType;
var flags = _selector.Selected!.ApplyCustomizeExcludingBodyType == 0 ? 0 : var flags = _selection.Design!.ApplyCustomizeExcludingBodyType == 0 ? 0 :
(_selector.Selected!.ApplyCustomize & available) == available ? 3 : 1; (_selection.Design!.ApplyCustomize & available) == available ? 3 : 1;
if (ImGui.CheckboxFlags("Apply All Customizations", ref flags, 3)) if (ImGui.CheckboxFlags("Apply All Customizations", ref flags, 3))
{ {
var newFlags = flags == 3; var newFlags = flags == 3;
_manager.ChangeApplyCustomize(_selector.Selected!, CustomizeIndex.Clan, newFlags); _manager.ChangeApplyCustomize(_selection.Design!, CustomizeIndex.Clan, newFlags);
_manager.ChangeApplyCustomize(_selector.Selected!, CustomizeIndex.Gender, newFlags); _manager.ChangeApplyCustomize(_selection.Design!, CustomizeIndex.Gender, newFlags);
foreach (var index in CustomizationExtensions.AllBasic) foreach (var index in CustomizationExtensions.AllBasic)
_manager.ChangeApplyCustomize(_selector.Selected!, index, newFlags); _manager.ChangeApplyCustomize(_selection.Design!, index, newFlags);
} }
var applyClan = _selector.Selected!.DoApplyCustomize(CustomizeIndex.Clan); var applyClan = _selection.Design!.DoApplyCustomize(CustomizeIndex.Clan);
if (ImUtf8.Checkbox($"Apply {CustomizeIndex.Clan.ToNameU8()}", ref applyClan)) if (ImUtf8.Checkbox($"Apply {CustomizeIndex.Clan.ToNameU8()}", ref applyClan))
_manager.ChangeApplyCustomize(_selector.Selected!, CustomizeIndex.Clan, applyClan); _manager.ChangeApplyCustomize(_selection.Design!, CustomizeIndex.Clan, applyClan);
var applyGender = _selector.Selected!.DoApplyCustomize(CustomizeIndex.Gender); var applyGender = _selection.Design!.DoApplyCustomize(CustomizeIndex.Gender);
if (ImUtf8.Checkbox($"Apply {CustomizeIndex.Gender.ToNameU8()}", ref applyGender)) if (ImUtf8.Checkbox($"Apply {CustomizeIndex.Gender.ToNameU8()}", ref applyGender))
_manager.ChangeApplyCustomize(_selector.Selected!, CustomizeIndex.Gender, applyGender); _manager.ChangeApplyCustomize(_selection.Design!, CustomizeIndex.Gender, applyGender);
foreach (var index in CustomizationExtensions.All.Where(set.IsAvailable)) foreach (var index in CustomizationExtensions.All.Where(set.IsAvailable))
{ {
var apply = _selector.Selected!.DoApplyCustomize(index); var apply = _selection.Design!.DoApplyCustomize(index);
if (ImUtf8.Checkbox($"Apply {set.Option(index)}", ref apply)) if (ImUtf8.Checkbox($"Apply {set.Option(index)}", ref apply))
_manager.ChangeApplyCustomize(_selector.Selected!, index, apply); _manager.ChangeApplyCustomize(_selection.Design!, index, apply);
} }
} }
private void DrawCrestApplication() private void DrawCrestApplication()
{ {
using var id = ImUtf8.PushId("Crests"u8); using var id = ImUtf8.PushId("Crests"u8);
var flags = (uint)_selector.Selected!.Application.Crest; var flags = (uint)_selection.Design!.Application.Crest;
var bigChange = ImGui.CheckboxFlags("Apply All Crests", ref flags, (uint)CrestExtensions.AllRelevant); var bigChange = ImGui.CheckboxFlags("Apply All Crests", ref flags, (uint)CrestExtensions.AllRelevant);
foreach (var flag in CrestExtensions.AllRelevantSet) foreach (var flag in CrestExtensions.AllRelevantSet)
{ {
var apply = bigChange ? ((CrestFlag)flags & flag) == flag : _selector.Selected!.DoApplyCrest(flag); var apply = bigChange ? ((CrestFlag)flags & flag) == flag : _selection.Design!.DoApplyCrest(flag);
if (ImUtf8.Checkbox($"Apply {flag.ToLabel()} Crest", ref apply) || bigChange) if (ImUtf8.Checkbox($"Apply {flag.ToLabel()} Crest", ref apply) || bigChange)
_manager.ChangeApplyCrest(_selector.Selected!, flag, apply); _manager.ChangeApplyCrest(_selection.Design!, flag, apply);
} }
} }
@ -261,7 +260,7 @@ public class DesignPanel
if (!h) if (!h)
return; return;
using var disabled = Im.Disabled(_selector.Selected!.WriteProtected()); using var disabled = Im.Disabled(_selection.Design!.WriteProtected());
DrawAllButtons(); DrawAllButtons();
@ -279,22 +278,22 @@ public class DesignPanel
{ {
void ApplyEquip(string label, EquipFlag allFlags, bool stain, IEnumerable<EquipSlot> slots) void ApplyEquip(string label, EquipFlag allFlags, bool stain, IEnumerable<EquipSlot> slots)
{ {
var flags = (uint)(allFlags & _selector.Selected!.Application.Equip); var flags = (uint)(allFlags & _selection.Design!.Application.Equip);
using var id = ImUtf8.PushId(label); using var id = ImUtf8.PushId(label);
var bigChange = ImGui.CheckboxFlags($"Apply All {label}", ref flags, (uint)allFlags); var bigChange = ImGui.CheckboxFlags($"Apply All {label}", ref flags, (uint)allFlags);
if (stain) if (stain)
foreach (var slot in slots) foreach (var slot in slots)
{ {
var apply = bigChange ? ((EquipFlag)flags).HasFlag(slot.ToStainFlag()) : _selector.Selected!.DoApplyStain(slot); var apply = bigChange ? ((EquipFlag)flags).HasFlag(slot.ToStainFlag()) : _selection.Design!.DoApplyStain(slot);
if (ImUtf8.Checkbox($"Apply {slot.ToName()} Dye", ref apply) || bigChange) if (ImUtf8.Checkbox($"Apply {slot.ToName()} Dye", ref apply) || bigChange)
_manager.ChangeApplyStains(_selector.Selected!, slot, apply); _manager.ChangeApplyStains(_selection.Design!, slot, apply);
} }
else else
foreach (var slot in slots) foreach (var slot in slots)
{ {
var apply = bigChange ? ((EquipFlag)flags).HasFlag(slot.ToFlag()) : _selector.Selected!.DoApplyEquip(slot); var apply = bigChange ? ((EquipFlag)flags).HasFlag(slot.ToFlag()) : _selection.Design!.DoApplyEquip(slot);
if (ImUtf8.Checkbox($"Apply {slot.ToName()}", ref apply) || bigChange) if (ImUtf8.Checkbox($"Apply {slot.ToName()}", ref apply) || bigChange)
_manager.ChangeApplyItem(_selector.Selected!, slot, apply); _manager.ChangeApplyItem(_selection.Design!, slot, apply);
} }
} }
@ -379,8 +378,8 @@ public class DesignPanel
size, size,
!enabled)) !enabled))
{ {
_manager.ChangeApplyMulti(_selector.Selected!, true, true, true, false, true, true, false, true); _manager.ChangeApplyMulti(_selection.Design!, true, true, true, false, true, true, false, true);
_manager.ChangeApplyMeta(_selector.Selected!, MetaIndex.Wetness, false); _manager.ChangeApplyMeta(_selection.Design!, MetaIndex.Wetness, false);
} }
if (!enabled) if (!enabled)
@ -390,7 +389,7 @@ public class DesignPanel
if (ImUtf8.ButtonEx("Disable Advanced"u8, "Disable all advanced dyes and customizations but keep everything else as is."u8, if (ImUtf8.ButtonEx("Disable Advanced"u8, "Disable all advanced dyes and customizations but keep everything else as is."u8,
size, size,
!enabled)) !enabled))
_manager.ChangeApplyMulti(_selector.Selected!, null, null, null, false, null, null, false, null); _manager.ChangeApplyMulti(_selection.Design!, null, null, null, false, null, null, false, null);
if (!enabled) if (!enabled)
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {_config.DeleteDesignModifier} while clicking."); ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {_config.DeleteDesignModifier} while clicking.");
@ -398,18 +397,18 @@ public class DesignPanel
if (equip is null && customize is null) if (equip is null && customize is null)
return; return;
_manager.ChangeApplyMulti(_selector.Selected!, equip, customize, equip, customize.HasValue && !customize.Value ? false : null, null, _manager.ChangeApplyMulti(_selection.Design!, equip, customize, equip, customize.HasValue && !customize.Value ? false : null, null,
equip, equip, equip); equip, equip, equip);
if (equip.HasValue) if (equip.HasValue)
{ {
_manager.ChangeApplyMeta(_selector.Selected!, MetaIndex.HatState, equip.Value); _manager.ChangeApplyMeta(_selection.Design!, MetaIndex.HatState, equip.Value);
_manager.ChangeApplyMeta(_selector.Selected!, MetaIndex.VisorState, equip.Value); _manager.ChangeApplyMeta(_selection.Design!, MetaIndex.VisorState, equip.Value);
_manager.ChangeApplyMeta(_selector.Selected!, MetaIndex.WeaponState, equip.Value); _manager.ChangeApplyMeta(_selection.Design!, MetaIndex.WeaponState, equip.Value);
_manager.ChangeApplyMeta(_selector.Selected!, MetaIndex.EarState, equip.Value); _manager.ChangeApplyMeta(_selection.Design!, MetaIndex.EarState, equip.Value);
} }
if (customize.HasValue) if (customize.HasValue)
_manager.ChangeApplyMeta(_selector.Selected!, MetaIndex.Wetness, customize.Value); _manager.ChangeApplyMeta(_selection.Design!, MetaIndex.Wetness, customize.Value);
} }
private static readonly IReadOnlyList<string> MetaLabels = private static readonly IReadOnlyList<string> MetaLabels =
@ -425,14 +424,14 @@ public class DesignPanel
{ {
using var id = ImUtf8.PushId("Meta"); using var id = ImUtf8.PushId("Meta");
const uint all = (uint)MetaExtensions.All; const uint all = (uint)MetaExtensions.All;
var flags = (uint)_selector.Selected!.Application.Meta; var flags = (uint)_selection.Design!.Application.Meta;
var bigChange = ImGui.CheckboxFlags("Apply All Meta Changes", ref flags, all); var bigChange = ImGui.CheckboxFlags("Apply All Meta Changes", ref flags, all);
foreach (var (index, label) in MetaExtensions.AllRelevant.Zip(MetaLabels)) foreach (var (index, label) in MetaExtensions.AllRelevant.Zip(MetaLabels))
{ {
var apply = bigChange ? ((MetaFlag)flags).HasFlag(index.ToFlag()) : _selector.Selected!.DoApplyMeta(index); var apply = bigChange ? ((MetaFlag)flags).HasFlag(index.ToFlag()) : _selection.Design!.DoApplyMeta(index);
if (ImUtf8.Checkbox(label, ref apply) || bigChange) if (ImUtf8.Checkbox(label, ref apply) || bigChange)
_manager.ChangeApplyMeta(_selector.Selected!, index, apply); _manager.ChangeApplyMeta(_selection.Design!, index, apply);
} }
} }
@ -444,13 +443,13 @@ public class DesignPanel
private void DrawBonusSlotApplication() private void DrawBonusSlotApplication()
{ {
using var id = ImUtf8.PushId("Bonus"u8); using var id = ImUtf8.PushId("Bonus"u8);
var flags = _selector.Selected!.Application.BonusItem; var flags = _selection.Design!.Application.BonusItem;
var bigChange = BonusExtensions.AllFlags.Count > 1 && ImUtf8.Checkbox("Apply All Bonus Slots"u8, ref flags, BonusExtensions.All); var bigChange = BonusExtensions.AllFlags.Count > 1 && ImUtf8.Checkbox("Apply All Bonus Slots"u8, ref flags, BonusExtensions.All);
foreach (var (index, label) in BonusExtensions.AllFlags.Zip(BonusSlotLabels)) foreach (var (index, label) in BonusExtensions.AllFlags.Zip(BonusSlotLabels))
{ {
var apply = bigChange ? flags.HasFlag(index) : _selector.Selected!.DoApplyBonusItem(index); var apply = bigChange ? flags.HasFlag(index) : _selection.Design!.DoApplyBonusItem(index);
if (ImUtf8.Checkbox(label, ref apply) || bigChange) if (ImUtf8.Checkbox(label, ref apply) || bigChange)
_manager.ChangeApplyBonusItem(_selector.Selected!, index, apply); _manager.ChangeApplyBonusItem(_selection.Design!, index, apply);
} }
} }
@ -458,20 +457,23 @@ public class DesignPanel
private void DrawParameterApplication() private void DrawParameterApplication()
{ {
using var id = Im.Id.Push("Parameter"u8); using var id = Im.Id.Push("Parameter"u8);
var flags = (ulong)_selector.Selected!.Application.Parameters; var flags = (ulong)_selection.Design!.Application.Parameters;
var bigChange = Im.Checkbox("Apply All Customize Parameters"u8, ref flags, (ulong)CustomizeParameterExtensions.All); var bigChange = Im.Checkbox("Apply All Customize Parameters"u8, ref flags, (ulong)CustomizeParameterExtensions.All);
foreach (var flag in CustomizeParameterExtensions.AllFlags) foreach (var flag in CustomizeParameterExtensions.AllFlags)
{ {
var apply = bigChange ? ((CustomizeParameterFlag)flags).HasFlag(flag) : _selector.Selected!.DoApplyParameter(flag); var apply = bigChange ? ((CustomizeParameterFlag)flags).HasFlag(flag) : _selection.Design!.DoApplyParameter(flag);
if (Im.Checkbox($"Apply {flag.ToNameU8()}", ref apply) || bigChange) if (Im.Checkbox($"Apply {flag.ToNameU8()}", ref apply) || bigChange)
_manager.ChangeApplyParameter(_selector.Selected!, flag, apply); _manager.ChangeApplyParameter(_selection.Design!, flag, apply);
} }
} }
public ReadOnlySpan<byte> Id
=> "Designs"u8;
public void Draw() public void Draw()
{ {
using var group = ImUtf8.Group(); using var group = ImUtf8.Group();
if (_selector.SelectedPaths.Count > 1) if (_selection.DesignPaths.Count > 1)
{ {
_multiDesignPanel.Draw(); _multiDesignPanel.Draw();
} }
@ -480,22 +482,22 @@ public class DesignPanel
DrawHeader(); DrawHeader();
DrawPanel(); DrawPanel();
if (_selector.Selected == null || _selector.Selected.WriteProtected()) if (_selection.Design == null || _selection.Design.WriteProtected())
return; return;
if (_importService.CreateDatTarget(out var dat)) if (_importService.CreateDatTarget(out var dat))
{ {
_manager.ChangeCustomize(_selector.Selected!, CustomizeIndex.Clan, dat.Customize[CustomizeIndex.Clan]); _manager.ChangeCustomize(_selection.Design!, CustomizeIndex.Clan, dat.Customize[CustomizeIndex.Clan]);
_manager.ChangeCustomize(_selector.Selected!, CustomizeIndex.Gender, dat.Customize[CustomizeIndex.Gender]); _manager.ChangeCustomize(_selection.Design!, CustomizeIndex.Gender, dat.Customize[CustomizeIndex.Gender]);
foreach (var idx in CustomizationExtensions.AllBasic) foreach (var idx in CustomizationExtensions.AllBasic)
_manager.ChangeCustomize(_selector.Selected!, idx, dat.Customize[idx]); _manager.ChangeCustomize(_selection.Design!, idx, dat.Customize[idx]);
Glamourer.Messager.NotificationMessage( Glamourer.Messager.NotificationMessage(
$"Applied games .dat file {dat.Description} customizations to {_selector.Selected.Name}.", NotificationType.Success, false); $"Applied games .dat file {dat.Description} customizations to {_selection.Design.Name}.", NotificationType.Success, false);
} }
else if (_importService.CreateCharaTarget(out var designBase, out var name)) else if (_importService.CreateCharaTarget(out var designBase, out var name))
{ {
_manager.ApplyDesign(_selector.Selected!, designBase); _manager.ApplyDesign(_selection.Design!, designBase);
Glamourer.Messager.NotificationMessage($"Applied Anamnesis .chara file {name} to {_selector.Selected.Name}.", Glamourer.Messager.NotificationMessage($"Applied Anamnesis .chara file {name} to {_selection.Design.Name}.",
NotificationType.Success, false); NotificationType.Success, false);
} }
} }
@ -506,12 +508,12 @@ public class DesignPanel
private void DrawPanel() private void DrawPanel()
{ {
using var table = Im.Table.Begin("##Panel"u8, 1, TableFlags.BordersOuter | TableFlags.ScrollY, Im.ContentRegion.Available); using var table = Im.Table.Begin("##Panel"u8, 1, TableFlags.BordersOuter | TableFlags.ScrollY, Im.ContentRegion.Available);
if (!table || _selector.Selected is null) if (!table || _selection.Design is null)
return; return;
ImGui.TableSetupScrollFreeze(0, 1); ImGui.TableSetupScrollFreeze(0, 1);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
if (_selector.Selected is null) if (_selection.Design is null)
return; return;
Im.Dummy(Vector2.Zero); Im.Dummy(Vector2.Zero);
@ -550,8 +552,8 @@ public class DesignPanel
if (_state.GetOrCreate(id, data.Objects[0], out var state)) if (_state.GetOrCreate(id, data.Objects[0], out var state))
{ {
using var _ = _selector.Selected!.TemporarilyRestrictApplication(ApplicationCollection.FromKeys()); using var _ = _selection.Design!.TemporarilyRestrictApplication(ApplicationCollection.FromKeys());
_state.ApplyDesign(state, _selector.Selected!, ApplySettings.ManualWithLinks with { IsFinal = true }); _state.ApplyDesign(state, _selection.Design!, ApplySettings.ManualWithLinks with { IsFinal = true });
} }
} }
@ -568,14 +570,14 @@ public class DesignPanel
if (_state.GetOrCreate(id, data.Objects[0], out var state)) if (_state.GetOrCreate(id, data.Objects[0], out var state))
{ {
using var _ = _selector.Selected!.TemporarilyRestrictApplication(ApplicationCollection.FromKeys()); using var _ = _selection.Design!.TemporarilyRestrictApplication(ApplicationCollection.FromKeys());
_state.ApplyDesign(state, _selector.Selected!, ApplySettings.ManualWithLinks with { IsFinal = true }); _state.ApplyDesign(state, _selection.Design!, ApplySettings.ManualWithLinks with { IsFinal = true });
} }
} }
private void DrawSaveToDat() private void DrawSaveToDat()
{ {
var verified = _importService.Verify(_selector.Selected!.DesignData.Customize, out _); var verified = _importService.Verify(_selection.Design!.DesignData.Customize, out _);
var tt = verified var tt = verified
? "Export the currently configured customizations of this design to a character creation data file." ? "Export the currently configured customizations of this design to a character creation data file."
: "The current design contains customizations that can not be applied during character creation."; : "The current design contains customizations that can not be applied during character creation.";
@ -585,8 +587,8 @@ public class DesignPanel
if (ImGuiUtil.DrawDisabledButton("Export to Dat", Vector2.Zero, tt, !verified)) if (ImGuiUtil.DrawDisabledButton("Export to Dat", Vector2.Zero, tt, !verified))
_fileDialog.SaveFileDialog("Save File...", ".dat", "FFXIV_CHARA_01.dat", ".dat", (v, path) => _fileDialog.SaveFileDialog("Save File...", ".dat", "FFXIV_CHARA_01.dat", ".dat", (v, path) =>
{ {
if (v && _selector.Selected != null) if (v && _selection.Design != null)
_importService.SaveDesignAsDat(path, _selector.Selected!.DesignData.Customize, _selector.Selected!.Name); _importService.SaveDesignAsDat(path, _selection.Design!.DesignData.Customize, _selection.Design!.Name);
}, startPath); }, startPath);
_fileDialog.Draw(); _fileDialog.Draw();
@ -595,33 +597,34 @@ public class DesignPanel
private static unsafe string GetUserPath() private static unsafe string GetUserPath()
=> Framework.Instance()->UserPathString; => Framework.Instance()->UserPathString;
}
private sealed class LockButton(DesignPanel panel) : Button private sealed class LockButton(DesignPanel panel) : Button
{ {
public override bool Visible public override bool Visible
=> panel._selector.Selected != null; => panel._selection.Design != null;
protected override string Description protected override string Description
=> panel._selector.Selected!.WriteProtected() => panel._selection.Design!.WriteProtected()
? "Make this design editable." ? "Make this design editable."
: "Write-protect this design."; : "Write-protect this design.";
protected override FontAwesomeIcon Icon protected override FontAwesomeIcon Icon
=> panel._selector.Selected!.WriteProtected() => panel._selection.Design!.WriteProtected()
? FontAwesomeIcon.Lock ? FontAwesomeIcon.Lock
: FontAwesomeIcon.LockOpen; : FontAwesomeIcon.LockOpen;
protected override void OnClick() protected override void OnClick()
=> panel._manager.SetWriteProtection(panel._selector.Selected!, !panel._selector.Selected!.WriteProtected()); => panel._manager.SetWriteProtection(panel._selection.Design!, !panel._selection.Design!.WriteProtected());
} }
private sealed class SetFromClipboardButton(DesignPanel panel) : Button private sealed class SetFromClipboardButton(DesignPanel panel) : Button
{ {
public override bool Visible public override bool Visible
=> panel._selector.Selected != null; => panel._selection.Design != null;
protected override bool Disabled protected override bool Disabled
=> panel._selector.Selected?.WriteProtected() ?? true; => panel._selection.Design?.WriteProtected() ?? true;
protected override string Description protected override string Description
=> "Try to apply a design from your clipboard over this design.\nHold Control to only apply gear.\nHold Shift to only apply customizations."; => "Try to apply a design from your clipboard over this design.\nHold Control to only apply gear.\nHold Shift to only apply customizations.";
@ -637,12 +640,12 @@ public class DesignPanel
var (applyEquip, applyCustomize) = UiHelpers.ConvertKeysToBool(); var (applyEquip, applyCustomize) = UiHelpers.ConvertKeysToBool();
var design = panel._converter.FromBase64(text, applyCustomize, applyEquip, out _) var design = panel._converter.FromBase64(text, applyCustomize, applyEquip, out _)
?? throw new Exception("The clipboard did not contain valid data."); ?? throw new Exception("The clipboard did not contain valid data.");
panel._manager.ApplyDesign(panel._selector.Selected!, design); panel._manager.ApplyDesign(panel._selection.Design!, design);
} }
catch (Exception ex) catch (Exception ex)
{ {
Glamourer.Messager.NotificationMessage(ex, $"Could not apply clipboard to {panel._selector.Selected!.Name}.", Glamourer.Messager.NotificationMessage(ex, $"Could not apply clipboard to {panel._selection.Design!.Name}.",
$"Could not apply clipboard to design {panel._selector.Selected!.Identifier}", NotificationType.Error, false); $"Could not apply clipboard to design {panel._selection.Design!.Identifier}", NotificationType.Error, false);
} }
} }
} }
@ -650,10 +653,10 @@ public class DesignPanel
private sealed class DesignUndoButton(DesignPanel panel) : Button private sealed class DesignUndoButton(DesignPanel panel) : Button
{ {
public override bool Visible public override bool Visible
=> panel._selector.Selected != null; => panel._selection.Design != null;
protected override bool Disabled protected override bool Disabled
=> !panel._manager.CanUndo(panel._selector.Selected) || (panel._selector.Selected?.WriteProtected() ?? true); => !panel._manager.CanUndo(panel._selection.Design) || (panel._selection.Design?.WriteProtected() ?? true);
protected override string Description protected override string Description
=> "Undo the last time you applied an entire design onto this design, if you accidentally overwrote your design with a different one."; => "Undo the last time you applied an entire design onto this design, if you accidentally overwrote your design with a different one.";
@ -665,11 +668,11 @@ public class DesignPanel
{ {
try try
{ {
panel._manager.UndoDesignChange(panel._selector.Selected!); panel._manager.UndoDesignChange(panel._selection.Design!);
} }
catch (Exception ex) catch (Exception ex)
{ {
Glamourer.Messager.NotificationMessage(ex, $"Could not undo last changes to {panel._selector.Selected!.Name}.", Glamourer.Messager.NotificationMessage(ex, $"Could not undo last changes to {panel._selection.Design!.Name}.",
NotificationType.Error, NotificationType.Error,
false); false);
} }
@ -679,7 +682,7 @@ public class DesignPanel
private sealed class ExportToClipboardButton(DesignPanel panel) : Button private sealed class ExportToClipboardButton(DesignPanel panel) : Button
{ {
public override bool Visible public override bool Visible
=> panel._selector.Selected != null; => panel._selection.Design != null;
protected override string Description protected override string Description
=> "Copy the current design to your clipboard."; => "Copy the current design to your clipboard.";
@ -691,13 +694,13 @@ public class DesignPanel
{ {
try try
{ {
var text = panel._converter.ShareBase64(panel._selector.Selected!); var text = panel._converter.ShareBase64(panel._selection.Design!);
ImGui.SetClipboardText(text); ImGui.SetClipboardText(text);
} }
catch (Exception ex) catch (Exception ex)
{ {
Glamourer.Messager.NotificationMessage(ex, $"Could not copy {panel._selector.Selected!.Name} data to clipboard.", Glamourer.Messager.NotificationMessage(ex, $"Could not copy {panel._selection.Design!.Name} data to clipboard.",
$"Could not copy data from design {panel._selector.Selected!.Identifier} to clipboard", NotificationType.Error, false); $"Could not copy data from design {panel._selection.Design!.Identifier} to clipboard", NotificationType.Error, false);
} }
} }
} }
@ -705,13 +708,13 @@ public class DesignPanel
private sealed class ApplyCharacterButton(DesignPanel panel) : Button private sealed class ApplyCharacterButton(DesignPanel panel) : Button
{ {
public override bool Visible public override bool Visible
=> panel._selector.Selected != null && panel._objects.Player.Valid; => panel._selection.Design != null && panel._objects.Player.Valid;
protected override string Description protected override string Description
=> "Overwrite this design with your character's current state."; => "Overwrite this design with your character's current state.";
protected override bool Disabled protected override bool Disabled
=> panel._selector.Selected?.WriteProtected() ?? true; => panel._selection.Design?.WriteProtected() ?? true;
protected override FontAwesomeIcon Icon protected override FontAwesomeIcon Icon
=> FontAwesomeIcon.UserEdit; => FontAwesomeIcon.UserEdit;
@ -726,13 +729,13 @@ public class DesignPanel
var design = panel._converter.Convert(state, ApplicationRules.FromModifiers(state)) var design = panel._converter.Convert(state, ApplicationRules.FromModifiers(state))
?? throw new Exception("The clipboard did not contain valid data."); ?? throw new Exception("The clipboard did not contain valid data.");
panel._selector.Selected!.GetMaterialDataRef().Clear(); panel._selection.Design!.GetMaterialDataRef().Clear();
panel._manager.ApplyDesign(panel._selector.Selected!, design); panel._manager.ApplyDesign(panel._selection.Design!, design);
} }
catch (Exception ex) catch (Exception ex)
{ {
Glamourer.Messager.NotificationMessage(ex, $"Could not apply player state to {panel._selector.Selected!.Name}.", Glamourer.Messager.NotificationMessage(ex, $"Could not apply player state to {panel._selection.Design!.Name}.",
$"Could not apply player state to design {panel._selector.Selected!.Identifier}", NotificationType.Error, false); $"Could not apply player state to design {panel._selection.Design!.Identifier}", NotificationType.Error, false);
} }
} }
} }
@ -746,12 +749,11 @@ public class DesignPanel
=> FontAwesomeIcon.Undo; => FontAwesomeIcon.Undo;
public override bool Visible public override bool Visible
=> panel._selector.Selected != null; => panel._selection.Design != null;
protected override bool Disabled protected override bool Disabled
=> (panel._selector.Selected?.WriteProtected() ?? true) || !panel._history.CanUndo(panel._selector.Selected); => (panel._selection.Design?.WriteProtected() ?? true) || !panel._history.CanUndo(panel._selection.Design);
protected override void OnClick() protected override void OnClick()
=> panel._history.Undo(panel._selector.Selected!); => panel._history.Undo(panel._selection.Design!);
}
} }

View file

@ -0,0 +1,12 @@
using Glamourer.Designs;
using Luna;
namespace Glamourer.Gui.Tabs.DesignTab;
public sealed class DesignSelection : IUiService, IDisposable
{
public Design? Design { get; private set; }
public void Dispose()
{ }
}

View file

@ -1,95 +1,107 @@
using Dalamud.Interface.Utility; using Glamourer.Interop.Penumbra;
using Glamourer.Interop.Penumbra;
using Dalamud.Bindings.ImGui;
using ImSharp; using ImSharp;
using OtterGui.Classes;
using OtterGui.Log;
using OtterGui.Raii;
using OtterGui.Text;
using OtterGui.Widgets;
using MouseWheelType = OtterGui.Widgets.MouseWheelType;
namespace Glamourer.Gui.Tabs.DesignTab; namespace Glamourer.Gui.Tabs.DesignTab;
public sealed class ModCombo : FilterComboCache<(Mod Mod, ModSettings Settings, int Count)> public sealed class ModCombo(PenumbraService penumbra, DesignSelection selection) : ImSharp.FilterComboBase<ModCombo.CacheItem>(new ModFilter())
{ {
public ModCombo(PenumbraService penumbra, Logger log, DesignFileSystemSelector selector) public readonly struct CacheItem(in Mod mod, in ModSettings settings, int count)
: base(() => penumbra.GetMods(selector.Selected?.FilteredItemNames.ToArray() ?? []), MouseWheelType.None, log)
=> SearchByParts = false;
protected override string ToString((Mod Mod, ModSettings Settings, int Count) obj)
=> obj.Mod.Name;
protected override bool IsVisible(int globalIndex, LowerString filter)
=> filter.IsContained(Items[globalIndex].Mod.Name) || filter.IsContained(Items[globalIndex].Mod.DirectoryName);
protected override bool DrawSelectable(int globalIdx, bool selected)
{ {
using var id = ImUtf8.PushId(globalIdx); public readonly StringPair Name = new(mod.Name);
var (mod, settings, count) = Items[globalIdx]; public readonly StringPair Directory = new(mod.DirectoryName);
bool ret; public readonly ModSettings Settings = settings;
var color = settings.Enabled public readonly int Count = count;
public readonly Vector4 Color = settings.Enabled
? count > 0 ? count > 0
? ColorId.ContainsItemsEnabled.Value() ? ColorId.ContainsItemsEnabled.Value().ToVector()
: ImGuiColor.Text.Get() : Im.Style[ImGuiColor.Text]
: count > 0 : count > 0
? ColorId.ContainsItemsDisabled.Value() ? ColorId.ContainsItemsDisabled.Value().ToVector()
: ImGuiColor.TextDisabled.Get(); : Im.Style[ImGuiColor.TextDisabled];
using (ImGuiColor.Text.Push(color))
{ public readonly bool DifferingNames = string.Equals(mod.Name, mod.DirectoryName, StringComparison.CurrentCultureIgnoreCase);
ret = ImUtf8.Selectable(mod.Name, selected);
} }
if (ImGui.IsItemHovered()) protected override float ItemHeight
=> Im.Style.TextHeightWithSpacing;
protected override IEnumerable<CacheItem> GetItems()
=> penumbra.GetMods(selection.Design?.FilteredItemNames.ToArray() ?? []).Select(t => new CacheItem(t.Mod, t.Settings, t.Count));
protected override bool DrawItem(in CacheItem item, int globalIndex, bool selected)
{ {
using var style = ImRaii.PushStyle(ImGuiStyleVar.PopupBorderSize, 2 * Im.Style.GlobalScale); bool ret;
using var tt = ImUtf8.Tooltip(); using (ImGuiColor.Text.Push(item.Color))
var namesDifferent = mod.Name != mod.DirectoryName;
Im.Dummy(new Vector2(300 * Im.Style.GlobalScale, 0));
using (ImUtf8.Group())
{ {
if (namesDifferent) ret = Im.Selectable(item.Name.Utf8, selected);
ImUtf8.Text("Directory Name"u8);
ImUtf8.Text("Enabled"u8);
ImUtf8.Text("Priority"u8);
ImUtf8.Text("Affected Design Items"u8);
DrawSettingsLeft(settings);
} }
ImGui.SameLine(Math.Max(ImGui.GetItemRectSize().X + 3 * Im.Style.ItemSpacing.X, 150 * Im.Style.GlobalScale)); if (Im.Item.Hovered())
using (ImUtf8.Group()) DrawTooltip(item);
{
if (namesDifferent)
ImUtf8.Text(mod.DirectoryName);
ImUtf8.Text($"{settings.Enabled}");
ImUtf8.Text($"{settings.Priority}");
ImUtf8.Text($"{count}");
DrawSettingsRight(settings);
}
}
return ret; return ret;
} }
public static void DrawSettingsLeft(ModSettings settings) private static void DrawTooltip(in CacheItem item)
{
using var style = ImStyleSingle.PopupBorderThickness.Push(2 * Im.Style.GlobalScale);
using var tt = Im.Tooltip.Begin();
Im.Dummy(new Vector2(300 * Im.Style.GlobalScale, 0));
using (Im.Group())
{
if (item.DifferingNames)
Im.Text("Directory Name"u8);
Im.Text("Enabled"u8);
Im.Text("Priority"u8);
Im.Text("Affected Design Items"u8);
DrawSettingsLeft(item.Settings);
}
Im.Line.Same(Math.Max(Im.Item.Size.X + 3 * Im.Style.ItemSpacing.X, 150 * Im.Style.GlobalScale));
using (Im.Group())
{
if (item.DifferingNames)
Im.Text(item.Directory.Utf8);
Im.Text($"{item.Settings.Enabled}");
Im.Text($"{item.Settings.Priority}");
Im.Text($"{item.Count}");
DrawSettingsRight(item.Settings);
}
}
private static void DrawSettingsLeft(in ModSettings settings)
{ {
foreach (var setting in settings.Settings) foreach (var setting in settings.Settings)
{ {
ImUtf8.Text(setting.Key); Im.Text(setting.Key);
for (var i = 1; i < setting.Value.Count; ++i) for (var i = 1; i < setting.Value.Count; ++i)
Im.Line.New(); Im.Line.New();
} }
} }
public static void DrawSettingsRight(ModSettings settings) private static void DrawSettingsRight(in ModSettings settings)
{ {
foreach (var setting in settings.Settings) foreach (var setting in settings.Settings)
{ {
if (setting.Value.Count == 0) if (setting.Value.Count == 0)
ImUtf8.Text("<None Enabled>"u8); Im.Text("<None Enabled>"u8);
else else
foreach (var option in setting.Value) foreach (var option in setting.Value)
ImUtf8.Text(option); Im.Text(option);
} }
} }
protected override bool IsSelected(CacheItem item, int globalIndex)
=> throw new NotImplementedException();
private sealed class ModFilter : TextFilterBase<CacheItem>
{
public override bool WouldBeVisible(in CacheItem item, int globalIndex)
=> base.WouldBeVisible(in item, globalIndex) || WouldBeVisible(item.Directory.Utf16);
protected override string ToFilterString(in CacheItem item, int globalIndex)
=> item.Name.Utf16;
}
} }

View file

@ -1,13 +1,7 @@
using Dalamud.Interface; using Glamourer.Designs;
using Dalamud.Interface.Utility;
using Glamourer.Designs;
using Glamourer.Interop.Material; using Glamourer.Interop.Material;
using Dalamud.Bindings.ImGui;
using ImSharp; using ImSharp;
using OtterGui.Extensions; using Luna;
using OtterGui.Raii;
using OtterGui.Text;
using static Glamourer.Gui.Tabs.HeaderDrawer;
namespace Glamourer.Gui.Tabs.DesignTab; namespace Glamourer.Gui.Tabs.DesignTab;
@ -17,9 +11,6 @@ public class MultiDesignPanel(
DesignColors colors, DesignColors colors,
Configuration config) Configuration config)
{ {
private readonly Button[] _leftButtons = [];
private readonly Button[] _rightButtons = []; //[new IncognitoButton(config)];
private readonly DesignColorCombo _colorCombo = new(colors, true); private readonly DesignColorCombo _colorCombo = new(colors, true);
public void Draw() public void Draw()
@ -27,13 +18,8 @@ public class MultiDesignPanel(
if (selector.SelectedPaths.Count == 0) if (selector.SelectedPaths.Count == 0)
return; return;
HeaderDrawer.Draw(string.Empty, 0, ImGuiColor.FrameBackground.Get().Color, _leftButtons, _rightButtons); var width = ImEx.ScaledVectorX(145);
using var child = ImUtf8.Child("##MultiPanel"u8, default, true); var treeNodePos = Im.Cursor.Position;
if (!child)
return;
var width = ImGuiHelpers.ScaledVector2(145, 0);
var treeNodePos = ImGui.GetCursorPos();
_numDesigns = DrawDesignList(); _numDesigns = DrawDesignList();
DrawCounts(treeNodePos); DrawCounts(treeNodePos);
var offset = DrawMultiTagger(width); var offset = DrawMultiTagger(width);
@ -49,18 +35,17 @@ public class MultiDesignPanel(
private void DrawCounts(Vector2 treeNodePos) private void DrawCounts(Vector2 treeNodePos)
{ {
var startPos = ImGui.GetCursorPos(); var startPos = Im.Cursor.Position;
var numFolders = selector.SelectedPaths.Count - _numDesigns; var numFolders = selector.SelectedPaths.Count - _numDesigns;
var text = (_numDesigns, numFolders) switch Im.Cursor.Position = treeNodePos;
ImEx.TextRightAligned((_numDesigns, numFolders) switch
{ {
(0, 0) => string.Empty, // should not happen (0, 0) => StringU8.Empty, // should not happen
( > 0, 0) => $"{_numDesigns} Designs", ( > 0, 0) => $"{_numDesigns} Designs",
(0, > 0) => $"{numFolders} Folders", (0, > 0) => $"{numFolders} Folders",
_ => $"{_numDesigns} Designs, {numFolders} Folders", _ => $"{_numDesigns} Designs, {numFolders} Folders",
}; });
ImGui.SetCursorPos(treeNodePos); Im.Cursor.Position = startPos;
ImUtf8.TextRightAligned(text);
ImGui.SetCursorPos(startPos);
} }
private void ResetCounts() private void ResetCounts()
@ -127,14 +112,14 @@ public class MultiDesignPanel(
{ {
using var id = Im.Id.Push(i++); using var id = Im.Id.Push(i++);
var (icon, text) = path is DesignFileSystem.Leaf l var (icon, text) = path is DesignFileSystem.Leaf l
? (FontAwesomeIcon.FileCircleMinus, l.Value.Name.Text) ? (LunaStyle.RemoveFileIcon, l.Value.Name.Text)
: (FontAwesomeIcon.FolderMinus, string.Empty); : (LunaStyle.RemoveFolderIcon, string.Empty);
ImGui.TableNextColumn(); table.NextColumn();
if (ImUtf8.IconButton(icon, "Remove from selection."u8, sizeType)) if (ImEx.Icon.Button(icon, "Remove from selection."u8, sizeType))
selector.RemovePathFromMultiSelection(path); selector.RemovePathFromMultiSelection(path);
ImUtf8.DrawFrameColumn(text); table.DrawFrameColumn(text);
ImUtf8.DrawFrameColumn(fullName); table.DrawFrameColumn(fullName);
if (CountLeaves(path)) if (CountLeaves(path))
++numDesigns; ++numDesigns;
@ -159,36 +144,32 @@ public class MultiDesignPanel(
private float DrawMultiTagger(Vector2 width) private float DrawMultiTagger(Vector2 width)
{ {
ImUtf8.TextFrameAligned("Multi Tagger:"u8); ImEx.TextFrameAligned("Multi Tagger:"u8);
Im.Line.Same(); Im.Line.Same();
var offset = ImGui.GetItemRectSize().X + Im.Style.WindowPadding.X; var offset = Im.Item.Size.X + Im.Style.WindowPadding.X;
ImGui.SetNextItemWidth(Im.ContentRegion.Available.X - 2 * (width.X + Im.Style.ItemSpacing.X)); Im.Item.SetNextWidth(Im.ContentRegion.Available.X - 2 * (width.X + Im.Style.ItemSpacing.X));
ImUtf8.InputText("##tag"u8, ref _tag, "Tag Name..."u8); Im.Input.Text("##tag"u8, ref _tag, "Tag Name..."u8);
UpdateTagCache(); UpdateTagCache();
var label = _addDesigns.Count > 0
? $"Add to {_addDesigns.Count} Designs"
: "Add";
var tooltip = _addDesigns.Count == 0
? _tag.Length == 0
? "No tag specified."
: $"All designs selected already contain the tag \"{_tag}\"."
: $"Add the tag \"{_tag}\" to {_addDesigns.Count} designs as a local tag:\n\n\t{string.Join("\n\t", _addDesigns.Select(m => m.Name.Text))}";
Im.Line.Same(); Im.Line.Same();
if (ImUtf8.ButtonEx(label, tooltip, width, _addDesigns.Count == 0)) if (ImEx.Button(_addDesigns.Count > 0
? $"Add to {_addDesigns.Count} Designs"
: "Add"u8, width, _addDesigns.Count is 0
? _tag.Length is 0
? "No tag specified."u8
: $"All designs selected already contain the tag \"{_tag}\"."
: $"Add the tag \"{_tag}\" to {_addDesigns.Count} designs as a local tag:\n\n\t{StringU8.Join("\n\t"u8, _addDesigns.Select(m => m.Name.Text))}", _addDesigns.Count is 0))
foreach (var design in _addDesigns) foreach (var design in _addDesigns)
editor.AddTag(design, _tag); editor.AddTag(design, _tag);
label = _removeDesigns.Count > 0
? $"Remove from {_removeDesigns.Count} Designs"
: "Remove";
tooltip = _removeDesigns.Count == 0
? _tag.Length == 0
? "No tag specified."
: $"No selected design contains the tag \"{_tag}\" locally."
: $"Remove the local tag \"{_tag}\" from {_removeDesigns.Count} designs:\n\n\t{string.Join("\n\t", _removeDesigns.Select(m => m.Item1.Name.Text))}";
Im.Line.Same(); Im.Line.Same();
if (ImUtf8.ButtonEx(label, tooltip, width, _removeDesigns.Count == 0)) if (ImEx.Button(_removeDesigns.Count > 0
? $"Remove from {_removeDesigns.Count} Designs"
: "Remove", width, _removeDesigns.Count is 0
? _tag.Length is 0
? "No tag specified."u8
: $"No selected design contains the tag \"{_tag}\" locally."
: $"Remove the local tag \"{_tag}\" from {_removeDesigns.Count} designs:\n\n\t{string.Join("\n\t", _removeDesigns.Select(m => m.Item1.Name.Text))}", _removeDesigns.Count is 0))
foreach (var (design, index) in _removeDesigns) foreach (var (design, index) in _removeDesigns)
editor.RemoveTag(design, index); editor.RemoveTag(design, index);
Im.Separator(); Im.Separator();
@ -197,24 +178,22 @@ public class MultiDesignPanel(
private void DrawMultiQuickDesignBar(float offset) private void DrawMultiQuickDesignBar(float offset)
{ {
ImUtf8.TextFrameAligned("Multi QDB:"u8); ImEx.TextFrameAligned("Multi QDB:"u8);
ImGui.SameLine(offset, Im.Style.ItemSpacing.X); Im.Line.Same(offset, Im.Style.ItemSpacing.X);
var buttonWidth = new Vector2((Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X) / 2, 0); var buttonWidth = new Vector2((Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X) / 2, 0);
var diff = _numDesigns - _numQuickDesignEnabled; var diff = _numDesigns - _numQuickDesignEnabled;
var tt = diff == 0 if (ImEx.Button("Display Selected Designs in QDB"u8, buttonWidth, diff is 0
? $"All {_numDesigns} selected designs are already displayed in the quick design bar." ? $"All {_numDesigns} selected designs are already displayed in the quick design bar."
: $"Display all {_numDesigns} selected designs in the quick design bar. Changes {diff} designs."; : $"Display all {_numDesigns} selected designs in the quick design bar. Changes {diff} designs.", diff is 0))
if (ImUtf8.ButtonEx("Display Selected Designs in QDB"u8, tt, buttonWidth, diff == 0))
{ {
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>()) foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>())
editor.SetQuickDesign(design.Value, true); editor.SetQuickDesign(design.Value, true);
} }
Im.Line.Same(); Im.Line.Same();
tt = _numQuickDesignEnabled == 0 if (ImEx.Button("Hide Selected Designs in QDB"u8, buttonWidth, _numQuickDesignEnabled is 0
? $"All {_numDesigns} selected designs are already hidden in the quick design bar." ? $"All {_numDesigns} selected designs are already hidden in the quick design bar."
: $"Hide all {_numDesigns} selected designs in the quick design bar. Changes {_numQuickDesignEnabled} designs."; : $"Hide all {_numDesigns} selected designs in the quick design bar. Changes {_numQuickDesignEnabled} designs.", _numQuickDesignEnabled is 0))
if (ImUtf8.ButtonEx("Hide Selected Designs in QDB"u8, tt, buttonWidth, _numQuickDesignEnabled == 0))
{ {
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>()) foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>())
editor.SetQuickDesign(design.Value, false); editor.SetQuickDesign(design.Value, false);
@ -225,22 +204,20 @@ public class MultiDesignPanel(
private void DrawMultiLock(float offset) private void DrawMultiLock(float offset)
{ {
ImUtf8.TextFrameAligned("Multi Lock:"u8); ImEx.TextFrameAligned("Multi Lock:"u8);
ImGui.SameLine(offset, Im.Style.ItemSpacing.X); Im.Line.Same(offset, Im.Style.ItemSpacing.X);
var buttonWidth = new Vector2((Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X) / 2, 0); var buttonWidth = new Vector2((Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X) / 2, 0);
var diff = _numDesigns - _numDesignsLocked; var diff = _numDesigns - _numDesignsLocked;
var tt = diff == 0 if (ImEx.Button("Turn Write-Protected"u8, buttonWidth, diff is 0
? $"All {_numDesigns} selected designs are already write protected." ? $"All {_numDesigns} selected designs are already write protected."
: $"Write-protect all {_numDesigns} designs. Changes {diff} designs."; : $"Write-protect all {_numDesigns} designs. Changes {diff} designs.", diff is 0))
if (ImUtf8.ButtonEx("Turn Write-Protected"u8, tt, buttonWidth, diff == 0))
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>()) foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>())
editor.SetWriteProtection(design.Value, true); editor.SetWriteProtection(design.Value, true);
Im.Line.Same(); Im.Line.Same();
tt = _numDesignsLocked == 0 if (ImEx.Button("Remove Write-Protection"u8, buttonWidth, _numDesignsLocked is 0
? $"None of the {_numDesigns} selected designs are write-protected." ? $"None of the {_numDesigns} selected designs are write-protected."
: $"Remove the write protection of the {_numDesigns} selected designs. Changes {_numDesignsLocked} designs."; : $"Remove the write protection of the {_numDesigns} selected designs. Changes {_numDesignsLocked} designs.", _numDesignsLocked is 0))
if (ImUtf8.ButtonEx("Remove Write-Protection"u8, tt, buttonWidth, _numDesignsLocked == 0))
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>()) foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>())
editor.SetWriteProtection(design.Value, false); editor.SetWriteProtection(design.Value, false);
Im.Separator(); Im.Separator();
@ -248,22 +225,20 @@ public class MultiDesignPanel(
private void DrawMultiResetSettings(float offset) private void DrawMultiResetSettings(float offset)
{ {
ImUtf8.TextFrameAligned("Settings:"u8); ImEx.TextFrameAligned("Settings:"u8);
ImGui.SameLine(offset, Im.Style.ItemSpacing.X); Im.Line.Same(offset, Im.Style.ItemSpacing.X);
var buttonWidth = new Vector2((Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X) / 2, 0); var buttonWidth = new Vector2((Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X) / 2, 0);
var diff = _numDesigns - _numDesignsResetSettings; var diff = _numDesigns - _numDesignsResetSettings;
var tt = diff == 0 if (ImEx.Button("Set Reset Temp. Settings"u8, buttonWidth, diff is 0
? $"All {_numDesigns} selected designs already reset temporary settings." ? $"All {_numDesigns} selected designs already reset temporary settings."
: $"Make all {_numDesigns} selected designs reset temporary settings. Changes {diff} designs."; : $"Make all {_numDesigns} selected designs reset temporary settings. Changes {diff} designs.", diff is 0))
if (ImUtf8.ButtonEx("Set Reset Temp. Settings"u8, tt, buttonWidth, diff == 0))
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>()) foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>())
editor.ChangeResetTemporarySettings(design.Value, true); editor.ChangeResetTemporarySettings(design.Value, true);
Im.Line.Same(); Im.Line.Same();
tt = _numDesignsResetSettings == 0 if (ImEx.Button("Remove Reset Temp. Settings"u8, buttonWidth, _numDesignsResetSettings is 0
? $"None of the {_numDesigns} selected designs reset temporary settings." ? $"None of the {_numDesigns} selected designs reset temporary settings."
: $"Stop all {_numDesigns} selected designs from resetting temporary settings. Changes {_numDesignsResetSettings} designs."; : $"Stop all {_numDesigns} selected designs from resetting temporary settings. Changes {_numDesignsResetSettings} designs.", _numDesignsResetSettings is 0))
if (ImUtf8.ButtonEx("Remove Reset Temp. Settings"u8, tt, buttonWidth, _numDesignsResetSettings == 0))
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>()) foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>())
editor.ChangeResetTemporarySettings(design.Value, false); editor.ChangeResetTemporarySettings(design.Value, false);
Im.Separator(); Im.Separator();
@ -271,22 +246,20 @@ public class MultiDesignPanel(
private void DrawMultiResetDyes(float offset) private void DrawMultiResetDyes(float offset)
{ {
ImUtf8.TextFrameAligned("Adv. Dyes:"u8); ImEx.TextFrameAligned("Adv. Dyes:"u8);
ImGui.SameLine(offset, Im.Style.ItemSpacing.X); Im.Line.Same(offset, Im.Style.ItemSpacing.X);
var buttonWidth = new Vector2((Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X) / 2, 0); var buttonWidth = new Vector2((Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X) / 2, 0);
var diff = _numDesigns - _numDesignsResetDyes; var diff = _numDesigns - _numDesignsResetDyes;
var tt = diff == 0 if (ImEx.Button("Set Reset Dyes"u8, buttonWidth, diff is 0
? $"All {_numDesigns} selected designs already reset advanced dyes." ? $"All {_numDesigns} selected designs already reset advanced dyes."
: $"Make all {_numDesigns} selected designs reset advanced dyes. Changes {diff} designs."; : $"Make all {_numDesigns} selected designs reset advanced dyes. Changes {diff} designs.", diff is 0))
if (ImUtf8.ButtonEx("Set Reset Dyes"u8, tt, buttonWidth, diff == 0))
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>()) foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>())
editor.ChangeResetAdvancedDyes(design.Value, true); editor.ChangeResetAdvancedDyes(design.Value, true);
Im.Line.Same(); Im.Line.Same();
tt = _numDesignsLocked == 0 if (ImEx.Button("Remove Reset Dyes"u8, buttonWidth, _numDesignsLocked is 0
? $"None of the {_numDesigns} selected designs reset advanced dyes." ? $"None of the {_numDesigns} selected designs reset advanced dyes."
: $"Stop all {_numDesigns} selected designs from resetting advanced dyes. Changes {_numDesignsResetDyes} designs."; : $"Stop all {_numDesigns} selected designs from resetting advanced dyes. Changes {_numDesignsResetDyes} designs.", _numDesignsResetDyes is 0))
if (ImUtf8.ButtonEx("Remove Reset Dyes"u8, tt, buttonWidth, _numDesignsResetDyes == 0))
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>()) foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>())
editor.ChangeResetAdvancedDyes(design.Value, false); editor.ChangeResetAdvancedDyes(design.Value, false);
Im.Separator(); Im.Separator();
@ -294,22 +267,20 @@ public class MultiDesignPanel(
private void DrawMultiForceRedraw(float offset) private void DrawMultiForceRedraw(float offset)
{ {
ImUtf8.TextFrameAligned("Redrawing:"u8); ImEx.TextFrameAligned("Redrawing:"u8);
ImGui.SameLine(offset, Im.Style.ItemSpacing.X); Im.Line.Same(offset, Im.Style.ItemSpacing.X);
var buttonWidth = new Vector2((Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X) / 2, 0); var buttonWidth = new Vector2((Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X) / 2, 0);
var diff = _numDesigns - _numDesignsForcedRedraw; var diff = _numDesigns - _numDesignsForcedRedraw;
var tt = diff == 0 if (ImEx.Button("Force Redraws"u8, buttonWidth, diff is 0
? $"All {_numDesigns} selected designs already force redraws." ? $"All {_numDesigns} selected designs already force redraws."
: $"Make all {_numDesigns} designs force redraws. Changes {diff} designs."; : $"Make all {_numDesigns} designs force redraws. Changes {diff} designs.", diff is 0))
if (ImUtf8.ButtonEx("Force Redraws"u8, tt, buttonWidth, diff == 0))
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>()) foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>())
editor.ChangeForcedRedraw(design.Value, true); editor.ChangeForcedRedraw(design.Value, true);
Im.Line.Same(); Im.Line.Same();
tt = _numDesignsLocked == 0 if (ImEx.Button("Remove Forced Redraws"u8, buttonWidth, _numDesignsLocked is 0
? $"None of the {_numDesigns} selected designs force redraws." ? $"None of the {_numDesigns} selected designs force redraws."
: $"Stop all {_numDesigns} selected designs from forcing redraws. Changes {_numDesignsForcedRedraw} designs."; : $"Stop all {_numDesigns} selected designs from forcing redraws. Changes {_numDesignsForcedRedraw} designs.", _numDesignsForcedRedraw is 0))
if (ImUtf8.ButtonEx("Remove Forced Redraws"u8, tt, buttonWidth, _numDesignsForcedRedraw == 0))
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>()) foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>())
editor.ChangeForcedRedraw(design.Value, false); editor.ChangeForcedRedraw(design.Value, false);
Im.Separator(); Im.Separator();
@ -319,39 +290,35 @@ public class MultiDesignPanel(
private void DrawMultiColor(Vector2 width, float offset) private void DrawMultiColor(Vector2 width, float offset)
{ {
ImUtf8.TextFrameAligned("Multi Colors:"u8); ImEx.TextFrameAligned("Multi Colors:"u8);
ImGui.SameLine(offset, Im.Style.ItemSpacing.X); Im.Line.Same(offset, Im.Style.ItemSpacing.X);
if (_colorCombo.Draw("##color"u8, _colorComboSelection, "Select a design color."u8, if (_colorCombo.Draw("##color"u8, _colorComboSelection, "Select a design color."u8,
Im.ContentRegion.Available.X - 2 * (width.X + Im.Style.ItemSpacing.X), out var newSelection)) Im.ContentRegion.Available.X - 2 * (width.X + Im.Style.ItemSpacing.X), out var newSelection))
_colorComboSelection = newSelection; _colorComboSelection = newSelection;
UpdateColorCache(); UpdateColorCache();
var label = _addDesigns.Count > 0 Im.Line.Same();
if (ImEx.Button(_addDesigns.Count > 0
? $"Set for {_addDesigns.Count} Designs" ? $"Set for {_addDesigns.Count} Designs"
: "Set"; : "Set"u8, width, _addDesigns.Count is 0
var tooltip = _addDesigns.Count is 0
? _colorComboSelection switch ? _colorComboSelection switch
{ {
null => "No color specified.", null => "No color specified."u8,
DesignColors.AutomaticName => "Use the other button to set to automatic.", DesignColors.AutomaticName => "Use the other button to set to automatic."u8,
_ => $"All designs selected are already set to the color \"{_colorComboSelection}\".", _ => $"All designs selected are already set to the color \"{_colorComboSelection}\".",
} }
: $"Set the color of {_addDesigns.Count} designs to \"{_colorComboSelection}\"\n\n\t{string.Join("\n\t", _addDesigns.Select(m => m.Name.Text))}"; : $"Set the color of {_addDesigns.Count} designs to \"{_colorComboSelection}\"\n\n\t{StringU8.Join("\n\t"u8, _addDesigns.Select(m => m.Name.Text))}", _addDesigns.Count is 0))
Im.Line.Same();
if (ImEx.Button(label, width, tooltip, _addDesigns.Count is 0))
{ {
foreach (var design in _addDesigns) foreach (var design in _addDesigns)
editor.ChangeColor(design, _colorComboSelection!); editor.ChangeColor(design, _colorComboSelection!);
} }
label = _removeDesigns.Count > 0
? $"Unset {_removeDesigns.Count} Designs"
: "Unset";
tooltip = _removeDesigns.Count == 0
? "No selected design is set to a non-automatic color."
: $"Set {_removeDesigns.Count} designs to use automatic color again:\n\n\t{string.Join("\n\t", _removeDesigns.Select(m => m.Item1.Name.Text))}";
Im.Line.Same(); Im.Line.Same();
if (ImEx.Button(label, width, tooltip, _removeDesigns.Count is 0)) if (ImEx.Button(_removeDesigns.Count > 0
? $"Unset {_removeDesigns.Count} Designs"
: "Unset"u8, width, _removeDesigns.Count is 0
? "No selected design is set to a non-automatic color."u8
: $"Set {_removeDesigns.Count} designs to use automatic color again:\n\n\t{StringU8.Join("\n\t"u8, _removeDesigns.Select(m => m.Item1.Name.Text))}", _removeDesigns.Count is 0))
{ {
foreach (var (design, _) in _removeDesigns) foreach (var (design, _) in _removeDesigns)
editor.ChangeColor(design, string.Empty); editor.ChangeColor(design, string.Empty);
@ -362,13 +329,12 @@ public class MultiDesignPanel(
private void DrawAdvancedButtons(float offset) private void DrawAdvancedButtons(float offset)
{ {
ImUtf8.TextFrameAligned("Delete Adv."u8); ImEx.TextFrameAligned("Delete Adv."u8);
ImGui.SameLine(offset, Im.Style.ItemSpacing.X); Im.Line.Same(offset, Im.Style.ItemSpacing.X);
var enabled = config.DeleteDesignModifier.IsActive(); var enabled = config.DeleteDesignModifier.IsActive();
var tt = _numDesignsWithAdvancedDyes is 0 if (ImEx.Button("Delete All Advanced Dyes"u8, Im.ContentRegion.Available with { Y = 0 }, _numDesignsWithAdvancedDyes is 0
? "No selected designs contain any advanced dyes." ? "No selected designs contain any advanced dyes."u8
: $"Delete {_numAdvancedDyes} advanced dyes from {_numDesignsWithAdvancedDyes} of the selected designs."; : $"Delete {_numAdvancedDyes} advanced dyes from {_numDesignsWithAdvancedDyes} of the selected designs.",
if (ImUtf8.ButtonEx("Delete All Advanced Dyes"u8, tt, new Vector2(Im.ContentRegion.Available.X, 0),
!enabled || _numDesignsWithAdvancedDyes is 0)) !enabled || _numDesignsWithAdvancedDyes is 0))
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>()) foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>())
@ -378,73 +344,74 @@ public class MultiDesignPanel(
} }
if (!enabled && _numDesignsWithAdvancedDyes is not 0) if (!enabled && _numDesignsWithAdvancedDyes is not 0)
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} while clicking to delete."); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} while clicking to delete.");
Im.Separator(); Im.Separator();
} }
private void DrawApplicationButtons(float offset) private void DrawApplicationButtons(float offset)
{ {
ImUtf8.TextFrameAligned("Application"u8); ImEx.TextFrameAligned("Application"u8);
ImGui.SameLine(offset, Im.Style.ItemSpacing.X); Im.Line.Same(offset, Im.Style.ItemSpacing.X);
var width = new Vector2((Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X) / 2, 0); var width = new Vector2((Im.ContentRegion.Available.X - Im.Style.ItemSpacing.X) / 2, 0);
var enabled = config.DeleteDesignModifier.IsActive(); var enabled = config.DeleteDesignModifier.IsActive();
bool? equip = null; bool? equip = null;
bool? customize = null; bool? customize = null;
var group = ImUtf8.Group(); using (Im.Group())
if (ImUtf8.ButtonEx("Disable Everything"u8, {
if (ImEx.Button("Disable Everything"u8, width,
_numDesigns > 0 _numDesigns > 0
? $"Disable application of everything, including any existing advanced dyes, advanced customizations, crests and wetness for all {_numDesigns} designs." ? $"Disable application of everything, including any existing advanced dyes, advanced customizations, crests and wetness for all {_numDesigns} designs."
: "No designs selected.", width, !enabled)) : "No designs selected."u8, !enabled))
{ {
equip = false; equip = false;
customize = false; customize = false;
} }
if (!enabled) if (!enabled)
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} while clicking."); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} while clicking.");
Im.Line.Same(); Im.Line.Same();
if (ImUtf8.ButtonEx("Enable Everything"u8, if (ImEx.Button("Enable Everything"u8, width,
_numDesigns > 0 _numDesigns > 0
? $"Enable application of everything, including any existing advanced dyes, advanced customizations, crests and wetness for all {_numDesigns} designs." ? $"Enable application of everything, including any existing advanced dyes, advanced customizations, crests and wetness for all {_numDesigns} designs."
: "No designs selected.", width, !enabled)) : "No designs selected."u8, !enabled))
{ {
equip = true; equip = true;
customize = true; customize = true;
} }
if (!enabled) if (!enabled)
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} while clicking."); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} while clicking.");
if (ImUtf8.ButtonEx("Equipment Only"u8, if (ImEx.Button("Equipment Only"u8, width,
_numDesigns > 0 _numDesigns > 0
? $"Enable application of anything related to gear, disable anything that is not related to gear for all {_numDesigns} designs." ? $"Enable application of anything related to gear, disable anything that is not related to gear for all {_numDesigns} designs."
: "No designs selected.", width, !enabled)) : "No designs selected."u8, !enabled))
{ {
equip = true; equip = true;
customize = false; customize = false;
} }
if (!enabled) if (!enabled)
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} while clicking."); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} while clicking.");
Im.Line.Same(); Im.Line.Same();
if (ImUtf8.ButtonEx("Customization Only"u8, if (ImEx.Button("Customization Only"u8, width,
_numDesigns > 0 _numDesigns > 0
? $"Enable application of anything related to customization, disable anything that is not related to customization for all {_numDesigns} designs." ? $"Enable application of anything related to customization, disable anything that is not related to customization for all {_numDesigns} designs."
: "No designs selected.", width, !enabled)) : "No designs selected."u8, !enabled))
{ {
equip = false; equip = false;
customize = true; customize = true;
} }
if (!enabled) if (!enabled)
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} while clicking."); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} while clicking.");
if (ImUtf8.ButtonEx("Default Application"u8, if (ImEx.Button("Default Application"u8, width,
_numDesigns > 0 _numDesigns > 0
? $"Set the application rules to the default values as if the {_numDesigns} were newly created,without any advanced features or wetness." ? $"Set the application rules to the default values as if the {_numDesigns} were newly created,without any advanced features or wetness."
: "No designs selected.", width, !enabled)) : "No designs selected."u8, !enabled))
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>().Select(l => l.Value)) foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>().Select(l => l.Value))
{ {
editor.ChangeApplyMulti(design, true, true, true, false, true, true, false, true); editor.ChangeApplyMulti(design, true, true, true, false, true, true, false, true);
@ -452,19 +419,19 @@ public class MultiDesignPanel(
} }
if (!enabled) if (!enabled)
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} while clicking."); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} while clicking.");
Im.Line.Same(); Im.Line.Same();
if (ImUtf8.ButtonEx("Disable Advanced"u8, _numDesigns > 0 if (ImEx.Button("Disable Advanced"u8, width, _numDesigns > 0
? $"Disable all advanced dyes and customizations but keep everything else as is for all {_numDesigns} designs." ? $"Disable all advanced dyes and customizations but keep everything else as is for all {_numDesigns} designs."
: "No designs selected.", width, !enabled)) : "No designs selected."u8, !enabled))
foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>().Select(l => l.Value)) foreach (var design in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>().Select(l => l.Value))
editor.ChangeApplyMulti(design, null, null, null, false, null, null, false, null); editor.ChangeApplyMulti(design, null, null, null, false, null, null, false, null);
if (!enabled) if (!enabled)
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} while clicking."); Im.Tooltip.OnHover(HoveredFlags.AllowWhenDisabled, $"Hold {config.DeleteDesignModifier} while clicking.");
}
group.Dispose();
Im.Separator(); Im.Separator();
if (equip is null && customize is null) if (equip is null && customize is null)
return; return;
@ -489,7 +456,7 @@ public class MultiDesignPanel(
{ {
_addDesigns.Clear(); _addDesigns.Clear();
_removeDesigns.Clear(); _removeDesigns.Clear();
if (_tag.Length == 0) if (_tag.Length is 0)
return; return;
foreach (var leaf in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>()) foreach (var leaf in selector.SelectedPaths.OfType<DesignFileSystem.Leaf>())

2
Luna

@ -1 +1 @@
Subproject commit e80bdf5c10c6c30efccdff7d1adcb4a638eba4df Subproject commit 0ee15af5c45b6c72df25b972e48b9a57347c25a5