mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
666 lines
27 KiB
C#
666 lines
27 KiB
C#
using Dalamud.Interface;
|
|
using Dalamud.Interface.ImGuiFileDialog;
|
|
using Dalamud.Interface.ImGuiNotification;
|
|
using FFXIVClientStructs.FFXIV.Client.System.Framework;
|
|
using Glamourer.Api.Enums;
|
|
using Glamourer.Automation;
|
|
using Glamourer.Designs;
|
|
using Glamourer.Designs.History;
|
|
using Glamourer.GameData;
|
|
using Glamourer.Gui.Customization;
|
|
using Glamourer.Gui.Equipment;
|
|
using Glamourer.Gui.Materials;
|
|
using Glamourer.Interop;
|
|
using Glamourer.State;
|
|
using ImGuiNET;
|
|
using OtterGui;
|
|
using OtterGui.Classes;
|
|
using OtterGui.Raii;
|
|
using OtterGui.Text;
|
|
using OtterGuiInternal.Structs;
|
|
using Penumbra.GameData.Enums;
|
|
using static Glamourer.Gui.Tabs.HeaderDrawer;
|
|
|
|
namespace Glamourer.Gui.Tabs.DesignTab;
|
|
|
|
public class DesignPanel
|
|
{
|
|
private readonly FileDialogManager _fileDialog = new();
|
|
private readonly DesignFileSystemSelector _selector;
|
|
private readonly CustomizationDrawer _customizationDrawer;
|
|
private readonly DesignManager _manager;
|
|
private readonly ObjectManager _objects;
|
|
private readonly StateManager _state;
|
|
private readonly EquipmentDrawer _equipmentDrawer;
|
|
private readonly ModAssociationsTab _modAssociations;
|
|
private readonly Configuration _config;
|
|
private readonly DesignDetailTab _designDetails;
|
|
private readonly ImportService _importService;
|
|
private readonly DesignConverter _converter;
|
|
private readonly MultiDesignPanel _multiDesignPanel;
|
|
private readonly CustomizeParameterDrawer _parameterDrawer;
|
|
private readonly DesignLinkDrawer _designLinkDrawer;
|
|
private readonly MaterialDrawer _materials;
|
|
private readonly EditorHistory _history;
|
|
private readonly Button[] _leftButtons;
|
|
private readonly Button[] _rightButtons;
|
|
|
|
|
|
public DesignPanel(DesignFileSystemSelector selector,
|
|
CustomizationDrawer customizationDrawer,
|
|
DesignManager manager,
|
|
ObjectManager objects,
|
|
StateManager state,
|
|
EquipmentDrawer equipmentDrawer,
|
|
ModAssociationsTab modAssociations,
|
|
Configuration config,
|
|
DesignDetailTab designDetails,
|
|
DesignConverter converter,
|
|
ImportService importService,
|
|
MultiDesignPanel multiDesignPanel,
|
|
CustomizeParameterDrawer parameterDrawer,
|
|
DesignLinkDrawer designLinkDrawer,
|
|
MaterialDrawer materials,
|
|
EditorHistory history)
|
|
{
|
|
_selector = selector;
|
|
_customizationDrawer = customizationDrawer;
|
|
_manager = manager;
|
|
_objects = objects;
|
|
_state = state;
|
|
_equipmentDrawer = equipmentDrawer;
|
|
_modAssociations = modAssociations;
|
|
_config = config;
|
|
_designDetails = designDetails;
|
|
_importService = importService;
|
|
_converter = converter;
|
|
_multiDesignPanel = multiDesignPanel;
|
|
_parameterDrawer = parameterDrawer;
|
|
_designLinkDrawer = designLinkDrawer;
|
|
_materials = materials;
|
|
_history = history;
|
|
_leftButtons =
|
|
[
|
|
new SetFromClipboardButton(this),
|
|
new DesignUndoButton(this),
|
|
new ExportToClipboardButton(this),
|
|
new ApplyCharacterButton(this),
|
|
new UndoButton(this),
|
|
];
|
|
_rightButtons =
|
|
[
|
|
new LockButton(this),
|
|
new IncognitoButton(_config.Ephemeral),
|
|
];
|
|
}
|
|
|
|
private void DrawHeader()
|
|
=> HeaderDrawer.Draw(SelectionName, 0, ImGui.GetColorU32(ImGuiCol.FrameBg), _leftButtons, _rightButtons);
|
|
|
|
private string SelectionName
|
|
=> _selector.Selected == null ? "No Selection" : _selector.IncognitoMode ? _selector.Selected.Incognito : _selector.Selected.Name.Text;
|
|
|
|
private void DrawEquipment()
|
|
{
|
|
using var h = ImRaii.CollapsingHeader("Equipment");
|
|
if (!h)
|
|
return;
|
|
|
|
_equipmentDrawer.Prepare();
|
|
|
|
var usedAllStain = _equipmentDrawer.DrawAllStain(out var newAllStain, _selector.Selected!.WriteProtected());
|
|
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
|
{
|
|
var data = EquipDrawData.FromDesign(_manager, _selector.Selected!, slot);
|
|
_equipmentDrawer.DrawEquip(data);
|
|
if (usedAllStain)
|
|
_manager.ChangeStains(_selector.Selected, slot, newAllStain);
|
|
}
|
|
|
|
var mainhand = EquipDrawData.FromDesign(_manager, _selector.Selected!, EquipSlot.MainHand);
|
|
var offhand = EquipDrawData.FromDesign(_manager, _selector.Selected!, EquipSlot.OffHand);
|
|
_equipmentDrawer.DrawWeapons(mainhand, offhand, true);
|
|
|
|
foreach (var slot in BonusExtensions.AllFlags)
|
|
{
|
|
var data = BonusDrawData.FromDesign(_manager, _selector.Selected!, slot);
|
|
_equipmentDrawer.DrawBonusItem(data);
|
|
}
|
|
|
|
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
|
DrawEquipmentMetaToggles();
|
|
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
|
}
|
|
|
|
private void DrawEquipmentMetaToggles()
|
|
{
|
|
using (var _ = ImRaii.Group())
|
|
{
|
|
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.HatState, _manager, _selector.Selected!));
|
|
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.CrestFromDesign(CrestFlag.Head, _manager, _selector.Selected!));
|
|
}
|
|
|
|
ImGui.SameLine();
|
|
using (var _ = ImRaii.Group())
|
|
{
|
|
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.VisorState, _manager, _selector.Selected!));
|
|
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.CrestFromDesign(CrestFlag.Body, _manager, _selector.Selected!));
|
|
}
|
|
|
|
ImGui.SameLine();
|
|
using (var _ = ImRaii.Group())
|
|
{
|
|
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.WeaponState, _manager, _selector.Selected!));
|
|
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.CrestFromDesign(CrestFlag.OffHand, _manager, _selector.Selected!));
|
|
}
|
|
}
|
|
|
|
private void DrawCustomize()
|
|
{
|
|
var header = _selector.Selected!.DesignData.ModelId == 0
|
|
? "Customization"
|
|
: $"Customization (Model Id #{_selector.Selected!.DesignData.ModelId})###Customization";
|
|
using var h = ImRaii.CollapsingHeader(header);
|
|
if (!h)
|
|
return;
|
|
|
|
if (_customizationDrawer.Draw(_selector.Selected!.DesignData.Customize, _selector.Selected.Application.Customize,
|
|
_selector.Selected!.WriteProtected(), false))
|
|
foreach (var idx in Enum.GetValues<CustomizeIndex>())
|
|
{
|
|
var flag = idx.ToFlag();
|
|
var newValue = _customizationDrawer.ChangeApply.HasFlag(flag);
|
|
_manager.ChangeApplyCustomize(_selector.Selected, idx, newValue);
|
|
if (_customizationDrawer.Changed.HasFlag(flag))
|
|
_manager.ChangeCustomize(_selector.Selected, idx, _customizationDrawer.Customize[idx]);
|
|
}
|
|
|
|
EquipmentDrawer.DrawMetaToggle(ToggleDrawData.FromDesign(MetaIndex.Wetness, _manager, _selector.Selected!));
|
|
ImGui.Dummy(new Vector2(ImGui.GetTextLineHeight() / 2));
|
|
}
|
|
|
|
private void DrawCustomizeParameters()
|
|
{
|
|
if (!_config.UseAdvancedParameters)
|
|
return;
|
|
|
|
using var h = ImRaii.CollapsingHeader("Advanced Customizations");
|
|
if (!h)
|
|
return;
|
|
|
|
_parameterDrawer.Draw(_manager, _selector.Selected!);
|
|
}
|
|
|
|
private void DrawMaterialValues()
|
|
{
|
|
if (!_config.UseAdvancedDyes)
|
|
return;
|
|
|
|
using var h = ImRaii.CollapsingHeader("Advanced Dyes");
|
|
if (!h)
|
|
return;
|
|
|
|
_materials.Draw(_selector.Selected!);
|
|
}
|
|
|
|
private void DrawCustomizeApplication()
|
|
{
|
|
using var id = ImRaii.PushId("Customizations");
|
|
var set = _selector.Selected!.CustomizeSet;
|
|
var available = set.SettingAvailable | CustomizeFlag.Clan | CustomizeFlag.Gender | CustomizeFlag.BodyType;
|
|
var flags = _selector.Selected!.ApplyCustomizeExcludingBodyType == 0 ? 0 :
|
|
(_selector.Selected!.ApplyCustomize & available) == available ? 3 : 1;
|
|
if (ImGui.CheckboxFlags("Apply All Customizations", ref flags, 3))
|
|
{
|
|
var newFlags = flags == 3;
|
|
_manager.ChangeApplyCustomize(_selector.Selected!, CustomizeIndex.Clan, newFlags);
|
|
_manager.ChangeApplyCustomize(_selector.Selected!, CustomizeIndex.Gender, newFlags);
|
|
foreach (var index in CustomizationExtensions.AllBasic)
|
|
_manager.ChangeApplyCustomize(_selector.Selected!, index, newFlags);
|
|
}
|
|
|
|
var applyClan = _selector.Selected!.DoApplyCustomize(CustomizeIndex.Clan);
|
|
if (ImGui.Checkbox($"Apply {CustomizeIndex.Clan.ToDefaultName()}", ref applyClan))
|
|
_manager.ChangeApplyCustomize(_selector.Selected!, CustomizeIndex.Clan, applyClan);
|
|
|
|
var applyGender = _selector.Selected!.DoApplyCustomize(CustomizeIndex.Gender);
|
|
if (ImGui.Checkbox($"Apply {CustomizeIndex.Gender.ToDefaultName()}", ref applyGender))
|
|
_manager.ChangeApplyCustomize(_selector.Selected!, CustomizeIndex.Gender, applyGender);
|
|
|
|
|
|
foreach (var index in CustomizationExtensions.All.Where(set.IsAvailable))
|
|
{
|
|
var apply = _selector.Selected!.DoApplyCustomize(index);
|
|
if (ImGui.Checkbox($"Apply {set.Option(index)}", ref apply))
|
|
_manager.ChangeApplyCustomize(_selector.Selected!, index, apply);
|
|
}
|
|
}
|
|
|
|
private void DrawCrestApplication()
|
|
{
|
|
using var id = ImRaii.PushId("Crests");
|
|
var flags = (uint)_selector.Selected!.Application.Crest;
|
|
var bigChange = ImGui.CheckboxFlags("Apply All Crests", ref flags, (uint)CrestExtensions.AllRelevant);
|
|
foreach (var flag in CrestExtensions.AllRelevantSet)
|
|
{
|
|
var apply = bigChange ? ((CrestFlag)flags & flag) == flag : _selector.Selected!.DoApplyCrest(flag);
|
|
if (ImGui.Checkbox($"Apply {flag.ToLabel()} Crest", ref apply) || bigChange)
|
|
_manager.ChangeApplyCrest(_selector.Selected!, flag, apply);
|
|
}
|
|
}
|
|
|
|
private void DrawApplicationRules()
|
|
{
|
|
using var h = ImRaii.CollapsingHeader("Application Rules");
|
|
if (!h)
|
|
return;
|
|
|
|
using var disabled = ImRaii.Disabled(_selector.Selected!.WriteProtected());
|
|
|
|
using (var _ = ImRaii.Group())
|
|
{
|
|
DrawCustomizeApplication();
|
|
ImUtf8.IconDummy();
|
|
DrawCrestApplication();
|
|
ImUtf8.IconDummy();
|
|
if (_config.UseAdvancedParameters)
|
|
{
|
|
DrawMetaApplication();
|
|
ImUtf8.IconDummy();
|
|
DrawBonusSlotApplication();
|
|
}
|
|
}
|
|
|
|
ImGui.SameLine(ImGui.GetContentRegionAvail().X / 2);
|
|
using (var _ = ImRaii.Group())
|
|
{
|
|
void ApplyEquip(string label, EquipFlag allFlags, bool stain, IEnumerable<EquipSlot> slots)
|
|
{
|
|
var flags = (uint)(allFlags & _selector.Selected!.Application.Equip);
|
|
using var id = ImRaii.PushId(label);
|
|
var bigChange = ImGui.CheckboxFlags($"Apply All {label}", ref flags, (uint)allFlags);
|
|
if (stain)
|
|
foreach (var slot in slots)
|
|
{
|
|
var apply = bigChange ? ((EquipFlag)flags).HasFlag(slot.ToStainFlag()) : _selector.Selected!.DoApplyStain(slot);
|
|
if (ImGui.Checkbox($"Apply {slot.ToName()} Dye", ref apply) || bigChange)
|
|
_manager.ChangeApplyStains(_selector.Selected!, slot, apply);
|
|
}
|
|
else
|
|
foreach (var slot in slots)
|
|
{
|
|
var apply = bigChange ? ((EquipFlag)flags).HasFlag(slot.ToFlag()) : _selector.Selected!.DoApplyEquip(slot);
|
|
if (ImGui.Checkbox($"Apply {slot.ToName()}", ref apply) || bigChange)
|
|
_manager.ChangeApplyItem(_selector.Selected!, slot, apply);
|
|
}
|
|
}
|
|
|
|
ApplyEquip("Weapons", ApplicationTypeExtensions.WeaponFlags, false, new[]
|
|
{
|
|
EquipSlot.MainHand,
|
|
EquipSlot.OffHand,
|
|
});
|
|
|
|
ImUtf8.IconDummy();
|
|
ApplyEquip("Armor", ApplicationTypeExtensions.ArmorFlags, false, EquipSlotExtensions.EquipmentSlots);
|
|
|
|
ImUtf8.IconDummy();
|
|
ApplyEquip("Accessories", ApplicationTypeExtensions.AccessoryFlags, false, EquipSlotExtensions.AccessorySlots);
|
|
|
|
ImUtf8.IconDummy();
|
|
ApplyEquip("Dyes", ApplicationTypeExtensions.StainFlags, true,
|
|
EquipSlotExtensions.FullSlots);
|
|
|
|
ImUtf8.IconDummy();
|
|
if (_config.UseAdvancedParameters)
|
|
{
|
|
DrawParameterApplication();
|
|
}
|
|
else
|
|
{
|
|
DrawMetaApplication();
|
|
ImUtf8.IconDummy();
|
|
DrawBonusSlotApplication();
|
|
}
|
|
}
|
|
}
|
|
|
|
private static readonly IReadOnlyList<string> MetaLabels =
|
|
[
|
|
"Apply Wetness",
|
|
"Apply Hat Visibility",
|
|
"Apply Visor State",
|
|
"Apply Weapon Visibility",
|
|
];
|
|
|
|
private void DrawMetaApplication()
|
|
{
|
|
using var id = ImRaii.PushId("Meta");
|
|
const uint all = (uint)MetaExtensions.All;
|
|
var flags = (uint)_selector.Selected!.Application.Meta;
|
|
var bigChange = ImGui.CheckboxFlags("Apply All Meta Changes", ref flags, all);
|
|
|
|
foreach (var (index, label) in MetaExtensions.AllRelevant.Zip(MetaLabels))
|
|
{
|
|
var apply = bigChange ? ((MetaFlag)flags).HasFlag(index.ToFlag()) : _selector.Selected!.DoApplyMeta(index);
|
|
if (ImGui.Checkbox(label, ref apply) || bigChange)
|
|
_manager.ChangeApplyMeta(_selector.Selected!, index, apply);
|
|
}
|
|
}
|
|
|
|
private static readonly IReadOnlyList<string> BonusSlotLabels =
|
|
[
|
|
"Apply Facewear",
|
|
];
|
|
|
|
private void DrawBonusSlotApplication()
|
|
{
|
|
using var id = ImUtf8.PushId("Bonus"u8);
|
|
var flags = _selector.Selected!.Application.BonusItem;
|
|
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))
|
|
{
|
|
var apply = bigChange ? flags.HasFlag(index) : _selector.Selected!.DoApplyBonusItem(index);
|
|
if (ImUtf8.Checkbox(label, ref apply) || bigChange)
|
|
_manager.ChangeApplyBonusItem(_selector.Selected!, index, apply);
|
|
}
|
|
}
|
|
|
|
|
|
private void DrawParameterApplication()
|
|
{
|
|
using var id = ImRaii.PushId("Parameter");
|
|
var flags = (uint)_selector.Selected!.Application.Parameters;
|
|
var bigChange = ImGui.CheckboxFlags("Apply All Customize Parameters", ref flags, (uint)CustomizeParameterExtensions.All);
|
|
foreach (var flag in CustomizeParameterExtensions.AllFlags)
|
|
{
|
|
var apply = bigChange ? ((CustomizeParameterFlag)flags).HasFlag(flag) : _selector.Selected!.DoApplyParameter(flag);
|
|
if (ImGui.Checkbox($"Apply {flag.ToName()}", ref apply) || bigChange)
|
|
_manager.ChangeApplyParameter(_selector.Selected!, flag, apply);
|
|
}
|
|
}
|
|
|
|
public void Draw()
|
|
{
|
|
using var group = ImRaii.Group();
|
|
if (_selector.SelectedPaths.Count > 1)
|
|
{
|
|
_multiDesignPanel.Draw();
|
|
}
|
|
else
|
|
{
|
|
DrawHeader();
|
|
DrawPanel();
|
|
|
|
if (_selector.Selected == null || _selector.Selected.WriteProtected())
|
|
return;
|
|
|
|
if (_importService.CreateDatTarget(out var dat))
|
|
{
|
|
_manager.ChangeCustomize(_selector.Selected!, CustomizeIndex.Clan, dat.Customize[CustomizeIndex.Clan]);
|
|
_manager.ChangeCustomize(_selector.Selected!, CustomizeIndex.Gender, dat.Customize[CustomizeIndex.Gender]);
|
|
foreach (var idx in CustomizationExtensions.AllBasic)
|
|
_manager.ChangeCustomize(_selector.Selected!, idx, dat.Customize[idx]);
|
|
Glamourer.Messager.NotificationMessage(
|
|
$"Applied games .dat file {dat.Description} customizations to {_selector.Selected.Name}.", NotificationType.Success, false);
|
|
}
|
|
else if (_importService.CreateCharaTarget(out var designBase, out var name))
|
|
{
|
|
_manager.ApplyDesign(_selector.Selected!, designBase);
|
|
Glamourer.Messager.NotificationMessage($"Applied Anamnesis .chara file {name} to {_selector.Selected.Name}.",
|
|
NotificationType.Success, false);
|
|
}
|
|
}
|
|
|
|
_importService.CreateDatSource();
|
|
}
|
|
|
|
private void DrawPanel()
|
|
{
|
|
using var table = ImUtf8.Table("##Panel", 1, ImGuiTableFlags.BordersOuter | ImGuiTableFlags.ScrollY, ImGui.GetContentRegionAvail());
|
|
if (!table || _selector.Selected == null)
|
|
return;
|
|
ImGui.TableSetupScrollFreeze(0, 1);
|
|
ImGui.TableNextColumn();
|
|
if (_selector.Selected == null)
|
|
return;
|
|
ImGui.Dummy(Vector2.Zero);
|
|
DrawButtonRow();
|
|
ImGui.TableNextColumn();
|
|
|
|
DrawCustomize();
|
|
DrawEquipment();
|
|
DrawCustomizeParameters();
|
|
DrawMaterialValues();
|
|
_designDetails.Draw();
|
|
DrawApplicationRules();
|
|
_modAssociations.Draw();
|
|
_designLinkDrawer.Draw();
|
|
}
|
|
|
|
private void DrawButtonRow()
|
|
{
|
|
DrawApplyToSelf();
|
|
ImGui.SameLine();
|
|
DrawApplyToTarget();
|
|
ImGui.SameLine();
|
|
_modAssociations.DrawApplyButton();
|
|
ImGui.SameLine();
|
|
DrawSaveToDat();
|
|
}
|
|
|
|
|
|
private void DrawApplyToSelf()
|
|
{
|
|
var (id, data) = _objects.PlayerData;
|
|
if (!ImGuiUtil.DrawDisabledButton("Apply to Yourself", Vector2.Zero,
|
|
"Apply the current design with its settings to your character.\nHold Control to only apply gear.\nHold Shift to only apply customizations.",
|
|
!data.Valid))
|
|
return;
|
|
|
|
if (_state.GetOrCreate(id, data.Objects[0], out var state))
|
|
{
|
|
using var _ = _selector.Selected!.TemporarilyRestrictApplication(ApplicationCollection.FromKeys());
|
|
_state.ApplyDesign(state, _selector.Selected!, ApplySettings.ManualWithLinks with { IsFinal = true });
|
|
}
|
|
}
|
|
|
|
private void DrawApplyToTarget()
|
|
{
|
|
var (id, data) = _objects.TargetData;
|
|
var tt = id.IsValid
|
|
? data.Valid
|
|
? "Apply the current design with its settings to your current target.\nHold Control to only apply gear.\nHold Shift to only apply customizations."
|
|
: "The current target can not be manipulated."
|
|
: "No valid target selected.";
|
|
if (!ImGuiUtil.DrawDisabledButton("Apply to Target", Vector2.Zero, tt, !data.Valid))
|
|
return;
|
|
|
|
if (_state.GetOrCreate(id, data.Objects[0], out var state))
|
|
{
|
|
using var _ = _selector.Selected!.TemporarilyRestrictApplication(ApplicationCollection.FromKeys());
|
|
_state.ApplyDesign(state, _selector.Selected!, ApplySettings.ManualWithLinks with { IsFinal = true });
|
|
}
|
|
}
|
|
|
|
private void DrawSaveToDat()
|
|
{
|
|
var verified = _importService.Verify(_selector.Selected!.DesignData.Customize, out _);
|
|
var tt = verified
|
|
? "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.";
|
|
var startPath = GetUserPath();
|
|
if (startPath.Length == 0)
|
|
startPath = null;
|
|
if (ImGuiUtil.DrawDisabledButton("Export to Dat", Vector2.Zero, tt, !verified))
|
|
_fileDialog.SaveFileDialog("Save File...", ".dat", "FFXIV_CHARA_01.dat", ".dat", (v, path) =>
|
|
{
|
|
if (v && _selector.Selected != null)
|
|
_importService.SaveDesignAsDat(path, _selector.Selected!.DesignData.Customize, _selector.Selected!.Name);
|
|
}, startPath);
|
|
|
|
_fileDialog.Draw();
|
|
}
|
|
|
|
private static unsafe string GetUserPath()
|
|
=> Framework.Instance()->UserPathString;
|
|
|
|
|
|
private sealed class LockButton(DesignPanel panel) : Button
|
|
{
|
|
public override bool Visible
|
|
=> panel._selector.Selected != null;
|
|
|
|
protected override string Description
|
|
=> panel._selector.Selected!.WriteProtected()
|
|
? "Make this design editable."
|
|
: "Write-protect this design.";
|
|
|
|
protected override FontAwesomeIcon Icon
|
|
=> panel._selector.Selected!.WriteProtected()
|
|
? FontAwesomeIcon.Lock
|
|
: FontAwesomeIcon.LockOpen;
|
|
|
|
protected override void OnClick()
|
|
=> panel._manager.SetWriteProtection(panel._selector.Selected!, !panel._selector.Selected!.WriteProtected());
|
|
}
|
|
|
|
private sealed class SetFromClipboardButton(DesignPanel panel) : Button
|
|
{
|
|
public override bool Visible
|
|
=> panel._selector.Selected != null;
|
|
|
|
protected override bool Disabled
|
|
=> panel._selector.Selected?.WriteProtected() ?? true;
|
|
|
|
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.";
|
|
|
|
protected override FontAwesomeIcon Icon
|
|
=> FontAwesomeIcon.Clipboard;
|
|
|
|
protected override void OnClick()
|
|
{
|
|
try
|
|
{
|
|
var text = ImGui.GetClipboardText();
|
|
var (applyEquip, applyCustomize) = UiHelpers.ConvertKeysToBool();
|
|
var design = panel._converter.FromBase64(text, applyCustomize, applyEquip, out _)
|
|
?? throw new Exception("The clipboard did not contain valid data.");
|
|
panel._manager.ApplyDesign(panel._selector.Selected!, design);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Glamourer.Messager.NotificationMessage(ex, $"Could not apply clipboard to {panel._selector.Selected!.Name}.",
|
|
$"Could not apply clipboard to design {panel._selector.Selected!.Identifier}", NotificationType.Error, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
private sealed class DesignUndoButton(DesignPanel panel) : Button
|
|
{
|
|
public override bool Visible
|
|
=> panel._selector.Selected != null;
|
|
|
|
protected override bool Disabled
|
|
=> !panel._manager.CanUndo(panel._selector.Selected) || (panel._selector.Selected?.WriteProtected() ?? true);
|
|
|
|
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.";
|
|
|
|
protected override FontAwesomeIcon Icon
|
|
=> FontAwesomeIcon.SyncAlt;
|
|
|
|
protected override void OnClick()
|
|
{
|
|
try
|
|
{
|
|
panel._manager.UndoDesignChange(panel._selector.Selected!);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Glamourer.Messager.NotificationMessage(ex, $"Could not undo last changes to {panel._selector.Selected!.Name}.",
|
|
NotificationType.Error,
|
|
false);
|
|
}
|
|
}
|
|
}
|
|
|
|
private sealed class ExportToClipboardButton(DesignPanel panel) : Button
|
|
{
|
|
public override bool Visible
|
|
=> panel._selector.Selected != null;
|
|
|
|
protected override string Description
|
|
=> "Copy the current design to your clipboard.";
|
|
|
|
protected override FontAwesomeIcon Icon
|
|
=> FontAwesomeIcon.Copy;
|
|
|
|
protected override void OnClick()
|
|
{
|
|
try
|
|
{
|
|
var text = panel._converter.ShareBase64(panel._selector.Selected!);
|
|
ImGui.SetClipboardText(text);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Glamourer.Messager.NotificationMessage(ex, $"Could not copy {panel._selector.Selected!.Name} data to clipboard.",
|
|
$"Could not copy data from design {panel._selector.Selected!.Identifier} to clipboard", NotificationType.Error, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
private sealed class ApplyCharacterButton(DesignPanel panel) : Button
|
|
{
|
|
public override bool Visible
|
|
=> panel._selector.Selected != null && panel._objects.Player.Valid;
|
|
|
|
protected override string Description
|
|
=> "Overwrite this design with your character's current state.";
|
|
|
|
protected override bool Disabled
|
|
=> panel._selector.Selected?.WriteProtected() ?? true;
|
|
|
|
protected override FontAwesomeIcon Icon
|
|
=> FontAwesomeIcon.UserEdit;
|
|
|
|
protected override void OnClick()
|
|
{
|
|
try
|
|
{
|
|
var (player, actor) = panel._objects.PlayerData;
|
|
if (!player.IsValid || !actor.Valid || !panel._state.GetOrCreate(player, actor.Objects[0], out var state))
|
|
throw new Exception("No player state available.");
|
|
|
|
var design = panel._converter.Convert(state, ApplicationRules.FromModifiers(state))
|
|
?? throw new Exception("The clipboard did not contain valid data.");
|
|
panel._manager.ApplyDesign(panel._selector.Selected!, design);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Glamourer.Messager.NotificationMessage(ex, $"Could not apply player state to {panel._selector.Selected!.Name}.",
|
|
$"Could not apply player state to design {panel._selector.Selected!.Identifier}", NotificationType.Error, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
private sealed class UndoButton(DesignPanel panel) : Button
|
|
{
|
|
protected override string Description
|
|
=> "Undo the last change.";
|
|
|
|
protected override FontAwesomeIcon Icon
|
|
=> FontAwesomeIcon.Undo;
|
|
|
|
public override bool Visible
|
|
=> panel._selector.Selected != null;
|
|
|
|
protected override bool Disabled
|
|
=> (panel._selector.Selected?.WriteProtected() ?? true) || !panel._history.CanUndo(panel._selector.Selected);
|
|
|
|
protected override void OnClick()
|
|
=> panel._history.Undo(panel._selector.Selected!);
|
|
}
|
|
}
|