mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2026-02-21 23:17:43 +01:00
Starting rework.
This commit is contained in:
parent
0fc8992271
commit
7af38aa2ce
58 changed files with 8857 additions and 4923 deletions
464
Glamourer/Gui/Interface.Actors.cs
Normal file
464
Glamourer/Gui/Interface.Actors.cs
Normal file
|
|
@ -0,0 +1,464 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Dalamud.Game.ClientState.Objects.Enums;
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Logging;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Structs;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
internal partial class Interface
|
||||
{
|
||||
private class ActorTab
|
||||
{
|
||||
private ObjectManager.ActorData _data = new(string.Empty, string.Empty, Actor.Null, false, Actor.Null);
|
||||
private CharacterSave _character = new();
|
||||
private Actor _nextSelect = Actor.Null;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
using var tab = ImRaii.TabItem("Actors");
|
||||
if (!tab)
|
||||
return;
|
||||
|
||||
DrawActorSelector();
|
||||
if (_data.Label.Length == 0)
|
||||
return;
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if (_data.Actor.IsHuman)
|
||||
DrawActorPanel();
|
||||
else
|
||||
DrawMonsterPanel();
|
||||
}
|
||||
|
||||
private void DrawActorPanel()
|
||||
{
|
||||
using var group = ImRaii.Group();
|
||||
if (DrawCustomization(_character.Customize, _character.Equipment, !_data.Modifiable))
|
||||
{
|
||||
Glamourer.RedrawManager.Set(_data.Actor.Address, _character);
|
||||
Glamourer.Penumbra.RedrawObject(_data.Actor.Character, RedrawType.Redraw, true);
|
||||
}
|
||||
|
||||
if (ImGui.Button("Set Machinist Goggles"))
|
||||
{
|
||||
Glamourer.RedrawManager.ChangeEquip(_data.Actor.Address, EquipSlot.Head, new CharacterArmor(265, 1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawMonsterPanel()
|
||||
{
|
||||
using var group = ImRaii.Group();
|
||||
var currentModel = (uint)_data.Actor.ModelId;
|
||||
var models = GameData.Models(Dalamud.GameData);
|
||||
var currentData = models.Models.TryGetValue(currentModel, out var c) ? c.FirstName : $"#{currentModel}";
|
||||
using var combo = ImRaii.Combo("Model Id", currentData);
|
||||
if (!combo)
|
||||
return;
|
||||
|
||||
foreach (var (id, data) in models.Models)
|
||||
{
|
||||
if (ImGui.Selectable(data.FirstName, id == currentModel) || id == currentModel)
|
||||
{
|
||||
_data.Actor.SetModelId((int)id);
|
||||
Glamourer.Penumbra.RedrawObject(_data.Actor.Character, RedrawType.Redraw, true);
|
||||
}
|
||||
ImGuiUtil.HoverTooltip(data.AllNames);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private LowerString _actorFilter = LowerString.Empty;
|
||||
|
||||
private void DrawActorSelector()
|
||||
{
|
||||
using var group = ImRaii.Group();
|
||||
var oldSpacing = ImGui.GetStyle().ItemSpacing;
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
ImGui.SetNextItemWidth(_actorSelectorWidth);
|
||||
LowerString.InputWithHint("##actorFilter", "Filter...", ref _actorFilter, 64);
|
||||
using (var child = ImRaii.Child("##actorSelector", new Vector2(_actorSelectorWidth, -ImGui.GetFrameHeight()), true))
|
||||
{
|
||||
if (!child)
|
||||
return;
|
||||
|
||||
_data.Actor = Actor.Null;
|
||||
_data.GPose = Actor.Null;
|
||||
_data.Modifiable = false;
|
||||
|
||||
style.Push(ImGuiStyleVar.ItemSpacing, oldSpacing);
|
||||
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeight());
|
||||
var remainder = ImGuiClip.FilteredClippedDraw(ObjectManager.GetEnumerator(), skips, CheckFilter, DrawSelectable);
|
||||
ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeight());
|
||||
style.Pop();
|
||||
}
|
||||
|
||||
DrawSelectionButtons();
|
||||
}
|
||||
|
||||
private void UpdateSelection(ObjectManager.ActorData data)
|
||||
{
|
||||
_data = data;
|
||||
_character.Load(_data.Actor);
|
||||
}
|
||||
|
||||
private bool CheckFilter(ObjectManager.ActorData data)
|
||||
{
|
||||
if (_nextSelect && _nextSelect == data.Actor || data.Label == _data.Label)
|
||||
UpdateSelection(data);
|
||||
return data.Label.Contains(_actorFilter.Lower, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private void DrawSelectable(ObjectManager.ActorData data)
|
||||
{
|
||||
var equal = data.Label == _data.Label;
|
||||
if (ImGui.Selectable(data.Label, equal) && !equal)
|
||||
UpdateSelection(data);
|
||||
}
|
||||
|
||||
private void DrawSelectionButtons()
|
||||
{
|
||||
_nextSelect = Actor.Null;
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
var buttonWidth = new Vector2(_actorSelectorWidth / 2, 0);
|
||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.UserCircle.ToIconString(), buttonWidth
|
||||
, "Select the local player character.", !ObjectManager.Player, true))
|
||||
_nextSelect = _inGPose ? ObjectManager.GPosePlayer : ObjectManager.Player;
|
||||
ImGui.SameLine();
|
||||
Actor targetActor = Dalamud.Targets.Target?.Address;
|
||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.HandPointer.ToIconString(), buttonWidth,
|
||||
"Select the current target, if it is in the list.", _inGPose || !targetActor, true))
|
||||
_nextSelect = targetActor;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly ActorTab _actorTab = new();
|
||||
}
|
||||
|
||||
//internal partial class Interface
|
||||
//{
|
||||
// private readonly CharacterSave _currentSave = new();
|
||||
// private string _newDesignName = string.Empty;
|
||||
// private bool _keyboardFocus;
|
||||
// private bool _holdShift;
|
||||
// private bool _holdCtrl;
|
||||
// private const string DesignNamePopupLabel = "Save Design As...";
|
||||
// private const uint RedHeaderColor = 0xFF1818C0;
|
||||
// private const uint GreenHeaderColor = 0xFF18C018;
|
||||
//
|
||||
// private void DrawPlayerHeader()
|
||||
// {
|
||||
// var color = _player == null ? RedHeaderColor : GreenHeaderColor;
|
||||
// var buttonColor = ImGui.GetColorU32(ImGuiCol.FrameBg);
|
||||
// using var c = ImRaii.PushColor(ImGuiCol.Text, color)
|
||||
// .Push(ImGuiCol.Button, buttonColor)
|
||||
// .Push(ImGuiCol.ButtonHovered, buttonColor)
|
||||
// .Push(ImGuiCol.ButtonActive, buttonColor);
|
||||
// using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
// .Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
// ImGui.Button($"{_currentLabel}##playerHeader", -Vector2.UnitX * 0.0001f);
|
||||
// }
|
||||
//
|
||||
// private static void DrawCopyClipboardButton(CharacterSave save)
|
||||
// {
|
||||
// ImGui.PushFont(UiBuilder.IconFont);
|
||||
// if (ImGui.Button(FontAwesomeIcon.Clipboard.ToIconString()))
|
||||
// ImGui.SetClipboardText(save.ToBase64());
|
||||
// ImGui.PopFont();
|
||||
// ImGuiUtil.HoverTooltip("Copy customization code to clipboard.");
|
||||
// }
|
||||
//
|
||||
// private static unsafe void ConditionalApply(CharacterSave save, FFXIVClientStructs.FFXIV.Client.Game.Character.Character* player)
|
||||
// {
|
||||
// //if (ImGui.GetIO().KeyShift)
|
||||
// // save.ApplyOnlyCustomizations(player);
|
||||
// //else if (ImGui.GetIO().KeyCtrl)
|
||||
// // save.ApplyOnlyEquipment(player);
|
||||
// //else
|
||||
// // save.Apply(player);
|
||||
// }
|
||||
//
|
||||
// private static unsafe void ConditionalApply(CharacterSave save, Character player)
|
||||
// => ConditionalApply(save, (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)player.Address);
|
||||
//
|
||||
// private static CharacterSave ConditionalCopy(CharacterSave save, bool shift, bool ctrl)
|
||||
// {
|
||||
// var copy = save.Copy();
|
||||
// if (shift)
|
||||
// {
|
||||
// copy.Load(new CharacterEquipment());
|
||||
// copy.SetHatState = false;
|
||||
// copy.SetVisorState = false;
|
||||
// copy.SetWeaponState = false;
|
||||
// copy.WriteEquipment = CharacterEquipMask.None;
|
||||
// }
|
||||
// else if (ctrl)
|
||||
// {
|
||||
// copy.Load(CharacterCustomization.Default);
|
||||
// copy.SetHatState = false;
|
||||
// copy.SetVisorState = false;
|
||||
// copy.SetWeaponState = false;
|
||||
// copy.WriteCustomizations = false;
|
||||
// }
|
||||
//
|
||||
// return copy;
|
||||
// }
|
||||
//
|
||||
// private bool DrawApplyClipboardButton()
|
||||
// {
|
||||
// ImGui.PushFont(UiBuilder.IconFont);
|
||||
// var applyButton = ImGui.Button(FontAwesomeIcon.Paste.ToIconString()) && _player != null;
|
||||
// ImGui.PopFont();
|
||||
// ImGuiUtil.HoverTooltip(
|
||||
// "Apply customization code from clipboard.\nHold Shift to apply only customizations.\nHold Control to apply only equipment.");
|
||||
//
|
||||
// if (!applyButton)
|
||||
// return false;
|
||||
//
|
||||
// try
|
||||
// {
|
||||
// var text = ImGui.GetClipboardText();
|
||||
// if (!text.Any())
|
||||
// return false;
|
||||
//
|
||||
// var save = CharacterSave.FromString(text);
|
||||
// ConditionalApply(save, _player!);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// PluginLog.Information($"{e}");
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// private void DrawSaveDesignButton()
|
||||
// {
|
||||
// ImGui.PushFont(UiBuilder.IconFont);
|
||||
// if (ImGui.Button(FontAwesomeIcon.Save.ToIconString()))
|
||||
// OpenDesignNamePopup(DesignNameUse.SaveCurrent);
|
||||
//
|
||||
// ImGui.PopFont();
|
||||
// ImGuiUtil.HoverTooltip("Save the current design.\nHold Shift to save only customizations.\nHold Control to save only equipment.");
|
||||
//
|
||||
// DrawDesignNamePopup(DesignNameUse.SaveCurrent);
|
||||
// }
|
||||
//
|
||||
// private void DrawTargetPlayerButton()
|
||||
// {
|
||||
// if (ImGui.Button("Target Player"))
|
||||
// Dalamud.Targets.SetTarget(_player);
|
||||
// }
|
||||
//
|
||||
// private unsafe void DrawApplyToPlayerButton(CharacterSave save)
|
||||
// {
|
||||
// if (!ImGui.Button("Apply to Self"))
|
||||
// return;
|
||||
//
|
||||
// var player = _inGPose
|
||||
// ? (Character?)Dalamud.Objects[GPoseObjectId]
|
||||
// : Dalamud.ClientState.LocalPlayer;
|
||||
// var fallback = _inGPose ? Dalamud.ClientState.LocalPlayer : null;
|
||||
// if (player == null)
|
||||
// return;
|
||||
//
|
||||
// ConditionalApply(save, (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)player.Address);
|
||||
// if (_inGPose)
|
||||
// ConditionalApply(save, (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)fallback!.Address);
|
||||
// Glamourer.Penumbra.UpdateCharacters(player, fallback);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// private static unsafe FFXIVClientStructs.FFXIV.Client.Game.Character.Character* TransformToCustomizable(
|
||||
// FFXIVClientStructs.FFXIV.Client.Game.Character.Character* actor)
|
||||
// {
|
||||
// if (actor == null)
|
||||
// return null;
|
||||
//
|
||||
// if (actor->ModelCharaId == 0)
|
||||
// return actor;
|
||||
//
|
||||
// actor->ModelCharaId = 0;
|
||||
// CharacterCustomization.Default.Write(actor);
|
||||
// return actor;
|
||||
// }
|
||||
//
|
||||
// private static unsafe FFXIVClientStructs.FFXIV.Client.Game.Character.Character* Convert(GameObject? actor)
|
||||
// {
|
||||
// return actor switch
|
||||
// {
|
||||
// null => null,
|
||||
// PlayerCharacter p => (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)p.Address,
|
||||
// BattleChara b => (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)b.Address,
|
||||
// _ => actor.ObjectKind switch
|
||||
// {
|
||||
// ObjectKind.BattleNpc => (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor.Address,
|
||||
// ObjectKind.Companion => (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor.Address,
|
||||
// ObjectKind.Retainer => (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor.Address,
|
||||
// ObjectKind.EventNpc => (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor.Address,
|
||||
// _ => null,
|
||||
// },
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// private unsafe void DrawApplyToTargetButton(CharacterSave save)
|
||||
// {
|
||||
// if (!ImGui.Button("Apply to Target"))
|
||||
// return;
|
||||
//
|
||||
// var player = TransformToCustomizable(Convert(Dalamud.Targets.Target));
|
||||
// if (player == null)
|
||||
// return;
|
||||
//
|
||||
// var fallBackCharacter = _gPoseActors.TryGetValue(new Utf8String(player->GameObject.Name).ToString(), out var f) ? f : null;
|
||||
// ConditionalApply(save, player);
|
||||
// if (fallBackCharacter != null)
|
||||
// ConditionalApply(save, fallBackCharacter!);
|
||||
// //Glamourer.Penumbra.UpdateCharacters(player, fallBackCharacter);
|
||||
// }
|
||||
//
|
||||
// private void DrawRevertButton()
|
||||
// {
|
||||
// if (!ImGuiUtil.DrawDisabledButton("Revert", Vector2.Zero, string.Empty, _player == null))
|
||||
// return;
|
||||
//
|
||||
// Glamourer.RevertableDesigns.Revert(_player!);
|
||||
// var fallBackCharacter = _gPoseActors.TryGetValue(_player!.Name.ToString(), out var f) ? f : null;
|
||||
// if (fallBackCharacter != null)
|
||||
// Glamourer.RevertableDesigns.Revert(fallBackCharacter);
|
||||
// Glamourer.Penumbra.UpdateCharacters(_player, fallBackCharacter);
|
||||
// }
|
||||
//
|
||||
// private void SaveNewDesign(CharacterSave save)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// var (folder, name) = _designs.FileSystem.CreateAllFolders(_newDesignName);
|
||||
// if (!name.Any())
|
||||
// return;
|
||||
//
|
||||
// var newDesign = new Design(folder, name) { Data = save };
|
||||
// folder.AddChild(newDesign);
|
||||
// _designs.Designs[newDesign.FullName()] = save;
|
||||
// _designs.SaveToFile();
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// PluginLog.Error($"Could not save new design {_newDesignName}:\n{e}");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private unsafe void DrawMonsterPanel()
|
||||
// {
|
||||
// if (DrawApplyClipboardButton())
|
||||
// Glamourer.Penumbra.UpdateCharacters(_player!);
|
||||
//
|
||||
// ImGui.SameLine();
|
||||
// if (ImGui.Button("Convert to Character"))
|
||||
// {
|
||||
// //TransformToCustomizable(_player);
|
||||
// _currentLabel = _currentLabel.Replace("(Monster)", "(NPC)");
|
||||
// Glamourer.Penumbra.UpdateCharacters(_player!);
|
||||
// }
|
||||
//
|
||||
// if (!_inGPose)
|
||||
// {
|
||||
// ImGui.SameLine();
|
||||
// DrawTargetPlayerButton();
|
||||
// }
|
||||
//
|
||||
// var currentModel = ((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)_player!.Address)->ModelCharaId;
|
||||
// using var combo = ImRaii.Combo("Model Id", currentModel.ToString());
|
||||
// if (!combo)
|
||||
// return;
|
||||
//
|
||||
// foreach (var (id, _) in _models.Skip(1))
|
||||
// {
|
||||
// if (!ImGui.Selectable($"{id:D6}##models", id == currentModel) || id == currentModel)
|
||||
// continue;
|
||||
//
|
||||
// ((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)_player!.Address)->ModelCharaId = 0;
|
||||
// Glamourer.Penumbra.UpdateCharacters(_player!);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void DrawPlayerPanel()
|
||||
// {
|
||||
// DrawCopyClipboardButton(_currentSave);
|
||||
// ImGui.SameLine();
|
||||
// var changes = !_currentSave.WriteProtected && DrawApplyClipboardButton();
|
||||
// ImGui.SameLine();
|
||||
// DrawSaveDesignButton();
|
||||
// ImGui.SameLine();
|
||||
// DrawApplyToPlayerButton(_currentSave);
|
||||
// if (!_inGPose)
|
||||
// {
|
||||
// ImGui.SameLine();
|
||||
// DrawApplyToTargetButton(_currentSave);
|
||||
// if (_player != null && !_currentSave.WriteProtected)
|
||||
// {
|
||||
// ImGui.SameLine();
|
||||
// DrawTargetPlayerButton();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// var data = _currentSave;
|
||||
// if (!_currentSave.WriteProtected)
|
||||
// {
|
||||
// ImGui.SameLine();
|
||||
// DrawRevertButton();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.8f);
|
||||
// data = data.Copy();
|
||||
// }
|
||||
//
|
||||
// if (DrawCustomization(ref data.Customizations) && _player != null)
|
||||
// {
|
||||
// Glamourer.RevertableDesigns.Add(_player);
|
||||
// _currentSave.Customizations.Write(_player.Address);
|
||||
// changes = true;
|
||||
// }
|
||||
//
|
||||
// changes |= DrawEquip(data.Equipment);
|
||||
// changes |= DrawMiscellaneous(data, _player);
|
||||
//
|
||||
// if (_player != null && changes)
|
||||
// Glamourer.Penumbra.UpdateCharacters(_player);
|
||||
// if (_currentSave.WriteProtected)
|
||||
// ImGui.PopStyleVar();
|
||||
// }
|
||||
//
|
||||
// private unsafe void DrawActorPanel()
|
||||
// {
|
||||
// using var group = ImRaii.Group();
|
||||
// DrawPlayerHeader();
|
||||
// using var child = ImRaii.Child("##playerData", -Vector2.One, true);
|
||||
// if (!child)
|
||||
// return;
|
||||
//
|
||||
// if (_player == null || ((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)_player.Address)->ModelCharaId == 0)
|
||||
// DrawPlayerPanel();
|
||||
// else
|
||||
// DrawMonsterPanel();
|
||||
// }
|
||||
//}
|
||||
418
Glamourer/Gui/Interface.Customization.cs
Normal file
418
Glamourer/Gui/Interface.Customization.cs
Normal file
|
|
@ -0,0 +1,418 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Logging;
|
||||
using Glamourer.Customization;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Race = Penumbra.GameData.Enums.Race;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
internal partial class Interface
|
||||
{
|
||||
private static byte _tempStorage;
|
||||
private static CustomizationId _tempType;
|
||||
|
||||
private static bool DrawCustomization(CharacterCustomization customize, CharacterEquip equip, bool locked)
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Character Customization"))
|
||||
return false;
|
||||
|
||||
var ret = DrawRaceGenderSelector(customize, equip, locked);
|
||||
var set = Glamourer.Customization.GetList(customize.Clan, customize.Gender);
|
||||
|
||||
foreach (var id in set.Order[CharaMakeParams.MenuType.Percentage])
|
||||
ret |= PercentageSelector(set, id, customize, locked);
|
||||
|
||||
Functions.IteratePairwise(set.Order[CharaMakeParams.MenuType.IconSelector], c => DrawIconSelector(set, c, customize, locked),
|
||||
ImGui.SameLine);
|
||||
|
||||
ret |= DrawMultiIconSelector(set, customize, locked);
|
||||
|
||||
foreach (var id in set.Order[CharaMakeParams.MenuType.ListSelector])
|
||||
ret |= DrawListSelector(set, id, customize, locked);
|
||||
|
||||
Functions.IteratePairwise(set.Order[CharaMakeParams.MenuType.ColorPicker], c => DrawColorPicker(set, c, customize, locked),
|
||||
ImGui.SameLine);
|
||||
|
||||
ret |= Checkbox(set.Option(CustomizationId.HighlightsOnFlag), customize.HighlightsOn, b => customize.HighlightsOn = b, locked);
|
||||
var xPos = _inputIntSize + _framedIconSize.X + 3 * ImGui.GetStyle().ItemSpacing.X;
|
||||
ImGui.SameLine(xPos);
|
||||
ret |= Checkbox($"{Glamourer.Customization.GetName(CustomName.Reverse)} {set.Option(CustomizationId.FacePaint)}",
|
||||
customize.FacePaintReversed, b => customize.FacePaintReversed = b, locked);
|
||||
ret |= Checkbox($"{Glamourer.Customization.GetName(CustomName.IrisSmall)} {Glamourer.Customization.GetName(CustomName.IrisSize)}",
|
||||
customize.SmallIris, b => customize.SmallIris = b, locked);
|
||||
|
||||
if (customize.Race != Race.Hrothgar)
|
||||
{
|
||||
ImGui.SameLine(xPos);
|
||||
ret |= Checkbox(set.Option(CustomizationId.LipColor), customize.Lipstick, b => customize.Lipstick = b, locked);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawRaceGenderSelector(CharacterCustomization customize, CharacterEquip equip, bool locked)
|
||||
{
|
||||
var ret = DrawGenderSelector(customize, equip, locked);
|
||||
ImGui.SameLine();
|
||||
using var group = ImRaii.Group();
|
||||
ret |= DrawRaceCombo(customize, equip, locked);
|
||||
var gender = Glamourer.Customization.GetName(CustomName.Gender);
|
||||
var clan = Glamourer.Customization.GetName(CustomName.Clan);
|
||||
ImGui.TextUnformatted($"{gender} & {clan}");
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawGenderSelector(CharacterCustomization customize, CharacterEquip equip, bool locked)
|
||||
{
|
||||
using var font = ImRaii.PushFont(UiBuilder.IconFont);
|
||||
var icon = customize.Gender == Gender.Male ? FontAwesomeIcon.Mars : FontAwesomeIcon.Venus;
|
||||
var restricted = customize.Race == Race.Hrothgar;
|
||||
if (restricted)
|
||||
icon = FontAwesomeIcon.MarsDouble;
|
||||
|
||||
if (!ImGuiUtil.DrawDisabledButton(icon.ToIconString(), _framedIconSize, string.Empty, restricted || locked, true))
|
||||
return false;
|
||||
|
||||
var gender = customize.Gender == Gender.Male ? Gender.Female : Gender.Male;
|
||||
return customize.ChangeGender(gender, locked ? CharacterEquip.Null : equip);
|
||||
}
|
||||
|
||||
private static bool DrawRaceCombo(CharacterCustomization customize, CharacterEquip equip, bool locked)
|
||||
{
|
||||
using var alpha = ImRaii.PushStyle(ImGuiStyleVar.Alpha, 0.5f, locked);
|
||||
ImGui.SetNextItemWidth(_raceSelectorWidth);
|
||||
using var combo = ImRaii.Combo("##subRaceCombo", customize.ClanName());
|
||||
if (!combo)
|
||||
return false;
|
||||
|
||||
if (locked)
|
||||
ImGui.CloseCurrentPopup();
|
||||
|
||||
var ret = false;
|
||||
foreach (var subRace in Enum.GetValues<SubRace>().Skip(1)) // Skip Unknown
|
||||
{
|
||||
if (ImGui.Selectable(CustomizeExtensions.ClanName(subRace, customize.Gender), subRace == customize.Clan))
|
||||
ret |= customize.ChangeRace(subRace, equip);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool Checkbox(string label, bool current, Action<bool> setter, bool locked)
|
||||
{
|
||||
var tmp = current;
|
||||
var ret = false;
|
||||
using var alpha = ImRaii.PushStyle(ImGuiStyleVar.Alpha, 0.5f, locked);
|
||||
if (ImGui.Checkbox($"##{label}", ref tmp) && tmp == current && !locked)
|
||||
{
|
||||
setter(tmp);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
alpha.Pop();
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted(label);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool PercentageSelector(CustomizationSet set, CustomizationId id, CharacterCustomization customization, bool locked)
|
||||
{
|
||||
using var bigGroup = ImRaii.Group();
|
||||
using var _ = ImRaii.PushId((int)id);
|
||||
int value = id == _tempType ? _tempStorage : customization[id];
|
||||
var count = set.Count(id);
|
||||
ImGui.SetNextItemWidth(_comboSelectorSize);
|
||||
|
||||
var (min, max) = locked ? (value, value) : (0, count - 1);
|
||||
using var alpha = ImRaii.PushStyle(ImGuiStyleVar.Alpha, 0.5f, locked);
|
||||
if (ImGui.SliderInt("##slider", ref value, min, max, string.Empty, ImGuiSliderFlags.AlwaysClamp) && !locked)
|
||||
{
|
||||
_tempStorage = (byte)value;
|
||||
_tempType = id;
|
||||
}
|
||||
|
||||
var ret = ImGui.IsItemDeactivatedAfterEdit();
|
||||
|
||||
ImGui.SameLine();
|
||||
ret |= InputInt("##input", id, --value, min, max, locked);
|
||||
|
||||
alpha.Pop();
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted(set.OptionName[(int)id]);
|
||||
|
||||
if (ret)
|
||||
customization[id] = _tempStorage;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool InputInt(string label, CustomizationId id, int startValue, int minValue, int maxValue, bool locked)
|
||||
{
|
||||
var tmp = startValue + 1;
|
||||
ImGui.SetNextItemWidth(_inputIntSize);
|
||||
if (ImGui.InputInt(label, ref tmp, 1, 1, ImGuiInputTextFlags.EnterReturnsTrue)
|
||||
&& !locked
|
||||
&& tmp != startValue + 1
|
||||
&& tmp >= minValue
|
||||
&& tmp <= maxValue)
|
||||
{
|
||||
_tempType = id;
|
||||
_tempStorage = (byte)(tmp - 1);
|
||||
}
|
||||
|
||||
var ret = ImGui.IsItemDeactivatedAfterEdit() && !locked;
|
||||
if (!locked)
|
||||
ImGuiUtil.HoverTooltip($"Input Range: [{minValue}, {maxValue}]");
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawIconSelector(CustomizationSet set, CustomizationId id, CharacterCustomization customize, bool locked)
|
||||
{
|
||||
const string popupName = "Style Picker";
|
||||
|
||||
using var bigGroup = ImRaii.Group();
|
||||
using var _ = ImRaii.PushId((int)id);
|
||||
var count = set.Count(id);
|
||||
var label = set.Option(id);
|
||||
|
||||
var current = set.DataByValue(id, _tempType == id ? _tempStorage : customize[id], out var custom);
|
||||
if (current < 0)
|
||||
{
|
||||
label = $"{label} (Custom #{customize[id]})";
|
||||
current = 0;
|
||||
custom = set.Data(id, 0);
|
||||
}
|
||||
|
||||
var icon = Glamourer.Customization.GetIcon(custom!.Value.IconId);
|
||||
using var alpha = ImRaii.PushStyle(ImGuiStyleVar.Alpha, 0.5f, locked);
|
||||
if (ImGui.ImageButton(icon.ImGuiHandle, _iconSize) && !locked)
|
||||
ImGui.OpenPopup(popupName);
|
||||
|
||||
ImGuiUtil.HoverIconTooltip(icon, _iconSize);
|
||||
|
||||
ImGui.SameLine();
|
||||
using var group = ImRaii.Group();
|
||||
var (min, max) = locked ? (current, current) : (1, count);
|
||||
var ret = InputInt("##text", id, current, min, max, locked);
|
||||
if (ret)
|
||||
customize[id] = set.Data(id, _tempStorage).Value;
|
||||
|
||||
ImGui.TextUnformatted($"{label} ({custom.Value.Value})");
|
||||
|
||||
ret |= DrawIconPickerPopup(popupName, set, id, customize);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawIconPickerPopup(string label, CustomizationSet set, CustomizationId id, CharacterCustomization customize)
|
||||
{
|
||||
using var popup = ImRaii.Popup(label, ImGuiWindowFlags.AlwaysAutoResize);
|
||||
if (!popup)
|
||||
return false;
|
||||
|
||||
var ret = false;
|
||||
var count = set.Count(id);
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
var custom = set.Data(id, i);
|
||||
var icon = Glamourer.Customization.GetIcon(custom.IconId);
|
||||
using var group = ImRaii.Group();
|
||||
if (ImGui.ImageButton(icon.ImGuiHandle, _iconSize))
|
||||
{
|
||||
customize[id] = custom.Value;
|
||||
ret = true;
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverIconTooltip(icon, _iconSize);
|
||||
|
||||
var text = custom.Value.ToString();
|
||||
var textWidth = ImGui.CalcTextSize(text).X;
|
||||
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (_iconSize.X - textWidth + 2 * ImGui.GetStyle().FramePadding.X) / 2);
|
||||
ImGui.TextUnformatted(text);
|
||||
group.Dispose();
|
||||
|
||||
if (i % 8 != 7)
|
||||
ImGui.SameLine();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawColorPicker(CustomizationSet set, CustomizationId id, CharacterCustomization customize, bool locked)
|
||||
{
|
||||
const string popupName = "Color Picker";
|
||||
using var _ = ImRaii.PushId((int)id);
|
||||
var ret = false;
|
||||
var count = set.Count(id);
|
||||
var label = set.Option(id);
|
||||
var (current, custom) = GetCurrentCustomization(set, id, customize);
|
||||
|
||||
using var alpha = ImRaii.PushStyle(ImGuiStyleVar.Alpha, 0.5f, locked);
|
||||
if (ImGui.ColorButton($"{current + 1}##color", ImGui.ColorConvertU32ToFloat4(custom.Color), ImGuiColorEditFlags.None, _framedIconSize)
|
||||
&& !locked)
|
||||
ImGui.OpenPopup(popupName);
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
using (var group = ImRaii.Group())
|
||||
{
|
||||
var (min, max) = locked ? (current, current) : (1, count);
|
||||
if (InputInt("##text", id, current, min, max, locked))
|
||||
{
|
||||
customize[id] = set.Data(id, current).Value;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
ImGui.TextUnformatted(label);
|
||||
}
|
||||
|
||||
return ret | DrawColorPickerPopup(popupName, set, id, customize);
|
||||
}
|
||||
|
||||
private static (int, Customization.Customization) GetCurrentCustomization(CustomizationSet set, CustomizationId id,
|
||||
CharacterCustomization customize)
|
||||
{
|
||||
var current = set.DataByValue(id, customize[id], out var custom);
|
||||
if (set.IsAvailable(id) && current < 0)
|
||||
{
|
||||
PluginLog.Warning($"Read invalid customization value {customize[id]} for {id}.");
|
||||
current = 0;
|
||||
custom = set.Data(id, 0);
|
||||
}
|
||||
|
||||
return (current, custom!.Value);
|
||||
}
|
||||
|
||||
private static bool DrawColorPickerPopup(string label, CustomizationSet set, CustomizationId id, CharacterCustomization customize)
|
||||
{
|
||||
using var popup = ImRaii.Popup(label, ImGuiWindowFlags.AlwaysAutoResize);
|
||||
if (!popup)
|
||||
return false;
|
||||
|
||||
var ret = false;
|
||||
var count = set.Count(id);
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
var custom = set.Data(id, i);
|
||||
if (ImGui.ColorButton((i + 1).ToString(), ImGui.ColorConvertU32ToFloat4(custom.Color)))
|
||||
{
|
||||
customize[id] = custom.Value;
|
||||
ret = true;
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
|
||||
if (i % 8 != 7)
|
||||
ImGui.SameLine();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawMultiIconSelector(CustomizationSet set, CharacterCustomization customize, bool locked)
|
||||
{
|
||||
using var bigGroup = ImRaii.Group();
|
||||
using var _ = ImRaii.PushId((int)CustomizationId.FacialFeaturesTattoos);
|
||||
using var alpha = ImRaii.PushStyle(ImGuiStyleVar.Alpha, 0.5f, locked);
|
||||
var ret = DrawMultiIcons(set, customize, locked);
|
||||
ImGui.SameLine();
|
||||
using var group = ImRaii.Group();
|
||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + ImGui.GetTextLineHeightWithSpacing() + 3 * ImGui.GetStyle().ItemSpacing.Y / 2);
|
||||
int value = customize[CustomizationId.FacialFeaturesTattoos];
|
||||
var (min, max) = locked ? (value, value) : (1, 256);
|
||||
if (InputInt(string.Empty, CustomizationId.FacialFeaturesTattoos, value, min, max, locked))
|
||||
{
|
||||
customize[CustomizationId.FacialFeaturesTattoos] = (byte)value;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
ImGui.TextUnformatted(set.Option(CustomizationId.FacialFeaturesTattoos));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawMultiIcons(CustomizationSet set, CharacterCustomization customize, bool locked)
|
||||
{
|
||||
using var _ = ImRaii.Group();
|
||||
var face = customize.Face;
|
||||
if (set.Faces.Count < face)
|
||||
face = 1;
|
||||
|
||||
var ret = false;
|
||||
var count = set.Count(CustomizationId.FacialFeaturesTattoos);
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
var enabled = customize.FacialFeature(i);
|
||||
var feature = set.FacialFeature(face, i);
|
||||
var icon = i == count - 1
|
||||
? LegacyTattoo ?? Glamourer.Customization.GetIcon(feature.IconId)
|
||||
: Glamourer.Customization.GetIcon(feature.IconId);
|
||||
if (ImGui.ImageButton(icon.ImGuiHandle, _iconSize, Vector2.Zero, Vector2.One, (int)ImGui.GetStyle().FramePadding.X,
|
||||
Vector4.Zero, enabled ? Vector4.One : RedTint)
|
||||
&& !locked)
|
||||
{
|
||||
customize.FacialFeature(i, !enabled);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
using var alpha = ImRaii.PushStyle(ImGuiStyleVar.Alpha, 1f, !locked);
|
||||
ImGuiUtil.HoverIconTooltip(icon, _iconSize);
|
||||
|
||||
if (i % 4 != 3)
|
||||
ImGui.SameLine();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool DrawListSelector(CustomizationSet set, CustomizationId id, CharacterCustomization customize, bool locked)
|
||||
{
|
||||
using var _ = ImRaii.PushId((int)id);
|
||||
using var bigGroup = ImRaii.Group();
|
||||
var ret = false;
|
||||
int current = customize[id];
|
||||
var count = set.Count(id);
|
||||
|
||||
ImGui.SetNextItemWidth(_comboSelectorSize * ImGui.GetIO().FontGlobalScale);
|
||||
using var alpha = ImRaii.PushStyle(ImGuiStyleVar.Alpha, 0.5f, locked);
|
||||
using (var combo = ImRaii.Combo("##combo", $"{set.Option(id)} #{current + 1}"))
|
||||
{
|
||||
if (combo)
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
if (!ImGui.Selectable($"{set.Option(id)} #{i + 1}##combo", i == current) || i == current || locked)
|
||||
continue;
|
||||
|
||||
customize[id] = (byte)i;
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
var (min, max) = locked ? (current, current) : (1, count);
|
||||
if (InputInt("##text", id, current, min, max, locked))
|
||||
{
|
||||
customize[id] = (byte)current;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
alpha.Pop();
|
||||
ImGui.TextUnformatted(set.Option(id));
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
104
Glamourer/Gui/Interface.SettingsTab.cs
Normal file
104
Glamourer/Gui/Interface.SettingsTab.cs
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
internal partial class Interface
|
||||
{
|
||||
private static void Checkmark(string label, string tooltip, bool value, Action<bool> setter)
|
||||
{
|
||||
if (ImGuiUtil.Checkbox(label, tooltip, value, setter))
|
||||
Glamourer.Config.Save();
|
||||
}
|
||||
|
||||
private static void ChangeAndSave<T>(T value, T currentValue, Action<T> setter) where T : IEquatable<T>
|
||||
{
|
||||
if (value.Equals(currentValue))
|
||||
return;
|
||||
|
||||
setter(value);
|
||||
Glamourer.Config.Save();
|
||||
}
|
||||
|
||||
private static void DrawColorPicker(string name, string tooltip, uint value, uint defaultValue, Action<uint> setter)
|
||||
{
|
||||
const ImGuiColorEditFlags flags = ImGuiColorEditFlags.AlphaPreviewHalf | ImGuiColorEditFlags.NoInputs;
|
||||
|
||||
var tmp = ImGui.ColorConvertU32ToFloat4(value);
|
||||
if (ImGui.ColorEdit4($"##{name}", ref tmp, flags))
|
||||
ChangeAndSave(ImGui.ColorConvertFloat4ToU32(tmp), value, setter);
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button($"Default##{name}"))
|
||||
ChangeAndSave(defaultValue, value, setter);
|
||||
ImGuiUtil.HoverTooltip(
|
||||
$"Reset to default: #{defaultValue & 0xFF:X2}{(defaultValue >> 8) & 0xFF:X2}{(defaultValue >> 16) & 0xFF:X2}{defaultValue >> 24:X2}");
|
||||
ImGui.SameLine();
|
||||
ImGui.Text(name);
|
||||
ImGuiUtil.HoverTooltip(tooltip);
|
||||
}
|
||||
|
||||
private static void DrawRestorePenumbraButton()
|
||||
{
|
||||
const string buttonLabel = "Re-Register Penumbra";
|
||||
if (!Glamourer.Config.AttachToPenumbra)
|
||||
{
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.Alpha, 0.5f);
|
||||
ImGui.Button(buttonLabel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui.Button(buttonLabel))
|
||||
Glamourer.Penumbra.Reattach(true);
|
||||
|
||||
ImGuiUtil.HoverTooltip(
|
||||
"If Penumbra did not register the functions for some reason, pressing this button might help restore functionality.");
|
||||
}
|
||||
|
||||
private static void DrawSettingsTab()
|
||||
{
|
||||
using var tab = ImRaii.TabItem("Settings");
|
||||
if (!tab)
|
||||
return;
|
||||
|
||||
var cfg = Glamourer.Config;
|
||||
ImGui.Dummy(_spacing);
|
||||
|
||||
Checkmark("Folders First", "Sort Folders before all designs instead of lexicographically.", cfg.FoldersFirst,
|
||||
v => cfg.FoldersFirst = v);
|
||||
Checkmark("Color Designs", "Color the names of designs in the selector using the colors from below for the given cases.",
|
||||
cfg.ColorDesigns,
|
||||
v => cfg.ColorDesigns = v);
|
||||
Checkmark("Show Locks", "Write-protected Designs show a lock besides their name in the selector.", cfg.ShowLocks,
|
||||
v => cfg.ShowLocks = v);
|
||||
Checkmark("Attach to Penumbra",
|
||||
"Allows you to right-click items in the Changed Items tab of a mod in Penumbra to apply them to your player character.",
|
||||
cfg.AttachToPenumbra,
|
||||
v =>
|
||||
{
|
||||
cfg.AttachToPenumbra = v;
|
||||
if (v)
|
||||
Glamourer.Penumbra.Reattach(true);
|
||||
else
|
||||
Glamourer.Penumbra.Unattach();
|
||||
});
|
||||
ImGui.SameLine();
|
||||
DrawRestorePenumbraButton();
|
||||
|
||||
Checkmark("Apply Fixed Designs",
|
||||
"Automatically apply fixed designs to characters and redraw them when anything changes.",
|
||||
cfg.ApplyFixedDesigns,
|
||||
v => { cfg.ApplyFixedDesigns = v; });
|
||||
|
||||
ImGui.Dummy(_spacing);
|
||||
|
||||
DrawColorPicker("Customization Color", "The color for designs that only apply their character customization.",
|
||||
cfg.CustomizationColor, GlamourerConfig.DefaultCustomizationColor, c => cfg.CustomizationColor = c);
|
||||
DrawColorPicker("Equipment Color", "The color for designs that only apply some or all of their equipment slots and stains.",
|
||||
cfg.EquipmentColor, GlamourerConfig.DefaultEquipmentColor, c => cfg.EquipmentColor = c);
|
||||
DrawColorPicker("State Color", "The color for designs that only apply some state modification.",
|
||||
cfg.StateColor, GlamourerConfig.DefaultStateColor, c => cfg.StateColor = c);
|
||||
}
|
||||
}
|
||||
58
Glamourer/Gui/Interface.State.cs
Normal file
58
Glamourer/Gui/Interface.State.cs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using Dalamud.Interface;
|
||||
using Glamourer.Customization;
|
||||
using ImGuiNET;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
internal partial class Interface
|
||||
{
|
||||
private static readonly ImGuiScene.TextureWrap? LegacyTattoo = GetLegacyTattooIcon();
|
||||
private static readonly Vector4 RedTint = new(0.6f, 0.3f, 0.3f, 1f);
|
||||
|
||||
|
||||
private static Vector2 _iconSize = Vector2.Zero;
|
||||
private static Vector2 _framedIconSize = Vector2.Zero;
|
||||
private static Vector2 _spacing = Vector2.Zero;
|
||||
private static float _actorSelectorWidth;
|
||||
private static float _inputIntSize;
|
||||
private static float _comboSelectorSize;
|
||||
private static float _raceSelectorWidth;
|
||||
private static bool _inGPose;
|
||||
|
||||
|
||||
private static void UpdateState()
|
||||
{
|
||||
// General
|
||||
_inGPose = ObjectManager.IsInGPose();
|
||||
_spacing = _spacing with { Y = ImGui.GetTextLineHeightWithSpacing() / 2 };
|
||||
_actorSelectorWidth = 200 * ImGuiHelpers.GlobalScale;
|
||||
|
||||
// Customize
|
||||
_iconSize = new Vector2(ImGui.GetTextLineHeightWithSpacing() * 2);
|
||||
_framedIconSize = _iconSize + 2 * ImGui.GetStyle().FramePadding;
|
||||
_inputIntSize = 2 * _framedIconSize.X + ImGui.GetStyle().ItemSpacing.X;
|
||||
_comboSelectorSize = 4 * _framedIconSize.X + 3 * ImGui.GetStyle().ItemSpacing.X;
|
||||
_raceSelectorWidth = _inputIntSize + _comboSelectorSize - _framedIconSize.X;
|
||||
|
||||
// _itemComboWidth = 6 * _actualIconSize.X + 4 * ImGui.GetStyle().ItemSpacing.X - ColorButtonWidth + 1;
|
||||
}
|
||||
|
||||
private static ImGuiScene.TextureWrap? GetLegacyTattooIcon()
|
||||
{
|
||||
using var resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("Glamourer.LegacyTattoo.raw");
|
||||
if (resource != null)
|
||||
{
|
||||
var rawImage = new byte[resource.Length];
|
||||
var length = resource.Read(rawImage, 0, (int)resource.Length);
|
||||
if (length != resource.Length)
|
||||
return null;
|
||||
|
||||
return Dalamud.PluginInterface.UiBuilder.LoadImageRaw(rawImage, 192, 192, 4);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,110 +1,139 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Glamourer.Designs;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Logging;
|
||||
using ImGuiNET;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData;
|
||||
using Penumbra.GameData.Enums;
|
||||
using OtterGui.Widgets;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
internal partial class Interface : IDisposable
|
||||
internal partial class Interface : Window, IDisposable
|
||||
{
|
||||
public const float SelectorWidth = 200;
|
||||
public const float MinWindowWidth = 675;
|
||||
public const int GPoseObjectId = 201;
|
||||
private const string PluginName = "Glamourer";
|
||||
private readonly string _glamourerHeader;
|
||||
|
||||
private readonly IReadOnlyDictionary<byte, Stain> _stains;
|
||||
private readonly IReadOnlyDictionary<uint, ModelChara> _models;
|
||||
private readonly IObjectIdentifier _identifier;
|
||||
private readonly Dictionary<EquipSlot, (ComboWithFilter<Item>, ComboWithFilter<Stain>)> _combos;
|
||||
private readonly ImGuiScene.TextureWrap? _legacyTattooIcon;
|
||||
private readonly Dictionary<EquipSlot, string> _equipSlotNames;
|
||||
private readonly DesignManager _designs;
|
||||
private readonly Glamourer _plugin;
|
||||
|
||||
private bool _visible;
|
||||
private bool _inGPose;
|
||||
private readonly Glamourer _plugin;
|
||||
|
||||
public Interface(Glamourer plugin)
|
||||
: base(GetLabel())
|
||||
{
|
||||
_plugin = plugin;
|
||||
_designs = plugin.Designs;
|
||||
_glamourerHeader = Glamourer.Version.Length > 0
|
||||
? $"{PluginName} v{Glamourer.Version}###{PluginName}Main"
|
||||
: $"{PluginName}###{PluginName}Main";
|
||||
_plugin = plugin;
|
||||
Dalamud.PluginInterface.UiBuilder.DisableGposeUiHide = true;
|
||||
Dalamud.PluginInterface.UiBuilder.Draw += Draw;
|
||||
Dalamud.PluginInterface.UiBuilder.OpenConfigUi += ToggleVisibility;
|
||||
|
||||
_equipSlotNames = GetEquipSlotNames();
|
||||
|
||||
_stains = GameData.Stains(Dalamud.GameData);
|
||||
_models = GameData.Models(Dalamud.GameData);
|
||||
_identifier = Penumbra.GameData.GameData.GetIdentifier(Dalamud.GameData, Dalamud.ClientState.ClientLanguage);
|
||||
|
||||
|
||||
var stainCombo = CreateDefaultStainCombo(_stains.Values.ToArray());
|
||||
|
||||
var equip = GameData.ItemsBySlot(Dalamud.GameData);
|
||||
_combos = equip.ToDictionary(kvp => kvp.Key, kvp => CreateCombos(kvp.Key, kvp.Value, stainCombo));
|
||||
_legacyTattooIcon = GetLegacyTattooIcon();
|
||||
Dalamud.PluginInterface.UiBuilder.OpenConfigUi += Toggle;
|
||||
SizeConstraints = new WindowSizeConstraints()
|
||||
{
|
||||
MinimumSize = new Vector2(675, 675),
|
||||
MaximumSize = ImGui.GetIO().DisplaySize,
|
||||
};
|
||||
}
|
||||
|
||||
public void ToggleVisibility()
|
||||
=> _visible = !_visible;
|
||||
public override void Draw()
|
||||
{
|
||||
using var tabBar = ImRaii.TabBar("##Tabs");
|
||||
if (!tabBar)
|
||||
return;
|
||||
|
||||
UpdateState();
|
||||
|
||||
_actorTab.Draw();
|
||||
DrawSettingsTab();
|
||||
// DrawSaves();
|
||||
// DrawFixedDesignsTab();
|
||||
// DrawRevertablesTab();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_legacyTattooIcon?.Dispose();
|
||||
Dalamud.PluginInterface.UiBuilder.Draw -= Draw;
|
||||
Dalamud.PluginInterface.UiBuilder.OpenConfigUi -= ToggleVisibility;
|
||||
Dalamud.PluginInterface.UiBuilder.OpenConfigUi -= Toggle;
|
||||
}
|
||||
|
||||
private void Draw()
|
||||
{
|
||||
if (!_visible)
|
||||
return;
|
||||
|
||||
ImGui.SetNextWindowSizeConstraints(Vector2.One * MinWindowWidth * ImGui.GetIO().FontGlobalScale,
|
||||
Vector2.One * 5000 * ImGui.GetIO().FontGlobalScale);
|
||||
if (!ImGui.Begin(_glamourerHeader, ref _visible))
|
||||
{
|
||||
ImGui.End();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using var tabBar = ImRaii.TabBar("##tabBar");
|
||||
if (!tabBar)
|
||||
return;
|
||||
|
||||
_inGPose = Dalamud.Objects[GPoseObjectId] != null;
|
||||
_iconSize = Vector2.One * ImGui.GetTextLineHeightWithSpacing() * 2;
|
||||
_actualIconSize = _iconSize + 2 * ImGui.GetStyle().FramePadding;
|
||||
_comboSelectorSize = 4 * _actualIconSize.X + 3 * ImGui.GetStyle().ItemSpacing.X;
|
||||
_percentageSize = _comboSelectorSize;
|
||||
_inputIntSize = 2 * _actualIconSize.X + ImGui.GetStyle().ItemSpacing.X;
|
||||
_raceSelectorWidth = _inputIntSize + _percentageSize - _actualIconSize.X;
|
||||
_itemComboWidth = 6 * _actualIconSize.X + 4 * ImGui.GetStyle().ItemSpacing.X - ColorButtonWidth + 1;
|
||||
|
||||
DrawPlayerTab();
|
||||
DrawSaves();
|
||||
DrawFixedDesignsTab();
|
||||
DrawConfigTab();
|
||||
DrawRevertablesTab();
|
||||
}
|
||||
finally
|
||||
{
|
||||
ImGui.End();
|
||||
}
|
||||
}
|
||||
private static string GetLabel()
|
||||
=> Glamourer.Version.Length == 0
|
||||
? "Glamourer###GlamourerConfigWindow"
|
||||
: $"Glamourer v{Glamourer.Version}###GlamourerConfigWindow";
|
||||
}
|
||||
|
||||
//public const float SelectorWidth = 200;
|
||||
//public const float MinWindowWidth = 675;
|
||||
//public const int GPoseObjectId = 201;
|
||||
//private const string PluginName = "Glamourer";
|
||||
//private readonly string _glamourerHeader;
|
||||
//
|
||||
//private readonly IReadOnlyDictionary<byte, Stain> _stains;
|
||||
//private readonly IReadOnlyDictionary<uint, ModelCeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeehara> _models;
|
||||
//private readonly IObjectIdentifier _identifier;
|
||||
//private readonly Dictionary<EquipSlot, (ComboWithFilter<Item>, ComboWithFilter<Stain>)> _combos;
|
||||
//private readonly ImGuiScene.TextureWrap? _legacyTattooIcon;
|
||||
//private readonly Dictionary<EquipSlot, string> _equipSlotNames;
|
||||
//private readonly DesignManager _designs;
|
||||
//private readonly Glamourer _plugin;
|
||||
//
|
||||
//private bool _visible;
|
||||
//private bool _inGPose;
|
||||
//
|
||||
//public Interface(Glamourer plugin)
|
||||
//{
|
||||
// _plugin = plugin;
|
||||
// _designs = plugin.Designs;
|
||||
// _glamourerHeader = Glamourer.Version.Length > 0
|
||||
// ? $"{PluginName} v{Glamourer.Version}###{PluginName}Main"
|
||||
// : $"{PluginName}###{PluginName}Main";
|
||||
// Dalamud.PluginInterface.UiBuilder.DisableGposeUiHide = true;
|
||||
// Dalamud.PluginInterface.UiBuilder.Draw += Draw;
|
||||
// Dalamud.PluginInterface.UiBuilder.OpenConfigUi += ToggleVisibility;
|
||||
//
|
||||
// _equipSlotNames = GetEquipSlotNames();
|
||||
//
|
||||
// _stains = GameData.Stains(Dalamud.GameData);
|
||||
// _models = GameData.Models(Dalamud.GameData);
|
||||
// _identifier = Penumbra.GameData.GameData.GetIdentifier(Dalamud.GameData, Dalamud.ClientState.ClientLanguage);
|
||||
//
|
||||
//
|
||||
// var stainCombo = CreateDefaultStainCombo(_stains.Values.ToArray());
|
||||
//
|
||||
// var equip = GameData.ItemsBySlot(Dalamud.GameData);
|
||||
// _combos = equip.ToDictionary(kvp => kvp.Key, kvp => CreateCombos(kvp.Key, kvp.Value, stainCombo));
|
||||
// _legacyTattooIcon = GetLegacyTattooIcon();
|
||||
//}
|
||||
//
|
||||
//public void ToggleVisibility()
|
||||
// => _visible = !_visible;
|
||||
//
|
||||
//
|
||||
//private void Draw()
|
||||
//{
|
||||
// if (!_visible)
|
||||
// return;
|
||||
//
|
||||
// ImGui.SetNextWindowSizeConstraints(Vector2.One * MinWindowWidth * ImGui.GetIO().FontGlobalScale,
|
||||
// Vector2.One * 5000 * ImGui.GetIO().FontGlobalScale);
|
||||
// if (!ImGui.Begin(_glamourerHeader, ref _visible))
|
||||
// {
|
||||
// ImGui.End();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// try
|
||||
// {
|
||||
// using var tabBar = ImRaii.TabBar("##tabBar");
|
||||
// if (!tabBar)
|
||||
// return;
|
||||
//
|
||||
// _inGPose = Dalamud.Objects[GPoseObjectId] != null;
|
||||
// _iconSize = Vector2.One * ImGui.GetTextLineHeightWithSpacing() * 2;
|
||||
// _actualIconSize = _iconSize + 2 * ImGui.GetStyle().FramePadding;
|
||||
// _comboSelectorSize = 4 * _actualIconSize.X + 3 * ImGui.GetStyle().ItemSpacing.X;
|
||||
// _percentageSize = _comboSelectorSize;
|
||||
// _inputIntSize = 2 * _actualIconSize.X + ImGui.GetStyle().ItemSpacing.X;
|
||||
// _raceSelectorWidth = _inputIntSize + _percentageSize - _actualIconSize.X;
|
||||
// _itemComboWidth = 6 * _actualIconSize.X + 4 * ImGui.GetStyle().ItemSpacing.X - ColorButtonWidth + 1;
|
||||
//
|
||||
// DrawPlayerTab();
|
||||
// DrawSaves();
|
||||
// DrawFixedDesignsTab();
|
||||
// DrawConfigTab();
|
||||
// DrawRevertablesTab();
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// ImGui.End();
|
||||
// }
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -1,308 +1,291 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using Dalamud.Game.ClientState.Objects.Enums;
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Logging;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.FileSystem;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Penumbra.PlayerWatch;
|
||||
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
internal partial class Interface
|
||||
{
|
||||
private readonly CharacterSave _currentSave = new();
|
||||
private string _newDesignName = string.Empty;
|
||||
private bool _keyboardFocus;
|
||||
private bool _holdShift;
|
||||
private bool _holdCtrl;
|
||||
private const string DesignNamePopupLabel = "Save Design As...";
|
||||
private const uint RedHeaderColor = 0xFF1818C0;
|
||||
private const uint GreenHeaderColor = 0xFF18C018;
|
||||
|
||||
private void DrawPlayerHeader()
|
||||
{
|
||||
var color = _player == null ? RedHeaderColor : GreenHeaderColor;
|
||||
var buttonColor = ImGui.GetColorU32(ImGuiCol.FrameBg);
|
||||
using var c = ImRaii.PushColor(ImGuiCol.Text, color)
|
||||
.Push(ImGuiCol.Button, buttonColor)
|
||||
.Push(ImGuiCol.ButtonHovered, buttonColor)
|
||||
.Push(ImGuiCol.ButtonActive, buttonColor);
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
ImGui.Button($"{_currentLabel}##playerHeader", -Vector2.UnitX * 0.0001f);
|
||||
}
|
||||
|
||||
private static void DrawCopyClipboardButton(CharacterSave save)
|
||||
{
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
if (ImGui.Button(FontAwesomeIcon.Clipboard.ToIconString()))
|
||||
ImGui.SetClipboardText(save.ToBase64());
|
||||
ImGui.PopFont();
|
||||
ImGuiUtil.HoverTooltip("Copy customization code to clipboard.");
|
||||
}
|
||||
|
||||
private static void ConditionalApply(CharacterSave save, Character player)
|
||||
{
|
||||
if (ImGui.GetIO().KeyShift)
|
||||
save.ApplyOnlyCustomizations(player);
|
||||
else if (ImGui.GetIO().KeyCtrl)
|
||||
save.ApplyOnlyEquipment(player);
|
||||
else
|
||||
save.Apply(player);
|
||||
}
|
||||
|
||||
private static CharacterSave ConditionalCopy(CharacterSave save, bool shift, bool ctrl)
|
||||
{
|
||||
var copy = save.Copy();
|
||||
if (shift)
|
||||
{
|
||||
copy.Load(new CharacterEquipment());
|
||||
copy.SetHatState = false;
|
||||
copy.SetVisorState = false;
|
||||
copy.SetWeaponState = false;
|
||||
copy.WriteEquipment = CharacterEquipMask.None;
|
||||
}
|
||||
else if (ctrl)
|
||||
{
|
||||
copy.Load(CharacterCustomization.Default);
|
||||
copy.SetHatState = false;
|
||||
copy.SetVisorState = false;
|
||||
copy.SetWeaponState = false;
|
||||
copy.WriteCustomizations = false;
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
private bool DrawApplyClipboardButton()
|
||||
{
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
var applyButton = ImGui.Button(FontAwesomeIcon.Paste.ToIconString()) && _player != null;
|
||||
ImGui.PopFont();
|
||||
ImGuiUtil.HoverTooltip(
|
||||
"Apply customization code from clipboard.\nHold Shift to apply only customizations.\nHold Control to apply only equipment.");
|
||||
|
||||
if (!applyButton)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
var text = ImGui.GetClipboardText();
|
||||
if (!text.Any())
|
||||
return false;
|
||||
|
||||
var save = CharacterSave.FromString(text);
|
||||
ConditionalApply(save, _player!);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLog.Information($"{e}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void DrawSaveDesignButton()
|
||||
{
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
if (ImGui.Button(FontAwesomeIcon.Save.ToIconString()))
|
||||
OpenDesignNamePopup(DesignNameUse.SaveCurrent);
|
||||
|
||||
ImGui.PopFont();
|
||||
ImGuiUtil.HoverTooltip("Save the current design.\nHold Shift to save only customizations.\nHold Control to save only equipment.");
|
||||
|
||||
DrawDesignNamePopup(DesignNameUse.SaveCurrent);
|
||||
}
|
||||
|
||||
private void DrawTargetPlayerButton()
|
||||
{
|
||||
if (ImGui.Button("Target Player"))
|
||||
Dalamud.Targets.SetTarget(_player);
|
||||
}
|
||||
|
||||
private void DrawApplyToPlayerButton(CharacterSave save)
|
||||
{
|
||||
if (!ImGui.Button("Apply to Self"))
|
||||
return;
|
||||
|
||||
var player = _inGPose
|
||||
? (Character?)Dalamud.Objects[GPoseObjectId]
|
||||
: Dalamud.ClientState.LocalPlayer;
|
||||
var fallback = _inGPose ? Dalamud.ClientState.LocalPlayer : null;
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
ConditionalApply(save, player);
|
||||
if (_inGPose)
|
||||
ConditionalApply(save, fallback!);
|
||||
Glamourer.Penumbra.UpdateCharacters(player, fallback);
|
||||
}
|
||||
|
||||
|
||||
private static Character? TransformToCustomizable(Character? actor)
|
||||
{
|
||||
if (actor == null)
|
||||
return null;
|
||||
|
||||
if (actor.ModelType() == 0)
|
||||
return actor;
|
||||
|
||||
actor.SetModelType(0);
|
||||
CharacterCustomization.Default.Write(actor.Address);
|
||||
return actor;
|
||||
}
|
||||
|
||||
private void DrawApplyToTargetButton(CharacterSave save)
|
||||
{
|
||||
if (!ImGui.Button("Apply to Target"))
|
||||
return;
|
||||
|
||||
var player = TransformToCustomizable(CharacterFactory.Convert(Dalamud.Targets.Target));
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
var fallBackCharacter = _gPoseActors.TryGetValue(player.Name.ToString(), out var f) ? f : null;
|
||||
ConditionalApply(save, player);
|
||||
if (fallBackCharacter != null)
|
||||
ConditionalApply(save, fallBackCharacter!);
|
||||
Glamourer.Penumbra.UpdateCharacters(player, fallBackCharacter);
|
||||
}
|
||||
|
||||
private void DrawRevertButton()
|
||||
{
|
||||
if (!ImGuiUtil.DrawDisabledButton("Revert", Vector2.Zero, string.Empty, _player == null))
|
||||
return;
|
||||
|
||||
Glamourer.RevertableDesigns.Revert(_player!);
|
||||
var fallBackCharacter = _gPoseActors.TryGetValue(_player!.Name.ToString(), out var f) ? f : null;
|
||||
if (fallBackCharacter != null)
|
||||
Glamourer.RevertableDesigns.Revert(fallBackCharacter);
|
||||
Glamourer.Penumbra.UpdateCharacters(_player, fallBackCharacter);
|
||||
}
|
||||
|
||||
private void SaveNewDesign(CharacterSave save)
|
||||
{
|
||||
try
|
||||
{
|
||||
var (folder, name) = _designs.FileSystem.CreateAllFolders(_newDesignName);
|
||||
if (!name.Any())
|
||||
return;
|
||||
|
||||
var newDesign = new Design(folder, name) { Data = save };
|
||||
folder.AddChild(newDesign);
|
||||
_designs.Designs[newDesign.FullName()] = save;
|
||||
_designs.SaveToFile();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLog.Error($"Could not save new design {_newDesignName}:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawMonsterPanel()
|
||||
{
|
||||
if (DrawApplyClipboardButton())
|
||||
Glamourer.Penumbra.UpdateCharacters(_player!);
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Convert to Character"))
|
||||
{
|
||||
TransformToCustomizable(_player);
|
||||
_currentLabel = _currentLabel.Replace("(Monster)", "(NPC)");
|
||||
Glamourer.Penumbra.UpdateCharacters(_player!);
|
||||
}
|
||||
|
||||
if (!_inGPose)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
DrawTargetPlayerButton();
|
||||
}
|
||||
|
||||
var currentModel = _player!.ModelType();
|
||||
using var combo = ImRaii.Combo("Model Id", currentModel.ToString());
|
||||
if (!combo)
|
||||
return;
|
||||
|
||||
foreach (var (id, _) in _models.Skip(1))
|
||||
{
|
||||
if (!ImGui.Selectable($"{id:D6}##models", id == currentModel) || id == currentModel)
|
||||
continue;
|
||||
|
||||
_player!.SetModelType((int)id);
|
||||
Glamourer.Penumbra.UpdateCharacters(_player!);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPlayerPanel()
|
||||
{
|
||||
DrawCopyClipboardButton(_currentSave);
|
||||
ImGui.SameLine();
|
||||
var changes = !_currentSave.WriteProtected && DrawApplyClipboardButton();
|
||||
ImGui.SameLine();
|
||||
DrawSaveDesignButton();
|
||||
ImGui.SameLine();
|
||||
DrawApplyToPlayerButton(_currentSave);
|
||||
if (!_inGPose)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
DrawApplyToTargetButton(_currentSave);
|
||||
if (_player != null && !_currentSave.WriteProtected)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
DrawTargetPlayerButton();
|
||||
}
|
||||
}
|
||||
|
||||
var data = _currentSave;
|
||||
if (!_currentSave.WriteProtected)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
DrawRevertButton();
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.8f);
|
||||
data = data.Copy();
|
||||
}
|
||||
|
||||
if (DrawCustomization(ref data.Customizations) && _player != null)
|
||||
{
|
||||
Glamourer.RevertableDesigns.Add(_player);
|
||||
_currentSave.Customizations.Write(_player.Address);
|
||||
changes = true;
|
||||
}
|
||||
|
||||
changes |= DrawEquip(data.Equipment);
|
||||
changes |= DrawMiscellaneous(data, _player);
|
||||
|
||||
if (_player != null && changes)
|
||||
Glamourer.Penumbra.UpdateCharacters(_player);
|
||||
if (_currentSave.WriteProtected)
|
||||
ImGui.PopStyleVar();
|
||||
}
|
||||
|
||||
private void DrawActorPanel()
|
||||
{
|
||||
using var group = ImRaii.Group();
|
||||
DrawPlayerHeader();
|
||||
using var child = ImRaii.Child("##playerData", -Vector2.One, true);
|
||||
if (!child)
|
||||
return;
|
||||
|
||||
if (_player == null || _player.ModelType() == 0)
|
||||
DrawPlayerPanel();
|
||||
else
|
||||
DrawMonsterPanel();
|
||||
}
|
||||
//private readonly CharacterSave _currentSave = new();
|
||||
//private string _newDesignName = string.Empty;
|
||||
//private bool _keyboardFocus;
|
||||
//private bool _holdShift;
|
||||
//private bool _holdCtrl;
|
||||
//private const string DesignNamePopupLabel = "Save Design As...";
|
||||
//private const uint RedHeaderColor = 0xFF1818C0;
|
||||
//private const uint GreenHeaderColor = 0xFF18C018;
|
||||
//
|
||||
//private void DrawPlayerHeader()
|
||||
//{
|
||||
// var color = _player == null ? RedHeaderColor : GreenHeaderColor;
|
||||
// var buttonColor = ImGui.GetColorU32(ImGuiCol.FrameBg);
|
||||
// using var c = ImRaii.PushColor(ImGuiCol.Text, color)
|
||||
// .Push(ImGuiCol.Button, buttonColor)
|
||||
// .Push(ImGuiCol.ButtonHovered, buttonColor)
|
||||
// .Push(ImGuiCol.ButtonActive, buttonColor);
|
||||
// using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
// .Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
// ImGui.Button($"{_currentLabel}##playerHeader", -Vector2.UnitX * 0.0001f);
|
||||
//}
|
||||
//
|
||||
//private static void DrawCopyClipboardButton(CharacterSave save)
|
||||
//{
|
||||
// ImGui.PushFont(UiBuilder.IconFont);
|
||||
// if (ImGui.Button(FontAwesomeIcon.Clipboard.ToIconString()))
|
||||
// ImGui.SetClipboardText(save.ToBase64());
|
||||
// ImGui.PopFont();
|
||||
// ImGuiUtil.HoverTooltip("Copy customization code to clipboard.");
|
||||
//}
|
||||
//
|
||||
//private static void ConditionalApply(CharacterSave save, Character player)
|
||||
//{
|
||||
// if (ImGui.GetIO().KeyShift)
|
||||
// save.ApplyOnlyCustomizations(player);
|
||||
// else if (ImGui.GetIO().KeyCtrl)
|
||||
// save.ApplyOnlyEquipment(player);
|
||||
// else
|
||||
// save.Apply(player);
|
||||
//}
|
||||
//
|
||||
//private static CharacterSave ConditionalCopy(CharacterSave save, bool shift, bool ctrl)
|
||||
//{
|
||||
// var copy = save.Copy();
|
||||
// if (shift)
|
||||
// {
|
||||
// copy.Load(new CharacterEquipment());
|
||||
// copy.SetHatState = false;
|
||||
// copy.SetVisorState = false;
|
||||
// copy.SetWeaponState = false;
|
||||
// copy.WriteEquipment = CharacterEquipMask.None;
|
||||
// }
|
||||
// else if (ctrl)
|
||||
// {
|
||||
// copy.Load(CharacterCustomization.Default);
|
||||
// copy.SetHatState = false;
|
||||
// copy.SetVisorState = false;
|
||||
// copy.SetWeaponState = false;
|
||||
// copy.WriteCustomizations = false;
|
||||
// }
|
||||
//
|
||||
// return copy;
|
||||
//}
|
||||
//
|
||||
//private bool DrawApplyClipboardButton()
|
||||
//{
|
||||
// ImGui.PushFont(UiBuilder.IconFont);
|
||||
// var applyButton = ImGui.Button(FontAwesomeIcon.Paste.ToIconString()) && _player != null;
|
||||
// ImGui.PopFont();
|
||||
// ImGuiUtil.HoverTooltip(
|
||||
// "Apply customization code from clipboard.\nHold Shift to apply only customizations.\nHold Control to apply only equipment.");
|
||||
//
|
||||
// if (!applyButton)
|
||||
// return false;
|
||||
//
|
||||
// try
|
||||
// {
|
||||
// var text = ImGui.GetClipboardText();
|
||||
// if (!text.Any())
|
||||
// return false;
|
||||
//
|
||||
// var save = CharacterSave.FromString(text);
|
||||
// ConditionalApply(save, _player!);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// PluginLog.Information($"{e}");
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// return true;
|
||||
//}
|
||||
//
|
||||
//private void DrawSaveDesignButton()
|
||||
//{
|
||||
// ImGui.PushFont(UiBuilder.IconFont);
|
||||
// if (ImGui.Button(FontAwesomeIcon.Save.ToIconString()))
|
||||
// OpenDesignNamePopup(DesignNameUse.SaveCurrent);
|
||||
//
|
||||
// ImGui.PopFont();
|
||||
// ImGuiUtil.HoverTooltip("Save the current design.\nHold Shift to save only customizations.\nHold Control to save only equipment.");
|
||||
//
|
||||
// DrawDesignNamePopup(DesignNameUse.SaveCurrent);
|
||||
//}
|
||||
//
|
||||
//private void DrawTargetPlayerButton()
|
||||
//{
|
||||
// if (ImGui.Button("Target Player"))
|
||||
// Dalamud.Targets.SetTarget(_player);
|
||||
//}
|
||||
//
|
||||
//private void DrawApplyToPlayerButton(CharacterSave save)
|
||||
//{
|
||||
// if (!ImGui.Button("Apply to Self"))
|
||||
// return;
|
||||
//
|
||||
// var player = _inGPose
|
||||
// ? (Character?)Dalamud.Objects[GPoseObjectId]
|
||||
// : Dalamud.ClientState.LocalPlayer;
|
||||
// var fallback = _inGPose ? Dalamud.ClientState.LocalPlayer : null;
|
||||
// if (player == null)
|
||||
// return;
|
||||
//
|
||||
// ConditionalApply(save, player);
|
||||
// if (_inGPose)
|
||||
// ConditionalApply(save, fallback!);
|
||||
// Glamourer.Penumbra.UpdateCharacters(player, fallback);
|
||||
//}
|
||||
//
|
||||
//
|
||||
//private static Character? TransformToCustomizable(Character? actor)
|
||||
//{
|
||||
// if (actor == null)
|
||||
// return null;
|
||||
//
|
||||
// if (actor.ModelType() == 0)
|
||||
// return actor;
|
||||
//
|
||||
// actor.SetModelType(0);
|
||||
// CharacterCustomization.Default.Write(actor.Address);
|
||||
// return actor;
|
||||
//}
|
||||
//
|
||||
//private void DrawApplyToTargetButton(CharacterSave save)
|
||||
//{
|
||||
// if (!ImGui.Button("Apply to Target"))
|
||||
// return;
|
||||
//
|
||||
// var player = TransformToCustomizable(CharacterFactory.Convert(Dalamud.Targets.Target));
|
||||
// if (player == null)
|
||||
// return;
|
||||
//
|
||||
// var fallBackCharacter = _gPoseActors.TryGetValue(player.Name.ToString(), out var f) ? f : null;
|
||||
// ConditionalApply(save, player);
|
||||
// if (fallBackCharacter != null)
|
||||
// ConditionalApply(save, fallBackCharacter!);
|
||||
// Glamourer.Penumbra.UpdateCharacters(player, fallBackCharacter);
|
||||
//}
|
||||
//
|
||||
//private void DrawRevertButton()
|
||||
//{
|
||||
// if (!ImGuiUtil.DrawDisabledButton("Revert", Vector2.Zero, string.Empty, _player == null))
|
||||
// return;
|
||||
//
|
||||
// Glamourer.RevertableDesigns.Revert(_player!);
|
||||
// var fallBackCharacter = _gPoseActors.TryGetValue(_player!.Name.ToString(), out var f) ? f : null;
|
||||
// if (fallBackCharacter != null)
|
||||
// Glamourer.RevertableDesigns.Revert(fallBackCharacter);
|
||||
// Glamourer.Penumbra.UpdateCharacters(_player, fallBackCharacter);
|
||||
//}
|
||||
//
|
||||
//private void SaveNewDesign(CharacterSave save)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// var (folder, name) = _designs.FileSystem.CreateAllFolders(_newDesignName);
|
||||
// if (!name.Any())
|
||||
// return;
|
||||
//
|
||||
// var newDesign = new Design(folder, name) { Data = save };
|
||||
// folder.AddChild(newDesign);
|
||||
// _designs.Designs[newDesign.FullName()] = save;
|
||||
// _designs.SaveToFile();
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// PluginLog.Error($"Could not save new design {_newDesignName}:\n{e}");
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//private void DrawMonsterPanel()
|
||||
//{
|
||||
// if (DrawApplyClipboardButton())
|
||||
// Glamourer.Penumbra.UpdateCharacters(_player!);
|
||||
//
|
||||
// ImGui.SameLine();
|
||||
// if (ImGui.Button("Convert to Character"))
|
||||
// {
|
||||
// TransformToCustomizable(_player);
|
||||
// _currentLabel = _currentLabel.Replace("(Monster)", "(NPC)");
|
||||
// Glamourer.Penumbra.UpdateCharacters(_player!);
|
||||
// }
|
||||
//
|
||||
// if (!_inGPose)
|
||||
// {
|
||||
// ImGui.SameLine();
|
||||
// DrawTargetPlayerButton();
|
||||
// }
|
||||
//
|
||||
// var currentModel = _player!.ModelType();
|
||||
// using var combo = ImRaii.Combo("Model Id", currentModel.ToString());
|
||||
// if (!combo)
|
||||
// return;
|
||||
//
|
||||
// foreach (var (id, _) in _models.Skip(1))
|
||||
// {
|
||||
// if (!ImGui.Selectable($"{id:D6}##models", id == currentModel) || id == currentModel)
|
||||
// continue;
|
||||
//
|
||||
// _player!.SetModelType((int)id);
|
||||
// Glamourer.Penumbra.UpdateCharacters(_player!);
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//private void DrawPlayerPanel()
|
||||
//{
|
||||
// DrawCopyClipboardButton(_currentSave);
|
||||
// ImGui.SameLine();
|
||||
// var changes = !_currentSave.WriteProtected && DrawApplyClipboardButton();
|
||||
// ImGui.SameLine();
|
||||
// DrawSaveDesignButton();
|
||||
// ImGui.SameLine();
|
||||
// DrawApplyToPlayerButton(_currentSave);
|
||||
// if (!_inGPose)
|
||||
// {
|
||||
// ImGui.SameLine();
|
||||
// DrawApplyToTargetButton(_currentSave);
|
||||
// if (_player != null && !_currentSave.WriteProtected)
|
||||
// {
|
||||
// ImGui.SameLine();
|
||||
// DrawTargetPlayerButton();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// var data = _currentSave;
|
||||
// if (!_currentSave.WriteProtected)
|
||||
// {
|
||||
// ImGui.SameLine();
|
||||
// DrawRevertButton();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.8f);
|
||||
// data = data.Copy();
|
||||
// }
|
||||
//
|
||||
// if (DrawCustomization(ref data.Customizations) && _player != null)
|
||||
// {
|
||||
// Glamourer.RevertableDesigns.Add(_player);
|
||||
// _currentSave.Customizations.Write(_player.Address);
|
||||
// changes = true;
|
||||
// }
|
||||
//
|
||||
// changes |= DrawEquip(data.Equipment);
|
||||
// changes |= DrawMiscellaneous(data, _player);
|
||||
//
|
||||
// if (_player != null && changes)
|
||||
// Glamourer.Penumbra.UpdateCharacters(_player);
|
||||
// if (_currentSave.WriteProtected)
|
||||
// ImGui.PopStyleVar();
|
||||
//}
|
||||
//
|
||||
//private void DrawActorPanel()
|
||||
//{
|
||||
// using var group = ImRaii.Group();
|
||||
// DrawPlayerHeader();
|
||||
// using var child = ImRaii.Child("##playerData", -Vector2.One, true);
|
||||
// if (!child)
|
||||
// return;
|
||||
//
|
||||
// if (_player == null || _player.ModelType() == 0)
|
||||
// DrawPlayerPanel();
|
||||
// else
|
||||
// DrawMonsterPanel();
|
||||
//}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,223 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Game.ClientState.Objects.Enums;
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Logging;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.PlayerWatch;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
internal partial class Interface
|
||||
{
|
||||
public const int CharacterScreenIndex = 240;
|
||||
public const int ExamineScreenIndex = 241;
|
||||
public const int FittingRoomIndex = 242;
|
||||
public const int DyePreviewIndex = 243;
|
||||
|
||||
private Character? _player;
|
||||
private string _currentLabel = string.Empty;
|
||||
private string _playerFilter = string.Empty;
|
||||
private string _playerFilterLower = string.Empty;
|
||||
private readonly Dictionary<string, int> _playerNames = new(100);
|
||||
private readonly Dictionary<string, Character?> _gPoseActors = new(CharacterScreenIndex - GPoseObjectId);
|
||||
|
||||
private void DrawPlayerFilter()
|
||||
{
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
ImGui.SetNextItemWidth(SelectorWidth * ImGui.GetIO().FontGlobalScale);
|
||||
if (ImGui.InputTextWithHint("##playerFilter", "Filter Players...", ref _playerFilter, 32))
|
||||
_playerFilterLower = _playerFilter.ToLowerInvariant();
|
||||
}
|
||||
|
||||
private void DrawGPoseSelectable(Character player)
|
||||
{
|
||||
var playerName = player.Name.ToString();
|
||||
if (!playerName.Any())
|
||||
return;
|
||||
|
||||
_gPoseActors[playerName] = null;
|
||||
|
||||
DrawSelectable(player, $"{playerName} (GPose)", true);
|
||||
}
|
||||
|
||||
private static string GetLabel(Character player, string playerName, int num)
|
||||
{
|
||||
if (player.ObjectKind == ObjectKind.Player)
|
||||
return num == 1 ? playerName : $"{playerName} #{num}";
|
||||
|
||||
if (player.ModelType() == 0)
|
||||
return num == 1 ? $"{playerName} (NPC)" : $"{playerName} #{num} (NPC)";
|
||||
|
||||
return num == 1 ? $"{playerName} (Monster)" : $"{playerName} #{num} (Monster)";
|
||||
}
|
||||
|
||||
private void DrawPlayerSelectable(Character player, int idx = 0)
|
||||
{
|
||||
var (playerName, modifiable) = idx switch
|
||||
{
|
||||
CharacterScreenIndex => ("Character Screen Actor", false),
|
||||
ExamineScreenIndex => ("Examine Screen Actor", false),
|
||||
FittingRoomIndex => ("Fitting Room Actor", false),
|
||||
DyePreviewIndex => ("Dye Preview Actor", false),
|
||||
_ => (player.Name.ToString(), true),
|
||||
};
|
||||
if (!playerName.Any())
|
||||
return;
|
||||
|
||||
if (_playerNames.TryGetValue(playerName, out var num))
|
||||
_playerNames[playerName] = ++num;
|
||||
else
|
||||
_playerNames[playerName] = num = 1;
|
||||
|
||||
if (_gPoseActors.ContainsKey(playerName))
|
||||
{
|
||||
_gPoseActors[playerName] = player;
|
||||
return;
|
||||
}
|
||||
|
||||
var label = GetLabel(player, playerName, num);
|
||||
DrawSelectable(player, label, modifiable);
|
||||
}
|
||||
|
||||
|
||||
private void DrawSelectable(Character player, string label, bool modifiable)
|
||||
{
|
||||
if (!_playerFilterLower.Any() || label.ToLowerInvariant().Contains(_playerFilterLower))
|
||||
if (ImGui.Selectable(label, _currentLabel == label))
|
||||
{
|
||||
_currentLabel = label;
|
||||
_currentSave.LoadCharacter(player);
|
||||
_player = player;
|
||||
_currentSave.WriteProtected = !modifiable;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_currentLabel != label)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
_currentSave.LoadCharacter(player);
|
||||
_player = player;
|
||||
_currentSave.WriteProtected = !modifiable;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLog.Error($"Could not load character {player.Name}s information:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSelectionButtons()
|
||||
{
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
using var font = ImRaii.PushFont(UiBuilder.IconFont);
|
||||
Character? select = null;
|
||||
var buttonWidth = Vector2.UnitX * SelectorWidth / 2;
|
||||
if (ImGui.Button(FontAwesomeIcon.UserCircle.ToIconString(), buttonWidth))
|
||||
select = Dalamud.ClientState.LocalPlayer;
|
||||
font.Pop();
|
||||
ImGuiUtil.HoverTooltip("Select the local player character.");
|
||||
ImGui.SameLine();
|
||||
font.Push(UiBuilder.IconFont);
|
||||
if (_inGPose)
|
||||
{
|
||||
style.Push(ImGuiStyleVar.Alpha, 0.5f);
|
||||
ImGui.Button(FontAwesomeIcon.HandPointer.ToIconString(), buttonWidth);
|
||||
style.Pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui.Button(FontAwesomeIcon.HandPointer.ToIconString(), buttonWidth))
|
||||
select = CharacterFactory.Convert(Dalamud.Targets.Target);
|
||||
}
|
||||
|
||||
font.Pop();
|
||||
ImGuiUtil.HoverTooltip("Select the current target, if it is in the list.");
|
||||
|
||||
if (select == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
_currentSave.LoadCharacter(select);
|
||||
_player = select;
|
||||
_currentLabel = _player.Name.ToString();
|
||||
_currentSave.WriteProtected = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLog.Error($"Could not load character {select.Name}s information:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPlayerSelector()
|
||||
{
|
||||
ImGui.BeginGroup();
|
||||
DrawPlayerFilter();
|
||||
if (!ImGui.BeginChild("##playerSelector",
|
||||
new Vector2(SelectorWidth * ImGui.GetIO().FontGlobalScale, -ImGui.GetFrameHeight() - 1), true))
|
||||
{
|
||||
ImGui.EndChild();
|
||||
ImGui.EndGroup();
|
||||
return;
|
||||
}
|
||||
|
||||
_playerNames.Clear();
|
||||
_gPoseActors.Clear();
|
||||
for (var i = GPoseObjectId; i < GPoseObjectId + 48; ++i)
|
||||
{
|
||||
var player = CharacterFactory.Convert(Dalamud.Objects[i]);
|
||||
if (player == null)
|
||||
break;
|
||||
|
||||
DrawGPoseSelectable(player);
|
||||
}
|
||||
|
||||
for (var i = 0; i < GPoseObjectId; ++i)
|
||||
{
|
||||
var player = CharacterFactory.Convert(Dalamud.Objects[i]);
|
||||
if (player != null)
|
||||
DrawPlayerSelectable(player);
|
||||
}
|
||||
|
||||
for (var i = CharacterScreenIndex; i < Dalamud.Objects.Length; ++i)
|
||||
{
|
||||
var player = CharacterFactory.Convert(Dalamud.Objects[i]);
|
||||
if (player != null)
|
||||
DrawPlayerSelectable(player, i);
|
||||
}
|
||||
|
||||
|
||||
using (var _ = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero))
|
||||
{
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
||||
DrawSelectionButtons();
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
|
||||
private void DrawPlayerTab()
|
||||
{
|
||||
using var tab = ImRaii.TabItem("Current Players");
|
||||
_player = null;
|
||||
if (!tab)
|
||||
return;
|
||||
|
||||
DrawPlayerSelector();
|
||||
|
||||
if (_currentLabel.Length == 0)
|
||||
return;
|
||||
|
||||
ImGui.SameLine();
|
||||
DrawActorPanel();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
|
||||
namespace Glamourer.Gui
|
||||
{
|
||||
internal partial class Interface
|
||||
{
|
||||
private static void DrawConfigCheckMark(string label, string tooltip, bool value, Action<bool> setter)
|
||||
{
|
||||
if (DrawCheckMark(label, value, setter))
|
||||
Glamourer.Config.Save();
|
||||
|
||||
ImGuiUtil.HoverTooltip(tooltip);
|
||||
}
|
||||
|
||||
private static void ChangeAndSave<T>(T value, T currentValue, Action<T> setter) where T : IEquatable<T>
|
||||
{
|
||||
if (value.Equals(currentValue))
|
||||
return;
|
||||
|
||||
setter(value);
|
||||
Glamourer.Config.Save();
|
||||
}
|
||||
|
||||
private static void DrawColorPicker(string name, string tooltip, uint value, uint defaultValue, Action<uint> setter)
|
||||
{
|
||||
const ImGuiColorEditFlags flags = ImGuiColorEditFlags.AlphaPreviewHalf | ImGuiColorEditFlags.NoInputs;
|
||||
|
||||
var tmp = ImGui.ColorConvertU32ToFloat4(value);
|
||||
if (ImGui.ColorEdit4($"##{name}", ref tmp, flags))
|
||||
ChangeAndSave(ImGui.ColorConvertFloat4ToU32(tmp), value, setter);
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button($"Default##{name}"))
|
||||
ChangeAndSave(defaultValue, value, setter);
|
||||
ImGuiUtil.HoverTooltip(
|
||||
$"Reset to default: #{defaultValue & 0xFF:X2}{(defaultValue >> 8) & 0xFF:X2}{(defaultValue >> 16) & 0xFF:X2}{defaultValue >> 24:X2}");
|
||||
ImGui.SameLine();
|
||||
ImGui.Text(name);
|
||||
ImGuiUtil.HoverTooltip(tooltip);
|
||||
}
|
||||
|
||||
private static void DrawRestorePenumbraButton()
|
||||
{
|
||||
const string buttonLabel = "Re-Register Penumbra";
|
||||
if (!Glamourer.Config.AttachToPenumbra)
|
||||
{
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.Alpha, 0.5f);
|
||||
ImGui.Button(buttonLabel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui.Button(buttonLabel))
|
||||
Glamourer.Penumbra.Reattach(true);
|
||||
|
||||
ImGuiUtil.HoverTooltip(
|
||||
"If Penumbra did not register the functions for some reason, pressing this button might help restore functionality.");
|
||||
}
|
||||
|
||||
private static void DrawConfigTab()
|
||||
{
|
||||
using var tab = ImRaii.TabItem("Config");
|
||||
if (!tab)
|
||||
return;
|
||||
|
||||
var cfg = Glamourer.Config;
|
||||
ImGui.Dummy(Vector2.UnitY * ImGui.GetTextLineHeightWithSpacing() / 2);
|
||||
|
||||
DrawConfigCheckMark("Folders First", "Sort Folders before all designs instead of lexicographically.", cfg.FoldersFirst,
|
||||
v => cfg.FoldersFirst = v);
|
||||
DrawConfigCheckMark("Color Designs", "Color the names of designs in the selector using the colors from below for the given cases.",
|
||||
cfg.ColorDesigns,
|
||||
v => cfg.ColorDesigns = v);
|
||||
DrawConfigCheckMark("Show Locks", "Write-protected Designs show a lock besides their name in the selector.", cfg.ShowLocks,
|
||||
v => cfg.ShowLocks = v);
|
||||
DrawConfigCheckMark("Attach to Penumbra",
|
||||
"Allows you to right-click items in the Changed Items tab of a mod in Penumbra to apply them to your player character.",
|
||||
cfg.AttachToPenumbra,
|
||||
v =>
|
||||
{
|
||||
cfg.AttachToPenumbra = v;
|
||||
if (v)
|
||||
Glamourer.Penumbra.Reattach(true);
|
||||
else
|
||||
Glamourer.Penumbra.Unattach();
|
||||
});
|
||||
ImGui.SameLine();
|
||||
DrawRestorePenumbraButton();
|
||||
|
||||
DrawConfigCheckMark("Apply Fixed Designs",
|
||||
"Automatically apply fixed designs to characters and redraw them when anything changes.",
|
||||
cfg.ApplyFixedDesigns,
|
||||
v =>
|
||||
{
|
||||
cfg.ApplyFixedDesigns = v;
|
||||
if (v)
|
||||
Glamourer.PlayerWatcher.Enable();
|
||||
else
|
||||
Glamourer.PlayerWatcher.Disable();
|
||||
});
|
||||
|
||||
ImGui.Dummy(Vector2.UnitY * ImGui.GetTextLineHeightWithSpacing() / 2);
|
||||
|
||||
DrawColorPicker("Customization Color", "The color for designs that only apply their character customization.",
|
||||
cfg.CustomizationColor, GlamourerConfig.DefaultCustomizationColor, c => cfg.CustomizationColor = c);
|
||||
DrawColorPicker("Equipment Color", "The color for designs that only apply some or all of their equipment slots and stains.",
|
||||
cfg.EquipmentColor, GlamourerConfig.DefaultEquipmentColor, c => cfg.EquipmentColor = c);
|
||||
DrawColorPicker("State Color", "The color for designs that only apply some state modification.",
|
||||
cfg.StateColor, GlamourerConfig.DefaultStateColor, c => cfg.StateColor = c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,478 +0,0 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Logging;
|
||||
using Glamourer.Customization;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
||||
namespace Glamourer.Gui
|
||||
{
|
||||
internal partial class Interface
|
||||
{
|
||||
private static bool DrawColorPickerPopup(string label, CustomizationSet set, CustomizationId id, out Customization.Customization value)
|
||||
{
|
||||
value = default;
|
||||
using var popup = ImRaii.Popup(label, ImGuiWindowFlags.AlwaysAutoResize);
|
||||
if (!popup)
|
||||
return false;
|
||||
|
||||
var ret = false;
|
||||
var count = set.Count(id);
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
var custom = set.Data(id, i);
|
||||
if (ImGui.ColorButton((i + 1).ToString(), ImGui.ColorConvertU32ToFloat4(custom.Color)))
|
||||
{
|
||||
value = custom;
|
||||
ret = true;
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
|
||||
if (i % 8 != 7)
|
||||
ImGui.SameLine();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private Vector2 _iconSize = Vector2.Zero;
|
||||
private Vector2 _actualIconSize = Vector2.Zero;
|
||||
private float _raceSelectorWidth;
|
||||
private float _inputIntSize;
|
||||
private float _comboSelectorSize;
|
||||
private float _percentageSize;
|
||||
private float _itemComboWidth;
|
||||
|
||||
private bool InputInt(string label, ref int value, int minValue, int maxValue)
|
||||
{
|
||||
var ret = false;
|
||||
var tmp = value + 1;
|
||||
ImGui.SetNextItemWidth(_inputIntSize);
|
||||
if (ImGui.InputInt(label, ref tmp, 1, 1, ImGuiInputTextFlags.EnterReturnsTrue) && tmp != value + 1 && tmp >= minValue && tmp <= maxValue)
|
||||
{
|
||||
value = tmp - 1;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip($"Input Range: [{minValue}, {maxValue}]");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static (int, Customization.Customization) GetCurrentCustomization(ref CharacterCustomization customization, CustomizationId id,
|
||||
CustomizationSet set)
|
||||
{
|
||||
var current = set.DataByValue(id, customization[id], out var custom);
|
||||
if (set.IsAvailable(id) && current < 0)
|
||||
{
|
||||
PluginLog.Warning($"Read invalid customization value {customization[id]} for {id}.");
|
||||
current = 0;
|
||||
custom = set.Data(id, 0);
|
||||
}
|
||||
|
||||
return (current, custom!.Value);
|
||||
}
|
||||
|
||||
private bool DrawColorPicker(string label, string tooltip, ref CharacterCustomization customization, CustomizationId id,
|
||||
CustomizationSet set)
|
||||
{
|
||||
var ret = false;
|
||||
var count = set.Count(id);
|
||||
|
||||
var (current, custom) = GetCurrentCustomization(ref customization, id, set);
|
||||
|
||||
var popupName = $"Color Picker##{id}";
|
||||
if (ImGui.ColorButton($"{current + 1}##color_{id}", ImGui.ColorConvertU32ToFloat4(custom.Color), ImGuiColorEditFlags.None,
|
||||
_actualIconSize))
|
||||
ImGui.OpenPopup(popupName);
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
using (var _ = ImRaii.Group())
|
||||
{
|
||||
if (InputInt($"##text_{id}", ref current, 1, count))
|
||||
{
|
||||
customization[id] = set.Data(id, current).Value;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
|
||||
ImGui.Text(label);
|
||||
ImGuiUtil.HoverTooltip(tooltip);
|
||||
}
|
||||
|
||||
if (!DrawColorPickerPopup(popupName, set, id, out var newCustom))
|
||||
return ret;
|
||||
|
||||
customization[id] = newCustom.Value;
|
||||
ret = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawListSelector(string label, string tooltip, ref CharacterCustomization customization, CustomizationId id,
|
||||
CustomizationSet set)
|
||||
{
|
||||
using var bigGroup = ImRaii.Group();
|
||||
var ret = false;
|
||||
int current = customization[id];
|
||||
var count = set.Count(id);
|
||||
|
||||
ImGui.SetNextItemWidth(_comboSelectorSize * ImGui.GetIO().FontGlobalScale);
|
||||
if (ImGui.BeginCombo($"##combo_{id}", $"{set.Option(id)} #{current + 1}"))
|
||||
{
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
if (ImGui.Selectable($"{set.Option(id)} #{i + 1}##combo", i == current) && i != current)
|
||||
{
|
||||
customization[id] = (byte) i;
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
if (InputInt($"##text_{id}", ref current, 1, count))
|
||||
{
|
||||
customization[id] = (byte) current;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.Text(label);
|
||||
ImGuiUtil.HoverTooltip(tooltip);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
private static readonly Vector4 NoColor = new(1f, 1f, 1f, 1f);
|
||||
private static readonly Vector4 RedColor = new(0.6f, 0.3f, 0.3f, 1f);
|
||||
|
||||
private bool DrawMultiSelector(ref CharacterCustomization customization, CustomizationSet set)
|
||||
{
|
||||
using var bigGroup = ImRaii.Group();
|
||||
var ret = false;
|
||||
var count = set.Count(CustomizationId.FacialFeaturesTattoos);
|
||||
using (var _ = ImRaii.Group())
|
||||
{
|
||||
var face = customization.Face;
|
||||
if (set.Faces.Count < face)
|
||||
face = 1;
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
var enabled = customization.FacialFeature(i);
|
||||
var feature = set.FacialFeature(face, i);
|
||||
var icon = i == count - 1
|
||||
? _legacyTattooIcon ?? Glamourer.Customization.GetIcon(feature.IconId)
|
||||
: Glamourer.Customization.GetIcon(feature.IconId);
|
||||
if (ImGui.ImageButton(icon.ImGuiHandle, _iconSize, Vector2.Zero, Vector2.One, (int) ImGui.GetStyle().FramePadding.X,
|
||||
Vector4.Zero,
|
||||
enabled ? NoColor : RedColor))
|
||||
{
|
||||
ret = true;
|
||||
customization.FacialFeature(i, !enabled);
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverIconTooltip(icon, _iconSize);
|
||||
|
||||
if (i % 4 != 3)
|
||||
ImGui.SameLine();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
using var group = ImRaii.Group();
|
||||
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + ImGui.GetTextLineHeightWithSpacing() + 3 * ImGui.GetStyle().ItemSpacing.Y / 2);
|
||||
int value = customization[CustomizationId.FacialFeaturesTattoos];
|
||||
if (InputInt($"##{CustomizationId.FacialFeaturesTattoos}", ref value, 1, 256))
|
||||
{
|
||||
customization[CustomizationId.FacialFeaturesTattoos] = (byte) value;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
ImGui.TextUnformatted(set.Option(CustomizationId.FacialFeaturesTattoos));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
private bool DrawIconPickerPopup(string label, CustomizationSet set, CustomizationId id, out Customization.Customization value)
|
||||
{
|
||||
value = default;
|
||||
using var popup = ImRaii.Popup(label, ImGuiWindowFlags.AlwaysAutoResize);
|
||||
if (!popup)
|
||||
return false;
|
||||
|
||||
var ret = false;
|
||||
var count = set.Count(id);
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
var custom = set.Data(id, i);
|
||||
var icon = Glamourer.Customization.GetIcon(custom.IconId);
|
||||
ImGui.BeginGroup();
|
||||
if (ImGui.ImageButton(icon.ImGuiHandle, _iconSize))
|
||||
{
|
||||
value = custom;
|
||||
ret = true;
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverIconTooltip(icon, _iconSize);
|
||||
|
||||
var text = custom.Value.ToString();
|
||||
var textWidth = ImGui.CalcTextSize(text).X;
|
||||
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + (_iconSize.X - textWidth + 2 * ImGui.GetStyle().FramePadding.X)/2);
|
||||
ImGui.Text(text);
|
||||
ImGui.EndGroup();
|
||||
if (i % 8 != 7)
|
||||
ImGui.SameLine();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawIconSelector(string label, string tooltip, ref CharacterCustomization customization, CustomizationId id,
|
||||
CustomizationSet set)
|
||||
{
|
||||
using var bigGroup = ImRaii.Group();
|
||||
var ret = false;
|
||||
var count = set.Count(id);
|
||||
|
||||
var current = set.DataByValue(id, customization[id], out var custom);
|
||||
if (current < 0)
|
||||
{
|
||||
label = $"{label} (Custom #{customization[id]})";
|
||||
current = 0;
|
||||
custom = set.Data(id, 0);
|
||||
}
|
||||
|
||||
var popupName = $"Style Picker##{id}";
|
||||
var icon = Glamourer.Customization.GetIcon(custom!.Value.IconId);
|
||||
if (ImGui.ImageButton(icon.ImGuiHandle, _iconSize))
|
||||
ImGui.OpenPopup(popupName);
|
||||
|
||||
ImGuiUtil.HoverIconTooltip(icon, _iconSize);
|
||||
|
||||
ImGui.SameLine();
|
||||
using var group = ImRaii.Group();
|
||||
if (InputInt($"##text_{id}", ref current, 1, count))
|
||||
{
|
||||
customization[id] = set.Data(id, current).Value;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (DrawIconPickerPopup(popupName, set, id, out var newCustom))
|
||||
{
|
||||
customization[id] = newCustom.Value;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
ImGui.TextUnformatted($"{label} ({custom.Value.Value})");
|
||||
ImGuiUtil.HoverTooltip(tooltip);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
private bool DrawPercentageSelector(string label, string tooltip, ref CharacterCustomization customization, CustomizationId id,
|
||||
CustomizationSet set)
|
||||
{
|
||||
using var bigGroup = ImRaii.Group();
|
||||
var ret = false;
|
||||
int value = customization[id];
|
||||
var count = set.Count(id);
|
||||
ImGui.SetNextItemWidth(_percentageSize * ImGui.GetIO().FontGlobalScale);
|
||||
if (ImGui.SliderInt($"##slider_{id}", ref value, 0, count - 1, "") && value != customization[id])
|
||||
{
|
||||
customization[id] = (byte) value;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
--value;
|
||||
if (InputInt($"##input_{id}", ref value, 0, count - 1))
|
||||
{
|
||||
customization[id] = (byte) (value + 1);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted(label);
|
||||
ImGuiUtil.HoverTooltip(tooltip);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawRaceSelector(ref CharacterCustomization customization)
|
||||
{
|
||||
using var group = ImRaii.Group();
|
||||
var ret = false;
|
||||
ImGui.SetNextItemWidth(_raceSelectorWidth);
|
||||
if (ImGui.BeginCombo("##subRaceCombo", ClanName(customization.Clan, customization.Gender)))
|
||||
{
|
||||
for (var i = 0; i < (int) SubRace.Veena; ++i)
|
||||
{
|
||||
if (ImGui.Selectable(ClanName((SubRace) i + 1, customization.Gender), (int) customization.Clan == i + 1))
|
||||
{
|
||||
var race = (SubRace) i + 1;
|
||||
ret |= ChangeRace(ref customization, race);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
ImGui.TextUnformatted(
|
||||
$"{Glamourer.Customization.GetName(CustomName.Gender)} & {Glamourer.Customization.GetName(CustomName.Clan)}");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawGenderSelector(ref CharacterCustomization customization)
|
||||
{
|
||||
var ret = false;
|
||||
using var font = ImRaii.PushFont(UiBuilder.IconFont);
|
||||
var icon = customization.Gender == Gender.Male ? FontAwesomeIcon.Mars : FontAwesomeIcon.Venus;
|
||||
var restricted = false;
|
||||
if (customization.Race == Race.Hrothgar)
|
||||
{
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.25f);
|
||||
icon = FontAwesomeIcon.MarsDouble;
|
||||
restricted = true;
|
||||
}
|
||||
|
||||
if (ImGui.Button(icon.ToIconString(), _actualIconSize) && !restricted)
|
||||
{
|
||||
var gender = customization.Gender == Gender.Male ? Gender.Female : Gender.Male;
|
||||
ret = ChangeGender(ref customization, gender);
|
||||
}
|
||||
|
||||
if (restricted)
|
||||
ImGui.PopStyleVar();
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawPicker(CustomizationSet set, CustomizationId id, ref CharacterCustomization customization)
|
||||
{
|
||||
if (!set.IsAvailable(id))
|
||||
return false;
|
||||
|
||||
switch (set.Type(id))
|
||||
{
|
||||
case CharaMakeParams.MenuType.ColorPicker: return DrawColorPicker(set.OptionName[(int) id], "", ref customization, id, set);
|
||||
case CharaMakeParams.MenuType.ListSelector: return DrawListSelector(set.OptionName[(int) id], "", ref customization, id, set);
|
||||
case CharaMakeParams.MenuType.IconSelector: return DrawIconSelector(set.OptionName[(int) id], "", ref customization, id, set);
|
||||
case CharaMakeParams.MenuType.MultiIconSelector: return DrawMultiSelector(ref customization, set);
|
||||
case CharaMakeParams.MenuType.Percentage:
|
||||
return DrawPercentageSelector(set.OptionName[(int) id], "", ref customization, id, set);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static CustomizationId[] GetCustomizationOrder()
|
||||
{
|
||||
var ret = (CustomizationId[])Enum.GetValues(typeof(CustomizationId));
|
||||
ret[(int) CustomizationId.TattooColor] = CustomizationId.EyeColorL;
|
||||
ret[(int) CustomizationId.EyeColorL] = CustomizationId.EyeColorR;
|
||||
ret[(int) CustomizationId.EyeColorR] = CustomizationId.TattooColor;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static readonly CustomizationId[] AllCustomizations = GetCustomizationOrder();
|
||||
|
||||
private bool DrawCustomization(ref CharacterCustomization custom)
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Character Customization"))
|
||||
return false;
|
||||
|
||||
var ret = DrawGenderSelector(ref custom);
|
||||
ImGui.SameLine();
|
||||
ret |= DrawRaceSelector(ref custom);
|
||||
|
||||
var set = Glamourer.Customization.GetList(custom.Clan, custom.Gender);
|
||||
|
||||
foreach (var id in AllCustomizations.Where(c => set.Type(c) == CharaMakeParams.MenuType.Percentage))
|
||||
ret |= DrawPicker(set, id, ref custom);
|
||||
|
||||
var odd = true;
|
||||
foreach (var id in AllCustomizations.Where((c, _) => set.Type(c) == CharaMakeParams.MenuType.IconSelector))
|
||||
{
|
||||
ret |= DrawPicker(set, id, ref custom);
|
||||
if (odd)
|
||||
ImGui.SameLine();
|
||||
odd = !odd;
|
||||
}
|
||||
|
||||
if (!odd)
|
||||
ImGui.NewLine();
|
||||
|
||||
ret |= DrawPicker(set, CustomizationId.FacialFeaturesTattoos, ref custom);
|
||||
|
||||
foreach (var id in AllCustomizations.Where(c => set.Type(c) == CharaMakeParams.MenuType.ListSelector))
|
||||
ret |= DrawPicker(set, id, ref custom);
|
||||
|
||||
odd = true;
|
||||
foreach (var id in AllCustomizations.Where(c => set.Type(c) == CharaMakeParams.MenuType.ColorPicker))
|
||||
{
|
||||
ret |= DrawPicker(set, id, ref custom);
|
||||
if (odd)
|
||||
ImGui.SameLine();
|
||||
odd = !odd;
|
||||
}
|
||||
|
||||
if (!odd)
|
||||
ImGui.NewLine();
|
||||
|
||||
var tmp = custom.HighlightsOn;
|
||||
if (ImGui.Checkbox(set.Option(CustomizationId.HighlightsOnFlag), ref tmp) && tmp != custom.HighlightsOn)
|
||||
{
|
||||
custom.HighlightsOn = tmp;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
var xPos = _inputIntSize + _actualIconSize.X + 3 * ImGui.GetStyle().ItemSpacing.X;
|
||||
ImGui.SameLine(xPos);
|
||||
tmp = custom.FacePaintReversed;
|
||||
if (ImGui.Checkbox($"{Glamourer.Customization.GetName(CustomName.Reverse)} {set.Option(CustomizationId.FacePaint)}", ref tmp)
|
||||
&& tmp != custom.FacePaintReversed)
|
||||
{
|
||||
custom.FacePaintReversed = tmp;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
tmp = custom.SmallIris;
|
||||
if (ImGui.Checkbox($"{Glamourer.Customization.GetName(CustomName.IrisSmall)} {Glamourer.Customization.GetName(CustomName.IrisSize)}",
|
||||
ref tmp)
|
||||
&& tmp != custom.SmallIris)
|
||||
{
|
||||
custom.SmallIris = tmp;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (custom.Race != Race.Hrothgar)
|
||||
{
|
||||
tmp = custom.Lipstick;
|
||||
ImGui.SameLine(xPos);
|
||||
if (ImGui.Checkbox(set.Option(CustomizationId.LipColor), ref tmp) && tmp != custom.Lipstick)
|
||||
{
|
||||
custom.Lipstick = tmp;
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,371 +4,371 @@ using System.Numerics;
|
|||
using Dalamud.Interface;
|
||||
using Dalamud.Logging;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.FileSystem;
|
||||
using Glamourer.Structs;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
internal partial class Interface
|
||||
{
|
||||
private int _totalObject;
|
||||
|
||||
private bool _inDesignMode;
|
||||
private Design? _selection;
|
||||
private string _newChildName = string.Empty;
|
||||
|
||||
private void DrawDesignSelector()
|
||||
{
|
||||
_totalObject = 0;
|
||||
ImGui.BeginGroup();
|
||||
if (ImGui.BeginChild("##selector", new Vector2(SelectorWidth * ImGui.GetIO().FontGlobalScale, -ImGui.GetFrameHeight() - 1), true))
|
||||
{
|
||||
DrawFolderContent(_designs.FileSystem.Root, Glamourer.Config.FoldersFirst ? SortMode.FoldersFirst : SortMode.Lexicographical);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, Vector2.Zero);
|
||||
ImGui.EndChild();
|
||||
ImGui.PopStyleVar();
|
||||
}
|
||||
|
||||
DrawDesignSelectorButtons();
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
|
||||
private void DrawPasteClipboardButton()
|
||||
{
|
||||
if (_selection!.Data.WriteProtected)
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.5f);
|
||||
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
var applyButton = ImGui.Button(FontAwesomeIcon.Paste.ToIconString());
|
||||
ImGui.PopFont();
|
||||
if (_selection!.Data.WriteProtected)
|
||||
ImGui.PopStyleVar();
|
||||
|
||||
ImGuiUtil.HoverTooltip("Overwrite with customization code from clipboard.");
|
||||
|
||||
if (_selection!.Data.WriteProtected || !applyButton)
|
||||
return;
|
||||
|
||||
var text = ImGui.GetClipboardText();
|
||||
if (!text.Any())
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
_selection!.Data = CharacterSave.FromString(text);
|
||||
_designs.SaveToFile();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLog.Information($"{e}");
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawNewFolderButton()
|
||||
{
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
if (ImGui.Button(FontAwesomeIcon.FolderPlus.ToIconString(), Vector2.UnitX * SelectorWidth / 5))
|
||||
OpenDesignNamePopup(DesignNameUse.NewFolder);
|
||||
ImGui.PopFont();
|
||||
ImGuiUtil.HoverTooltip("Create a new, empty Folder.");
|
||||
|
||||
DrawDesignNamePopup(DesignNameUse.NewFolder);
|
||||
}
|
||||
|
||||
private void DrawNewDesignButton()
|
||||
{
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
if (ImGui.Button(FontAwesomeIcon.Plus.ToIconString(), Vector2.UnitX * SelectorWidth / 5))
|
||||
OpenDesignNamePopup(DesignNameUse.NewDesign);
|
||||
ImGui.PopFont();
|
||||
ImGuiUtil.HoverTooltip("Create a new, empty Design.");
|
||||
|
||||
DrawDesignNamePopup(DesignNameUse.NewDesign);
|
||||
}
|
||||
|
||||
private void DrawClipboardDesignButton()
|
||||
{
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
if (ImGui.Button(FontAwesomeIcon.Paste.ToIconString(), Vector2.UnitX * SelectorWidth / 5))
|
||||
OpenDesignNamePopup(DesignNameUse.FromClipboard);
|
||||
ImGui.PopFont();
|
||||
ImGuiUtil.HoverTooltip("Create a new design from the customization string in your clipboard.");
|
||||
|
||||
DrawDesignNamePopup(DesignNameUse.FromClipboard);
|
||||
}
|
||||
|
||||
private void DrawDeleteDesignButton()
|
||||
{
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
var style = _selection == null;
|
||||
if (style)
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.5f);
|
||||
if (ImGui.Button(FontAwesomeIcon.Trash.ToIconString(), Vector2.UnitX * SelectorWidth / 5) && _selection != null)
|
||||
{
|
||||
_designs.DeleteAllChildren(_selection, false);
|
||||
_selection = null;
|
||||
}
|
||||
|
||||
ImGui.PopFont();
|
||||
if (style)
|
||||
ImGui.PopStyleVar();
|
||||
ImGuiUtil.HoverTooltip("Delete the currently selected Design.");
|
||||
}
|
||||
|
||||
private void DrawDuplicateDesignButton()
|
||||
{
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
if (_selection == null)
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.5f);
|
||||
if (ImGui.Button(FontAwesomeIcon.Clone.ToIconString(), Vector2.UnitX * SelectorWidth / 5) && _selection != null)
|
||||
OpenDesignNamePopup(DesignNameUse.DuplicateDesign);
|
||||
ImGui.PopFont();
|
||||
if (_selection == null)
|
||||
ImGui.PopStyleVar();
|
||||
ImGuiUtil.HoverTooltip(
|
||||
"Clone the currently selected Design.\nHold Shift to only clone the customizations.\nHold Control to only clone the equipment.");
|
||||
|
||||
DrawDesignNamePopup(DesignNameUse.DuplicateDesign);
|
||||
}
|
||||
|
||||
private void DrawDesignSelectorButtons()
|
||||
{
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.Push(ImGuiStyleVar.FrameRounding, 0f);
|
||||
|
||||
DrawNewFolderButton();
|
||||
ImGui.SameLine();
|
||||
DrawNewDesignButton();
|
||||
ImGui.SameLine();
|
||||
DrawClipboardDesignButton();
|
||||
ImGui.SameLine();
|
||||
DrawDuplicateDesignButton();
|
||||
ImGui.SameLine();
|
||||
DrawDeleteDesignButton();
|
||||
}
|
||||
|
||||
private void DrawDesignHeaderButtons()
|
||||
{
|
||||
DrawCopyClipboardButton(_selection!.Data);
|
||||
ImGui.SameLine();
|
||||
DrawPasteClipboardButton();
|
||||
ImGui.SameLine();
|
||||
DrawApplyToPlayerButton(_selection!.Data);
|
||||
if (!_inGPose)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
DrawApplyToTargetButton(_selection!.Data);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
DrawCheckbox("Write Protected", _selection!.Data.WriteProtected, v => _selection!.Data.WriteProtected = v, false);
|
||||
}
|
||||
|
||||
private void DrawDesignPanel()
|
||||
{
|
||||
if (ImGui.BeginChild("##details", -Vector2.One * 0.001f, true))
|
||||
{
|
||||
DrawDesignHeaderButtons();
|
||||
var data = _selection!.Data;
|
||||
var prot = _selection!.Data.WriteProtected;
|
||||
if (prot)
|
||||
{
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.8f);
|
||||
data = data.Copy();
|
||||
}
|
||||
|
||||
DrawGeneralSettings(data, prot);
|
||||
var mask = data.WriteEquipment;
|
||||
if (DrawEquip(data.Equipment, ref mask) && !prot)
|
||||
{
|
||||
data.WriteEquipment = mask;
|
||||
_designs.SaveToFile();
|
||||
}
|
||||
|
||||
if (DrawCustomization(ref data.Customizations) && !prot)
|
||||
_designs.SaveToFile();
|
||||
|
||||
if (DrawMiscellaneous(data, null) && !prot)
|
||||
_designs.SaveToFile();
|
||||
|
||||
if (prot)
|
||||
ImGui.PopStyleVar();
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSaves()
|
||||
{
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.IndentSpacing, 12.5f * ImGui.GetIO().FontGlobalScale);
|
||||
using var tab = ImRaii.TabItem("Designs");
|
||||
_inDesignMode = tab.Success;
|
||||
if (!_inDesignMode)
|
||||
return;
|
||||
|
||||
DrawDesignSelector();
|
||||
|
||||
if (_selection != null)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
DrawDesignPanel();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCheckbox(string label, bool value, Action<bool> setter, bool prot)
|
||||
{
|
||||
var tmp = value;
|
||||
if (ImGui.Checkbox(label, ref tmp) && tmp != value)
|
||||
{
|
||||
setter(tmp);
|
||||
if (!prot)
|
||||
_designs.SaveToFile();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawGeneralSettings(CharacterSave data, bool prot)
|
||||
{
|
||||
ImGui.BeginGroup();
|
||||
DrawCheckbox("Apply Customizations", data.WriteCustomizations, v => data.WriteCustomizations = v, prot);
|
||||
DrawCheckbox("Write Weapon State", data.SetWeaponState, v => data.SetWeaponState = v, prot);
|
||||
ImGui.EndGroup();
|
||||
ImGui.SameLine();
|
||||
ImGui.BeginGroup();
|
||||
DrawCheckbox("Write Hat State", data.SetHatState, v => data.SetHatState = v, prot);
|
||||
DrawCheckbox("Write Visor State", data.SetVisorState, v => data.SetVisorState = v, prot);
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
|
||||
private void RenameChildInput(IFileSystemBase child)
|
||||
{
|
||||
ImGui.SetNextItemWidth(150);
|
||||
if (!ImGui.InputTextWithHint("##fsNewName", "Rename...", ref _newChildName, 64,
|
||||
ImGuiInputTextFlags.EnterReturnsTrue))
|
||||
return;
|
||||
|
||||
if (_newChildName.Any() && _newChildName != child.Name)
|
||||
try
|
||||
{
|
||||
var oldPath = child.FullName();
|
||||
if (_designs.FileSystem.Rename(child, _newChildName))
|
||||
_designs.UpdateAllChildren(oldPath, child);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLog.Error($"Could not rename {child.Name} to {_newChildName}:\n{e}");
|
||||
}
|
||||
else if (child is Folder f)
|
||||
try
|
||||
{
|
||||
var oldPath = child.FullName();
|
||||
if (_designs.FileSystem.Merge(f, f.Parent, true))
|
||||
_designs.UpdateAllChildren(oldPath, f.Parent);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLog.Error($"Could not merge folder {child.Name} into parent:\n{e}");
|
||||
}
|
||||
|
||||
_newChildName = string.Empty;
|
||||
}
|
||||
|
||||
private void ContextMenu(IFileSystemBase child)
|
||||
{
|
||||
var label = $"##fsPopup{child.FullName()}";
|
||||
if (ImGui.BeginPopup(label))
|
||||
{
|
||||
if (ImGui.MenuItem("Delete") && ImGui.GetIO().KeyCtrl && ImGui.GetIO().KeyShift)
|
||||
_designs.DeleteAllChildren(child, false);
|
||||
ImGuiUtil.HoverTooltip("Hold Control and Shift to delete.");
|
||||
|
||||
RenameChildInput(child);
|
||||
|
||||
if (child is Design d && ImGui.MenuItem("Copy to Clipboard"))
|
||||
ImGui.SetClipboardText(d.Data.ToBase64());
|
||||
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||
{
|
||||
_newChildName = child.Name;
|
||||
ImGui.OpenPopup(label);
|
||||
}
|
||||
}
|
||||
|
||||
private static uint GetDesignColor(CharacterSave save)
|
||||
{
|
||||
const uint white = 0xFFFFFFFF;
|
||||
const uint grey = 0xFF808080;
|
||||
if (!Glamourer.Config.ColorDesigns)
|
||||
return white;
|
||||
|
||||
var changesStates = save.SetHatState || save.SetVisorState || save.SetWeaponState || save.IsWet || save.Alpha != 1.0f;
|
||||
if (save.WriteCustomizations)
|
||||
if (save.WriteEquipment != CharacterEquipMask.None)
|
||||
return white;
|
||||
else
|
||||
return changesStates ? white : Glamourer.Config.CustomizationColor;
|
||||
|
||||
if (save.WriteEquipment != CharacterEquipMask.None)
|
||||
return changesStates ? white : Glamourer.Config.EquipmentColor;
|
||||
|
||||
return changesStates ? Glamourer.Config.StateColor : grey;
|
||||
}
|
||||
|
||||
private void DrawFolderContent(Folder folder, SortMode mode)
|
||||
{
|
||||
foreach (var child in folder.AllChildren(mode).ToArray())
|
||||
{
|
||||
if (child.IsFolder(out var subFolder))
|
||||
{
|
||||
var treeNode = ImGui.TreeNodeEx($"{subFolder.Name}##{_totalObject}");
|
||||
DrawOrnaments(child);
|
||||
|
||||
if (treeNode)
|
||||
{
|
||||
DrawFolderContent(subFolder, mode);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
else
|
||||
{
|
||||
_totalObject += subFolder.TotalDescendantLeaves();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (child is not Design d)
|
||||
continue;
|
||||
|
||||
++_totalObject;
|
||||
var color = GetDesignColor(d.Data);
|
||||
using var c = ImRaii.PushColor(ImGuiCol.Text, color);
|
||||
|
||||
var selected = ImGui.Selectable($"{child.Name}##{_totalObject}", ReferenceEquals(child, _selection));
|
||||
c.Pop();
|
||||
DrawOrnaments(child);
|
||||
|
||||
if (Glamourer.Config.ShowLocks && d.Data.WriteProtected)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
using var font = ImRaii.PushFont(UiBuilder.IconFont);
|
||||
c.Push(ImGuiCol.Text, color);
|
||||
ImGui.TextUnformatted(FontAwesomeIcon.Lock.ToIconString());
|
||||
}
|
||||
|
||||
if (selected)
|
||||
_selection = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawOrnaments(IFileSystemBase child)
|
||||
{
|
||||
FileSystemImGui.DragDropSource(child);
|
||||
if (FileSystemImGui.DragDropTarget(_designs.FileSystem, child, out var oldPath, out var draggedFolder))
|
||||
_designs.UpdateAllChildren(oldPath, draggedFolder!);
|
||||
ContextMenu(child);
|
||||
}
|
||||
}
|
||||
//internal partial class Interface
|
||||
//{
|
||||
// private int _totalObject;
|
||||
//
|
||||
// private bool _inDesignMode;
|
||||
// private Design? _selection;
|
||||
// private string _newChildName = string.Empty;
|
||||
//
|
||||
// private void DrawDesignSelector()
|
||||
// {
|
||||
// _totalObject = 0;
|
||||
// ImGui.BeginGroup();
|
||||
// if (ImGui.BeginChild("##selector", new Vector2(SelectorWidth * ImGui.GetIO().FontGlobalScale, -ImGui.GetFrameHeight() - 1), true))
|
||||
// {
|
||||
// DrawFolderContent(_designs.FileSystem.Root, Glamourer.Config.FoldersFirst ? SortMode.FoldersFirst : SortMode.Lexicographical);
|
||||
// ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, Vector2.Zero);
|
||||
// ImGui.EndChild();
|
||||
// ImGui.PopStyleVar();
|
||||
// }
|
||||
//
|
||||
// DrawDesignSelectorButtons();
|
||||
// ImGui.EndGroup();
|
||||
// }
|
||||
//
|
||||
// private void DrawPasteClipboardButton()
|
||||
// {
|
||||
// if (_selection!.Data.WriteProtected)
|
||||
// ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.5f);
|
||||
//
|
||||
// ImGui.PushFont(UiBuilder.IconFont);
|
||||
// var applyButton = ImGui.Button(FontAwesomeIcon.Paste.ToIconString());
|
||||
// ImGui.PopFont();
|
||||
// if (_selection!.Data.WriteProtected)
|
||||
// ImGui.PopStyleVar();
|
||||
//
|
||||
// ImGuiUtil.HoverTooltip("Overwrite with customization code from clipboard.");
|
||||
//
|
||||
// if (_selection!.Data.WriteProtected || !applyButton)
|
||||
// return;
|
||||
//
|
||||
// var text = ImGui.GetClipboardText();
|
||||
// if (!text.Any())
|
||||
// return;
|
||||
//
|
||||
// try
|
||||
// {
|
||||
// _selection!.Data = CharacterSave.FromString(text);
|
||||
// _designs.SaveToFile();
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// PluginLog.Information($"{e}");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void DrawNewFolderButton()
|
||||
// {
|
||||
// ImGui.PushFont(UiBuilder.IconFont);
|
||||
// if (ImGui.Button(FontAwesomeIcon.FolderPlus.ToIconString(), Vector2.UnitX * SelectorWidth / 5))
|
||||
// OpenDesignNamePopup(DesignNameUse.NewFolder);
|
||||
// ImGui.PopFont();
|
||||
// ImGuiUtil.HoverTooltip("Create a new, empty Folder.");
|
||||
//
|
||||
// DrawDesignNamePopup(DesignNameUse.NewFolder);
|
||||
// }
|
||||
//
|
||||
// private void DrawNewDesignButton()
|
||||
// {
|
||||
// ImGui.PushFont(UiBuilder.IconFont);
|
||||
// if (ImGui.Button(FontAwesomeIcon.Plus.ToIconString(), Vector2.UnitX * SelectorWidth / 5))
|
||||
// OpenDesignNamePopup(DesignNameUse.NewDesign);
|
||||
// ImGui.PopFont();
|
||||
// ImGuiUtil.HoverTooltip("Create a new, empty Design.");
|
||||
//
|
||||
// DrawDesignNamePopup(DesignNameUse.NewDesign);
|
||||
// }
|
||||
//
|
||||
// private void DrawClipboardDesignButton()
|
||||
// {
|
||||
// ImGui.PushFont(UiBuilder.IconFont);
|
||||
// if (ImGui.Button(FontAwesomeIcon.Paste.ToIconString(), Vector2.UnitX * SelectorWidth / 5))
|
||||
// OpenDesignNamePopup(DesignNameUse.FromClipboard);
|
||||
// ImGui.PopFont();
|
||||
// ImGuiUtil.HoverTooltip("Create a new design from the customization string in your clipboard.");
|
||||
//
|
||||
// DrawDesignNamePopup(DesignNameUse.FromClipboard);
|
||||
// }
|
||||
//
|
||||
// private void DrawDeleteDesignButton()
|
||||
// {
|
||||
// ImGui.PushFont(UiBuilder.IconFont);
|
||||
// var style = _selection == null;
|
||||
// if (style)
|
||||
// ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.5f);
|
||||
// if (ImGui.Button(FontAwesomeIcon.Trash.ToIconString(), Vector2.UnitX * SelectorWidth / 5) && _selection != null)
|
||||
// {
|
||||
// _designs.DeleteAllChildren(_selection, false);
|
||||
// _selection = null;
|
||||
// }
|
||||
//
|
||||
// ImGui.PopFont();
|
||||
// if (style)
|
||||
// ImGui.PopStyleVar();
|
||||
// ImGuiUtil.HoverTooltip("Delete the currently selected Design.");
|
||||
// }
|
||||
//
|
||||
// private void DrawDuplicateDesignButton()
|
||||
// {
|
||||
// ImGui.PushFont(UiBuilder.IconFont);
|
||||
// if (_selection == null)
|
||||
// ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.5f);
|
||||
// if (ImGui.Button(FontAwesomeIcon.Clone.ToIconString(), Vector2.UnitX * SelectorWidth / 5) && _selection != null)
|
||||
// OpenDesignNamePopup(DesignNameUse.DuplicateDesign);
|
||||
// ImGui.PopFont();
|
||||
// if (_selection == null)
|
||||
// ImGui.PopStyleVar();
|
||||
// ImGuiUtil.HoverTooltip(
|
||||
// "Clone the currently selected Design.\nHold Shift to only clone the customizations.\nHold Control to only clone the equipment.");
|
||||
//
|
||||
// DrawDesignNamePopup(DesignNameUse.DuplicateDesign);
|
||||
// }
|
||||
//
|
||||
// private void DrawDesignSelectorButtons()
|
||||
// {
|
||||
// using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
// .Push(ImGuiStyleVar.FrameRounding, 0f);
|
||||
//
|
||||
// DrawNewFolderButton();
|
||||
// ImGui.SameLine();
|
||||
// DrawNewDesignButton();
|
||||
// ImGui.SameLine();
|
||||
// DrawClipboardDesignButton();
|
||||
// ImGui.SameLine();
|
||||
// DrawDuplicateDesignButton();
|
||||
// ImGui.SameLine();
|
||||
// DrawDeleteDesignButton();
|
||||
// }
|
||||
//
|
||||
// private void DrawDesignHeaderButtons()
|
||||
// {
|
||||
// DrawCopyClipboardButton(_selection!.Data);
|
||||
// ImGui.SameLine();
|
||||
// DrawPasteClipboardButton();
|
||||
// ImGui.SameLine();
|
||||
// DrawApplyToPlayerButton(_selection!.Data);
|
||||
// if (!_inGPose)
|
||||
// {
|
||||
// ImGui.SameLine();
|
||||
// DrawApplyToTargetButton(_selection!.Data);
|
||||
// }
|
||||
//
|
||||
// ImGui.SameLine();
|
||||
// DrawCheckbox("Write Protected", _selection!.Data.WriteProtected, v => _selection!.Data.WriteProtected = v, false);
|
||||
// }
|
||||
//
|
||||
// private void DrawDesignPanel()
|
||||
// {
|
||||
// if (ImGui.BeginChild("##details", -Vector2.One * 0.001f, true))
|
||||
// {
|
||||
// DrawDesignHeaderButtons();
|
||||
// var data = _selection!.Data;
|
||||
// var prot = _selection!.Data.WriteProtected;
|
||||
// if (prot)
|
||||
// {
|
||||
// ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.8f);
|
||||
// data = data.Copy();
|
||||
// }
|
||||
//
|
||||
// DrawGeneralSettings(data, prot);
|
||||
// var mask = data.WriteEquipment;
|
||||
// if (DrawEquip(data.Equipment, ref mask) && !prot)
|
||||
// {
|
||||
// data.WriteEquipment = mask;
|
||||
// _designs.SaveToFile();
|
||||
// }
|
||||
//
|
||||
// if (DrawCustomization(ref data.Customizations) && !prot)
|
||||
// _designs.SaveToFile();
|
||||
//
|
||||
// if (DrawMiscellaneous(data, null) && !prot)
|
||||
// _designs.SaveToFile();
|
||||
//
|
||||
// if (prot)
|
||||
// ImGui.PopStyleVar();
|
||||
//
|
||||
// ImGui.EndChild();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void DrawSaves()
|
||||
// {
|
||||
// using var style = ImRaii.PushStyle(ImGuiStyleVar.IndentSpacing, 12.5f * ImGui.GetIO().FontGlobalScale);
|
||||
// using var tab = ImRaii.TabItem("Designs");
|
||||
// _inDesignMode = tab.Success;
|
||||
// if (!_inDesignMode)
|
||||
// return;
|
||||
//
|
||||
// DrawDesignSelector();
|
||||
//
|
||||
// if (_selection != null)
|
||||
// {
|
||||
// ImGui.SameLine();
|
||||
// DrawDesignPanel();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void DrawCheckbox(string label, bool value, Action<bool> setter, bool prot)
|
||||
// {
|
||||
// var tmp = value;
|
||||
// if (ImGui.Checkbox(label, ref tmp) && tmp != value)
|
||||
// {
|
||||
// setter(tmp);
|
||||
// if (!prot)
|
||||
// _designs.SaveToFile();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void DrawGeneralSettings(CharacterSave data, bool prot)
|
||||
// {
|
||||
// ImGui.BeginGroup();
|
||||
// DrawCheckbox("Apply Customizations", data.WriteCustomizations, v => data.WriteCustomizations = v, prot);
|
||||
// DrawCheckbox("Write Weapon State", data.SetWeaponState, v => data.SetWeaponState = v, prot);
|
||||
// ImGui.EndGroup();
|
||||
// ImGui.SameLine();
|
||||
// ImGui.BeginGroup();
|
||||
// DrawCheckbox("Write Hat State", data.SetHatState, v => data.SetHatState = v, prot);
|
||||
// DrawCheckbox("Write Visor State", data.SetVisorState, v => data.SetVisorState = v, prot);
|
||||
// ImGui.EndGroup();
|
||||
// }
|
||||
//
|
||||
// private void RenameChildInput(IFileSystemBase child)
|
||||
// {
|
||||
// ImGui.SetNextItemWidth(150);
|
||||
// if (!ImGui.InputTextWithHint("##fsNewName", "Rename...", ref _newChildName, 64,
|
||||
// ImGuiInputTextFlags.EnterReturnsTrue))
|
||||
// return;
|
||||
//
|
||||
// if (_newChildName.Any() && _newChildName != child.Name)
|
||||
// try
|
||||
// {
|
||||
// var oldPath = child.FullName();
|
||||
// if (_designs.FileSystem.Rename(child, _newChildName))
|
||||
// _designs.UpdateAllChildren(oldPath, child);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// PluginLog.Error($"Could not rename {child.Name} to {_newChildName}:\n{e}");
|
||||
// }
|
||||
// else if (child is Folder f)
|
||||
// try
|
||||
// {
|
||||
// var oldPath = child.FullName();
|
||||
// if (_designs.FileSystem.Merge(f, f.Parent, true))
|
||||
// _designs.UpdateAllChildren(oldPath, f.Parent);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// PluginLog.Error($"Could not merge folder {child.Name} into parent:\n{e}");
|
||||
// }
|
||||
//
|
||||
// _newChildName = string.Empty;
|
||||
// }
|
||||
//
|
||||
// private void ContextMenu(IFileSystemBase child)
|
||||
// {
|
||||
// var label = $"##fsPopup{child.FullName()}";
|
||||
// if (ImGui.BeginPopup(label))
|
||||
// {
|
||||
// if (ImGui.MenuItem("Delete") && ImGui.GetIO().KeyCtrl && ImGui.GetIO().KeyShift)
|
||||
// _designs.DeleteAllChildren(child, false);
|
||||
// ImGuiUtil.HoverTooltip("Hold Control and Shift to delete.");
|
||||
//
|
||||
// RenameChildInput(child);
|
||||
//
|
||||
// if (child is Design d && ImGui.MenuItem("Copy to Clipboard"))
|
||||
// ImGui.SetClipboardText(d.Data.ToBase64());
|
||||
//
|
||||
// ImGui.EndPopup();
|
||||
// }
|
||||
//
|
||||
// if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||
// {
|
||||
// _newChildName = child.Name;
|
||||
// ImGui.OpenPopup(label);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private static uint GetDesignColor(CharacterSave save)
|
||||
// {
|
||||
// const uint white = 0xFFFFFFFF;
|
||||
// const uint grey = 0xFF808080;
|
||||
// if (!Glamourer.Config.ColorDesigns)
|
||||
// return white;
|
||||
//
|
||||
// var changesStates = save.SetHatState || save.SetVisorState || save.SetWeaponState || save.IsWet || save.Alpha != 1.0f;
|
||||
// if (save.WriteCustomizations)
|
||||
// if (save.WriteEquipment != CharacterEquipMask.None)
|
||||
// return white;
|
||||
// else
|
||||
// return changesStates ? white : Glamourer.Config.CustomizationColor;
|
||||
//
|
||||
// if (save.WriteEquipment != CharacterEquipMask.None)
|
||||
// return changesStates ? white : Glamourer.Config.EquipmentColor;
|
||||
//
|
||||
// return changesStates ? Glamourer.Config.StateColor : grey;
|
||||
// }
|
||||
//
|
||||
// private void DrawFolderContent(Folder folder, SortMode mode)
|
||||
// {
|
||||
// foreach (var child in folder.AllChildren(mode).ToArray())
|
||||
// {
|
||||
// if (child.IsFolder(out var subFolder))
|
||||
// {
|
||||
// var treeNode = ImGui.TreeNodeEx($"{subFolder.Name}##{_totalObject}");
|
||||
// DrawOrnaments(child);
|
||||
//
|
||||
// if (treeNode)
|
||||
// {
|
||||
// DrawFolderContent(subFolder, mode);
|
||||
// ImGui.TreePop();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// _totalObject += subFolder.TotalDescendantLeaves();
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (child is not Design d)
|
||||
// continue;
|
||||
//
|
||||
// ++_totalObject;
|
||||
// var color = GetDesignColor(d.Data);
|
||||
// using var c = ImRaii.PushColor(ImGuiCol.Text, color);
|
||||
//
|
||||
// var selected = ImGui.Selectable($"{child.Name}##{_totalObject}", ReferenceEquals(child, _selection));
|
||||
// c.Pop();
|
||||
// DrawOrnaments(child);
|
||||
//
|
||||
// if (Glamourer.Config.ShowLocks && d.Data.WriteProtected)
|
||||
// {
|
||||
// ImGui.SameLine();
|
||||
// using var font = ImRaii.PushFont(UiBuilder.IconFont);
|
||||
// c.Push(ImGuiCol.Text, color);
|
||||
// ImGui.TextUnformatted(FontAwesomeIcon.Lock.ToIconString());
|
||||
// }
|
||||
//
|
||||
// if (selected)
|
||||
// _selection = d;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void DrawOrnaments(IFileSystemBase child)
|
||||
// {
|
||||
// FileSystemImGui.DragDropSource(child);
|
||||
// if (FileSystemImGui.DragDropTarget(_designs.FileSystem, child, out var oldPath, out var draggedFolder))
|
||||
// _designs.UpdateAllChildren(oldPath, draggedFolder!);
|
||||
// ContextMenu(child);
|
||||
// }
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -1,184 +1,196 @@
|
|||
using Dalamud.Interface;
|
||||
using Glamourer.Structs;
|
||||
using ImGuiNET;
|
||||
using Lumina.Text;
|
||||
using OtterGui;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Gui
|
||||
{
|
||||
internal partial class Interface
|
||||
{
|
||||
private bool DrawStainSelector(ComboWithFilter<Stain> stainCombo, EquipSlot slot, StainId stainIdx)
|
||||
{
|
||||
stainCombo.PostPreview = null;
|
||||
if (_stains.TryGetValue((byte) stainIdx, out var stain))
|
||||
{
|
||||
var previewPush = PushColor(stain, ImGuiCol.FrameBg);
|
||||
stainCombo.PostPreview = () => ImGui.PopStyleColor(previewPush);
|
||||
}
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
var change = stainCombo.Draw(string.Empty, out var newStain) && !newStain.RowIndex.Equals(stainIdx);
|
||||
if (!change && (byte) stainIdx != 0)
|
||||
{
|
||||
ImGuiUtil.HoverTooltip("Right-click to clear.");
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||
{
|
||||
change = true;
|
||||
newStain = Stain.None;
|
||||
}
|
||||
}
|
||||
|
||||
if (!change)
|
||||
return false;
|
||||
|
||||
if (_player == null)
|
||||
return _inDesignMode && (_selection?.Data.WriteStain(slot, newStain.RowIndex) ?? false);
|
||||
|
||||
Glamourer.RevertableDesigns.Add(_player);
|
||||
newStain.Write(_player.Address, slot);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private bool DrawItemSelector(ComboWithFilter<Item> equipCombo, Lumina.Excel.GeneratedSheets.Item item, EquipSlot slot = EquipSlot.Unknown)
|
||||
{
|
||||
var currentName = item.Name.ToString();
|
||||
var change = equipCombo.Draw(currentName, out var newItem, _itemComboWidth) && newItem.Base.RowId != item.RowId;
|
||||
if (!change && !ReferenceEquals(item, SmallClothes))
|
||||
{
|
||||
ImGuiUtil.HoverTooltip("Right-click to clear.");
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||
{
|
||||
change = true;
|
||||
newItem = Item.Nothing(slot);
|
||||
}
|
||||
}
|
||||
|
||||
if (!change)
|
||||
return false;
|
||||
|
||||
newItem = new Item(newItem.Base, newItem.Name, slot);
|
||||
if (_player == null)
|
||||
return _inDesignMode && (_selection?.Data.WriteItem(newItem) ?? false);
|
||||
|
||||
Glamourer.RevertableDesigns.Add(_player);
|
||||
newItem.Write(_player.Address);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private static bool DrawCheckbox(CharacterEquipMask flag, ref CharacterEquipMask mask)
|
||||
{
|
||||
var tmp = (uint) mask;
|
||||
var ret = false;
|
||||
if (ImGui.CheckboxFlags($"##flag_{(uint) flag}", ref tmp, (uint) flag) && tmp != (uint) mask)
|
||||
{
|
||||
mask = (CharacterEquipMask) tmp;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip("Enable writing this slot in this save.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static readonly Lumina.Excel.GeneratedSheets.Item SmallClothes = new(){ Name = new SeString("Nothing"), RowId = 0 };
|
||||
private static readonly Lumina.Excel.GeneratedSheets.Item SmallClothesNpc = new(){ Name = new SeString("Smallclothes (NPC)"), RowId = 1 };
|
||||
private static readonly Lumina.Excel.GeneratedSheets.Item Unknown = new(){ Name = new SeString("Unknown"), RowId = 2 };
|
||||
|
||||
private Lumina.Excel.GeneratedSheets.Item Identify(SetId set, WeaponType weapon, ushort variant, EquipSlot slot)
|
||||
{
|
||||
return (uint) set switch
|
||||
{
|
||||
0 => SmallClothes,
|
||||
9903 => SmallClothesNpc,
|
||||
_ => _identifier.Identify(set, weapon, variant, slot) ?? Unknown,
|
||||
};
|
||||
}
|
||||
|
||||
private bool DrawEquipSlot(EquipSlot slot, CharacterArmor equip)
|
||||
{
|
||||
var (equipCombo, stainCombo) = _combos[slot];
|
||||
|
||||
var ret = DrawStainSelector(stainCombo, slot, equip.Stain);
|
||||
ImGui.SameLine();
|
||||
var item = Identify(equip.Set, new WeaponType(), equip.Variant, slot);
|
||||
ret |= DrawItemSelector(equipCombo, item, slot);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawEquipSlotWithCheck(EquipSlot slot, CharacterArmor equip, CharacterEquipMask flag, ref CharacterEquipMask mask)
|
||||
{
|
||||
var ret = DrawCheckbox(flag, ref mask);
|
||||
ImGui.SameLine();
|
||||
ret |= DrawEquipSlot(slot, equip);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawWeapon(EquipSlot slot, CharacterWeapon weapon)
|
||||
{
|
||||
var (equipCombo, stainCombo) = _combos[slot];
|
||||
|
||||
var ret = DrawStainSelector(stainCombo, slot, weapon.Stain);
|
||||
ImGui.SameLine();
|
||||
var item = Identify(weapon.Set, weapon.Type, weapon.Variant, slot);
|
||||
ret |= DrawItemSelector(equipCombo, item, slot);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawWeaponWithCheck(EquipSlot slot, CharacterWeapon weapon, CharacterEquipMask flag, ref CharacterEquipMask mask)
|
||||
{
|
||||
var ret = DrawCheckbox(flag, ref mask);
|
||||
ImGui.SameLine();
|
||||
ret |= DrawWeapon(slot, weapon);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawEquip(CharacterEquipment equip)
|
||||
{
|
||||
var ret = false;
|
||||
if (ImGui.CollapsingHeader("Character Equipment"))
|
||||
{
|
||||
ret |= DrawWeapon(EquipSlot.MainHand, equip.MainHand);
|
||||
ret |= DrawWeapon(EquipSlot.OffHand, equip.OffHand);
|
||||
ret |= DrawEquipSlot(EquipSlot.Head, equip.Head);
|
||||
ret |= DrawEquipSlot(EquipSlot.Body, equip.Body);
|
||||
ret |= DrawEquipSlot(EquipSlot.Hands, equip.Hands);
|
||||
ret |= DrawEquipSlot(EquipSlot.Legs, equip.Legs);
|
||||
ret |= DrawEquipSlot(EquipSlot.Feet, equip.Feet);
|
||||
ret |= DrawEquipSlot(EquipSlot.Ears, equip.Ears);
|
||||
ret |= DrawEquipSlot(EquipSlot.Neck, equip.Neck);
|
||||
ret |= DrawEquipSlot(EquipSlot.Wrists, equip.Wrists);
|
||||
ret |= DrawEquipSlot(EquipSlot.RFinger, equip.RFinger);
|
||||
ret |= DrawEquipSlot(EquipSlot.LFinger, equip.LFinger);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawEquip(CharacterEquipment equip, ref CharacterEquipMask mask)
|
||||
{
|
||||
var ret = false;
|
||||
if (ImGui.CollapsingHeader("Character Equipment"))
|
||||
{
|
||||
ret |= DrawWeaponWithCheck(EquipSlot.MainHand, equip.MainHand, CharacterEquipMask.MainHand, ref mask);
|
||||
ret |= DrawWeaponWithCheck(EquipSlot.OffHand, equip.OffHand, CharacterEquipMask.OffHand, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Head, equip.Head, CharacterEquipMask.Head, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Body, equip.Body, CharacterEquipMask.Body, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Hands, equip.Hands, CharacterEquipMask.Hands, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Legs, equip.Legs, CharacterEquipMask.Legs, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Feet, equip.Feet, CharacterEquipMask.Feet, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Ears, equip.Ears, CharacterEquipMask.Ears, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Neck, equip.Neck, CharacterEquipMask.Neck, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Wrists, equip.Wrists, CharacterEquipMask.Wrists, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.RFinger, equip.RFinger, CharacterEquipMask.RFinger, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.LFinger, equip.LFinger, CharacterEquipMask.LFinger, ref mask);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
//internal partial class Interface
|
||||
//{
|
||||
// private bool DrawStainSelector(ComboWithFilter<Stain> stainCombo, EquipSlot slot, StainId stainIdx)
|
||||
// {
|
||||
// stainCombo.PostPreview = null;
|
||||
// if (_stains.TryGetValue((byte)stainIdx, out var stain))
|
||||
// {
|
||||
// var previewPush = PushColor(stain, ImGuiCol.FrameBg);
|
||||
// stainCombo.PostPreview = () => ImGui.PopStyleColor(previewPush);
|
||||
// }
|
||||
//
|
||||
// var change = stainCombo.Draw(string.Empty, out var newStain) && !newStain.RowIndex.Equals(stainIdx);
|
||||
// if (!change && (byte)stainIdx != 0)
|
||||
// {
|
||||
// ImGuiUtil.HoverTooltip("Right-click to clear.");
|
||||
// if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||
// {
|
||||
// change = true;
|
||||
// newStain = Stain.None;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!change)
|
||||
// return false;
|
||||
//
|
||||
// if (_player == null)
|
||||
// return _inDesignMode && (_selection?.Data.WriteStain(slot, newStain.RowIndex) ?? false);
|
||||
//
|
||||
// Glamourer.RevertableDesigns.Add(_player);
|
||||
// newStain.Write(_player.Address, slot);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// private bool DrawItemSelector(ComboWithFilter<Item> equipCombo, Lumina.Excel.GeneratedSheets.Item item, EquipSlot slot = EquipSlot.Unknown)
|
||||
// {
|
||||
// var currentName = item.Name.ToString();
|
||||
// var change = equipCombo.Draw(currentName, out var newItem, _itemComboWidth) && newItem.Base.RowId != item.RowId;
|
||||
// if (!change && !ReferenceEquals(item, SmallClothes))
|
||||
// {
|
||||
// ImGuiUtil.HoverTooltip("Right-click to clear.");
|
||||
// if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||
// {
|
||||
// change = true;
|
||||
// newItem = Item.Nothing(slot);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!change)
|
||||
// return false;
|
||||
//
|
||||
// newItem = new Item(newItem.Base, newItem.Name, slot);
|
||||
// if (_player == null)
|
||||
// return _inDesignMode && (_selection?.Data.WriteItem(newItem) ?? false);
|
||||
//
|
||||
// Glamourer.RevertableDesigns.Add(_player);
|
||||
// newItem.Write(_player.Address);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// private static bool DrawCheckbox(CharacterEquipMask flag, ref CharacterEquipMask mask)
|
||||
// {
|
||||
// var tmp = (uint)mask;
|
||||
// var ret = false;
|
||||
// if (ImGui.CheckboxFlags($"##flag_{(uint)flag}", ref tmp, (uint)flag) && tmp != (uint)mask)
|
||||
// {
|
||||
// mask = (CharacterEquipMask)tmp;
|
||||
// ret = true;
|
||||
// }
|
||||
//
|
||||
// if (ImGui.IsItemHovered())
|
||||
// ImGui.SetTooltip("Enable writing this slot in this save.");
|
||||
// return ret;
|
||||
// }
|
||||
//
|
||||
// private static readonly Lumina.Excel.GeneratedSheets.Item SmallClothes = new()
|
||||
// {
|
||||
// Name = new SeString("Nothing"),
|
||||
// RowId = 0,
|
||||
// };
|
||||
//
|
||||
// private static readonly Lumina.Excel.GeneratedSheets.Item SmallClothesNpc = new()
|
||||
// {
|
||||
// Name = new SeString("Smallclothes (NPC)"),
|
||||
// RowId = 1,
|
||||
// };
|
||||
//
|
||||
// private static readonly Lumina.Excel.GeneratedSheets.Item Unknown = new()
|
||||
// {
|
||||
// Name = new SeString("Unknown"),
|
||||
// RowId = 2,
|
||||
// };
|
||||
//
|
||||
// private Lumina.Excel.GeneratedSheets.Item Identify(SetId set, WeaponType weapon, ushort variant, EquipSlot slot)
|
||||
// {
|
||||
// return (uint)set switch
|
||||
// {
|
||||
// 0 => SmallClothes,
|
||||
// 9903 => SmallClothesNpc,
|
||||
// _ => _identifier.Identify(set, weapon, variant, slot) ?? Unknown,
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// private bool DrawEquipSlot(EquipSlot slot, CharacterArmor equip)
|
||||
// {
|
||||
// var (equipCombo, stainCombo) = _combos[slot];
|
||||
//
|
||||
// var ret = DrawStainSelector(stainCombo, slot, equip.Stain);
|
||||
// ImGui.SameLine();
|
||||
// var item = Identify(equip.Set, new WeaponType(), equip.Variant, slot);
|
||||
// ret |= DrawItemSelector(equipCombo, item, slot);
|
||||
//
|
||||
// return ret;
|
||||
// }
|
||||
//
|
||||
// private bool DrawEquipSlotWithCheck(EquipSlot slot, CharacterArmor equip, CharacterEquipMask flag, ref CharacterEquipMask mask)
|
||||
// {
|
||||
// var ret = DrawCheckbox(flag, ref mask);
|
||||
// ImGui.SameLine();
|
||||
// ret |= DrawEquipSlot(slot, equip);
|
||||
// return ret;
|
||||
// }
|
||||
//
|
||||
// private bool DrawWeapon(EquipSlot slot, CharacterWeapon weapon)
|
||||
// {
|
||||
// var (equipCombo, stainCombo) = _combos[slot];
|
||||
//
|
||||
// var ret = DrawStainSelector(stainCombo, slot, weapon.Stain);
|
||||
// ImGui.SameLine();
|
||||
// var item = Identify(weapon.Set, weapon.Type, weapon.Variant, slot);
|
||||
// ret |= DrawItemSelector(equipCombo, item, slot);
|
||||
//
|
||||
// return ret;
|
||||
// }
|
||||
//
|
||||
// private bool DrawWeaponWithCheck(EquipSlot slot, CharacterWeapon weapon, CharacterEquipMask flag, ref CharacterEquipMask mask)
|
||||
// {
|
||||
// var ret = DrawCheckbox(flag, ref mask);
|
||||
// ImGui.SameLine();
|
||||
// ret |= DrawWeapon(slot, weapon);
|
||||
// return ret;
|
||||
// }
|
||||
//
|
||||
// private bool DrawEquip(CharacterEquipment equip)
|
||||
// {
|
||||
// var ret = false;
|
||||
// if (ImGui.CollapsingHeader("Character Equipment"))
|
||||
// {
|
||||
// ret |= DrawWeapon(EquipSlot.MainHand, equip.MainHand);
|
||||
// ret |= DrawWeapon(EquipSlot.OffHand, equip.OffHand);
|
||||
// ret |= DrawEquipSlot(EquipSlot.Head, equip.Head);
|
||||
// ret |= DrawEquipSlot(EquipSlot.Body, equip.Body);
|
||||
// ret |= DrawEquipSlot(EquipSlot.Hands, equip.Hands);
|
||||
// ret |= DrawEquipSlot(EquipSlot.Legs, equip.Legs);
|
||||
// ret |= DrawEquipSlot(EquipSlot.Feet, equip.Feet);
|
||||
// ret |= DrawEquipSlot(EquipSlot.Ears, equip.Ears);
|
||||
// ret |= DrawEquipSlot(EquipSlot.Neck, equip.Neck);
|
||||
// ret |= DrawEquipSlot(EquipSlot.Wrists, equip.Wrists);
|
||||
// ret |= DrawEquipSlot(EquipSlot.RFinger, equip.RFinger);
|
||||
// ret |= DrawEquipSlot(EquipSlot.LFinger, equip.LFinger);
|
||||
// }
|
||||
//
|
||||
// return ret;
|
||||
// }
|
||||
//
|
||||
// private bool DrawEquip(CharacterEquipment equip, ref CharacterEquipMask mask)
|
||||
// {
|
||||
// var ret = false;
|
||||
// if (ImGui.CollapsingHeader("Character Equipment"))
|
||||
// {
|
||||
// ret |= DrawWeaponWithCheck(EquipSlot.MainHand, equip.MainHand, CharacterEquipMask.MainHand, ref mask);
|
||||
// ret |= DrawWeaponWithCheck(EquipSlot.OffHand, equip.OffHand, CharacterEquipMask.OffHand, ref mask);
|
||||
// ret |= DrawEquipSlotWithCheck(EquipSlot.Head, equip.Head, CharacterEquipMask.Head, ref mask);
|
||||
// ret |= DrawEquipSlotWithCheck(EquipSlot.Body, equip.Body, CharacterEquipMask.Body, ref mask);
|
||||
// ret |= DrawEquipSlotWithCheck(EquipSlot.Hands, equip.Hands, CharacterEquipMask.Hands, ref mask);
|
||||
// ret |= DrawEquipSlotWithCheck(EquipSlot.Legs, equip.Legs, CharacterEquipMask.Legs, ref mask);
|
||||
// ret |= DrawEquipSlotWithCheck(EquipSlot.Feet, equip.Feet, CharacterEquipMask.Feet, ref mask);
|
||||
// ret |= DrawEquipSlotWithCheck(EquipSlot.Ears, equip.Ears, CharacterEquipMask.Ears, ref mask);
|
||||
// ret |= DrawEquipSlotWithCheck(EquipSlot.Neck, equip.Neck, CharacterEquipMask.Neck, ref mask);
|
||||
// ret |= DrawEquipSlotWithCheck(EquipSlot.Wrists, equip.Wrists, CharacterEquipMask.Wrists, ref mask);
|
||||
// ret |= DrawEquipSlotWithCheck(EquipSlot.RFinger, equip.RFinger, CharacterEquipMask.RFinger, ref mask);
|
||||
// ret |= DrawEquipSlotWithCheck(EquipSlot.LFinger, equip.LFinger, CharacterEquipMask.LFinger, ref mask);
|
||||
// }
|
||||
//
|
||||
// return ret;
|
||||
// }
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -4,165 +4,165 @@ using System.Linq;
|
|||
using System.Numerics;
|
||||
using Dalamud.Interface;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.FileSystem;
|
||||
using Glamourer.Structs;
|
||||
using ImGuiNET;
|
||||
using OtterGui.Raii;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
internal partial class Interface
|
||||
{
|
||||
private const string FixDragDropLabel = "##FixDragDrop";
|
||||
|
||||
private List<string>? _fullPathCache;
|
||||
private string _newFixCharacterName = string.Empty;
|
||||
private string _newFixDesignPath = string.Empty;
|
||||
private JobGroup? _newFixDesignGroup;
|
||||
private Design? _newFixDesign;
|
||||
private int _fixDragDropIdx = -1;
|
||||
|
||||
private static unsafe bool IsDropping()
|
||||
=> ImGui.AcceptDragDropPayload(FixDragDropLabel).NativePtr != null;
|
||||
|
||||
private void DrawFixedDesignsTab()
|
||||
{
|
||||
_newFixDesignGroup ??= Glamourer.FixedDesignManager.FixedDesigns.JobGroups[1];
|
||||
|
||||
using var tabItem = ImRaii.TabItem("Fixed Designs");
|
||||
if (!tabItem)
|
||||
{
|
||||
_fullPathCache = null;
|
||||
_newFixDesign = null;
|
||||
_newFixDesignPath = string.Empty;
|
||||
_newFixDesignGroup = Glamourer.FixedDesignManager.FixedDesigns.JobGroups[1];
|
||||
return;
|
||||
}
|
||||
|
||||
_fullPathCache ??= Glamourer.FixedDesignManager.FixedDesigns.Data.Select(d => d.Design.FullName()).ToList();
|
||||
|
||||
using var table = ImRaii.Table("##FixedTable", 4);
|
||||
var buttonWidth = 23.5f * ImGuiHelpers.GlobalScale;
|
||||
|
||||
ImGui.TableSetupColumn("##DeleteColumn", ImGuiTableColumnFlags.WidthFixed, 2 * buttonWidth);
|
||||
ImGui.TableSetupColumn("Character", ImGuiTableColumnFlags.WidthFixed, 200 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.TableSetupColumn("Jobs", ImGuiTableColumnFlags.WidthFixed, 175 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.TableSetupColumn("Design", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableHeadersRow();
|
||||
var xPos = 0f;
|
||||
|
||||
using var style = new ImRaii.Style();
|
||||
using var font = new ImRaii.Font();
|
||||
for (var i = 0; i < _fullPathCache.Count; ++i)
|
||||
{
|
||||
var path = _fullPathCache[i];
|
||||
var name = Glamourer.FixedDesignManager.FixedDesigns.Data[i];
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
style.Push(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemSpacing / 2);
|
||||
font.Push(UiBuilder.IconFont);
|
||||
if (ImGui.Button($"{FontAwesomeIcon.Trash.ToIconChar()}##{i}"))
|
||||
{
|
||||
_fullPathCache.RemoveAt(i--);
|
||||
Glamourer.FixedDesignManager.FixedDesigns.Remove(name);
|
||||
continue;
|
||||
}
|
||||
|
||||
var tmp = name.Enabled;
|
||||
ImGui.SameLine();
|
||||
xPos = ImGui.GetCursorPosX();
|
||||
if (ImGui.Checkbox($"##Enabled{i}", ref tmp))
|
||||
if (tmp && Glamourer.FixedDesignManager.FixedDesigns.EnableDesign(name)
|
||||
|| !tmp && Glamourer.FixedDesignManager.FixedDesigns.DisableDesign(name))
|
||||
{
|
||||
Glamourer.Config.FixedDesigns[i].Enabled = tmp;
|
||||
Glamourer.Config.Save();
|
||||
}
|
||||
|
||||
style.Pop();
|
||||
font.Pop();
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.Selectable($"{name.Name}##Fix{i}");
|
||||
if (ImGui.BeginDragDropSource())
|
||||
{
|
||||
_fixDragDropIdx = i;
|
||||
ImGui.SetDragDropPayload("##FixDragDrop", IntPtr.Zero, 0);
|
||||
ImGui.Text($"Dragging {name.Name} ({path})...");
|
||||
ImGui.EndDragDropSource();
|
||||
}
|
||||
|
||||
if (ImGui.BeginDragDropTarget())
|
||||
{
|
||||
if (IsDropping() && _fixDragDropIdx >= 0)
|
||||
{
|
||||
var d = Glamourer.FixedDesignManager.FixedDesigns.Data[_fixDragDropIdx];
|
||||
Glamourer.FixedDesignManager.FixedDesigns.Move(d, i);
|
||||
var p = _fullPathCache[_fixDragDropIdx];
|
||||
_fullPathCache.RemoveAt(_fixDragDropIdx);
|
||||
_fullPathCache.Insert(i, p);
|
||||
_fixDragDropIdx = -1;
|
||||
}
|
||||
|
||||
ImGui.EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.Text(Glamourer.FixedDesignManager.FixedDesigns.Data[i].Jobs.Name);
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.Text(path);
|
||||
}
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
font.Push(UiBuilder.IconFont);
|
||||
|
||||
ImGui.SetCursorPosX(xPos);
|
||||
if (_newFixDesign == null || _newFixCharacterName == string.Empty)
|
||||
{
|
||||
style.Push(ImGuiStyleVar.Alpha, 0.5f);
|
||||
ImGui.Button($"{FontAwesomeIcon.Plus.ToIconChar()}##NewFix");
|
||||
style.Pop();
|
||||
}
|
||||
else if (ImGui.Button($"{FontAwesomeIcon.Plus.ToIconChar()}##NewFix"))
|
||||
{
|
||||
_fullPathCache.Add(_newFixDesignPath);
|
||||
Glamourer.FixedDesignManager.FixedDesigns.Add(_newFixCharacterName, _newFixDesign, _newFixDesignGroup.Value, false);
|
||||
_newFixCharacterName = string.Empty;
|
||||
_newFixDesignPath = string.Empty;
|
||||
_newFixDesign = null;
|
||||
_newFixDesignGroup = Glamourer.FixedDesignManager.FixedDesigns.JobGroups[1];
|
||||
}
|
||||
|
||||
font.Pop();
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||
ImGui.InputTextWithHint("##NewFix", "Enter new Character", ref _newFixCharacterName, 32);
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.SetNextItemWidth(-1);
|
||||
using var combo = ImRaii.Combo("##NewFixDesignGroup", _newFixDesignGroup.Value.Name);
|
||||
if (combo)
|
||||
foreach (var (id, group) in Glamourer.FixedDesignManager.FixedDesigns.JobGroups)
|
||||
{
|
||||
ImGui.SetNextItemWidth(-1);
|
||||
if (ImGui.Selectable($"{group.Name}##NewFixDesignGroup", group.Name == _newFixDesignGroup.Value.Name))
|
||||
_newFixDesignGroup = group;
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.SetNextItemWidth(-1);
|
||||
using var combo2 = ImRaii.Combo("##NewFixPath", _newFixDesignPath);
|
||||
if (!combo2)
|
||||
return;
|
||||
|
||||
foreach (var design in _plugin.Designs.FileSystem.Root.AllLeaves(SortMode.Lexicographical).Cast<Design>())
|
||||
{
|
||||
var fullName = design.FullName();
|
||||
ImGui.SetNextItemWidth(-1);
|
||||
if (!ImGui.Selectable($"{fullName}##NewFixDesign", fullName == _newFixDesignPath))
|
||||
continue;
|
||||
|
||||
_newFixDesignPath = fullName;
|
||||
_newFixDesign = design;
|
||||
}
|
||||
}
|
||||
}
|
||||
//internal partial class Interface
|
||||
//{
|
||||
// private const string FixDragDropLabel = "##FixDragDrop";
|
||||
//
|
||||
// private List<string>? _fullPathCache;
|
||||
// private string _newFixCharacterName = string.Empty;
|
||||
// private string _newFixDesignPath = string.Empty;
|
||||
// private JobGroup? _newFixDesignGroup;
|
||||
// private Design? _newFixDesign;
|
||||
// private int _fixDragDropIdx = -1;
|
||||
//
|
||||
// private static unsafe bool IsDropping()
|
||||
// => ImGui.AcceptDragDropPayload(FixDragDropLabel).NativePtr != null;
|
||||
//
|
||||
// private void DrawFixedDesignsTab()
|
||||
// {
|
||||
// _newFixDesignGroup ??= Glamourer.FixedDesignManager.FixedDesigns.JobGroups[1];
|
||||
//
|
||||
// using var tabItem = ImRaii.TabItem("Fixed Designs");
|
||||
// if (!tabItem)
|
||||
// {
|
||||
// _fullPathCache = null;
|
||||
// _newFixDesign = null;
|
||||
// _newFixDesignPath = string.Empty;
|
||||
// _newFixDesignGroup = Glamourer.FixedDesignManager.FixedDesigns.JobGroups[1];
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// _fullPathCache ??= Glamourer.FixedDesignManager.FixedDesigns.Data.Select(d => d.Design.FullName()).ToList();
|
||||
//
|
||||
// using var table = ImRaii.Table("##FixedTable", 4);
|
||||
// var buttonWidth = 23.5f * ImGuiHelpers.GlobalScale;
|
||||
//
|
||||
// ImGui.TableSetupColumn("##DeleteColumn", ImGuiTableColumnFlags.WidthFixed, 2 * buttonWidth);
|
||||
// ImGui.TableSetupColumn("Character", ImGuiTableColumnFlags.WidthFixed, 200 * ImGuiHelpers.GlobalScale);
|
||||
// ImGui.TableSetupColumn("Jobs", ImGuiTableColumnFlags.WidthFixed, 175 * ImGuiHelpers.GlobalScale);
|
||||
// ImGui.TableSetupColumn("Design", ImGuiTableColumnFlags.WidthStretch);
|
||||
// ImGui.TableHeadersRow();
|
||||
// var xPos = 0f;
|
||||
//
|
||||
// using var style = new ImRaii.Style();
|
||||
// using var font = new ImRaii.Font();
|
||||
// for (var i = 0; i < _fullPathCache.Count; ++i)
|
||||
// {
|
||||
// var path = _fullPathCache[i];
|
||||
// var name = Glamourer.FixedDesignManager.FixedDesigns.Data[i];
|
||||
//
|
||||
// ImGui.TableNextRow();
|
||||
// ImGui.TableNextColumn();
|
||||
// style.Push(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemSpacing / 2);
|
||||
// font.Push(UiBuilder.IconFont);
|
||||
// if (ImGui.Button($"{FontAwesomeIcon.Trash.ToIconChar()}##{i}"))
|
||||
// {
|
||||
// _fullPathCache.RemoveAt(i--);
|
||||
// Glamourer.FixedDesignManager.FixedDesigns.Remove(name);
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// var tmp = name.Enabled;
|
||||
// ImGui.SameLine();
|
||||
// xPos = ImGui.GetCursorPosX();
|
||||
// if (ImGui.Checkbox($"##Enabled{i}", ref tmp))
|
||||
// if (tmp && Glamourer.FixedDesignManager.FixedDesigns.EnableDesign(name)
|
||||
// || !tmp && Glamourer.FixedDesignManager.FixedDesigns.DisableDesign(name))
|
||||
// {
|
||||
// Glamourer.Config.FixedDesigns[i].Enabled = tmp;
|
||||
// Glamourer.Config.Save();
|
||||
// }
|
||||
//
|
||||
// style.Pop();
|
||||
// font.Pop();
|
||||
// ImGui.TableNextColumn();
|
||||
// ImGui.Selectable($"{name.Name}##Fix{i}");
|
||||
// if (ImGui.BeginDragDropSource())
|
||||
// {
|
||||
// _fixDragDropIdx = i;
|
||||
// ImGui.SetDragDropPayload("##FixDragDrop", IntPtr.Zero, 0);
|
||||
// ImGui.Text($"Dragging {name.Name} ({path})...");
|
||||
// ImGui.EndDragDropSource();
|
||||
// }
|
||||
//
|
||||
// if (ImGui.BeginDragDropTarget())
|
||||
// {
|
||||
// if (IsDropping() && _fixDragDropIdx >= 0)
|
||||
// {
|
||||
// var d = Glamourer.FixedDesignManager.FixedDesigns.Data[_fixDragDropIdx];
|
||||
// Glamourer.FixedDesignManager.FixedDesigns.Move(d, i);
|
||||
// var p = _fullPathCache[_fixDragDropIdx];
|
||||
// _fullPathCache.RemoveAt(_fixDragDropIdx);
|
||||
// _fullPathCache.Insert(i, p);
|
||||
// _fixDragDropIdx = -1;
|
||||
// }
|
||||
//
|
||||
// ImGui.EndDragDropTarget();
|
||||
// }
|
||||
//
|
||||
// ImGui.TableNextColumn();
|
||||
// ImGui.Text(Glamourer.FixedDesignManager.FixedDesigns.Data[i].Jobs.Name);
|
||||
// ImGui.TableNextColumn();
|
||||
// ImGui.Text(path);
|
||||
// }
|
||||
//
|
||||
// ImGui.TableNextRow();
|
||||
// ImGui.TableNextColumn();
|
||||
// font.Push(UiBuilder.IconFont);
|
||||
//
|
||||
// ImGui.SetCursorPosX(xPos);
|
||||
// if (_newFixDesign == null || _newFixCharacterName == string.Empty)
|
||||
// {
|
||||
// style.Push(ImGuiStyleVar.Alpha, 0.5f);
|
||||
// ImGui.Button($"{FontAwesomeIcon.Plus.ToIconChar()}##NewFix");
|
||||
// style.Pop();
|
||||
// }
|
||||
// else if (ImGui.Button($"{FontAwesomeIcon.Plus.ToIconChar()}##NewFix"))
|
||||
// {
|
||||
// _fullPathCache.Add(_newFixDesignPath);
|
||||
// Glamourer.FixedDesignManager.FixedDesigns.Add(_newFixCharacterName, _newFixDesign, _newFixDesignGroup.Value, false);
|
||||
// _newFixCharacterName = string.Empty;
|
||||
// _newFixDesignPath = string.Empty;
|
||||
// _newFixDesign = null;
|
||||
// _newFixDesignGroup = Glamourer.FixedDesignManager.FixedDesigns.JobGroups[1];
|
||||
// }
|
||||
//
|
||||
// font.Pop();
|
||||
// ImGui.TableNextColumn();
|
||||
// ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
|
||||
// ImGui.InputTextWithHint("##NewFix", "Enter new Character", ref _newFixCharacterName, 32);
|
||||
// ImGui.TableNextColumn();
|
||||
// ImGui.SetNextItemWidth(-1);
|
||||
// using var combo = ImRaii.Combo("##NewFixDesignGroup", _newFixDesignGroup.Value.Name);
|
||||
// if (combo)
|
||||
// foreach (var (id, group) in Glamourer.FixedDesignManager.FixedDesigns.JobGroups)
|
||||
// {
|
||||
// ImGui.SetNextItemWidth(-1);
|
||||
// if (ImGui.Selectable($"{group.Name}##NewFixDesignGroup", group.Name == _newFixDesignGroup.Value.Name))
|
||||
// _newFixDesignGroup = group;
|
||||
// }
|
||||
//
|
||||
// ImGui.TableNextColumn();
|
||||
// ImGui.SetNextItemWidth(-1);
|
||||
// using var combo2 = ImRaii.Combo("##NewFixPath", _newFixDesignPath);
|
||||
// if (!combo2)
|
||||
// return;
|
||||
//
|
||||
// foreach (var design in _plugin.Designs.FileSystem.Root.AllLeaves(SortMode.Lexicographical).Cast<Design>())
|
||||
// {
|
||||
// var fullName = design.FullName();
|
||||
// ImGui.SetNextItemWidth(-1);
|
||||
// if (!ImGui.Selectable($"{fullName}##NewFixDesign", fullName == _newFixDesignPath))
|
||||
// continue;
|
||||
//
|
||||
// _newFixDesignPath = fullName;
|
||||
// _newFixDesign = design;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -6,197 +6,98 @@ using Glamourer.Structs;
|
|||
using ImGuiNET;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
||||
namespace Glamourer.Gui
|
||||
{
|
||||
internal partial class Interface
|
||||
{
|
||||
// Push the stain color to type and if it is too bright, turn the text color black.
|
||||
// Return number of pushed styles.
|
||||
private static int PushColor(Stain stain, ImGuiCol type = ImGuiCol.Button)
|
||||
{
|
||||
ImGui.PushStyleColor(type, stain.RgbaColor);
|
||||
if (stain.Intensity > 127)
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, 0xFF101010);
|
||||
return 2;
|
||||
}
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
return 1;
|
||||
}
|
||||
//internal partial class Interface
|
||||
//{
|
||||
// // Push the stain color to type and if it is too bright, turn the text color black.
|
||||
// // Return number of pushed styles.
|
||||
// private static int PushColor(Stain stain, ImGuiCol type = ImGuiCol.Button)
|
||||
// {
|
||||
// ImGui.PushStyleColor(type, stain.RgbaColor);
|
||||
// if (stain.Intensity > 127)
|
||||
// {
|
||||
// ImGui.PushStyleColor(ImGuiCol.Text, 0xFF101010);
|
||||
// return 2;
|
||||
// }
|
||||
//
|
||||
// return 1;
|
||||
// }
|
||||
//
|
||||
|
||||
// Go through a whole customization struct and fix up all settings that need fixing.
|
||||
private static void FixUpAttributes(ref CharacterCustomization customization)
|
||||
{
|
||||
var set = Glamourer.Customization.GetList(customization.Clan, customization.Gender);
|
||||
foreach (CustomizationId id in Enum.GetValues(typeof(CustomizationId)))
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case CustomizationId.Race: break;
|
||||
case CustomizationId.Clan: break;
|
||||
case CustomizationId.BodyType: break;
|
||||
case CustomizationId.Gender: break;
|
||||
case CustomizationId.FacialFeaturesTattoos: break;
|
||||
case CustomizationId.HighlightsOnFlag: break;
|
||||
case CustomizationId.Face: break;
|
||||
default:
|
||||
var count = set.Count(id);
|
||||
if (set.DataByValue(id, customization[id], out _) < 0)
|
||||
if (count == 0)
|
||||
customization[id] = 0;
|
||||
else
|
||||
customization[id] = set.Data(id, 0).Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
// Change a race and fix up all required customizations afterwards.
|
||||
private static bool ChangeRace(ref CharacterCustomization customization, SubRace clan)
|
||||
{
|
||||
if (clan == customization.Clan)
|
||||
return false;
|
||||
|
||||
var race = clan.ToRace();
|
||||
customization.Race = race;
|
||||
customization.Clan = clan;
|
||||
|
||||
if (race == Race.Hrothgar)
|
||||
customization.Gender = Gender.Male;
|
||||
|
||||
FixUpAttributes(ref customization);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Change a gender and fix up all required customizations afterwards.
|
||||
private static bool ChangeGender(ref CharacterCustomization customization, Gender gender)
|
||||
{
|
||||
if (gender == customization.Gender)
|
||||
return false;
|
||||
|
||||
customization.Gender = gender;
|
||||
FixUpAttributes(ref customization);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string ClanName(SubRace race, Gender gender)
|
||||
{
|
||||
if (gender == Gender.Female)
|
||||
return race switch
|
||||
{
|
||||
SubRace.Midlander => Glamourer.Customization.GetName(CustomName.MidlanderM),
|
||||
SubRace.Highlander => Glamourer.Customization.GetName(CustomName.HighlanderM),
|
||||
SubRace.Wildwood => Glamourer.Customization.GetName(CustomName.WildwoodM),
|
||||
SubRace.Duskwight => Glamourer.Customization.GetName(CustomName.DuskwightM),
|
||||
SubRace.Plainsfolk => Glamourer.Customization.GetName(CustomName.PlainsfolkM),
|
||||
SubRace.Dunesfolk => Glamourer.Customization.GetName(CustomName.DunesfolkM),
|
||||
SubRace.SeekerOfTheSun => Glamourer.Customization.GetName(CustomName.SeekerOfTheSunM),
|
||||
SubRace.KeeperOfTheMoon => Glamourer.Customization.GetName(CustomName.KeeperOfTheMoonM),
|
||||
SubRace.Seawolf => Glamourer.Customization.GetName(CustomName.SeawolfM),
|
||||
SubRace.Hellsguard => Glamourer.Customization.GetName(CustomName.HellsguardM),
|
||||
SubRace.Raen => Glamourer.Customization.GetName(CustomName.RaenM),
|
||||
SubRace.Xaela => Glamourer.Customization.GetName(CustomName.XaelaM),
|
||||
SubRace.Helion => Glamourer.Customization.GetName(CustomName.HelionM),
|
||||
SubRace.Lost => Glamourer.Customization.GetName(CustomName.LostM),
|
||||
SubRace.Rava => Glamourer.Customization.GetName(CustomName.RavaF),
|
||||
SubRace.Veena => Glamourer.Customization.GetName(CustomName.VeenaF),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(race), race, null),
|
||||
};
|
||||
|
||||
return race switch
|
||||
{
|
||||
SubRace.Midlander => Glamourer.Customization.GetName(CustomName.MidlanderF),
|
||||
SubRace.Highlander => Glamourer.Customization.GetName(CustomName.HighlanderF),
|
||||
SubRace.Wildwood => Glamourer.Customization.GetName(CustomName.WildwoodF),
|
||||
SubRace.Duskwight => Glamourer.Customization.GetName(CustomName.DuskwightF),
|
||||
SubRace.Plainsfolk => Glamourer.Customization.GetName(CustomName.PlainsfolkF),
|
||||
SubRace.Dunesfolk => Glamourer.Customization.GetName(CustomName.DunesfolkF),
|
||||
SubRace.SeekerOfTheSun => Glamourer.Customization.GetName(CustomName.SeekerOfTheSunF),
|
||||
SubRace.KeeperOfTheMoon => Glamourer.Customization.GetName(CustomName.KeeperOfTheMoonF),
|
||||
SubRace.Seawolf => Glamourer.Customization.GetName(CustomName.SeawolfF),
|
||||
SubRace.Hellsguard => Glamourer.Customization.GetName(CustomName.HellsguardF),
|
||||
SubRace.Raen => Glamourer.Customization.GetName(CustomName.RaenF),
|
||||
SubRace.Xaela => Glamourer.Customization.GetName(CustomName.XaelaF),
|
||||
SubRace.Helion => Glamourer.Customization.GetName(CustomName.HelionM),
|
||||
SubRace.Lost => Glamourer.Customization.GetName(CustomName.LostM),
|
||||
SubRace.Rava => Glamourer.Customization.GetName(CustomName.RavaF),
|
||||
SubRace.Veena => Glamourer.Customization.GetName(CustomName.VeenaF),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(race), race, null),
|
||||
};
|
||||
}
|
||||
|
||||
private enum DesignNameUse
|
||||
{
|
||||
SaveCurrent,
|
||||
NewDesign,
|
||||
DuplicateDesign,
|
||||
NewFolder,
|
||||
FromClipboard,
|
||||
}
|
||||
|
||||
private void DrawDesignNamePopup(DesignNameUse use)
|
||||
{
|
||||
if (ImGui.BeginPopup($"{DesignNamePopupLabel}{use}"))
|
||||
{
|
||||
if (ImGui.InputText("##designName", ref _newDesignName, 64, ImGuiInputTextFlags.EnterReturnsTrue)
|
||||
&& _newDesignName.Any())
|
||||
{
|
||||
switch (use)
|
||||
{
|
||||
case DesignNameUse.SaveCurrent:
|
||||
SaveNewDesign(ConditionalCopy(_currentSave, _holdShift, _holdCtrl));
|
||||
break;
|
||||
case DesignNameUse.NewDesign:
|
||||
var empty = new CharacterSave();
|
||||
empty.Load(CharacterCustomization.Default);
|
||||
empty.WriteCustomizations = false;
|
||||
SaveNewDesign(empty);
|
||||
break;
|
||||
case DesignNameUse.DuplicateDesign:
|
||||
SaveNewDesign(ConditionalCopy(_selection!.Data, _holdShift, _holdCtrl));
|
||||
break;
|
||||
case DesignNameUse.NewFolder:
|
||||
_designs.FileSystem
|
||||
.CreateAllFolders($"{_newDesignName}/a"); // Filename is just ignored, but all folders are created.
|
||||
break;
|
||||
case DesignNameUse.FromClipboard:
|
||||
try
|
||||
{
|
||||
var text = ImGui.GetClipboardText();
|
||||
var save = CharacterSave.FromString(text);
|
||||
SaveNewDesign(save);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
PluginLog.Information($"Could not save new Design from Clipboard:\n{e}");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_newDesignName = string.Empty;
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
|
||||
if (_keyboardFocus)
|
||||
{
|
||||
ImGui.SetKeyboardFocusHere();
|
||||
_keyboardFocus = false;
|
||||
}
|
||||
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenDesignNamePopup(DesignNameUse use)
|
||||
{
|
||||
_newDesignName = string.Empty;
|
||||
_keyboardFocus = true;
|
||||
_holdCtrl = ImGui.GetIO().KeyCtrl;
|
||||
_holdShift = ImGui.GetIO().KeyShift;
|
||||
ImGui.OpenPopup($"{DesignNamePopupLabel}{use}");
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
//
|
||||
// private enum DesignNameUse
|
||||
// {
|
||||
// SaveCurrent,
|
||||
// NewDesign,
|
||||
// DuplicateDesign,
|
||||
// NewFolder,
|
||||
// FromClipboard,
|
||||
// }
|
||||
//
|
||||
// private void DrawDesignNamePopup(DesignNameUse use)
|
||||
// {
|
||||
// if (ImGui.BeginPopup($"{DesignNamePopupLabel}{use}"))
|
||||
// {
|
||||
// if (ImGui.InputText("##designName", ref _newDesignName, 64, ImGuiInputTextFlags.EnterReturnsTrue)
|
||||
// && _newDesignName.Any())
|
||||
// {
|
||||
// switch (use)
|
||||
// {
|
||||
// case DesignNameUse.SaveCurrent:
|
||||
// SaveNewDesign(ConditionalCopy(_currentSave, _holdShift, _holdCtrl));
|
||||
// break;
|
||||
// case DesignNameUse.NewDesign:
|
||||
// var empty = new CharacterSave();
|
||||
// empty.Load(CharacterCustomization.Default);
|
||||
// empty.WriteCustomizations = false;
|
||||
// SaveNewDesign(empty);
|
||||
// break;
|
||||
// case DesignNameUse.DuplicateDesign:
|
||||
// SaveNewDesign(ConditionalCopy(_selection!.Data, _holdShift, _holdCtrl));
|
||||
// break;
|
||||
// case DesignNameUse.NewFolder:
|
||||
// _designs.FileSystem
|
||||
// .CreateAllFolders($"{_newDesignName}/a"); // Filename is just ignored, but all folders are created.
|
||||
// break;
|
||||
// case DesignNameUse.FromClipboard:
|
||||
// try
|
||||
// {
|
||||
// var text = ImGui.GetClipboardText();
|
||||
// var save = CharacterSave.FromString(text);
|
||||
// SaveNewDesign(save);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// PluginLog.Information($"Could not save new Design from Clipboard:\n{e}");
|
||||
// }
|
||||
//
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// _newDesignName = string.Empty;
|
||||
// ImGui.CloseCurrentPopup();
|
||||
// }
|
||||
//
|
||||
// if (_keyboardFocus)
|
||||
// {
|
||||
// ImGui.SetKeyboardFocusHere();
|
||||
// _keyboardFocus = false;
|
||||
// }
|
||||
//
|
||||
// ImGui.EndPopup();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void OpenDesignNamePopup(DesignNameUse use)
|
||||
// {
|
||||
// _newDesignName = string.Empty;
|
||||
// _keyboardFocus = true;
|
||||
// _holdCtrl = ImGui.GetIO().KeyCtrl;
|
||||
// _holdShift = ImGui.GetIO().KeyShift;
|
||||
// ImGui.OpenPopup($"{DesignNamePopupLabel}{use}");
|
||||
// }
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -4,92 +4,81 @@ using System.Reflection;
|
|||
using ImGuiNET;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using Glamourer.Structs;
|
||||
using Item = Glamourer.Structs.Item;
|
||||
using Stain = Glamourer.Structs.Stain;
|
||||
|
||||
namespace Glamourer.Gui
|
||||
{
|
||||
internal partial class Interface
|
||||
{
|
||||
private const float ColorButtonWidth = 22.5f;
|
||||
private const float ColorComboWidth = 140f;
|
||||
private const float ItemComboWidth = 350f;
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
private static readonly Vector4 GreyVector = new(0.5f, 0.5f, 0.5f, 1);
|
||||
//internal partial class Interface
|
||||
//{
|
||||
// private const float ColorButtonWidth = 22.5f;
|
||||
// private const float ColorComboWidth = 140f;
|
||||
// private const float ItemComboWidth = 350f;
|
||||
//
|
||||
// private static readonly Vector4 GreyVector = new(0.5f, 0.5f, 0.5f, 1);
|
||||
//
|
||||
// private static ComboWithFilter<Stain> CreateDefaultStainCombo(IReadOnlyList<Stain> stains)
|
||||
// => new("##StainCombo", ColorComboWidth, ColorButtonWidth, stains,
|
||||
// s => s.Name.ToString())
|
||||
// {
|
||||
// Flags = ImGuiComboFlags.NoArrowButton | ImGuiComboFlags.HeightLarge,
|
||||
// PreList = () =>
|
||||
// {
|
||||
// ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, Vector2.Zero);
|
||||
// ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero);
|
||||
// ImGui.PushStyleVar(ImGuiStyleVar.FrameRounding, 0);
|
||||
// },
|
||||
// PostList = () => { ImGui.PopStyleVar(3); },
|
||||
// CreateSelectable = s =>
|
||||
// {
|
||||
// var push = PushColor(s);
|
||||
// var ret = ImGui.Button($"{s.Name}##Stain{(byte)s.RowIndex}",
|
||||
// Vector2.UnitX * (ColorComboWidth - ImGui.GetStyle().ScrollbarSize));
|
||||
// ImGui.PopStyleColor(push);
|
||||
// return ret;
|
||||
// },
|
||||
// ItemsAtOnce = 12,
|
||||
// };
|
||||
//
|
||||
// private ComboWithFilter<Item> CreateItemCombo(EquipSlot slot, IReadOnlyList<Item> items)
|
||||
// => new($"{_equipSlotNames[slot]}##Equip", ItemComboWidth, ItemComboWidth, items, i => i.Name)
|
||||
// {
|
||||
// Flags = ImGuiComboFlags.HeightLarge,
|
||||
// CreateSelectable = i =>
|
||||
// {
|
||||
// var ret = ImGui.Selectable(i.Name);
|
||||
// var setId = $"({(int)i.MainModel.id})";
|
||||
// var size = ImGui.CalcTextSize(setId).X;
|
||||
// ImGui.SameLine(ImGui.GetWindowContentRegionWidth() - size - ImGui.GetStyle().ItemInnerSpacing.X);
|
||||
// ImGui.TextColored(GreyVector, setId);
|
||||
// return ret;
|
||||
// },
|
||||
// };
|
||||
//
|
||||
// private (ComboWithFilter<Item>, ComboWithFilter<Stain>) CreateCombos(EquipSlot slot, IReadOnlyList<Item> items,
|
||||
// ComboWithFilter<Stain> defaultStain)
|
||||
// => (CreateItemCombo(slot, items), new ComboWithFilter<Stain>($"##{slot}Stain", defaultStain));
|
||||
//
|
||||
|
||||
private static ComboWithFilter<Stain> CreateDefaultStainCombo(IReadOnlyList<Stain> stains)
|
||||
=> new("##StainCombo", ColorComboWidth, ColorButtonWidth, stains,
|
||||
s => s.Name.ToString())
|
||||
{
|
||||
Flags = ImGuiComboFlags.NoArrowButton | ImGuiComboFlags.HeightLarge,
|
||||
PreList = () =>
|
||||
{
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, Vector2.Zero);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FrameRounding, 0);
|
||||
},
|
||||
PostList = () => { ImGui.PopStyleVar(3); },
|
||||
CreateSelectable = s =>
|
||||
{
|
||||
var push = PushColor(s);
|
||||
var ret = ImGui.Button($"{s.Name}##Stain{(byte) s.RowIndex}",
|
||||
Vector2.UnitX * (ColorComboWidth - ImGui.GetStyle().ScrollbarSize));
|
||||
ImGui.PopStyleColor(push);
|
||||
return ret;
|
||||
},
|
||||
ItemsAtOnce = 12,
|
||||
};
|
||||
|
||||
private ComboWithFilter<Item> CreateItemCombo(EquipSlot slot, IReadOnlyList<Item> items)
|
||||
=> new($"{_equipSlotNames[slot]}##Equip", ItemComboWidth, ItemComboWidth, items, i => i.Name)
|
||||
{
|
||||
Flags = ImGuiComboFlags.HeightLarge,
|
||||
CreateSelectable = i =>
|
||||
{
|
||||
var ret = ImGui.Selectable(i.Name);
|
||||
var setId = $"({(int) i.MainModel.id})";
|
||||
var size = ImGui.CalcTextSize(setId).X;
|
||||
ImGui.SameLine(ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X - size - ImGui.GetStyle().ItemInnerSpacing.X);
|
||||
ImGui.TextColored(GreyVector, setId);
|
||||
return ret;
|
||||
},
|
||||
};
|
||||
|
||||
private (ComboWithFilter<Item>, ComboWithFilter<Stain>) CreateCombos(EquipSlot slot, IReadOnlyList<Item> items,
|
||||
ComboWithFilter<Stain> defaultStain)
|
||||
=> (CreateItemCombo(slot, items), new ComboWithFilter<Stain>($"##{slot}Stain", defaultStain));
|
||||
|
||||
private static ImGuiScene.TextureWrap? GetLegacyTattooIcon()
|
||||
{
|
||||
using var resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("Glamourer.LegacyTattoo.raw");
|
||||
if (resource != null)
|
||||
{
|
||||
var rawImage = new byte[resource.Length];
|
||||
resource.Read(rawImage, 0, (int) resource.Length);
|
||||
return Dalamud.PluginInterface.UiBuilder.LoadImageRaw(rawImage, 192, 192, 4);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Dictionary<EquipSlot, string> GetEquipSlotNames()
|
||||
{
|
||||
var sheet = Dalamud.GameData.GetExcelSheet<Addon>()!;
|
||||
var ret = new Dictionary<EquipSlot, string>(12)
|
||||
{
|
||||
[EquipSlot.MainHand] = sheet.GetRow(738)?.Text.ToString() ?? "Main Hand",
|
||||
[EquipSlot.OffHand] = sheet.GetRow(739)?.Text.ToString() ?? "Off Hand",
|
||||
[EquipSlot.Head] = sheet.GetRow(740)?.Text.ToString() ?? "Head",
|
||||
[EquipSlot.Body] = sheet.GetRow(741)?.Text.ToString() ?? "Body",
|
||||
[EquipSlot.Hands] = sheet.GetRow(742)?.Text.ToString() ?? "Hands",
|
||||
[EquipSlot.Legs] = sheet.GetRow(744)?.Text.ToString() ?? "Legs",
|
||||
[EquipSlot.Feet] = sheet.GetRow(745)?.Text.ToString() ?? "Feet",
|
||||
[EquipSlot.Ears] = sheet.GetRow(746)?.Text.ToString() ?? "Ears",
|
||||
[EquipSlot.Neck] = sheet.GetRow(747)?.Text.ToString() ?? "Neck",
|
||||
[EquipSlot.Wrists] = sheet.GetRow(748)?.Text.ToString() ?? "Wrists",
|
||||
[EquipSlot.RFinger] = sheet.GetRow(749)?.Text.ToString() ?? "Right Ring",
|
||||
[EquipSlot.LFinger] = sheet.GetRow(750)?.Text.ToString() ?? "Left Ring",
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// private static Dictionary<EquipSlot, string> GetEquipSlotNames()
|
||||
// {
|
||||
// var sheet = Dalamud.GameData.GetExcelSheet<Addon>()!;
|
||||
// var ret = new Dictionary<EquipSlot, string>(12)
|
||||
// {
|
||||
// [EquipSlot.MainHand] = sheet.GetRow(738)?.Text.ToString() ?? "Main Hand",
|
||||
// [EquipSlot.OffHand] = sheet.GetRow(739)?.Text.ToString() ?? "Off Hand",
|
||||
// [EquipSlot.Head] = sheet.GetRow(740)?.Text.ToString() ?? "Head",
|
||||
// [EquipSlot.Body] = sheet.GetRow(741)?.Text.ToString() ?? "Body",
|
||||
// [EquipSlot.Hands] = sheet.GetRow(742)?.Text.ToString() ?? "Hands",
|
||||
// [EquipSlot.Legs] = sheet.GetRow(744)?.Text.ToString() ?? "Legs",
|
||||
// [EquipSlot.Feet] = sheet.GetRow(745)?.Text.ToString() ?? "Feet",
|
||||
// [EquipSlot.Ears] = sheet.GetRow(746)?.Text.ToString() ?? "Ears",
|
||||
// [EquipSlot.Neck] = sheet.GetRow(747)?.Text.ToString() ?? "Neck",
|
||||
// [EquipSlot.Wrists] = sheet.GetRow(748)?.Text.ToString() ?? "Wrists",
|
||||
// [EquipSlot.RFinger] = sheet.GetRow(749)?.Text.ToString() ?? "Right Ring",
|
||||
// [EquipSlot.LFinger] = sheet.GetRow(750)?.Text.ToString() ?? "Left Ring",
|
||||
// };
|
||||
// return ret;
|
||||
// }
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -4,60 +4,49 @@ using ImGuiNET;
|
|||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
internal partial class Interface
|
||||
{
|
||||
private static bool DrawCheckMark(string label, bool value, Action<bool> setter)
|
||||
{
|
||||
var startValue = value;
|
||||
if (ImGui.Checkbox(label, ref startValue) && startValue != value)
|
||||
{
|
||||
setter(startValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool DrawMiscellaneous(CharacterSave save, Character? player)
|
||||
{
|
||||
var ret = false;
|
||||
if (!ImGui.CollapsingHeader("Miscellaneous"))
|
||||
return ret;
|
||||
|
||||
ret |= DrawCheckMark("Hat Visible", save.HatState, v =>
|
||||
{
|
||||
save.HatState = v;
|
||||
player?.SetHatVisible(v);
|
||||
});
|
||||
|
||||
ret |= DrawCheckMark("Weapon Visible", save.WeaponState, v =>
|
||||
{
|
||||
save.WeaponState = v;
|
||||
player?.SetWeaponHidden(!v);
|
||||
});
|
||||
|
||||
ret |= DrawCheckMark("Visor Toggled", save.VisorState, v =>
|
||||
{
|
||||
save.VisorState = v;
|
||||
player?.SetVisorToggled(v);
|
||||
});
|
||||
|
||||
ret |= DrawCheckMark("Is Wet", save.IsWet, v =>
|
||||
{
|
||||
save.IsWet = v;
|
||||
player?.SetWetness(v);
|
||||
});
|
||||
|
||||
var alpha = save.Alpha;
|
||||
if (ImGui.DragFloat("Alpha", ref alpha, 0.01f, 0f, 1f, "%.2f") && alpha != save.Alpha)
|
||||
{
|
||||
alpha = (float)Math.Round(alpha > 1 ? 1 : alpha < 0 ? 0 : alpha, 2);
|
||||
save.Alpha = alpha;
|
||||
ret = true;
|
||||
if (player != null)
|
||||
player.Alpha() = alpha;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
//internal partial class Interface
|
||||
//{
|
||||
//
|
||||
// private static bool DrawMiscellaneous(CharacterSave save, Character? player)
|
||||
// {
|
||||
// var ret = false;
|
||||
// if (!ImGui.CollapsingHeader("Miscellaneous"))
|
||||
// return ret;
|
||||
//
|
||||
// ret |= DrawCheckMark("Hat Visible", save.HatState, v =>
|
||||
// {
|
||||
// save.HatState = v;
|
||||
// player?.SetHatVisible(v);
|
||||
// });
|
||||
//
|
||||
// ret |= DrawCheckMark("Weapon Visible", save.WeaponState, v =>
|
||||
// {
|
||||
// save.WeaponState = v;
|
||||
// player?.SetWeaponHidden(!v);
|
||||
// });
|
||||
//
|
||||
// ret |= DrawCheckMark("Visor Toggled", save.VisorState, v =>
|
||||
// {
|
||||
// save.VisorState = v;
|
||||
// player?.SetVisorToggled(v);
|
||||
// });
|
||||
//
|
||||
// ret |= DrawCheckMark("Is Wet", save.IsWet, v =>
|
||||
// {
|
||||
// save.IsWet = v;
|
||||
// player?.SetWetness(v);
|
||||
// });
|
||||
//
|
||||
// var alpha = save.Alpha;
|
||||
// if (ImGui.DragFloat("Alpha", ref alpha, 0.01f, 0f, 1f, "%.2f") && alpha != save.Alpha)
|
||||
// {
|
||||
// alpha = (float)Math.Round(alpha > 1 ? 1 : alpha < 0 ? 0 : alpha, 2);
|
||||
// save.Alpha = alpha;
|
||||
// ret = true;
|
||||
// if (player != null)
|
||||
// player.Alpha() = alpha;
|
||||
// }
|
||||
//
|
||||
// return ret;
|
||||
// }
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -6,82 +6,82 @@ using OtterGui.Raii;
|
|||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
internal partial class Interface
|
||||
{
|
||||
private string? _currentRevertableName;
|
||||
private CharacterSave? _currentRevertable;
|
||||
|
||||
private void DrawRevertablesSelector()
|
||||
{
|
||||
ImGui.BeginGroup();
|
||||
DrawPlayerFilter();
|
||||
if (!ImGui.BeginChild("##playerSelector",
|
||||
new Vector2(SelectorWidth * ImGui.GetIO().FontGlobalScale, -ImGui.GetFrameHeight() - 1), true))
|
||||
{
|
||||
ImGui.EndChild();
|
||||
ImGui.EndGroup();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var (name, save) in Glamourer.RevertableDesigns.Saves)
|
||||
{
|
||||
if (name.ToLowerInvariant().Contains(_playerFilterLower) && ImGui.Selectable(name, name == _currentRevertableName))
|
||||
{
|
||||
_currentRevertableName = name;
|
||||
_currentRevertable = save;
|
||||
}
|
||||
}
|
||||
|
||||
using (var _ = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero))
|
||||
{
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
||||
DrawSelectionButtons();
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
|
||||
private void DrawRevertablePanel()
|
||||
{
|
||||
using var group = ImRaii.Group();
|
||||
{
|
||||
var buttonColor = ImGui.GetColorU32(ImGuiCol.FrameBg);
|
||||
using var color = ImRaii.PushColor(ImGuiCol.Text, GreenHeaderColor)
|
||||
.Push(ImGuiCol.Button, buttonColor)
|
||||
.Push(ImGuiCol.ButtonHovered, buttonColor)
|
||||
.Push(ImGuiCol.ButtonActive, buttonColor);
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
ImGui.Button($"{_currentRevertableName}##playerHeader", -Vector2.UnitX * 0.0001f);
|
||||
}
|
||||
|
||||
if (!ImGui.BeginChild("##revertableData", -Vector2.One, true))
|
||||
{
|
||||
ImGui.EndChild();
|
||||
return;
|
||||
}
|
||||
|
||||
var save = _currentRevertable!.Copy();
|
||||
DrawCustomization(ref save.Customizations);
|
||||
DrawEquip(save.Equipment);
|
||||
DrawMiscellaneous(save, null);
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
private void DrawRevertablesTab()
|
||||
{
|
||||
using var tabItem = ImRaii.TabItem("Revertables");
|
||||
if (!tabItem)
|
||||
return;
|
||||
|
||||
DrawRevertablesSelector();
|
||||
|
||||
if (_currentRevertableName == null)
|
||||
return;
|
||||
|
||||
ImGui.SameLine();
|
||||
DrawRevertablePanel();
|
||||
}
|
||||
}
|
||||
//internal partial class Interface
|
||||
//{
|
||||
// private string? _currentRevertableName;
|
||||
// private CharacterSave? _currentRevertable;
|
||||
//
|
||||
// private void DrawRevertablesSelector()
|
||||
// {
|
||||
// ImGui.BeginGroup();
|
||||
// DrawPlayerFilter();
|
||||
// if (!ImGui.BeginChild("##playerSelector",
|
||||
// new Vector2(SelectorWidth * ImGui.GetIO().FontGlobalScale, -ImGui.GetFrameHeight() - 1), true))
|
||||
// {
|
||||
// ImGui.EndChild();
|
||||
// ImGui.EndGroup();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// foreach (var (name, save) in Glamourer.RevertableDesigns.Saves)
|
||||
// {
|
||||
// if (name.ToLowerInvariant().Contains(_playerFilterLower) && ImGui.Selectable(name, name == _currentRevertableName))
|
||||
// {
|
||||
// _currentRevertableName = name;
|
||||
// _currentRevertable = save;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// using (var _ = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero))
|
||||
// {
|
||||
// ImGui.EndChild();
|
||||
// }
|
||||
//
|
||||
// DrawSelectionButtons();
|
||||
// ImGui.EndGroup();
|
||||
// }
|
||||
//
|
||||
// private void DrawRevertablePanel()
|
||||
// {
|
||||
// using var group = ImRaii.Group();
|
||||
// {
|
||||
// var buttonColor = ImGui.GetColorU32(ImGuiCol.FrameBg);
|
||||
// using var color = ImRaii.PushColor(ImGuiCol.Text, GreenHeaderColor)
|
||||
// .Push(ImGuiCol.Button, buttonColor)
|
||||
// .Push(ImGuiCol.ButtonHovered, buttonColor)
|
||||
// .Push(ImGuiCol.ButtonActive, buttonColor);
|
||||
// using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
// .Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
// ImGui.Button($"{_currentRevertableName}##playerHeader", -Vector2.UnitX * 0.0001f);
|
||||
// }
|
||||
//
|
||||
// if (!ImGui.BeginChild("##revertableData", -Vector2.One, true))
|
||||
// {
|
||||
// ImGui.EndChild();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// var save = _currentRevertable!.Copy();
|
||||
// DrawCustomization(ref save.Customizations);
|
||||
// DrawEquip(save.Equipment);
|
||||
// DrawMiscellaneous(save, null);
|
||||
//
|
||||
// ImGui.EndChild();
|
||||
// }
|
||||
//
|
||||
// [Conditional("DEBUG")]
|
||||
// private void DrawRevertablesTab()
|
||||
// {
|
||||
// using var tabItem = ImRaii.TabItem("Revertables");
|
||||
// if (!tabItem)
|
||||
// return;
|
||||
//
|
||||
// DrawRevertablesSelector();
|
||||
//
|
||||
// if (_currentRevertableName == null)
|
||||
// return;
|
||||
//
|
||||
// ImGui.SameLine();
|
||||
// DrawRevertablePanel();
|
||||
// }
|
||||
//}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue