mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2026-02-21 15:07:43 +01:00
Do the Reworkings
This commit is contained in:
parent
a67cd8ad89
commit
e3a58340b3
23 changed files with 1067 additions and 943 deletions
|
|
@ -1,17 +1,13 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Reflection;
|
||||
using Dalamud.Game.Command;
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Utility.Signatures;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using Glamourer.Api;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Gui;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.State;
|
||||
using OtterGui.Log;
|
||||
using Penumbra.GameData;
|
||||
|
||||
namespace Glamourer;
|
||||
|
|
@ -32,6 +28,7 @@ public class Glamourer : IDalamudPlugin
|
|||
|
||||
|
||||
public static GlamourerConfig Config = null!;
|
||||
public static Logger Log = null!;
|
||||
|
||||
public static IObjectIdentifier Identifier = null!;
|
||||
public static PenumbraAttach Penumbra = null!;
|
||||
|
|
@ -55,6 +52,7 @@ public class Glamourer : IDalamudPlugin
|
|||
try
|
||||
{
|
||||
Dalamud.Initialize(pluginInterface);
|
||||
Log = new Logger();
|
||||
|
||||
Customization = CustomizationManager.Create(Dalamud.PluginInterface, Dalamud.GameData, Dalamud.ClientState.ClientLanguage);
|
||||
RestrictedGear = GameData.RestrictedGear(Dalamud.GameData);
|
||||
|
|
|
|||
65
Glamourer/Gui/Customization/CustomizationDrawer.Color.cs
Normal file
65
Glamourer/Gui/Customization/CustomizationDrawer.Color.cs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
using System.Numerics;
|
||||
using Glamourer.Customization;
|
||||
using ImGuiNET;
|
||||
using OtterGui.Raii;
|
||||
|
||||
namespace Glamourer.Gui.Customization;
|
||||
|
||||
internal partial class CustomizationDrawer
|
||||
{
|
||||
private const string ColorPickerPopupName = "ColorPicker";
|
||||
|
||||
private void DrawColorPicker(CustomizationId id)
|
||||
{
|
||||
using var _ = SetId(id);
|
||||
var (current, custom) = GetCurrentCustomization(id);
|
||||
var color = ImGui.ColorConvertU32ToFloat4(custom.Color);
|
||||
|
||||
// Print 1-based index instead of 0.
|
||||
if (ImGui.ColorButton($"{current + 1}##color", color, ImGuiColorEditFlags.None, _framedIconSize))
|
||||
ImGui.OpenPopup(ColorPickerPopupName);
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
using (var group = ImRaii.Group())
|
||||
{
|
||||
DataInputInt(current);
|
||||
ImGui.TextUnformatted(_currentOption);
|
||||
}
|
||||
|
||||
DrawColorPickerPopup();
|
||||
}
|
||||
|
||||
private void DrawColorPickerPopup()
|
||||
{
|
||||
using var popup = ImRaii.Popup(ColorPickerPopupName, ImGuiWindowFlags.AlwaysAutoResize);
|
||||
if (!popup)
|
||||
return;
|
||||
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
for (var i = 0; i < _currentCount; ++i)
|
||||
{
|
||||
var custom = _set.Data(_currentId, i, _customize[CustomizationId.Face]);
|
||||
if (ImGui.ColorButton((i + 1).ToString(), ImGui.ColorConvertU32ToFloat4(custom.Color)))
|
||||
{
|
||||
UpdateValue(custom.Value);
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
|
||||
if (i % 8 != 7)
|
||||
ImGui.SameLine();
|
||||
}
|
||||
}
|
||||
|
||||
// Obtain the current customization and print a warning if it is not known.
|
||||
private (int, CustomizationData) GetCurrentCustomization(CustomizationId id)
|
||||
{
|
||||
var current = _set.DataByValue(id, _customize[id], out var custom);
|
||||
if (!_set.IsAvailable(id) || current >= 0)
|
||||
return (current, custom!.Value);
|
||||
|
||||
Glamourer.Log.Warning($"Read invalid customization value {_customize[id]} for {id}.");
|
||||
return (0, _set.Data(id, 0));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Dalamud.Interface;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Util;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
||||
namespace Glamourer.Gui.Customization;
|
||||
|
||||
internal partial class CustomizationDrawer
|
||||
{
|
||||
private void DrawRaceGenderSelector()
|
||||
{
|
||||
DrawGenderSelector();
|
||||
ImGui.SameLine();
|
||||
using var group = ImRaii.Group();
|
||||
DrawRaceCombo();
|
||||
var gender = Glamourer.Customization.GetName(CustomName.Gender);
|
||||
var clan = Glamourer.Customization.GetName(CustomName.Clan);
|
||||
ImGui.TextUnformatted($"{gender} & {clan}");
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (!ImGuiUtil.DrawDisabledButton(icon.ToIconString(), _framedIconSize, string.Empty, restricted, 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, false);
|
||||
}
|
||||
|
||||
private void DrawRaceCombo()
|
||||
{
|
||||
ImGui.SetNextItemWidth(_raceSelectorWidth);
|
||||
using var combo = ImRaii.Combo("##subRaceCombo", _customize.ClanName());
|
||||
if (!combo)
|
||||
return;
|
||||
|
||||
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, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
109
Glamourer/Gui/Customization/CustomizationDrawer.Icon.cs
Normal file
109
Glamourer/Gui/Customization/CustomizationDrawer.Icon.cs
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Glamourer.Customization;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
||||
namespace Glamourer.Gui.Customization;
|
||||
|
||||
internal partial class CustomizationDrawer
|
||||
{
|
||||
private const string IconSelectorPopup = "Style Picker";
|
||||
|
||||
private void DrawIconSelector(CustomizationId id)
|
||||
{
|
||||
using var _ = SetId(id);
|
||||
using var bigGroup = ImRaii.Group();
|
||||
var label = _currentOption;
|
||||
|
||||
var current = _set.DataByValue(id, _currentByte, out var custom);
|
||||
if (current < 0)
|
||||
{
|
||||
label = $"{_currentOption} (Custom #{_customize[id]})";
|
||||
current = 0;
|
||||
custom = _set.Data(id, 0);
|
||||
}
|
||||
|
||||
var icon = Glamourer.Customization.GetIcon(custom!.Value.IconId);
|
||||
if (ImGui.ImageButton(icon.ImGuiHandle, _iconSize))
|
||||
ImGui.OpenPopup(IconSelectorPopup);
|
||||
ImGuiUtil.HoverIconTooltip(icon, _iconSize);
|
||||
|
||||
ImGui.SameLine();
|
||||
using (var group = ImRaii.Group())
|
||||
{
|
||||
if (_currentId == CustomizationId.Face)
|
||||
FaceInputInt(current);
|
||||
else
|
||||
DataInputInt(current);
|
||||
ImGui.TextUnformatted($"{label} ({custom.Value.Value})");
|
||||
}
|
||||
|
||||
DrawIconPickerPopup();
|
||||
}
|
||||
|
||||
private void UpdateFace(CustomizationData data)
|
||||
{
|
||||
// Hrothgar Hack
|
||||
var value = _set.Race == Race.Hrothgar ? data.Value + 4 : data.Value;
|
||||
if (_customize.Face == value)
|
||||
return;
|
||||
|
||||
_customize.Face = value;
|
||||
foreach (var actor in _actors)
|
||||
Glamourer.Penumbra.RedrawObject(actor.Character, RedrawType.Redraw, false);
|
||||
}
|
||||
|
||||
private void FaceInputInt(int currentIndex)
|
||||
{
|
||||
++currentIndex;
|
||||
ImGui.SetNextItemWidth(_inputIntSize);
|
||||
if (ImGui.InputInt("##text", ref currentIndex, 1, 1))
|
||||
{
|
||||
currentIndex = Math.Clamp(currentIndex - 1, 0, _currentCount - 1);
|
||||
var data = _set.Data(_currentId, currentIndex, _customize.Face);
|
||||
UpdateFace(data);
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip($"Input Range: [1, {_currentCount}]");
|
||||
}
|
||||
|
||||
private void DrawIconPickerPopup()
|
||||
{
|
||||
using var popup = ImRaii.Popup(IconSelectorPopup, ImGuiWindowFlags.AlwaysAutoResize);
|
||||
if (!popup)
|
||||
return;
|
||||
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
||||
for (var i = 0; i < _currentCount; ++i)
|
||||
{
|
||||
var custom = _set.Data(_currentId, i, _customize.Face);
|
||||
var icon = Glamourer.Customization.GetIcon(custom.IconId);
|
||||
using (var _ = ImRaii.Group())
|
||||
{
|
||||
if (ImGui.ImageButton(icon.ImGuiHandle, _iconSize))
|
||||
{
|
||||
if (_currentId == CustomizationId.Face)
|
||||
UpdateFace(custom);
|
||||
else
|
||||
UpdateValue(custom.Value);
|
||||
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);
|
||||
}
|
||||
|
||||
if (i % 8 != 7)
|
||||
ImGui.SameLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
148
Glamourer/Gui/Customization/CustomizationDrawer.Main.cs
Normal file
148
Glamourer/Gui/Customization/CustomizationDrawer.Main.cs
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
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);
|
||||
|
||||
d.Checkbox(d._set.Option(CustomizationId.HighlightsOnFlag), customize.HighlightsOn, b => customize.HighlightsOn = b);
|
||||
var xPos = d._inputIntSize + d._framedIconSize.X + 3 * ImGui.GetStyle().ItemSpacing.X;
|
||||
ImGui.SameLine(xPos);
|
||||
d.Checkbox($"{Glamourer.Customization.GetName(CustomName.Reverse)} {d._set.Option(CustomizationId.FacePaint)}",
|
||||
customize.FacePaintReversed, b => customize.FacePaintReversed = b);
|
||||
d.Checkbox($"{Glamourer.Customization.GetName(CustomName.IrisSmall)} {Glamourer.Customization.GetName(CustomName.IrisSize)}",
|
||||
customize.SmallIris, b => customize.SmallIris = b);
|
||||
|
||||
if (customize.Race != Race.Hrothgar)
|
||||
{
|
||||
ImGui.SameLine(xPos);
|
||||
d.Checkbox(d._set.Option(CustomizationId.LipColor), customize.Lipstick, b => customize.Lipstick = b);
|
||||
}
|
||||
}
|
||||
|
||||
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 CustomizationId _currentId;
|
||||
private CustomizationByteValue _currentByte = CustomizationByteValue.Zero;
|
||||
private int _currentCount;
|
||||
private string _currentOption = string.Empty;
|
||||
|
||||
// Prepare a new customization option.
|
||||
private ImRaii.Id SetId(CustomizationId id)
|
||||
{
|
||||
_currentId = id;
|
||||
_currentByte = _customize[id];
|
||||
_currentCount = _set.Count(id, _customize.Face);
|
||||
_currentOption = _set.Option(id);
|
||||
return ImRaii.PushId((int)id);
|
||||
}
|
||||
|
||||
// Update the current id with a value,
|
||||
// also update actors if any.
|
||||
private void UpdateValue(CustomizationByteValue value)
|
||||
{
|
||||
if (_customize[_currentId] == value)
|
||||
return;
|
||||
|
||||
_customize[_currentId] = value;
|
||||
UpdateActors();
|
||||
}
|
||||
|
||||
// Update all relevant Actors by calling the UpdateCustomize game function.
|
||||
private void UpdateActors()
|
||||
{
|
||||
foreach (var actor in _actors.Where(a => a && a.DrawObject))
|
||||
Glamourer.RedrawManager.UpdateCustomize(actor.DrawObject, _customize);
|
||||
}
|
||||
}
|
||||
51
Glamourer/Gui/Customization/CustomizationDrawer.Multi.cs
Normal file
51
Glamourer/Gui/Customization/CustomizationDrawer.Multi.cs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
using System.Linq;
|
||||
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 _ = SetId(CustomizationId.FacialFeaturesTattoos);
|
||||
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(CustomizationId.FacialFeaturesTattoos));
|
||||
}
|
||||
|
||||
private void DrawMultiIcons()
|
||||
{
|
||||
using var _ = ImRaii.Group();
|
||||
for (var i = 0; i < _currentCount; ++i)
|
||||
{
|
||||
var enabled = _customize.FacialFeatures[i];
|
||||
var feature = _set.FacialFeature(_customize.Face, i);
|
||||
var icon = i == _currentCount - 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))
|
||||
{
|
||||
_customize.FacialFeatures.Set(i, !enabled);
|
||||
UpdateActors();
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverIconTooltip(icon, _iconSize);
|
||||
if (i % 4 != 3)
|
||||
ImGui.SameLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
104
Glamourer/Gui/Customization/CustomizationDrawer.Simple.cs
Normal file
104
Glamourer/Gui/Customization/CustomizationDrawer.Simple.cs
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Glamourer.Customization;
|
||||
using ImGuiNET;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
|
||||
namespace Glamourer.Gui.Customization;
|
||||
|
||||
internal partial class CustomizationDrawer
|
||||
{
|
||||
private void DrawListSelector(CustomizationId id)
|
||||
{
|
||||
using var _ = SetId(id);
|
||||
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((CustomizationByteValue)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((CustomizationByteValue)Math.Clamp(tmp - 1, 0, _currentCount - 1));
|
||||
ImGuiUtil.HoverTooltip($"Input Range: [1, {_currentCount}]");
|
||||
}
|
||||
|
||||
private void PercentageSelector(CustomizationId id)
|
||||
{
|
||||
using var _ = SetId(id);
|
||||
using var bigGroup = ImRaii.Group();
|
||||
|
||||
DrawPercentageSlider();
|
||||
ImGui.SameLine();
|
||||
PercentageInputInt();
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted(_currentOption);
|
||||
}
|
||||
|
||||
private void DrawPercentageSlider()
|
||||
{
|
||||
var tmp = (int)_currentByte.Value;
|
||||
ImGui.SetNextItemWidth(_comboSelectorSize);
|
||||
if (ImGui.SliderInt("##slider", ref tmp, 0, _currentCount - 1, "%i", ImGuiSliderFlags.AlwaysClamp))
|
||||
UpdateValue((CustomizationByteValue)tmp);
|
||||
}
|
||||
|
||||
private void PercentageInputInt()
|
||||
{
|
||||
var tmp = (int)_currentByte.Value;
|
||||
ImGui.SetNextItemWidth(_inputIntSize);
|
||||
if (ImGui.InputInt("##text", ref tmp, 1, 1))
|
||||
UpdateValue((CustomizationByteValue)Math.Clamp(tmp, 0, _currentCount - 1));
|
||||
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);
|
||||
foreach (var actor in _actors.Where(a => a && a.DrawObject))
|
||||
Glamourer.RedrawManager.UpdateCustomize(actor.DrawObject, _customize);
|
||||
}
|
||||
}
|
||||
|
||||
// Integral input for an icon- or color based item.
|
||||
private void DataInputInt(int currentIndex)
|
||||
{
|
||||
++currentIndex;
|
||||
ImGui.SetNextItemWidth(_inputIntSize);
|
||||
if (ImGui.InputInt("##text", ref currentIndex, 1, 1))
|
||||
{
|
||||
currentIndex = Math.Clamp(currentIndex - 1, 0, _currentCount - 1);
|
||||
var data = _set.Data(_currentId, currentIndex, _customize.Face);
|
||||
UpdateValue(data.Value);
|
||||
}
|
||||
ImGuiUtil.HoverTooltip($"Input Range: [1, {_currentCount}]");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Dalamud.Interface;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.Structs;
|
||||
|
|
@ -10,8 +9,6 @@ using OtterGui;
|
|||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using static Glamourer.Interop.Actor;
|
||||
using static Lumina.Data.Parsing.Layer.LayerCommon;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
|
|
@ -19,13 +16,16 @@ internal partial class Interface
|
|||
{
|
||||
//public class EquipmentDrawer
|
||||
//{
|
||||
// private static
|
||||
// private static readonly IReadOnlyDictionary<StainId, Stain> Stains;
|
||||
//
|
||||
// private Race _race;
|
||||
// private Gender _gender;
|
||||
// private CharacterEquip _equip;
|
||||
// private IReadOnlyCollection<Actor> _actors = Array.Empty<Actor>();
|
||||
//
|
||||
// static EquipmentDrawer()
|
||||
// => Stains = GameData.Stains(Dalamud.GameData);
|
||||
//
|
||||
// public static void Draw(Customize customize, CharacterEquip equip, IReadOnlyCollection<Actor> actors, bool locked)
|
||||
// {
|
||||
// var d = new EquipmentDrawer()
|
||||
|
|
@ -44,13 +44,10 @@ 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 found = Stains.TryGetValue(stainIdx, out var stain);
|
||||
// using var color = ImRaii.PushColor(ImGuiCol.FrameBg, stain.RgbaColor, found);
|
||||
// var change = stainCombo.Draw(string.Empty, out var newStain) && !newStain.RowIndex.Equals(stainIdx);
|
||||
// if ()
|
||||
// if (!change && (byte)stainIdx != 0)
|
||||
// {
|
||||
// ImGuiUtil.HoverTooltip("Right-click to clear.");
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
using System.Numerics;
|
||||
using Dalamud.Interface;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using Glamourer.Gui.Customization;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.State;
|
||||
using ImGuiNET;
|
||||
|
|
@ -57,12 +58,8 @@ internal partial class Interface
|
|||
if (_currentData.Valid)
|
||||
_currentSave.Update(_currentData.Objects[0]);
|
||||
|
||||
var d = _currentData.Objects[0].DrawObject.Pointer;
|
||||
var x = (*(delegate* unmanaged<Human*, byte>**)d)[50](d);
|
||||
ImGui.Text($"{x} {_currentData.Objects[0].ModelId}");
|
||||
if (x == 1)
|
||||
CustomizationDrawer.Draw(_currentSave.Data.Customize, _currentSave.Data.Equipment, _currentData.Objects,
|
||||
_identifier is Actor.SpecialIdentifier);
|
||||
CustomizationDrawer.Draw(_currentSave.Data.Customize, _currentSave.Data.Equipment, _currentData.Objects,
|
||||
_identifier is Actor.SpecialIdentifier);
|
||||
}
|
||||
|
||||
private const uint RedHeaderColor = 0xFF1818C0;
|
||||
|
|
|
|||
|
|
@ -1,402 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Logging;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.Util;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
using OtterGui.Raii;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Race = Penumbra.GameData.Enums.Race;
|
||||
|
||||
namespace Glamourer.Gui;
|
||||
|
||||
internal partial class Interface
|
||||
{
|
||||
private class CustomizationDrawer
|
||||
{
|
||||
private Customize _customize;
|
||||
private CharacterEquip _equip;
|
||||
private IReadOnlyCollection<Actor> _actors = Array.Empty<Actor>();
|
||||
private CustomizationSet _set = 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);
|
||||
|
||||
d.Checkbox(d._set.Option(CustomizationId.HighlightsOnFlag), customize.HighlightsOn, b => customize.HighlightsOn = b);
|
||||
var xPos = _inputIntSize + _framedIconSize.X + 3 * ImGui.GetStyle().ItemSpacing.X;
|
||||
ImGui.SameLine(xPos);
|
||||
d.Checkbox($"{Glamourer.Customization.GetName(CustomName.Reverse)} {d._set.Option(CustomizationId.FacePaint)}",
|
||||
customize.FacePaintReversed, b => customize.FacePaintReversed = b);
|
||||
d.Checkbox($"{Glamourer.Customization.GetName(CustomName.IrisSmall)} {Glamourer.Customization.GetName(CustomName.IrisSize)}",
|
||||
customize.SmallIris, b => customize.SmallIris = b);
|
||||
|
||||
if (customize.Race != Race.Hrothgar)
|
||||
{
|
||||
ImGui.SameLine(xPos);
|
||||
d.Checkbox(d._set.Option(CustomizationId.LipColor), customize.Lipstick, b => customize.Lipstick = b);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawRaceGenderSelector()
|
||||
{
|
||||
DrawGenderSelector();
|
||||
ImGui.SameLine();
|
||||
using var group = ImRaii.Group();
|
||||
DrawRaceCombo();
|
||||
var gender = Glamourer.Customization.GetName(CustomName.Gender);
|
||||
var clan = Glamourer.Customization.GetName(CustomName.Clan);
|
||||
ImGui.TextUnformatted($"{gender} & {clan}");
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (!ImGuiUtil.DrawDisabledButton(icon.ToIconString(), _framedIconSize, string.Empty, restricted, 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, false);
|
||||
}
|
||||
|
||||
private void DrawRaceCombo()
|
||||
{
|
||||
ImGui.SetNextItemWidth(_raceSelectorWidth);
|
||||
using var combo = ImRaii.Combo("##subRaceCombo", _customize.ClanName());
|
||||
if (!combo)
|
||||
return;
|
||||
|
||||
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))
|
||||
foreach (var actor in _actors.Where(a => a && a.DrawObject))
|
||||
Glamourer.Penumbra.RedrawObject(actor.Character, RedrawType.Redraw, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void Checkbox(string label, bool current, Action<bool> setter)
|
||||
{
|
||||
var tmp = current;
|
||||
if (ImGui.Checkbox($"##{label}", ref tmp) && tmp != current)
|
||||
{
|
||||
setter(tmp);
|
||||
foreach (var actor in _actors.Where(a => a && a.DrawObject))
|
||||
Glamourer.RedrawManager.UpdateCustomize(actor.DrawObject, _customize);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted(label);
|
||||
}
|
||||
|
||||
private void PercentageSelector(CustomizationId id)
|
||||
{
|
||||
using var bigGroup = ImRaii.Group();
|
||||
using var _ = ImRaii.PushId((int)id);
|
||||
int value = _customize[id];
|
||||
var count = _set.Count(id);
|
||||
ImGui.SetNextItemWidth(_comboSelectorSize);
|
||||
|
||||
void OnChange(int v)
|
||||
{
|
||||
_customize[id] = (byte)v;
|
||||
foreach (var actor in _actors.Where(a => a && a.DrawObject))
|
||||
Glamourer.RedrawManager.UpdateCustomize(actor.DrawObject, _customize);
|
||||
}
|
||||
|
||||
if (ImGui.SliderInt("##slider", ref value, 0, count - 1, "%i", ImGuiSliderFlags.AlwaysClamp))
|
||||
OnChange(value);
|
||||
|
||||
ImGui.SameLine();
|
||||
InputInt("##input", --value, 0, count - 1, OnChange);
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted(_set.OptionName[(int)id]);
|
||||
}
|
||||
|
||||
private static void InputInt(string label, int startValue, int minValue, int maxValue, Action<int> setter)
|
||||
{
|
||||
var tmp = startValue + 1;
|
||||
ImGui.SetNextItemWidth(_inputIntSize);
|
||||
if (ImGui.InputInt(label, ref tmp, 1, 1, ImGuiInputTextFlags.EnterReturnsTrue)
|
||||
&& tmp != startValue + 1
|
||||
&& tmp >= minValue
|
||||
&& tmp <= maxValue)
|
||||
setter(tmp);
|
||||
|
||||
ImGuiUtil.HoverTooltip($"Input Range: [{minValue}, {maxValue}]");
|
||||
}
|
||||
|
||||
private void DrawIconSelector(CustomizationId id)
|
||||
{
|
||||
const string popupName = "Style Picker";
|
||||
|
||||
using var bigGroup = ImRaii.Group();
|
||||
using var _ = ImRaii.PushId((int)id);
|
||||
var count = _set.Count(id, _customize.Face);
|
||||
var label = _set.Option(id);
|
||||
|
||||
var current = _set.DataByValue(id, _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);
|
||||
if (ImGui.ImageButton(icon.ImGuiHandle, _iconSize))
|
||||
ImGui.OpenPopup(popupName);
|
||||
|
||||
ImGuiUtil.HoverIconTooltip(icon, _iconSize);
|
||||
|
||||
void OnChange(int v)
|
||||
{
|
||||
var value = _set.Data(id, v - 1).Value;
|
||||
// Hrothgar hack
|
||||
if (_set.Race == Race.Hrothgar && id == CustomizationId.Face)
|
||||
value += 4;
|
||||
|
||||
if (_customize[id] == value)
|
||||
return;
|
||||
|
||||
_customize[id] = value;
|
||||
foreach (var actor in _actors.Where(a => a && a.DrawObject))
|
||||
Glamourer.RedrawManager.UpdateCustomize(actor.DrawObject, _customize);
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
using var group = ImRaii.Group();
|
||||
InputInt("##text", current, 1, count, OnChange);
|
||||
|
||||
ImGui.TextUnformatted($"{label} ({custom.Value.Value})");
|
||||
|
||||
DrawIconPickerPopup(popupName, id, OnChange);
|
||||
}
|
||||
|
||||
private void DrawIconPickerPopup(string label, CustomizationId id, Action<int> setter)
|
||||
{
|
||||
using var popup = ImRaii.Popup(label, ImGuiWindowFlags.AlwaysAutoResize);
|
||||
if (!popup)
|
||||
return;
|
||||
|
||||
var count = _set.Count(id, _customize.Face);
|
||||
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, _customize.Face);
|
||||
var icon = Glamourer.Customization.GetIcon(custom.IconId);
|
||||
using var group = ImRaii.Group();
|
||||
if (ImGui.ImageButton(icon.ImGuiHandle, _iconSize))
|
||||
{
|
||||
setter(custom.Value);
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawColorPicker(CustomizationId id)
|
||||
{
|
||||
const string popupName = "Color Picker";
|
||||
using var _ = ImRaii.PushId((int)id);
|
||||
var count = _set.Count(id);
|
||||
var label = _set.Option(id);
|
||||
var (current, custom) = GetCurrentCustomization(id);
|
||||
|
||||
if (ImGui.ColorButton($"{current + 1}##color", ImGui.ColorConvertU32ToFloat4(custom.Color), ImGuiColorEditFlags.None,
|
||||
_framedIconSize))
|
||||
ImGui.OpenPopup(popupName);
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
void OnChange(int v)
|
||||
{
|
||||
_customize[id] = _set.Data(id, v).Value;
|
||||
foreach (var actor in _actors.Where(a => a && a.DrawObject))
|
||||
Glamourer.RedrawManager.UpdateCustomize(actor.DrawObject, _customize);
|
||||
}
|
||||
|
||||
using (var group = ImRaii.Group())
|
||||
{
|
||||
InputInt("##text", current, 1, count, OnChange);
|
||||
ImGui.TextUnformatted(label);
|
||||
}
|
||||
|
||||
DrawColorPickerPopup(popupName, id, OnChange);
|
||||
}
|
||||
|
||||
private (int, Customization.Customization) GetCurrentCustomization(CustomizationId id)
|
||||
{
|
||||
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 void DrawColorPickerPopup(string label, CustomizationId id, Action<int> setter)
|
||||
{
|
||||
using var popup = ImRaii.Popup(label, ImGuiWindowFlags.AlwaysAutoResize);
|
||||
if (!popup)
|
||||
return;
|
||||
|
||||
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)))
|
||||
{
|
||||
setter(custom.Value);
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
|
||||
if (i % 8 != 7)
|
||||
ImGui.SameLine();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawMultiIconSelector()
|
||||
{
|
||||
using var bigGroup = ImRaii.Group();
|
||||
using var _ = ImRaii.PushId((int)CustomizationId.FacialFeaturesTattoos);
|
||||
|
||||
void OnChange(int v)
|
||||
{
|
||||
_customize[CustomizationId.FacialFeaturesTattoos] = (byte)v;
|
||||
foreach (var actor in _actors.Where(a => a && a.DrawObject))
|
||||
Glamourer.RedrawManager.UpdateCustomize(actor.DrawObject, _customize);
|
||||
}
|
||||
|
||||
DrawMultiIcons();
|
||||
ImGui.SameLine();
|
||||
int value = _customize[CustomizationId.FacialFeaturesTattoos];
|
||||
using var group = ImRaii.Group();
|
||||
ImGui.Dummy(new Vector2(0, ImGui.GetTextLineHeightWithSpacing() + ImGui.GetStyle().ItemSpacing.Y / 2));
|
||||
InputInt(string.Empty, --value, 0, 255, OnChange);
|
||||
|
||||
ImGui.TextUnformatted(_set.Option(CustomizationId.FacialFeaturesTattoos));
|
||||
}
|
||||
|
||||
private void DrawMultiIcons()
|
||||
{
|
||||
using var _ = ImRaii.Group();
|
||||
var face = _customize.Face;
|
||||
|
||||
var ret = false;
|
||||
var count = _set.Count(CustomizationId.FacialFeaturesTattoos);
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
var enabled = _customize.FacialFeatures[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))
|
||||
{
|
||||
_customize.FacialFeatures.Set(i, !enabled);
|
||||
foreach (var actor in _actors.Where(a => a && a.DrawObject))
|
||||
Glamourer.RedrawManager.UpdateCustomize(actor.DrawObject, _customize);
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverIconTooltip(icon, _iconSize);
|
||||
if (i % 4 != 3)
|
||||
ImGui.SameLine();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawListSelector(CustomizationId id)
|
||||
{
|
||||
using var _ = ImRaii.PushId((int)id);
|
||||
using var bigGroup = ImRaii.Group();
|
||||
int current = _customize[id];
|
||||
var count = _set.Count(id);
|
||||
|
||||
void OnChange(int v)
|
||||
{
|
||||
_customize[id] = (byte)v;
|
||||
foreach (var actor in _actors.Where(a => a && a.DrawObject))
|
||||
Glamourer.RedrawManager.UpdateCustomize(actor.DrawObject, _customize);
|
||||
}
|
||||
|
||||
ImGui.SetNextItemWidth(_comboSelectorSize * ImGui.GetIO().FontGlobalScale);
|
||||
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)
|
||||
continue;
|
||||
|
||||
OnChange(i);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
InputInt("##text", current, 1, count, OnChange);
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted(_set.Option(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
using Glamourer.Gui.Customization;
|
||||
using Glamourer.Interop;
|
||||
using Glamourer.State;
|
||||
using ImGuiNET;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using System.Numerics;
|
||||
using Dalamud.Interface;
|
||||
using ImGuiNET;
|
||||
|
||||
|
|
@ -8,41 +6,12 @@ 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 void UpdateState()
|
||||
{
|
||||
// General
|
||||
_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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using System.Linq;
|
|||
using System.Numerics;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Logging;
|
||||
using Glamourer.Gui.Customization;
|
||||
using ImGuiNET;
|
||||
using OtterGui.Raii;
|
||||
|
||||
|
|
@ -56,6 +57,7 @@ internal partial class Interface : Window, IDisposable
|
|||
public void Dispose()
|
||||
{
|
||||
Dalamud.PluginInterface.UiBuilder.OpenConfigUi -= Toggle;
|
||||
CustomizationDrawer.Dispose();
|
||||
}
|
||||
|
||||
private static string GetLabel()
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ public struct CharacterData
|
|||
|
||||
public interface ICharacterData
|
||||
{
|
||||
public CharacterData Data { get; }
|
||||
public ref CharacterData Data { get; }
|
||||
|
||||
//public bool ApplyModel();
|
||||
//public bool ApplyCustomize(Customize target);
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ namespace Glamourer.State;
|
|||
|
||||
public unsafe class CurrentDesign : ICharacterData
|
||||
{
|
||||
public CharacterData Data
|
||||
=> _drawData;
|
||||
public ref CharacterData Data
|
||||
=> ref _drawData;
|
||||
|
||||
private CharacterData _drawData;
|
||||
private CharacterData _initialData;
|
||||
|
|
|
|||
|
|
@ -90,12 +90,12 @@ public static unsafe class CustomizeExtensions
|
|||
customize.Load(newCustomize);
|
||||
}
|
||||
|
||||
public static bool ChangeCustomization(this Customize customize, CharacterEquip equip, CustomizationId id, byte value)
|
||||
public static bool ChangeCustomization(this Customize customize, CharacterEquip equip, CustomizationId id, CustomizationByteValue value)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case CustomizationId.Race: return customize.ChangeRace(equip, (SubRace)value);
|
||||
case CustomizationId.Gender: return customize.ChangeGender(equip, (Gender)value);
|
||||
case CustomizationId.Race: return customize.ChangeRace(equip, (SubRace)value.Value);
|
||||
case CustomizationId.Gender: return customize.ChangeGender(equip, (Gender)value.Value);
|
||||
}
|
||||
|
||||
if (customize[id] == value)
|
||||
|
|
@ -113,17 +113,17 @@ public static unsafe class CustomizeExtensions
|
|||
{
|
||||
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;
|
||||
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, customize[id], out _) < 0)
|
||||
customize[id] = count == 0 ? (byte)0 : set.Data(id, 0).Value;
|
||||
customize[id] = count == 0 ? CustomizationByteValue.Zero : set.Data(id, 0).Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -131,7 +131,7 @@ public static unsafe class CustomizeExtensions
|
|||
|
||||
private static void FixRestrictedGear(Customize customize, CharacterEquip equip, Gender gender, Race race)
|
||||
{
|
||||
if (race == customize.Race && gender == customize.Gender)
|
||||
if (!equip || race == customize.Race && gender == customize.Gender)
|
||||
return;
|
||||
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue