mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2026-02-19 22:17:44 +01:00
.
This commit is contained in:
parent
145b64bb7a
commit
4cf082aa19
37 changed files with 1362 additions and 1255 deletions
|
|
@ -1,11 +1,12 @@
|
|||
using System.Numerics;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using Glamourer.Customization;
|
||||
using ImGuiNET;
|
||||
using OtterGui.Raii;
|
||||
|
||||
namespace Glamourer.Gui.Customization;
|
||||
|
||||
internal partial class CustomizationDrawer
|
||||
public partial class CustomizationDrawer
|
||||
{
|
||||
private const string ColorPickerPopupName = "ColorPicker";
|
||||
|
||||
|
|
@ -26,7 +27,6 @@ internal partial class CustomizationDrawer
|
|||
DataInputInt(current);
|
||||
ImGui.TextUnformatted(_currentOption);
|
||||
}
|
||||
|
||||
DrawColorPickerPopup();
|
||||
}
|
||||
|
||||
|
|
@ -56,10 +56,9 @@ internal partial class CustomizationDrawer
|
|||
private (int, CustomizeData) GetCurrentCustomization(CustomizeIndex index)
|
||||
{
|
||||
var current = _set.DataByValue(index, _customize[index], out var custom, _customize.Face);
|
||||
if (!_set.IsAvailable(index) || current >= 0)
|
||||
return (current, custom!.Value);
|
||||
if (_set.IsAvailable(index) && current < 0)
|
||||
throw new Exception($"Read invalid customization value {_customize[index]} for {index}.");
|
||||
|
||||
Glamourer.Log.Warning($"Read invalid customization value {_customize[index]} for {index}.");
|
||||
return (0, _set.Data(index, 0));
|
||||
return (current, custom!.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,12 +6,12 @@ using Glamourer.Util;
|
|||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Gui.Customization;
|
||||
|
||||
internal partial class CustomizationDrawer
|
||||
public partial class CustomizationDrawer
|
||||
{
|
||||
private void DrawRaceGenderSelector()
|
||||
{
|
||||
|
|
@ -26,21 +26,20 @@ internal partial class CustomizationDrawer
|
|||
|
||||
private void DrawGenderSelector()
|
||||
{
|
||||
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;
|
||||
using var font = ImRaii.PushFont(UiBuilder.IconFont);
|
||||
var icon = _customize.Gender switch
|
||||
{
|
||||
Gender.Male when _customize.Race is Race.Hrothgar => FontAwesomeIcon.MarsDouble,
|
||||
Gender.Male => FontAwesomeIcon.Mars,
|
||||
Gender.Female => FontAwesomeIcon.Venus,
|
||||
|
||||
if (!ImGuiUtil.DrawDisabledButton(icon.ToIconString(), _framedIconSize, string.Empty, restricted, true))
|
||||
_ => throw new Exception($"Gender value {_customize.Gender} is not a valid gender for a design."),
|
||||
};
|
||||
|
||||
if (!ImGuiUtil.DrawDisabledButton(icon.ToIconString(), _framedIconSize, string.Empty, icon == FontAwesomeIcon.MarsDouble, true))
|
||||
return;
|
||||
|
||||
var gender = _customize.Gender == Gender.Male ? Gender.Female : Gender.Male;
|
||||
if (!_customize.ChangeGender(_equip, gender))
|
||||
return;
|
||||
|
||||
foreach (var actor in _actors.Where(a => a))
|
||||
Glamourer.Penumbra.RedrawObject(actor.Character, RedrawType.Redraw);
|
||||
Changed |= _customize.ChangeGender(CharacterEquip.Null, _customize.Gender is Gender.Male ? Gender.Female : Gender.Male);
|
||||
}
|
||||
|
||||
private void DrawRaceCombo()
|
||||
|
|
@ -52,12 +51,8 @@ internal partial class CustomizationDrawer
|
|||
|
||||
foreach (var subRace in Enum.GetValues<SubRace>().Skip(1)) // Skip Unknown
|
||||
{
|
||||
if (!ImGui.Selectable(CustomizeExtensions.ClanName(subRace, _customize.Gender), subRace == _customize.Clan)
|
||||
|| !_customize.ChangeRace(_equip, subRace))
|
||||
continue;
|
||||
|
||||
foreach (var actor in _actors.Where(a => a && a.DrawObject))
|
||||
Glamourer.Penumbra.RedrawObject(actor.Character, RedrawType.Redraw);
|
||||
if (ImGui.Selectable(CustomizeExtensions.ClanName(subRace, _customize.Gender), subRace == _customize.Clan))
|
||||
Changed |= _customize.ChangeRace(CharacterEquip.Null, subRace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Glamourer.Customization;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.Api.Enums;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
||||
namespace Glamourer.Gui.Customization;
|
||||
|
||||
internal partial class CustomizationDrawer
|
||||
public partial class CustomizationDrawer
|
||||
{
|
||||
private const string IconSelectorPopup = "Style Picker";
|
||||
|
||||
|
|
@ -40,22 +38,23 @@ internal partial class CustomizationDrawer
|
|||
FaceInputInt(current);
|
||||
else
|
||||
DataInputInt(current);
|
||||
|
||||
ImGui.TextUnformatted($"{label} ({custom.Value.Value})");
|
||||
}
|
||||
|
||||
DrawIconPickerPopup();
|
||||
}
|
||||
|
||||
private void UpdateFace(CustomizeData data)
|
||||
private bool UpdateFace(CustomizeData data)
|
||||
{
|
||||
// Hrothgar Hack
|
||||
var value = _set.Race == Race.Hrothgar ? data.Value + 4 : data.Value;
|
||||
if (_customize.Face == value)
|
||||
return;
|
||||
return false;
|
||||
|
||||
_customize.Face = value;
|
||||
foreach (var actor in _actors)
|
||||
Glamourer.Penumbra.RedrawObject(actor.Character, RedrawType.Redraw);
|
||||
_customize.Face = value;
|
||||
Changed |= CustomizeFlag.Face;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void FaceInputInt(int currentIndex)
|
||||
|
|
@ -78,6 +77,7 @@ internal partial class CustomizationDrawer
|
|||
if (!popup)
|
||||
return;
|
||||
|
||||
var ret = false;
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
for (var i = 0; i < _currentCount; ++i)
|
||||
|
|
@ -107,4 +107,45 @@ internal partial class CustomizationDrawer
|
|||
ImGui.SameLine();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Only used for facial features, so fixed ID.
|
||||
private void DrawMultiIconSelector()
|
||||
{
|
||||
using var bigGroup = ImRaii.Group();
|
||||
DrawMultiIcons();
|
||||
ImGui.SameLine();
|
||||
using var group = ImRaii.Group();
|
||||
ImGui.Dummy(new Vector2(0, ImGui.GetTextLineHeightWithSpacing() + ImGui.GetStyle().ItemSpacing.Y / 2));
|
||||
|
||||
_currentCount = 256;
|
||||
PercentageInputInt();
|
||||
|
||||
ImGui.TextUnformatted(_set.Option(CustomizeIndex.LegacyTattoo));
|
||||
}
|
||||
|
||||
private void DrawMultiIcons()
|
||||
{
|
||||
var options = _set.Order[CharaMakeParams.MenuType.IconCheckmark];
|
||||
using var _ = ImRaii.Group();
|
||||
foreach (var (featureIdx, idx) in options.WithIndex())
|
||||
{
|
||||
using var id = SetId(featureIdx);
|
||||
var enabled = _customize.Get(featureIdx) != CustomizeValue.Zero;
|
||||
var feature = _set.Data(featureIdx, 0, _customize.Face);
|
||||
var icon = featureIdx == CustomizeIndex.LegacyTattoo
|
||||
? _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))
|
||||
{
|
||||
_customize.Set(featureIdx, enabled ? CustomizeValue.Zero : CustomizeValue.Max);
|
||||
Changed |= _currentFlag;
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverIconTooltip(icon, _iconSize);
|
||||
if (idx % 4 != 3)
|
||||
ImGui.SameLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,137 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Interop;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer.Gui.Customization;
|
||||
|
||||
internal partial class CustomizationDrawer
|
||||
{
|
||||
private static readonly Vector4 RedTint = new(0.6f, 0.3f, 0.3f, 1f);
|
||||
private static readonly ImGuiScene.TextureWrap? LegacyTattoo;
|
||||
|
||||
private readonly Vector2 _iconSize;
|
||||
private readonly Vector2 _framedIconSize;
|
||||
private readonly float _inputIntSize;
|
||||
private readonly float _comboSelectorSize;
|
||||
private readonly float _raceSelectorWidth;
|
||||
|
||||
private Customize _customize;
|
||||
private CharacterEquip _equip;
|
||||
private IReadOnlyCollection<Actor> _actors = Array.Empty<Actor>();
|
||||
private CustomizationSet _set = null!;
|
||||
|
||||
private CustomizationDrawer()
|
||||
{
|
||||
_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;
|
||||
}
|
||||
|
||||
static CustomizationDrawer()
|
||||
=> LegacyTattoo = GetLegacyTattooIcon();
|
||||
|
||||
public static void Dispose()
|
||||
=> LegacyTattoo?.Dispose();
|
||||
|
||||
private static ImGuiScene.TextureWrap? GetLegacyTattooIcon()
|
||||
{
|
||||
using var resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("Glamourer.LegacyTattoo.raw");
|
||||
if (resource == null)
|
||||
return null;
|
||||
|
||||
var rawImage = new byte[resource.Length];
|
||||
var length = resource.Read(rawImage, 0, (int)resource.Length);
|
||||
return length == resource.Length
|
||||
? Dalamud.PluginInterface.UiBuilder.LoadImageRaw(rawImage, 192, 192, 4)
|
||||
: null;
|
||||
}
|
||||
|
||||
public static void Draw(Customize customize, CharacterEquip equip, IReadOnlyCollection<Actor> actors, bool locked)
|
||||
{
|
||||
var d = new CustomizationDrawer()
|
||||
{
|
||||
_customize = customize,
|
||||
_equip = equip,
|
||||
_actors = actors,
|
||||
};
|
||||
|
||||
|
||||
if (!ImGui.CollapsingHeader("Character Customization"))
|
||||
return;
|
||||
|
||||
using var disabled = ImRaii.Disabled(locked);
|
||||
|
||||
d.DrawRaceGenderSelector();
|
||||
|
||||
d._set = Glamourer.Customization.GetList(customize.Clan, customize.Gender);
|
||||
|
||||
foreach (var id in d._set.Order[CharaMakeParams.MenuType.Percentage])
|
||||
d.PercentageSelector(id);
|
||||
|
||||
Functions.IteratePairwise(d._set.Order[CharaMakeParams.MenuType.IconSelector], d.DrawIconSelector, ImGui.SameLine);
|
||||
|
||||
d.DrawMultiIconSelector();
|
||||
|
||||
foreach (var id in d._set.Order[CharaMakeParams.MenuType.ListSelector])
|
||||
d.DrawListSelector(id);
|
||||
|
||||
Functions.IteratePairwise(d._set.Order[CharaMakeParams.MenuType.ColorPicker], d.DrawColorPicker, ImGui.SameLine);
|
||||
|
||||
Functions.IteratePairwise(d._set.Order[CharaMakeParams.MenuType.Checkmark], d.DrawCheckbox,
|
||||
() => ImGui.SameLine(d._inputIntSize + d._framedIconSize.X + 3 * ImGui.GetStyle().ItemSpacing.X));
|
||||
}
|
||||
|
||||
public static void Draw(Customize customize, IReadOnlyCollection<Actor> actors, bool locked = false)
|
||||
=> Draw(customize, CharacterEquip.Null, actors, locked);
|
||||
|
||||
public static void Draw(Customize customize, CharacterEquip equip, bool locked = false)
|
||||
=> Draw(customize, equip, Array.Empty<Actor>(), locked);
|
||||
|
||||
public static void Draw(Customize customize, bool locked = false)
|
||||
=> Draw(customize, CharacterEquip.Null, Array.Empty<Actor>(), locked);
|
||||
|
||||
// Set state for drawing of current customization.
|
||||
private CustomizeIndex _currentIndex;
|
||||
private CustomizeValue _currentByte = CustomizeValue.Zero;
|
||||
private int _currentCount;
|
||||
private string _currentOption = string.Empty;
|
||||
|
||||
// Prepare a new customization option.
|
||||
private ImRaii.Id SetId(CustomizeIndex index)
|
||||
{
|
||||
_currentIndex = index;
|
||||
_currentByte = _customize[index];
|
||||
_currentCount = _set.Count(index, _customize.Face);
|
||||
_currentOption = _set.Option(index);
|
||||
return ImRaii.PushId((int)index);
|
||||
}
|
||||
|
||||
// Update the current id with a value,
|
||||
// also update actors if any.
|
||||
private void UpdateValue(CustomizeValue value)
|
||||
{
|
||||
if (_customize[_currentIndex] == value)
|
||||
return;
|
||||
|
||||
_customize[_currentIndex] = value;
|
||||
UpdateActors();
|
||||
}
|
||||
|
||||
// Update all relevant Actors by calling the UpdateCustomize game function.
|
||||
private void UpdateActors()
|
||||
{
|
||||
foreach (var actor in _actors)
|
||||
Glamourer.RedrawManager.UpdateCustomize(actor, _customize);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
using System.Numerics;
|
||||
using Glamourer.Customization;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
|
||||
namespace Glamourer.Gui.Customization;
|
||||
|
||||
internal partial class CustomizationDrawer
|
||||
{
|
||||
// Only used for facial features, so fixed ID.
|
||||
private void DrawMultiIconSelector()
|
||||
{
|
||||
using var bigGroup = ImRaii.Group();
|
||||
DrawMultiIcons();
|
||||
ImGui.SameLine();
|
||||
using var group = ImRaii.Group();
|
||||
ImGui.Dummy(new Vector2(0, ImGui.GetTextLineHeightWithSpacing() + ImGui.GetStyle().ItemSpacing.Y / 2));
|
||||
|
||||
_currentCount = 256;
|
||||
PercentageInputInt();
|
||||
|
||||
ImGui.TextUnformatted(_set.Option(CustomizeIndex.LegacyTattoo));
|
||||
}
|
||||
|
||||
private void DrawMultiIcons()
|
||||
{
|
||||
var options = _set.Order[CharaMakeParams.MenuType.IconCheckmark];
|
||||
using var _ = ImRaii.Group();
|
||||
foreach (var (featureIdx, idx) in options.WithIndex())
|
||||
{
|
||||
using var id = SetId(featureIdx);
|
||||
var enabled = _customize.Get(featureIdx) != CustomizeValue.Zero;
|
||||
var feature = _set.Data(featureIdx, 0, _customize.Face);
|
||||
var icon = featureIdx == CustomizeIndex.LegacyTattoo
|
||||
? 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))
|
||||
{
|
||||
_customize.Set(featureIdx, enabled ? CustomizeValue.Zero : CustomizeValue.Max);
|
||||
UpdateActors();
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverIconTooltip(icon, _iconSize);
|
||||
if (idx % 4 != 3)
|
||||
ImGui.SameLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,44 +6,8 @@ using OtterGui.Raii;
|
|||
|
||||
namespace Glamourer.Gui.Customization;
|
||||
|
||||
internal partial class CustomizationDrawer
|
||||
public partial class CustomizationDrawer
|
||||
{
|
||||
private void DrawListSelector(CustomizeIndex index)
|
||||
{
|
||||
using var _ = SetId(index);
|
||||
using var bigGroup = ImRaii.Group();
|
||||
|
||||
ListCombo();
|
||||
ImGui.SameLine();
|
||||
ListInputInt();
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted(_currentOption);
|
||||
}
|
||||
|
||||
private void ListCombo()
|
||||
{
|
||||
ImGui.SetNextItemWidth(_comboSelectorSize * ImGui.GetIO().FontGlobalScale);
|
||||
using var combo = ImRaii.Combo("##combo", $"{_currentOption} #{_currentByte.Value + 1}");
|
||||
|
||||
if (!combo)
|
||||
return;
|
||||
|
||||
for (var i = 0; i < _currentCount; ++i)
|
||||
{
|
||||
if (ImGui.Selectable($"{_currentOption} #{i + 1}##combo", i == _currentByte.Value))
|
||||
UpdateValue((CustomizeValue)i);
|
||||
}
|
||||
}
|
||||
|
||||
private void ListInputInt()
|
||||
{
|
||||
var tmp = _currentByte.Value + 1;
|
||||
ImGui.SetNextItemWidth(_inputIntSize);
|
||||
if (ImGui.InputInt("##text", ref tmp, 1, 1) && tmp > 0 && tmp <= _currentCount)
|
||||
UpdateValue((CustomizeValue)Math.Clamp(tmp - 1, 0, _currentCount - 1));
|
||||
ImGuiUtil.HoverTooltip($"Input Range: [1, {_currentCount}]");
|
||||
}
|
||||
|
||||
private void PercentageSelector(CustomizeIndex index)
|
||||
{
|
||||
using var _ = SetId(index);
|
||||
|
|
@ -73,26 +37,6 @@ internal partial class CustomizationDrawer
|
|||
ImGuiUtil.HoverTooltip($"Input Range: [0, {_currentCount - 1}]");
|
||||
}
|
||||
|
||||
|
||||
// Draw one of the four checkboxes for single bool customization options.
|
||||
private void Checkbox(string label, bool current, Action<bool> setter)
|
||||
{
|
||||
var tmp = current;
|
||||
if (ImGui.Checkbox(label, ref tmp) && tmp != current)
|
||||
{
|
||||
setter(tmp);
|
||||
UpdateActors();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a customize checkbox.
|
||||
private void DrawCheckbox(CustomizeIndex idx)
|
||||
{
|
||||
using var id = SetId(idx);
|
||||
Checkbox(_set.Option(idx), _customize.Get(idx) != CustomizeValue.Zero,
|
||||
b => _customize.Set(idx, b ? CustomizeValue.Max : CustomizeValue.Zero));
|
||||
}
|
||||
|
||||
// Integral input for an icon- or color based item.
|
||||
private void DataInputInt(int currentIndex)
|
||||
{
|
||||
|
|
@ -107,4 +51,52 @@ internal partial class CustomizationDrawer
|
|||
|
||||
ImGuiUtil.HoverTooltip($"Input Range: [1, {_currentCount}]");
|
||||
}
|
||||
|
||||
private void DrawListSelector(CustomizeIndex index)
|
||||
{
|
||||
using var _ = SetId(index);
|
||||
using var bigGroup = ImRaii.Group();
|
||||
|
||||
ListCombo();
|
||||
ImGui.SameLine();
|
||||
ListInputInt();
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted(_currentOption);
|
||||
}
|
||||
|
||||
private void ListCombo()
|
||||
{
|
||||
ImGui.SetNextItemWidth(_comboSelectorSize * ImGui.GetIO().FontGlobalScale);
|
||||
using var combo = ImRaii.Combo("##combo", $"{_currentOption} #{_currentByte.Value + 1}");
|
||||
|
||||
if (!combo)
|
||||
return;
|
||||
|
||||
for (var i = 0; i < _currentCount; ++i)
|
||||
{
|
||||
if (ImGui.Selectable($"{_currentOption} #{i + 1}##combo", i == _currentByte.Value))
|
||||
UpdateValue((CustomizeValue)i);
|
||||
}
|
||||
}
|
||||
|
||||
private void ListInputInt()
|
||||
{
|
||||
var tmp = _currentByte.Value + 1;
|
||||
ImGui.SetNextItemWidth(_inputIntSize);
|
||||
if (ImGui.InputInt("##text", ref tmp, 1, 1) && tmp > 0 && tmp <= _currentCount)
|
||||
UpdateValue((CustomizeValue)Math.Clamp(tmp - 1, 0, _currentCount - 1));
|
||||
ImGuiUtil.HoverTooltip($"Input Range: [1, {_currentCount}]");
|
||||
}
|
||||
|
||||
// Draw a customize checkbox.
|
||||
private void DrawCheckbox(CustomizeIndex idx)
|
||||
{
|
||||
using var id = SetId(idx);
|
||||
var tmp = _currentByte != CustomizeValue.Zero;
|
||||
if (ImGui.Checkbox(_currentOption, ref tmp))
|
||||
{
|
||||
_customize.Set(idx, tmp ? CustomizeValue.Max : CustomizeValue.Zero);
|
||||
Changed |= _currentFlag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
172
Glamourer/Gui/Customization/CustomizationDrawer.cs
Normal file
172
Glamourer/Gui/Customization/CustomizationDrawer.cs
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Dalamud.Plugin;
|
||||
using Glamourer.Customization;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using CustomizeData = Penumbra.GameData.Structs.CustomizeData;
|
||||
|
||||
namespace Glamourer.Gui.Customization;
|
||||
|
||||
public partial class CustomizationDrawer : IDisposable
|
||||
{
|
||||
private readonly Vector4 _redTint = new(0.6f, 0.3f, 0.3f, 1f);
|
||||
private readonly ImGuiScene.TextureWrap? _legacyTattoo;
|
||||
|
||||
private bool _withFlags = false;
|
||||
private Exception? _terminate = null;
|
||||
|
||||
private readonly unsafe CustomizeData* _data;
|
||||
|
||||
private Customize _customize;
|
||||
private CustomizationSet _set = null!;
|
||||
|
||||
public unsafe CustomizeData CustomizeData
|
||||
=> *_data;
|
||||
|
||||
public CustomizeFlag CurrentFlag { get; private set; }
|
||||
public CustomizeFlag Changed { get; private set; }
|
||||
|
||||
public bool RequiresRedraw
|
||||
=> Changed.RequiresRedraw();
|
||||
|
||||
private bool _locked = false;
|
||||
private Vector2 _iconSize;
|
||||
private Vector2 _framedIconSize;
|
||||
private float _inputIntSize;
|
||||
private float _comboSelectorSize;
|
||||
private float _raceSelectorWidth;
|
||||
|
||||
public CustomizationDrawer(DalamudPluginInterface pi)
|
||||
{
|
||||
_legacyTattoo = GetLegacyTattooIcon(pi);
|
||||
unsafe
|
||||
{
|
||||
_data = (CustomizeData*)Marshal.AllocHGlobal(sizeof(CustomizeData));
|
||||
*_data = Customize.Default;
|
||||
_customize = new Customize(_data);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_legacyTattoo?.Dispose();
|
||||
unsafe
|
||||
{
|
||||
Marshal.FreeHGlobal((nint)_data);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Draw(Customize current, bool locked)
|
||||
{
|
||||
_withFlags = false;
|
||||
CurrentFlag = CustomizeFlagExtensions.All;
|
||||
Init(current, locked);
|
||||
return DrawInternal();
|
||||
}
|
||||
|
||||
public bool Draw(Customize current, CustomizeFlag currentFlags, bool locked)
|
||||
{
|
||||
_withFlags = true;
|
||||
CurrentFlag = currentFlags;
|
||||
Init(current, locked);
|
||||
return DrawInternal();
|
||||
}
|
||||
|
||||
private void Init(Customize current, bool locked)
|
||||
{
|
||||
UpdateSizes();
|
||||
_terminate = null;
|
||||
Changed = 0;
|
||||
_customize.Load(current);
|
||||
_locked = locked;
|
||||
}
|
||||
|
||||
// Set state for drawing of current customization.
|
||||
private CustomizeIndex _currentIndex;
|
||||
private CustomizeFlag _currentFlag;
|
||||
private CustomizeValue _currentByte = CustomizeValue.Zero;
|
||||
private int _currentCount;
|
||||
private string _currentOption = string.Empty;
|
||||
|
||||
// Prepare a new customization option.
|
||||
private ImRaii.Id SetId(CustomizeIndex index)
|
||||
{
|
||||
_currentIndex = index;
|
||||
_currentFlag = index.ToFlag();
|
||||
_currentByte = _customize[index];
|
||||
_currentCount = _set.Count(index, _customize.Face);
|
||||
_currentOption = _set.Option(index);
|
||||
return ImRaii.PushId((int)index);
|
||||
}
|
||||
|
||||
// Update the current id with a new value.
|
||||
private void UpdateValue(CustomizeValue value)
|
||||
{
|
||||
if (_currentByte == value)
|
||||
return;
|
||||
|
||||
_customize[_currentIndex] = value;
|
||||
Changed |= _currentFlag;
|
||||
}
|
||||
|
||||
private bool DrawInternal()
|
||||
{
|
||||
using var disabled = ImRaii.Disabled(_locked);
|
||||
|
||||
try
|
||||
{
|
||||
DrawRaceGenderSelector();
|
||||
_set = Glamourer.Customization.GetList(_customize.Clan, _customize.Gender);
|
||||
|
||||
foreach (var id in _set.Order[CharaMakeParams.MenuType.Percentage])
|
||||
PercentageSelector(id);
|
||||
|
||||
Functions.IteratePairwise(_set.Order[CharaMakeParams.MenuType.IconSelector], DrawIconSelector, ImGui.SameLine);
|
||||
|
||||
DrawMultiIconSelector();
|
||||
|
||||
foreach (var id in _set.Order[CharaMakeParams.MenuType.ListSelector])
|
||||
DrawListSelector(id);
|
||||
|
||||
Functions.IteratePairwise(_set.Order[CharaMakeParams.MenuType.ColorPicker], DrawColorPicker, ImGui.SameLine);
|
||||
|
||||
Functions.IteratePairwise(_set.Order[CharaMakeParams.MenuType.Checkmark], DrawCheckbox,
|
||||
() => ImGui.SameLine(_inputIntSize + _framedIconSize.X + 3 * ImGui.GetStyle().ItemSpacing.X));
|
||||
return Changed != 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_terminate = ex;
|
||||
using var color = ImRaii.PushColor(ImGuiCol.Text, 0xFF4040FF);
|
||||
ImGui.NewLine();
|
||||
ImGuiUtil.TextWrapped(_terminate.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSizes()
|
||||
{
|
||||
_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;
|
||||
}
|
||||
|
||||
private static ImGuiScene.TextureWrap? GetLegacyTattooIcon(DalamudPluginInterface pi)
|
||||
{
|
||||
using var resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("Glamourer.LegacyTattoo.raw");
|
||||
if (resource == null)
|
||||
return null;
|
||||
|
||||
var rawImage = new byte[resource.Length];
|
||||
var length = resource.Read(rawImage, 0, (int)resource.Length);
|
||||
return length == resource.Length
|
||||
? pi.UiBuilder.LoadImageRaw(rawImage, 192, 192, 4)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Utility;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Util;
|
||||
using ImGuiNET;
|
||||
|
|
@ -13,26 +15,55 @@ using Penumbra.GameData.Structs;
|
|||
|
||||
namespace Glamourer.Gui.Equipment;
|
||||
|
||||
public partial class EquipmentDrawer
|
||||
public class EquipmentDrawer
|
||||
{
|
||||
private readonly FilterComboColors _stainCombo;
|
||||
private readonly StainData _stainData;
|
||||
private readonly ItemCombo[] _itemCombo;
|
||||
private readonly ItemManager _items;
|
||||
private readonly FilterComboColors _stainCombo;
|
||||
private readonly StainData _stainData;
|
||||
private readonly ItemCombo[] _itemCombo;
|
||||
private readonly Dictionary<(FullEquipType, EquipSlot), WeaponCombo> _weaponCombo;
|
||||
|
||||
public EquipmentDrawer(ItemManager items)
|
||||
{
|
||||
_items = items;
|
||||
_stainData = items.Stains;
|
||||
_stainCombo = new FilterComboColors(140,
|
||||
_stainData.Data.Prepend(new KeyValuePair<byte, (string Name, uint Dye, bool Gloss)>(0, ("None", 0, false))));
|
||||
_itemCombo = EquipSlotExtensions.EqdpSlots.Select(e => new ItemCombo(items, e)).ToArray();
|
||||
_itemCombo = EquipSlotExtensions.EqdpSlots.Select(e => new ItemCombo(items, e)).ToArray();
|
||||
_weaponCombo = new Dictionary<(FullEquipType, EquipSlot), WeaponCombo>(FullEquipTypeExtensions.WeaponTypes.Count * 2);
|
||||
foreach (var type in Enum.GetValues<FullEquipType>())
|
||||
{
|
||||
if (type.ToSlot() is EquipSlot.MainHand)
|
||||
_weaponCombo.TryAdd((type, EquipSlot.MainHand), new WeaponCombo(items, type, EquipSlot.MainHand));
|
||||
else if (type.ToSlot() is EquipSlot.OffHand)
|
||||
_weaponCombo.TryAdd((type, EquipSlot.OffHand), new WeaponCombo(items, type, EquipSlot.OffHand));
|
||||
|
||||
var offhand = type.Offhand();
|
||||
if (offhand is not FullEquipType.Unknown && !_weaponCombo.ContainsKey((offhand, EquipSlot.OffHand)))
|
||||
_weaponCombo.TryAdd((offhand, EquipSlot.OffHand), new WeaponCombo(items, type, EquipSlot.OffHand));
|
||||
}
|
||||
|
||||
_weaponCombo.Add((FullEquipType.Unknown, EquipSlot.MainHand), new WeaponCombo(items, FullEquipType.Unknown, EquipSlot.MainHand));
|
||||
}
|
||||
|
||||
public bool DrawArmor(DesignBase design, EquipSlot slot, out Item armor)
|
||||
private string VerifyRestrictedGear(Item gear, EquipSlot slot, Gender gender, Race race)
|
||||
{
|
||||
Debug.Assert(slot.IsEquipment() || slot.IsAccessory());
|
||||
if (slot.IsAccessory())
|
||||
return gear.Name;
|
||||
|
||||
var (changed, _) = _items.RestrictedGear.ResolveRestricted(gear.Model, slot, race, gender);
|
||||
if (changed)
|
||||
return gear.Name + " (Restricted)";
|
||||
|
||||
return gear.Name;
|
||||
}
|
||||
|
||||
public bool DrawArmor(Item current, EquipSlot slot, out Item armor, Gender gender = Gender.Unknown, Race race = Race.Unknown)
|
||||
{
|
||||
Debug.Assert(slot.IsEquipment() || slot.IsAccessory(), $"Called {nameof(DrawArmor)} on {slot}.");
|
||||
var combo = _itemCombo[slot.ToIndex()];
|
||||
armor = design.Armor(slot);
|
||||
var change = combo.Draw(armor.Name, armor.ItemId, 320 * ImGuiHelpers.GlobalScale);
|
||||
armor = current;
|
||||
var change = combo.Draw(VerifyRestrictedGear(armor, slot, gender, race), armor.ItemId, 320 * ImGuiHelpers.GlobalScale);
|
||||
if (armor.ModelBase.Value != 0)
|
||||
{
|
||||
ImGuiUtil.HoverTooltip("Right-click to clear.");
|
||||
|
|
@ -41,6 +72,10 @@ public partial class EquipmentDrawer
|
|||
change = true;
|
||||
armor = ItemManager.NothingItem(slot);
|
||||
}
|
||||
else if (change)
|
||||
{
|
||||
armor = combo.CurrentSelection.WithStain(armor.Stain);
|
||||
}
|
||||
}
|
||||
else if (change)
|
||||
{
|
||||
|
|
@ -50,14 +85,77 @@ public partial class EquipmentDrawer
|
|||
return change;
|
||||
}
|
||||
|
||||
public bool DrawStain(DesignBase design, EquipSlot slot, out Stain stain)
|
||||
public bool DrawStain(StainId current, EquipSlot slot, out Stain stain)
|
||||
{
|
||||
Debug.Assert(slot.IsEquipment() || slot.IsAccessory());
|
||||
var armor = design.Armor(slot);
|
||||
var found = _stainData.TryGetValue(armor.Stain, out stain);
|
||||
if (!_stainCombo.Draw($"##stain{slot}", stain.RgbaColor, found))
|
||||
var found = _stainData.TryGetValue(current, out stain);
|
||||
if (!_stainCombo.Draw($"##stain{slot}", stain.RgbaColor, stain.Name, found))
|
||||
return false;
|
||||
|
||||
return _stainData.TryGetValue(_stainCombo.CurrentSelection.Key, out stain);
|
||||
}
|
||||
|
||||
public bool DrawMainhand(Weapon current, bool drawAll, out Weapon weapon)
|
||||
{
|
||||
weapon = current;
|
||||
if (!_weaponCombo.TryGetValue((drawAll ? FullEquipType.Unknown : current.Type, EquipSlot.MainHand), out var combo))
|
||||
return false;
|
||||
|
||||
if (!combo.Draw(weapon.Name, weapon.ItemId, 320 * ImGuiHelpers.GlobalScale))
|
||||
return false;
|
||||
|
||||
weapon = combo.CurrentSelection.WithStain(current.Stain);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DrawOffhand(Weapon current, FullEquipType mainType, out Weapon weapon)
|
||||
{
|
||||
weapon = current;
|
||||
var offType = mainType.Offhand();
|
||||
if (offType == FullEquipType.Unknown)
|
||||
return false;
|
||||
|
||||
if (!_weaponCombo.TryGetValue((offType, EquipSlot.OffHand), out var combo))
|
||||
return false;
|
||||
|
||||
var change = combo.Draw(weapon.Name, weapon.ItemId, 320 * ImGuiHelpers.GlobalScale);
|
||||
if (offType.ToSlot() is EquipSlot.OffHand && weapon.ModelBase.Value != 0)
|
||||
{
|
||||
ImGuiUtil.HoverTooltip("Right-click to clear.");
|
||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||
{
|
||||
change = true;
|
||||
weapon = ItemManager.NothingItem(offType);
|
||||
}
|
||||
}
|
||||
else if (change)
|
||||
{
|
||||
weapon = combo.CurrentSelection.WithStain(current.Stain);
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
public bool DrawApply(Design design, EquipSlot slot, out bool enabled)
|
||||
{
|
||||
enabled = design.DoApplyEquip(slot);
|
||||
var tmp = enabled;
|
||||
if (!ImGuiUtil.Checkbox($"##apply{slot}", string.Empty, enabled, v => tmp = v))
|
||||
return false;
|
||||
|
||||
var change = enabled != tmp;
|
||||
enabled = tmp;
|
||||
return change;
|
||||
}
|
||||
|
||||
public bool DrawApplyStain(Design design, EquipSlot slot, out bool enabled)
|
||||
{
|
||||
enabled = design.DoApplyStain(slot);
|
||||
var tmp = enabled;
|
||||
if (!ImGuiUtil.Checkbox($"##applyStain{slot}", string.Empty, enabled, v => tmp = v))
|
||||
return false;
|
||||
|
||||
var change = enabled != tmp;
|
||||
enabled = tmp;
|
||||
return change;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Dalamud.Interface;
|
||||
using Glamourer.Structs;
|
||||
using Glamourer.Util;
|
||||
using ImGuiNET;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
|
|
@ -12,52 +8,53 @@ using OtterGui.Classes;
|
|||
using OtterGui.Raii;
|
||||
using OtterGui.Widgets;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Item = Glamourer.Designs.Item;
|
||||
|
||||
namespace Glamourer.Gui.Equipment;
|
||||
|
||||
public sealed class ItemCombo : FilterComboCache<Item>
|
||||
{
|
||||
public readonly string Label;
|
||||
public readonly EquipSlot Slot;
|
||||
|
||||
private uint _lastItemId;
|
||||
private uint _previewId;
|
||||
public readonly string Label;
|
||||
private uint _currentItem;
|
||||
|
||||
public ItemCombo(ItemManager items, EquipSlot slot)
|
||||
: base(GetItems(items, slot))
|
||||
: base(() => GetItems(items, slot))
|
||||
{
|
||||
Label = GetLabel(slot);
|
||||
Slot = slot;
|
||||
_lastItemId = ItemManager.NothingId(slot);
|
||||
_previewId = _lastItemId;
|
||||
_currentItem = ItemManager.NothingId(slot);
|
||||
}
|
||||
|
||||
protected override void DrawList(float width, float itemHeight)
|
||||
{
|
||||
if (_previewId != _lastItemId)
|
||||
{
|
||||
_lastItemId = _previewId;
|
||||
CurrentSelectionIdx = Items.IndexOf(i => i.ItemId == _lastItemId);
|
||||
CurrentSelection = Items[CurrentSelectionIdx];
|
||||
}
|
||||
base.DrawList(width, itemHeight);
|
||||
if (NewSelection != null && Items.Count > NewSelection.Value)
|
||||
CurrentSelection = Items[NewSelection.Value];
|
||||
}
|
||||
|
||||
protected override int UpdateCurrentSelected(int currentSelected)
|
||||
{
|
||||
if (CurrentSelection.ItemId != _currentItem)
|
||||
{
|
||||
CurrentSelectionIdx = Items.IndexOf(i => i.ItemId == _currentItem);
|
||||
CurrentSelection = CurrentSelectionIdx >= 0 ? Items[CurrentSelectionIdx] : default;
|
||||
return base.UpdateCurrentSelected(CurrentSelectionIdx);
|
||||
}
|
||||
|
||||
return currentSelected;
|
||||
}
|
||||
|
||||
public bool Draw(string previewName, uint previewIdx, float width)
|
||||
{
|
||||
_previewId = previewIdx;
|
||||
return Draw(Label, previewName, width, ImGui.GetTextLineHeightWithSpacing());
|
||||
_currentItem = previewIdx;
|
||||
return Draw(Label, previewName, string.Empty, width, ImGui.GetTextLineHeightWithSpacing());
|
||||
}
|
||||
|
||||
protected override bool DrawSelectable(int globalIdx, bool selected)
|
||||
{
|
||||
var obj = Items[globalIdx];
|
||||
var name = ToString(obj);
|
||||
var ret = ImGui.Selectable(name, selected);
|
||||
var obj = Items[globalIdx];
|
||||
var name = ToString(obj);
|
||||
var ret = ImGui.Selectable(name, selected);
|
||||
ImGui.SameLine();
|
||||
using var color = ImRaii.PushColor(ImGuiCol.Text, 0xFF808080);
|
||||
ImGuiUtil.RightAlign($"({obj.ModelBase.Value}-{obj.Variant})");
|
||||
return ret;
|
||||
|
|
@ -89,12 +86,18 @@ public sealed class ItemCombo : FilterComboCache<Item>
|
|||
};
|
||||
}
|
||||
|
||||
private static IEnumerable<Item> GetItems(ItemManager items, EquipSlot slot)
|
||||
private static IReadOnlyList<Item> GetItems(ItemManager items, EquipSlot slot)
|
||||
{
|
||||
var nothing = ItemManager.NothingItem(slot);
|
||||
if (!items.Items.TryGetValue(slot.ToEquipType(), out var list))
|
||||
return new[] { nothing };
|
||||
return new[]
|
||||
{
|
||||
nothing,
|
||||
};
|
||||
|
||||
return list.Select(i => new Item(i)).Append(ItemManager.SmallClothesItem(slot)).OrderBy(i => i.Name).Prepend(nothing);
|
||||
var enumerable = list.Select(i => new Item(i));
|
||||
if (slot.IsEquipment())
|
||||
enumerable = enumerable.Append(ItemManager.SmallClothesItem(slot));
|
||||
return enumerable.OrderBy(i => i.Name).Prepend(nothing).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
107
Glamourer/Gui/Equipment/WeaponCombo.cs
Normal file
107
Glamourer/Gui/Equipment/WeaponCombo.cs
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Util;
|
||||
using ImGuiNET;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using OtterGui;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui.Raii;
|
||||
using OtterGui.Widgets;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
||||
namespace Glamourer.Gui.Equipment;
|
||||
|
||||
public sealed class WeaponCombo : FilterComboCache<Weapon>
|
||||
{
|
||||
public readonly string Label;
|
||||
private uint _currentItem;
|
||||
|
||||
public WeaponCombo(ItemManager items, FullEquipType type, EquipSlot offhand)
|
||||
: base(offhand is EquipSlot.OffHand ? () => GetOff(items, type) : () => GetMain(items, type))
|
||||
=> Label = GetLabel(offhand);
|
||||
|
||||
protected override void DrawList(float width, float itemHeight)
|
||||
{
|
||||
base.DrawList(width, itemHeight);
|
||||
if (NewSelection != null && Items.Count > NewSelection.Value)
|
||||
CurrentSelection = Items[NewSelection.Value];
|
||||
}
|
||||
|
||||
protected override int UpdateCurrentSelected(int currentSelected)
|
||||
{
|
||||
if (CurrentSelection.ItemId != _currentItem)
|
||||
{
|
||||
CurrentSelectionIdx = Items.IndexOf(i => i.ItemId == _currentItem);
|
||||
CurrentSelection = CurrentSelectionIdx >= 0 ? Items[CurrentSelectionIdx] : default;
|
||||
return base.UpdateCurrentSelected(CurrentSelectionIdx);
|
||||
}
|
||||
|
||||
return currentSelected;
|
||||
}
|
||||
|
||||
public bool Draw(string previewName, uint previewIdx, float width)
|
||||
{
|
||||
_currentItem = previewIdx;
|
||||
return Draw(Label, previewName, string.Empty, width, ImGui.GetTextLineHeightWithSpacing());
|
||||
}
|
||||
|
||||
protected override bool DrawSelectable(int globalIdx, bool selected)
|
||||
{
|
||||
var obj = Items[globalIdx];
|
||||
var name = ToString(obj);
|
||||
var ret = ImGui.Selectable(name, selected);
|
||||
ImGui.SameLine();
|
||||
using var color = ImRaii.PushColor(ImGuiCol.Text, 0xFF808080);
|
||||
ImGuiUtil.RightAlign($"({obj.ModelBase.Value}-{obj.WeaponBase.Value}-{obj.Variant})");
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected override bool IsVisible(int globalIndex, LowerString filter)
|
||||
=> base.IsVisible(globalIndex, filter) || filter.IsContained(Items[globalIndex].ModelBase.ToString());
|
||||
|
||||
protected override string ToString(Weapon obj)
|
||||
=> obj.Name;
|
||||
|
||||
private static string GetLabel(EquipSlot offhand)
|
||||
{
|
||||
var sheet = Dalamud.GameData.GetExcelSheet<Addon>()!;
|
||||
return offhand is EquipSlot.OffHand
|
||||
? sheet.GetRow(739)?.Text.ToString() ?? "Off Hand"
|
||||
: sheet.GetRow(738)?.Text.ToString() ?? "Main Hand";
|
||||
}
|
||||
|
||||
private static IReadOnlyList<Weapon> GetMain(ItemManager items, FullEquipType type)
|
||||
{
|
||||
var list = new List<Weapon>();
|
||||
if (type is FullEquipType.Unknown)
|
||||
foreach (var t in Enum.GetValues<FullEquipType>().Where(t => t.ToSlot() == EquipSlot.MainHand))
|
||||
list.AddRange(items.Items[t].Select(w => new Weapon(w, false)));
|
||||
else if (type.ToSlot() is EquipSlot.MainHand)
|
||||
list.AddRange(items.Items[type].Select(w => new Weapon(w, false)));
|
||||
list.Sort((w1, w2) => string.CompareOrdinal(w1.Name, w2.Name));
|
||||
return list;
|
||||
}
|
||||
|
||||
private static IReadOnlyList<Weapon> GetOff(ItemManager items, FullEquipType type)
|
||||
{
|
||||
if (type.ToSlot() == EquipSlot.OffHand)
|
||||
{
|
||||
var nothing = ItemManager.NothingItem(type);
|
||||
if (!items.Items.TryGetValue(type, out var list))
|
||||
return new[]
|
||||
{
|
||||
nothing,
|
||||
};
|
||||
|
||||
return list.Select(w => new Weapon(w, true)).OrderBy(w => w.Name).Prepend(nothing).ToList();
|
||||
}
|
||||
else if (items.Items.TryGetValue(type, out var list))
|
||||
{
|
||||
return list.Select(w => new Weapon(w, true)).OrderBy(w => w.Name).ToList();
|
||||
}
|
||||
|
||||
return Array.Empty<Weapon>();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Dalamud.Interface;
|
||||
using Glamourer.Gui.Customization;
|
||||
using Glamourer.Gui.Equipment;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.State;
|
||||
using ImGuiNET;
|
||||
|
|
@ -20,18 +19,20 @@ internal partial class Interface
|
|||
private class ActorTab
|
||||
{
|
||||
private readonly Interface _main;
|
||||
private readonly CurrentManipulations _manipulations;
|
||||
private readonly ActiveDesign.Manager _activeDesigns;
|
||||
private readonly ObjectManager _objects;
|
||||
|
||||
public ActorTab(Interface main, CurrentManipulations manipulations)
|
||||
public ActorTab(Interface main, ActiveDesign.Manager activeDesigns, ObjectManager objects)
|
||||
{
|
||||
_main = main;
|
||||
_manipulations = manipulations;
|
||||
_activeDesigns = activeDesigns;
|
||||
_objects = objects;
|
||||
}
|
||||
|
||||
private ActorIdentifier _identifier = ActorIdentifier.Invalid;
|
||||
private ObjectManager.ActorData _currentData = ObjectManager.ActorData.Invalid;
|
||||
private string _currentLabel = string.Empty;
|
||||
private ActiveDesign? _currentSave;
|
||||
private ActiveDesign? _currentSave;
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
|
|
@ -40,7 +41,7 @@ internal partial class Interface
|
|||
return;
|
||||
|
||||
DrawActorSelector();
|
||||
if (!ObjectManager.Actors.TryGetValue(_identifier, out _currentData))
|
||||
if (!_objects.TryGetValue(_identifier, out _currentData))
|
||||
_currentData = ObjectManager.ActorData.Invalid;
|
||||
else
|
||||
_currentLabel = _currentData.Label;
|
||||
|
|
@ -66,14 +67,31 @@ internal partial class Interface
|
|||
_currentSave.Update(_currentData.Objects[0]);
|
||||
|
||||
RevertButton();
|
||||
CustomizationDrawer.Draw(_currentSave.Customize(), _currentSave.Equipment(), _currentData.Objects,
|
||||
_identifier.Type == IdentifierType.Special);
|
||||
if (_main._customizationDrawer.Draw(_currentSave.Customize(), _identifier.Type == IdentifierType.Special))
|
||||
_activeDesigns.ChangeCustomize(_currentSave, _main._customizationDrawer.Changed, _main._customizationDrawer.CustomizeData, false);
|
||||
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
{
|
||||
_main._equipmentDrawer.DrawStain(_currentSave, slot, out var stain);
|
||||
var current = _currentSave.Armor(slot);
|
||||
if (_main._equipmentDrawer.DrawStain(current.Stain, slot, out var stain))
|
||||
_activeDesigns.ChangeStain(_currentSave, slot, stain.RowIndex, false);
|
||||
ImGui.SameLine();
|
||||
_main._equipmentDrawer.DrawArmor(_currentSave, slot, out var armor);
|
||||
if (_main._equipmentDrawer.DrawArmor(current, slot, out var armor, _currentSave.Customize().Gender, _currentSave.Customize().Race))
|
||||
_activeDesigns.ChangeEquipment(_currentSave, slot, armor, false);
|
||||
}
|
||||
|
||||
var currentMain = _currentSave.WeaponMain;
|
||||
if (_main._equipmentDrawer.DrawStain(currentMain.Stain, EquipSlot.MainHand, out var stainMain))
|
||||
_activeDesigns.ChangeStain(_currentSave, EquipSlot.MainHand, stainMain.RowIndex, false);
|
||||
ImGui.SameLine();
|
||||
_main._equipmentDrawer.DrawMainhand(currentMain, true, out var main);
|
||||
if (currentMain.Type.Offhand() != FullEquipType.Unknown)
|
||||
{
|
||||
var currentOff = _currentSave.WeaponOff;
|
||||
if (_main._equipmentDrawer.DrawStain(currentOff.Stain, EquipSlot.OffHand, out var stainOff))
|
||||
_activeDesigns.ChangeStain(_currentSave, EquipSlot.OffHand, stainOff.RowIndex, false);
|
||||
ImGui.SameLine();
|
||||
_main._equipmentDrawer.DrawOffhand(currentOff, main.Type, out var off);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -83,18 +101,14 @@ internal partial class Interface
|
|||
private unsafe void RevertButton()
|
||||
{
|
||||
if (ImGui.Button("Revert"))
|
||||
{
|
||||
_manipulations.DeleteSave(_identifier);
|
||||
|
||||
//foreach (var actor in _currentData.Objects)
|
||||
// _currentSave!.ApplyToActor(actor);
|
||||
//
|
||||
//if (_currentData.Objects.Count > 0)
|
||||
// _currentSave = _manipulations.GetOrCreateSave(_currentData.Objects[0]);
|
||||
//
|
||||
//_currentSave!.Reset();
|
||||
}
|
||||
|
||||
_activeDesigns.RevertDesign(_currentSave!);
|
||||
//foreach (var actor in _currentData.Objects)
|
||||
// _currentSave!.ApplyToActor(actor);
|
||||
//
|
||||
//if (_currentData.Objects.Count > 0)
|
||||
// _currentSave = _manipulations.GetOrCreateSave(_currentData.Objects[0]);
|
||||
//
|
||||
//_currentSave!.Reset();
|
||||
if (_currentData.Objects.Count > 0)
|
||||
ImGui.TextUnformatted(_currentData.Objects[0].Pointer->GameObject.DataID.ToString());
|
||||
//VisorBox();
|
||||
|
|
@ -215,24 +229,24 @@ internal partial class Interface
|
|||
if (!child)
|
||||
return;
|
||||
|
||||
ObjectManager.Update();
|
||||
_objects.Update();
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, oldSpacing);
|
||||
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeight());
|
||||
var remainder = ImGuiClip.FilteredClippedDraw(ObjectManager.List, skips, CheckFilter, DrawSelectable);
|
||||
var remainder = ImGuiClip.FilteredClippedDraw(_objects, skips, CheckFilter, DrawSelectable);
|
||||
ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeight());
|
||||
}
|
||||
|
||||
private bool CheckFilter((ActorIdentifier, ObjectManager.ActorData) pair)
|
||||
=> _actorFilter.IsEmpty || pair.Item2.Label.Contains(_actorFilter.Lower, StringComparison.OrdinalIgnoreCase);
|
||||
private bool CheckFilter(KeyValuePair<ActorIdentifier, ObjectManager.ActorData> pair)
|
||||
=> _actorFilter.IsEmpty || pair.Value.Label.Contains(_actorFilter.Lower, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
private void DrawSelectable((ActorIdentifier, ObjectManager.ActorData) pair)
|
||||
private void DrawSelectable(KeyValuePair<ActorIdentifier, ObjectManager.ActorData> pair)
|
||||
{
|
||||
var equal = pair.Item1.Equals(_identifier);
|
||||
if (ImGui.Selectable(pair.Item2.Label, equal) && !equal)
|
||||
var equal = pair.Key.Equals(_identifier);
|
||||
if (ImGui.Selectable(pair.Value.Label, equal) && !equal)
|
||||
{
|
||||
_identifier = pair.Item1.CreatePermanent();
|
||||
_currentData = pair.Item2;
|
||||
_currentSave = _currentData.Valid ? _manipulations.GetOrCreateSave(_currentData.Objects[0]) : null;
|
||||
_identifier = pair.Key.CreatePermanent();
|
||||
_currentData = pair.Value;
|
||||
_currentSave = _currentData.Valid ? _activeDesigns.GetOrCreateSave(_currentData.Objects[0]) : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -243,325 +257,14 @@ internal partial class Interface
|
|||
var buttonWidth = new Vector2(_actorSelectorWidth / 2, 0);
|
||||
|
||||
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.UserCircle.ToIconString(), buttonWidth
|
||||
, "Select the local player character.", !ObjectManager.Player, true))
|
||||
_identifier = ObjectManager.Player.GetIdentifier();
|
||||
, "Select the local player character.", !_objects.Player, true))
|
||||
_identifier = _objects.Player.GetIdentifier();
|
||||
|
||||
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.", ObjectManager.IsInGPose || !targetActor, true))
|
||||
"Select the current target, if it is in the list.", _objects.IsInGPose || !targetActor, true))
|
||||
_identifier = targetActor.GetIdentifier();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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();
|
||||
// }
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
using Glamourer.Gui.Customization;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.State;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
|
|
@ -17,15 +15,15 @@ internal partial class Interface
|
|||
{
|
||||
private class DebugStateTab
|
||||
{
|
||||
private readonly CurrentManipulations _currentManipulations;
|
||||
private readonly ActiveDesign.Manager _activeDesigns;
|
||||
|
||||
private LowerString _manipulationFilter = LowerString.Empty;
|
||||
private ActorIdentifier _selection = ActorIdentifier.Invalid;
|
||||
private ActiveDesign? _save = null;
|
||||
private bool _delete = false;
|
||||
|
||||
public DebugStateTab(CurrentManipulations currentManipulations)
|
||||
=> _currentManipulations = currentManipulations;
|
||||
public DebugStateTab(ActiveDesign.Manager activeDesigns)
|
||||
=> _activeDesigns = activeDesigns;
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public void Draw()
|
||||
|
|
@ -43,7 +41,7 @@ internal partial class Interface
|
|||
if (_delete)
|
||||
{
|
||||
_delete = false;
|
||||
_currentManipulations.DeleteSave(_selection);
|
||||
_activeDesigns.DeleteSave(_selection);
|
||||
_selection = ActorIdentifier.Invalid;
|
||||
}
|
||||
}
|
||||
|
|
@ -56,7 +54,7 @@ internal partial class Interface
|
|||
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, oldSpacing);
|
||||
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeight());
|
||||
var remainder = ImGuiClip.FilteredClippedDraw(_currentManipulations, skips, CheckFilter, DrawSelectable);
|
||||
var remainder = ImGuiClip.FilteredClippedDraw(_activeDesigns, skips, CheckFilter, DrawSelectable);
|
||||
ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeight());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using Dalamud.Interface;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Gui.Customization;
|
||||
using Glamourer.Gui.Designs;
|
||||
|
|
@ -37,9 +38,7 @@ internal partial class Interface
|
|||
{
|
||||
using var tab = ImRaii.TabItem("Designs");
|
||||
if (!tab)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Selector.Draw(GetDesignSelectorSize());
|
||||
ImGui.SameLine();
|
||||
|
|
@ -55,12 +54,25 @@ internal partial class Interface
|
|||
if (!child || Selector.Selected == null)
|
||||
return;
|
||||
|
||||
CustomizationDrawer.Draw(Selector.Selected.Customize(), Selector.Selected.Equipment(), true);
|
||||
_main._customizationDrawer.Draw(Selector.Selected.Customize(), CustomizeFlagExtensions.All, true);
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
{
|
||||
_main._equipmentDrawer.DrawStain(Selector.Selected, slot, out var stain);
|
||||
var current = Selector.Selected.Armor(slot);
|
||||
_main._equipmentDrawer.DrawStain(current.Stain, slot, out var stain);
|
||||
ImGui.SameLine();
|
||||
_main._equipmentDrawer.DrawArmor(Selector.Selected, slot, out var armor);
|
||||
_main._equipmentDrawer.DrawArmor(current, slot, out var armor);
|
||||
}
|
||||
|
||||
var currentMain = Selector.Selected.WeaponMain;
|
||||
_main._equipmentDrawer.DrawStain(currentMain.Stain, EquipSlot.MainHand, out var stainMain);
|
||||
ImGui.SameLine();
|
||||
_main._equipmentDrawer.DrawMainhand(currentMain, true, out var main);
|
||||
if (currentMain.Type.Offhand() != FullEquipType.Unknown)
|
||||
{
|
||||
var currentOff = Selector.Selected.WeaponOff;
|
||||
_main._equipmentDrawer.DrawStain(currentOff.Stain, EquipSlot.OffHand, out var stainOff);
|
||||
ImGui.SameLine();
|
||||
_main._equipmentDrawer.DrawOffhand(currentOff, main.Type, out var off);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,8 +50,9 @@ internal partial class Interface
|
|||
return;
|
||||
}
|
||||
|
||||
if (ImGui.Button(buttonLabel))
|
||||
Glamourer.Penumbra.Reattach(true);
|
||||
// TODO
|
||||
//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.");
|
||||
|
|
@ -73,18 +74,6 @@ internal partial class Interface
|
|||
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",
|
||||
|
|
|
|||
|
|
@ -1,32 +1,38 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Plugin;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Gui.Customization;
|
||||
using Glamourer.Gui.Equipment;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.State;
|
||||
using Glamourer.Util;
|
||||
using ImGuiNET;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Data;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
internal partial class Interface : Window, IDisposable
|
||||
{
|
||||
private readonly EquipmentDrawer _equipmentDrawer;
|
||||
private readonly DalamudPluginInterface _pi;
|
||||
|
||||
private readonly EquipmentDrawer _equipmentDrawer;
|
||||
private readonly CustomizationDrawer _customizationDrawer;
|
||||
|
||||
private readonly ActorTab _actorTab;
|
||||
private readonly DesignTab _designTab;
|
||||
private readonly DebugStateTab _debugStateTab;
|
||||
private readonly DebugDataTab _debugDataTab;
|
||||
|
||||
public Interface(ItemManager items, CurrentManipulations manipulations, Design.Manager manager, DesignFileSystem fileSystem)
|
||||
public Interface(DalamudPluginInterface pi, ItemManager items, ActiveDesign.Manager activeDesigns, Design.Manager manager,
|
||||
DesignFileSystem fileSystem, ObjectManager objects)
|
||||
: base(GetLabel())
|
||||
{
|
||||
_pi = pi;
|
||||
_equipmentDrawer = new EquipmentDrawer(items);
|
||||
_customizationDrawer = new CustomizationDrawer(pi);
|
||||
Dalamud.PluginInterface.UiBuilder.DisableGposeUiHide = true;
|
||||
Dalamud.PluginInterface.UiBuilder.OpenConfigUi += Toggle;
|
||||
SizeConstraints = new WindowSizeConstraints()
|
||||
|
|
@ -34,8 +40,8 @@ internal partial class Interface : Window, IDisposable
|
|||
MinimumSize = new Vector2(675, 675),
|
||||
MaximumSize = ImGui.GetIO().DisplaySize,
|
||||
};
|
||||
_actorTab = new ActorTab(this, manipulations);
|
||||
_debugStateTab = new DebugStateTab(manipulations);
|
||||
_actorTab = new ActorTab(this, activeDesigns, objects);
|
||||
_debugStateTab = new DebugStateTab(activeDesigns);
|
||||
_debugDataTab = new DebugDataTab(Glamourer.Customization);
|
||||
_designTab = new DesignTab(this, manager, fileSystem);
|
||||
}
|
||||
|
|
@ -67,8 +73,8 @@ internal partial class Interface : Window, IDisposable
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
Dalamud.PluginInterface.UiBuilder.OpenConfigUi -= Toggle;
|
||||
CustomizationDrawer.Dispose();
|
||||
_pi.UiBuilder.OpenConfigUi -= Toggle;
|
||||
_customizationDrawer.Dispose();
|
||||
_designTab.Dispose();
|
||||
}
|
||||
|
||||
|
|
@ -77,90 +83,3 @@ internal partial class Interface : Window, IDisposable
|
|||
? "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();
|
||||
// }
|
||||
//}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue