From fbb41636df91c55a05aeca13a96442d7afa0764e Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Mon, 2 Aug 2021 16:13:48 +0200 Subject: [PATCH] Fix a bunch of shit and update. --- .../Customization/CustomizationOptions.cs | 4 +- .../Customization/CustomizationSet.cs | 51 +- .../Customization/CustomizationStruct.cs | 247 +++++++++ Glamourer.zip | Bin 62987 -> 66972 bytes Glamourer/Glamourer.csproj | 4 +- Glamourer/Glamourer.json | 2 +- Glamourer/Gui/ComboWithFilter.cs | 7 +- Glamourer/Gui/Interface.cs | 475 +++++++++++++++--- repo.json | 4 +- 9 files changed, 708 insertions(+), 86 deletions(-) create mode 100644 Glamourer.GameData/Customization/CustomizationStruct.cs diff --git a/Glamourer.GameData/Customization/CustomizationOptions.cs b/Glamourer.GameData/Customization/CustomizationOptions.cs index d04926a..b3f497f 100644 --- a/Glamourer.GameData/Customization/CustomizationOptions.cs +++ b/Glamourer.GameData/Customization/CustomizationOptions.cs @@ -106,7 +106,7 @@ namespace Glamourer.Customization { var row = _customizeSheet.GetRow(value); return row == null - ? new Customization(id, (byte) index, value, 0) + ? new Customization(id, (byte) (index + 1), value, 0) : new Customization(id, row.FeatureID, row.Icon, (ushort) row.RowId); } @@ -192,8 +192,6 @@ namespace Glamourer.Customization if (set.Faces.Count > 0) set.SetAvailable(CustomizationId.Face); - - var count = race.ToRace() == Race.Hrothgar ? set.HairStyles.Count : set.Faces.Count; var featureDict = new List>(count); for (var i = 0; i < count; ++i) diff --git a/Glamourer.GameData/Customization/CustomizationSet.cs b/Glamourer.GameData/Customization/CustomizationSet.cs index 9741441..a744710 100644 --- a/Glamourer.GameData/Customization/CustomizationSet.cs +++ b/Glamourer.GameData/Customization/CustomizationSet.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Linq; +using ImGuiScene; using Penumbra.GameData.Enums; namespace Glamourer.Customization @@ -37,7 +39,7 @@ namespace Glamourer.Customization public Race Race => Clan.ToRace(); - private int _settingAvailable = DefaultAvailable; + private int _settingAvailable; internal void SetAvailable(CustomizationId id) => _settingAvailable |= 1 << (int) id; @@ -71,7 +73,52 @@ namespace Glamourer.Customization public IReadOnlyDictionary OptionName { get; internal set; } = null!; public Customization FacialFeature(int faceIdx, int idx) - => FeaturesTattoos[faceIdx][idx]; + => FeaturesTattoos[faceIdx - 1][idx]; + + public int DataByValue(CustomizationId id, byte value, out Customization? custom) + { + var type = id.ToType(); + custom = null; + if (type == CharaMakeParams.MenuType.Percentage || type == CharaMakeParams.MenuType.ListSelector) + { + if (value < Count(id)) + { + custom = new Customization(id, value, 0, value); + return value; + } + + return -1; + } + + int Get(IEnumerable list, ref Customization? output) + { + var (val, idx) = list.Cast().Select((c, i) => (c, i)).FirstOrDefault(c => c.c!.Value.Value == value); + if (val == null) + return -1; + + output = val; + return idx; + } + + return id switch + { + CustomizationId.SkinColor => Get(SkinColors, ref custom), + CustomizationId.EyeColorL => Get(EyeColors, ref custom), + CustomizationId.EyeColorR => Get(EyeColors, ref custom), + CustomizationId.HairColor => Get(HairColors, ref custom), + CustomizationId.HighlightColor => Get(HighlightColors, ref custom), + CustomizationId.TattooColor => Get(TattooColors, ref custom), + CustomizationId.LipColor => Get(LipColorsDark.Concat(LipColorsLight), ref custom), + CustomizationId.FacePaintColor => Get(FacePaintColorsDark.Concat(FacePaintColorsLight), ref custom), + + CustomizationId.Face => Get(Faces, ref custom), + CustomizationId.Hairstyle => Get(HairStyles, ref custom), + CustomizationId.TailEarShape => Get(TailEarShapes, ref custom), + CustomizationId.FacePaint => Get(FacePaints, ref custom), + CustomizationId.FacialFeaturesTattoos => Get(FeaturesTattoos[0], ref custom), + _ => throw new ArgumentOutOfRangeException(nameof(id), id, null), + }; + } public Customization Data(CustomizationId id, int idx) { diff --git a/Glamourer.GameData/Customization/CustomizationStruct.cs b/Glamourer.GameData/Customization/CustomizationStruct.cs new file mode 100644 index 0000000..941ea66 --- /dev/null +++ b/Glamourer.GameData/Customization/CustomizationStruct.cs @@ -0,0 +1,247 @@ +using System; +using System.Runtime.InteropServices; +using Penumbra.GameData.Enums; + +namespace Glamourer.Customization +{ + [StructLayout(LayoutKind.Sequential)] + public unsafe struct CustomizationStruct + { + public CustomizationStruct(IntPtr ptr) + => _ptr = (byte*) ptr; + + private readonly byte* _ptr; + + public byte this[CustomizationId id] + { + get => id switch + { + // Needs to handle the Highlander Race in enum. + CustomizationId.Race => (byte) (_ptr[(int) CustomizationId.Race] > 1 ? _ptr[(int) CustomizationId.Race] + 1 : 1), + // Needs to handle Gender.Unknown = 0. + CustomizationId.Gender => (byte) (_ptr[(int) id] + 1), + // Just a flag. + CustomizationId.HighlightsOnFlag => (byte) ((_ptr[(int) id] & 128) == 128 ? 1 : 0), + // Eye also includes iris flag at bit 128. + CustomizationId.EyeShape => (byte) (_ptr[(int) CustomizationId.EyeShape] & 127), + // Mouth also includes Lipstick flag at bit 128. + CustomizationId.Mouth => (byte) (_ptr[(int) CustomizationId.Mouth] & 127), + // FacePaint also includes Reverse bit at 128. + CustomizationId.FacePaint => (byte) (_ptr[(int) CustomizationId.FacePaint] & 127), + _ => _ptr[(int) id], + }; + set + { + _ptr[(int) id] = id switch + { + CustomizationId.Race => (byte) (value > (byte) Race.Midlander ? value - 1 : value), + CustomizationId.Gender => (byte) (value - 1), + CustomizationId.HighlightsOnFlag => (byte) (value != 0 ? 128 : 0), + CustomizationId.EyeShape => (byte) ((_ptr[(int) CustomizationId.EyeShape] & 128) | (value & 127)), + CustomizationId.Mouth => (byte) ((_ptr[(int) CustomizationId.Mouth] & 128) | (value & 127)), + CustomizationId.FacePaint => (byte) ((_ptr[(int) CustomizationId.FacePaint] & 128) | (value & 127)), + _ => value, + }; + + if (Race != Race.Hrothgar) + return; + + // Handle Hrothgar Face being dependent on hairstyle, 2 faces per hairstyle. + switch (id) + { + case CustomizationId.Hairstyle: + _ptr[(int) CustomizationId.Face] = (byte) ((value + 1) / 2); + break; + case CustomizationId.Face: + _ptr[(int) CustomizationId.Hairstyle] = (byte) (value * 2 - 1); + break; + } + } + } + + public Race Race + { + get => (Race) this[CustomizationId.Race]; + set => this[CustomizationId.Race] = (byte) value; + } + + public Gender Gender + { + get => (Gender) this[CustomizationId.Gender]; + set => this[CustomizationId.Gender] = (byte) value; + } + + public byte BodyType + { + get => this[CustomizationId.BodyType]; + set => this[CustomizationId.BodyType] = value; + } + + public byte Height + { + get => _ptr[(int) CustomizationId.Height]; + set => _ptr[(int) CustomizationId.Height] = value; + } + + public SubRace Clan + { + get => (SubRace) this[CustomizationId.Clan]; + set => this[CustomizationId.Clan] = (byte) value; + } + + public byte Face + { + get => this[CustomizationId.Face]; + set => this[CustomizationId.Face] = value; + } + + public byte Hairstyle + { + get => this[CustomizationId.Hairstyle]; + set => this[CustomizationId.Hairstyle] = value; + } + + public bool HighlightsOn + { + get => this[CustomizationId.HighlightsOnFlag] == 1; + set => this[CustomizationId.HighlightsOnFlag] = (byte) (value ? 1 : 0); + } + + public byte SkinColor + { + get => this[CustomizationId.SkinColor]; + set => this[CustomizationId.SkinColor] = value; + } + + public byte EyeColorRight + { + get => this[CustomizationId.EyeColorR]; + set => this[CustomizationId.EyeColorR] = value; + } + + public byte HairColor + { + get => this[CustomizationId.HairColor]; + set => this[CustomizationId.HairColor] = value; + } + + public byte HighlightsColor + { + get => this[CustomizationId.HighlightColor]; + set => this[CustomizationId.HighlightColor] = value; + } + + public bool FacialFeature(int idx) + => (this[CustomizationId.FacialFeaturesTattoos] & (1 << idx)) != 0; + + public void FacialFeature(int idx, bool set) + { + if (set) + this[CustomizationId.FacialFeaturesTattoos] |= (byte) (1 << idx); + else + this[CustomizationId.FacialFeaturesTattoos] &= (byte) ~(1 << idx); + } + + public byte FacialFeatures + { + get => this[CustomizationId.FacialFeaturesTattoos]; + set => this[CustomizationId.FacialFeaturesTattoos] = value; + } + + public byte TattooColor + { + get => this[CustomizationId.TattooColor]; + set => this[CustomizationId.TattooColor] = value; + } + + public byte Eyebrow + { + get => this[CustomizationId.Eyebrows]; + set => this[CustomizationId.Eyebrows] = value; + } + + public byte EyeColorLeft + { + get => this[CustomizationId.EyeColorL]; + set => this[CustomizationId.EyeColorL] = value; + } + + public byte Eye + { + get => this[CustomizationId.EyeShape]; + set => this[CustomizationId.EyeShape] = value; + } + + public bool SmallIris + { + get => (_ptr[(int) CustomizationId.EyeShape] & 128) == 128; + set => _ptr[(int) CustomizationId.EyeShape] = (byte) (this[CustomizationId.EyeShape] | (value ? 128u : 0u)); + } + + public byte Nose + { + get => _ptr[(int) CustomizationId.Nose]; + set => _ptr[(int) CustomizationId.Nose] = value; + } + + public byte Jaw + { + get => _ptr[(int) CustomizationId.Jaw]; + set => _ptr[(int) CustomizationId.Jaw] = value; + } + + public byte Mouth + { + get => this[CustomizationId.Mouth]; + set => this[CustomizationId.Mouth] = value; + } + + public bool LipstickSet + { + get => (_ptr[(int) CustomizationId.Mouth] & 128) == 128; + set => _ptr[(int) CustomizationId.Mouth] = (byte) (this[CustomizationId.Mouth] | (value ? 128u : 0u)); + } + + public byte LipColor + { + get => _ptr[(int) CustomizationId.LipColor]; + set => _ptr[(int) CustomizationId.LipColor] = value; + } + + public byte MuscleMass + { + get => _ptr[(int) CustomizationId.MuscleToneOrTailEarLength]; + set => _ptr[(int) CustomizationId.MuscleToneOrTailEarLength] = value; + } + + public byte TailShape + { + get => _ptr[(int) CustomizationId.TailEarShape]; + set => _ptr[(int) CustomizationId.TailEarShape] = value; + } + + public byte BustSize + { + get => _ptr[(int) CustomizationId.BustSize]; + set => _ptr[(int) CustomizationId.BustSize] = value; + } + + public byte FacePaint + { + get => this[CustomizationId.FacePaint]; + set => this[CustomizationId.FacePaint] = value; + } + + public bool FacePaintReversed + { + get => (_ptr[(int) CustomizationId.FacePaint] & 128) == 128; + set => _ptr[(int) CustomizationId.FacePaint] = (byte) (this[CustomizationId.FacePaint] | (value ? 128u : 0u)); + } + + public byte FacePaintColor + { + get => _ptr[(int) CustomizationId.FacePaintColor]; + set => _ptr[(int) CustomizationId.FacePaintColor] = value; + } + } +} diff --git a/Glamourer.zip b/Glamourer.zip index 694ece51c156ea51a3f0bbd556c39e7ba2ab1ebd..7ce7be88b8714a2d5fb9df93cc64a4bc459f439d 100644 GIT binary patch delta 34624 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 z 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 delta 30599 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�k1Qj8=>0Qz-(0NRCOj}0LH!oTjk6b|F z{TBb@T9A65G2`I8mnG$)Z?Uz*a7^HYC(&7j!1E)&yM(ama>x(%VYQNhH|VX5*8>q{ z$8#Wlx!SYo&Q0AyCcmj(*1C}{WSszb3NByz9+eNAuuASP{$1FSWZ+_qXjgY5(OmF^ z(@v9gq7y4gPf*DpAJ@i%n=tWkn)z_hIktQJ_L2GVDH7TUL(l*(^C^t)6q@65eOxj~ z95zQ4vLDE7)M?RNZCD*;*=#avp;};+<*{w5e@y~{ozgRA!CtG^IlE7-o%@`E;Iv!Q zsXbd0>dWB<;t^_b$RFhGMO!PF?_8QnPQxInG^I(?3-i)Ui94_2*Hrt#xcjkb6$Ow% zT$_+Zo{kMULIM!x;)C7rtR{?_Z$hOymR>G!@pH5%YC zYMd?UUC(ez?#K`<_-xV!U11eh#0<84ihX&ULv3d8aYFG=AvC!~jM5d{mVH^BwSjX} zntR{J`L(83Es8U|WYE<7Q7eDSan#D}-&hm-5%z=HBjF=|b~EKl+}=ZMLP2X0qUijo z^1BZa0obw)Rri6Vj|Rl+5AeI~>nlS|V}OP?%Kx4BHi;1GE8Wlk&+q+dYW|<4m@~-| z>MQ=w|7&>u@&)sM3;ugQ#+6h6^;H;x(mCk_>Z=gM$y^dW^jBU8zRe^n=&t}6hui;@ F{THd&D;)p; diff --git a/Glamourer/Glamourer.csproj b/Glamourer/Glamourer.csproj index 30c483c..536d05f 100644 --- a/Glamourer/Glamourer.csproj +++ b/Glamourer/Glamourer.csproj @@ -4,8 +4,8 @@ preview Glamourer Glamourer - 1.0.0.0 - 1.0.0.0 + 0.0.1.1 + 0.0.1.1 SoftOtter Glamourer Copyright © 2020 diff --git a/Glamourer/Glamourer.json b/Glamourer/Glamourer.json index 2f94105..9faa343 100644 --- a/Glamourer/Glamourer.json +++ b/Glamourer/Glamourer.json @@ -3,7 +3,7 @@ "Name": "Glamourer", "Description": "Adds functionality to change appearance of actors. Requires Penumbra to be installed and activated to work.", "InternalName": "Glamourer", - "AssemblyVersion": "0.0.1.0", + "AssemblyVersion": "0.0.1.1", "RepoUrl": "https://github.com/Ottermandias/Glamourer", "ApplicableVersion": "any", "DalamudApiLevel": 3, diff --git a/Glamourer/Gui/ComboWithFilter.cs b/Glamourer/Gui/ComboWithFilter.cs index 2729ff7..85b2dfc 100644 --- a/Glamourer/Gui/ComboWithFilter.cs +++ b/Glamourer/Gui/ComboWithFilter.cs @@ -15,6 +15,7 @@ namespace Glamourer.Gui private string _currentFilterLower = string.Empty; private bool _focus; private readonly float _size; + private readonly float _previewSize; private readonly IReadOnlyList _items; private readonly IReadOnlyList _itemNamesLower; private readonly Func _itemToName; @@ -31,7 +32,7 @@ namespace Glamourer.Gui public ImGuiComboFlags Flags { get; set; } = ImGuiComboFlags.None; public int ItemsAtOnce { get; set; } = 12; - public ComboWithFilter(string label, float size, IReadOnlyList items, Func itemToName) + public ComboWithFilter(string label, float size, float previewSize, IReadOnlyList items, Func itemToName) { _label = label; _filterLabel = $"##_{label}_filter"; @@ -39,6 +40,7 @@ namespace Glamourer.Gui _itemToName = itemToName; _items = items; _size = size; + _previewSize = previewSize; _itemNamesLower = _items.Select(i => _itemToName(i).ToLowerInvariant()).ToList(); } @@ -52,6 +54,7 @@ namespace Glamourer.Gui _items = other._items; _itemNamesLower = other._itemNamesLower; _size = other._size; + _previewSize = other._previewSize; PrePreview = other.PrePreview; PostPreview = other.PostPreview; CreateSelectable = other.CreateSelectable; @@ -130,7 +133,7 @@ namespace Glamourer.Gui public bool Draw(string currentName, out T? value) { value = default; - ImGui.SetNextItemWidth(_size); + ImGui.SetNextItemWidth(_previewSize); PrePreview?.Invoke(); if (!ImGui.BeginCombo(_label, currentName, Flags)) { diff --git a/Glamourer/Gui/Interface.cs b/Glamourer/Gui/Interface.cs index 95b9e7d..fa4a009 100644 --- a/Glamourer/Gui/Interface.cs +++ b/Glamourer/Gui/Interface.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; -using Dalamud.Data.LuminaExtensions; using Dalamud.Game.ClientState.Actors; using Dalamud.Game.ClientState.Actors.Types; +using Dalamud.Plugin; using Glamourer.Customization; using ImGuiNET; using Penumbra.Api; @@ -12,17 +12,17 @@ using Penumbra.GameData; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; using Penumbra.PlayerWatch; -using SDL2; namespace Glamourer.Gui { - internal class Interface : IDisposable + internal partial class Interface : IDisposable { public const int GPoseActorId = 201; private const string PluginName = "Glamourer"; private readonly string _glamourerHeader; - private const int ColorButtonWidth = 140; + private const float ColorButtonWidth = 22.5f; + private const float ColorComboWidth = 140f; private readonly IReadOnlyDictionary _stains; private readonly IReadOnlyDictionary> _equip; @@ -35,7 +35,11 @@ namespace Glamourer.Gui private Actor? _player; - private static readonly Vector2 FeatureIconSize = new(80, 80); + private static readonly Vector2 FeatureIconSizeIntern = + Vector2.One * ImGui.GetTextLineHeightWithSpacing() * 2 / ImGui.GetIO().FontGlobalScale; + + public static Vector2 FeatureIconSize + => FeatureIconSizeIntern * ImGui.GetIO().FontGlobalScale; public Interface() @@ -52,7 +56,7 @@ namespace Glamourer.Gui _actors = GlamourerPlugin.PluginInterface.ClientState.Actors; _playerWatcher = PlayerWatchFactory.Create(GlamourerPlugin.PluginInterface); - var stainCombo = new ComboWithFilter("##StainCombo", ColorButtonWidth, _stains.Values.ToArray(), + var stainCombo = new ComboWithFilter("##StainCombo", ColorComboWidth, ColorButtonWidth, _stains.Values.ToArray(), s => s.Name.ToString()) { Flags = ImGuiComboFlags.NoArrowButton | ImGuiComboFlags.HeightLarge, @@ -67,7 +71,7 @@ namespace Glamourer.Gui { var push = PushColor(s); var ret = ImGui.Button($"{s.Name}##Stain{(byte) s.RowIndex}", - Vector2.UnitX * (ColorButtonWidth - ImGui.GetStyle().ScrollbarSize)); + Vector2.UnitX * (ColorComboWidth - ImGui.GetStyle().ScrollbarSize)); ImGui.PopStyleColor(push); return ret; }, @@ -75,7 +79,7 @@ namespace Glamourer.Gui }; _combos = _equip.ToDictionary(kvp => kvp.Key, - kvp => (new ComboWithFilter($"{kvp.Key}##Equip", 300, kvp.Value, i => i.Name) { Flags = ImGuiComboFlags.HeightLarge } + kvp => (new ComboWithFilter($"{kvp.Key}##Equip", 300, 300, kvp.Value, i => i.Name) { Flags = ImGuiComboFlags.HeightLarge } , new ComboWithFilter($"##{kvp.Key}Stain", stainCombo)) ); } @@ -115,7 +119,7 @@ namespace Glamourer.Gui stainCombo.PostPreview = () => ImGui.PopStyleColor(previewPush); } - if (stainCombo.Draw(name, out var newStain) && _player != null) + if (stainCombo.Draw(string.Empty, out var newStain) && _player != null) { newStain.Write(_player.Address, slot); return true; @@ -176,101 +180,424 @@ namespace Glamourer.Gui private SubRace _currentSubRace = SubRace.Midlander; private Gender _currentGender = Gender.Male; - private CustomizationId _currentCustomization = CustomizationId.Hairstyle; private static readonly string[] SubRaceNames = ((SubRace[]) Enum.GetValues(typeof(SubRace))).Skip(1).Select(s => s.ToName()).ToArray(); - - private void DrawStuff() + private static bool DrawColorPickerPopup(string label, CustomizationSet set, CustomizationId id, out Customization.Customization value) { - if (ImGui.BeginCombo("SubRace", _currentSubRace.ToString())) + value = default; + if (!ImGui.BeginPopup(label, ImGuiWindowFlags.AlwaysAutoResize)) + return false; + + var ret = false; + var count = set.Count(id); + using var raii = new ImGuiRaii().PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero) + .PushStyle(ImGuiStyleVar.FrameRounding, 0); + for (var i = 0; i < count; ++i) + { + var custom = set.Data(id, i); + if (ImGui.ColorButton($"{i}", ImGui.ColorConvertU32ToFloat4(custom.Color))) + { + value = custom; + ret = true; + ImGui.CloseCurrentPopup(); + } + + if (i % 8 != 7) + ImGui.SameLine(); + } + + ImGui.EndPopup(); + return ret; + } + + private static void FixUpAttributes(CustomizationStruct customization) + { + var set = GlamourerPlugin.Customization.GetList(customization.Clan, customization.Gender); + foreach (CustomizationId id in Enum.GetValues(typeof(CustomizationId))) + { + switch (id) + { + case CustomizationId.Race: break; + case CustomizationId.Clan: break; + case CustomizationId.BodyType: break; + case CustomizationId.Gender: break; + case CustomizationId.FacialFeaturesTattoos: break; + case CustomizationId.Face: + if (customization.Race != Race.Hrothgar) + goto default; + break; + default: + var count = set.Count(id); + if (customization[id] >= count) + customization[id] = set.Data(id, 0).Value; + break; + } + } + } + + private static bool ChangeRace(CustomizationStruct customization, SubRace clan) + { + if (clan == customization.Clan) + return false; + + var race = clan.ToRace(); + customization.Race = race; + customization.Clan = clan; + + customization.Gender = race switch + { + Race.Hrothgar => Gender.Male, + Race.Viera => Gender.Female, + _ => customization.Gender, + }; + + FixUpAttributes(customization); + + return true; + } + + private static bool ChangeGender(CustomizationStruct customization, Gender gender) + { + if (gender == customization.Gender) + return false; + + customization.Gender = gender; + FixUpAttributes(customization); + + return true; + } + + private static bool DrawColorPicker(string label, string tooltip, CustomizationStruct customization, CustomizationId id, + CustomizationSet set) + { + var ret = false; + var count = set.Count(id); + + var current = set.DataByValue(id, customization[id], out var custom); + if (current < 0) + { + PluginLog.Warning($"Read invalid customization value {customization[id]} for {id}."); + current = 0; + custom = set.Data(id, 0); + } + + var popupName = $"Color Picker##{id}"; + if (ImGui.ColorButton($"{current}##color_{id}", ImGui.ColorConvertU32ToFloat4(custom!.Value.Color))) + ImGui.OpenPopup(popupName); + + ImGui.SameLine(); + ImGui.SetNextItemWidth(50 + 2 * 22.5f * ImGui.GetIO().FontGlobalScale); + if (ImGui.InputInt($"##text_{id}", ref current, 1) && current != customization[id] && current >= 0 && current < count) + { + customization[id] = set.Data(id, current).Value; + ret = true; + } + + if (ImGui.IsItemHovered()) + ImGui.SetTooltip($"Input Range: [0, {count - 1}]"); + + ImGui.SameLine(); + ImGui.Text(label); + if (tooltip.Any() && ImGui.IsItemHovered()) + ImGui.SetTooltip(tooltip); + + if (!DrawColorPickerPopup(popupName, set, id, out var newCustom)) + return ret; + + customization[id] = newCustom.Value; + ret = true; + + return ret; + } + + private static bool DrawListSelector(string label, string tooltip, CustomizationStruct customization, CustomizationId id, + CustomizationSet set) + { + var ret = false; + int current = customization[id]; + var count = set.Count(id); + + ImGui.SetNextItemWidth(150 * ImGui.GetIO().FontGlobalScale); + if (ImGui.BeginCombo($"##combo_{id}", $"{id} #{current + 1}")) + { + for (var i = 0; i < count; ++i) + { + if (ImGui.Selectable($"{id} #{i + 1}##combo", i == current) && i != current) + { + customization[id] = (byte) i; + ret = true; + } + } + + ImGui.EndCombo(); + } + + ImGui.SameLine(); + ImGui.SetNextItemWidth(50 + 2 * 22.5f * ImGui.GetIO().FontGlobalScale); + if (ImGui.InputInt($"##text_{id}", ref current, 1) && current != customization[id] && current >= 0 && current < count) + { + customization[id] = set.Data(id, current).Value; + ret = true; + } + + ImGui.SameLine(); + ImGui.Text(label); + if (tooltip.Any() && ImGui.IsItemHovered()) + ImGui.SetTooltip(tooltip); + + return ret; + } + + private static readonly Vector4 NoColor = new(1f, 1f, 1f, 1f); + private static readonly Vector4 RedColor = new(0.6f, 0.3f, 0.3f, 1f); + + private static bool DrawMultiSelector(CustomizationStruct customization, CustomizationSet set) + { + var ret = false; + var count = set.Count(CustomizationId.FacialFeaturesTattoos); + using var raii = new ImGuiRaii().PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemSpacing / 2); + for (var i = 0; i < count; ++i) + { + var enabled = customization.FacialFeature(i); + var feature = set.FacialFeature(set.Race == Race.Hrothgar ? customization.Hairstyle : customization.Face, i); + var icon = GlamourerPlugin.Customization.GetIcon(feature.IconId); + if (ImGui.ImageButton(icon.ImGuiHandle, FeatureIconSize, Vector2.Zero, Vector2.One, (int) ImGui.GetStyle().FramePadding.X, + Vector4.Zero, + enabled ? NoColor : RedColor)) + { + ret = true; + customization.FacialFeature(i, !enabled); + } + + if (ImGui.IsItemHovered()) + { + using var tt = ImGuiRaii.NewTooltip(); + ImGui.Image(icon.ImGuiHandle, new Vector2(icon.Width, icon.Height)); + } + + ImGui.SameLine(); + } + + raii.PopStyles(); + raii.Group(); + int value = customization[CustomizationId.FacialFeaturesTattoos]; + ImGui.SetNextItemWidth(50 + 2 * 22.5f * ImGui.GetIO().FontGlobalScale); + if (ImGui.InputInt($"##{CustomizationId.FacialFeaturesTattoos}", ref value, 1) + && value != customization[CustomizationId.FacialFeaturesTattoos] + && value > 0 + && value < 256) + { + customization[CustomizationId.FacialFeaturesTattoos] = (byte) value; + ret = true; + } + + ImGui.Text("Facial Features & Tattoos"); + + + return ret; + } + + private static bool DrawIconPickerPopup(string label, CustomizationSet set, CustomizationId id, out Customization.Customization value) + { + value = default; + if (!ImGui.BeginPopup(label, ImGuiWindowFlags.AlwaysAutoResize)) + return false; + + var ret = false; + var count = set.Count(id); + using var raii = new ImGuiRaii().PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero) + .PushStyle(ImGuiStyleVar.FrameRounding, 0); + for (var i = 0; i < count; ++i) + { + var custom = set.Data(id, i); + var icon = GlamourerPlugin.Customization.GetIcon(custom.IconId); + if (ImGui.ImageButton(icon.ImGuiHandle, FeatureIconSize)) + { + value = custom; + ret = true; + ImGui.CloseCurrentPopup(); + } + + if (ImGui.IsItemHovered()) + { + using var tt = ImGuiRaii.NewTooltip(); + ImGui.Image(icon.ImGuiHandle, new Vector2(icon.Width, icon.Height)); + } + + if (i % 8 != 7) + ImGui.SameLine(); + } + + ImGui.EndPopup(); + return ret; + } + + private static bool DrawIconSelector(string label, string tooltip, CustomizationStruct customization, CustomizationId id, + CustomizationSet set) + { + var ret = false; + var count = set.Count(id); + + var current = set.DataByValue(id, customization[id], out var custom); + if (current < 0) + { + PluginLog.Warning($"Read invalid customization value {customization[id]} for {id}."); + current = 0; + custom = set.Data(id, 0); + } + + var popupName = $"Style Picker##{id}"; + var icon = GlamourerPlugin.Customization.GetIcon(custom!.Value.IconId); + if (ImGui.ImageButton(icon.ImGuiHandle, FeatureIconSize)) + ImGui.OpenPopup(popupName); + + if (ImGui.IsItemHovered()) + { + using var tt = ImGuiRaii.NewTooltip(); + ImGui.Image(icon.ImGuiHandle, new Vector2(icon.Width, icon.Height)); + } + + ImGui.SameLine(); + using var group = ImGuiRaii.NewGroup(); + ImGui.SetNextItemWidth(50 + 2 * 22.5f * ImGui.GetIO().FontGlobalScale); + var oldIdx = current; + if (ImGui.InputInt($"##text_{id}", ref current, 1) && current != oldIdx && current >= 0 && current < count) + { + customization[id] = set.Data(id, current).Value; + ret = true; + } + + if (ImGui.IsItemHovered()) + ImGui.SetTooltip($"Input Range: [0, {count - 1}]"); + + if (DrawIconPickerPopup(popupName, set, id, out var newCustom)) + { + customization[id] = newCustom.Value; + ret = true; + } + + ImGui.Text(label); + if (tooltip.Any() && ImGui.IsItemHovered()) + ImGui.SetTooltip(tooltip); + + return ret; + } + + + private static bool DrawPercentageSelector(string label, string tooltip, CustomizationStruct customization, CustomizationId id, + CustomizationSet set) + { + var ret = false; + int value = customization[id]; + var count = set.Count(id); + ImGui.SetNextItemWidth(150 * ImGui.GetIO().FontGlobalScale); + if (ImGui.SliderInt($"##slider_{id}", ref value, 0, count - 1, "") && value != customization[id]) + { + customization[id] = (byte) value; + ret = true; + } + + ImGui.SameLine(); + ImGui.SetNextItemWidth(50 + 2 * 22.5f * ImGui.GetIO().FontGlobalScale); + if (ImGui.InputInt($"##input_{id}", ref value, 1) && value != customization[id] && value >= 0 && value < count) + { + customization[id] = (byte) value; + ret = true; + } + + if (ImGui.IsItemHovered()) + ImGui.SetTooltip($"Input Range: [0, {count - 1}]"); + + ImGui.SameLine(); + ImGui.Text(label); + if (tooltip.Any() && ImGui.IsItemHovered()) + ImGui.SetTooltip(tooltip); + + return ret; + } + + private bool DrawStuff() + { + var ret = false; + var x = new CustomizationStruct(_player!.Address + 0x1898); + _currentSubRace = x.Clan; + ImGui.SetNextItemWidth(150 * ImGui.GetIO().FontGlobalScale); + if (ImGui.BeginCombo("SubRace", SubRaceNames[(int) _currentSubRace - 1])) { for (var i = 0; i < SubRaceNames.Length; ++i) { if (ImGui.Selectable(SubRaceNames[i], (int) _currentSubRace == i + 1)) - _currentSubRace = (SubRace) (i + 1); + { + _currentSubRace = (SubRace) i + 1; + ret |= ChangeRace(x, _currentSubRace); + } } ImGui.EndCombo(); } + _currentGender = x.Gender; + ImGui.SetNextItemWidth(150 * ImGui.GetIO().FontGlobalScale); if (ImGui.BeginCombo("Gender", _currentGender.ToName())) { - if (ImGui.Selectable(Gender.Male.ToName(), _currentGender == Gender.Male)) + if (_currentSubRace.ToRace() != Race.Viera + && ImGui.Selectable(Gender.Male.ToName(), _currentGender == Gender.Male) + && _currentGender != Gender.Male) + { _currentGender = Gender.Male; - if (ImGui.Selectable(Gender.Female.ToName(), _currentGender == Gender.Female)) + ret = ChangeGender(x, _currentGender); + } + + if (_currentSubRace.ToRace() != Race.Hrothgar + && ImGui.Selectable(Gender.Female.ToName(), _currentGender == Gender.Female) + && _currentGender != Gender.Female) + { _currentGender = Gender.Female; + ret = ChangeGender(x, _currentGender); + } + ImGui.EndCombo(); } - var set = GlamourerPlugin.Customization.GetList(_currentSubRace, _currentGender); - if (ImGui.BeginCombo("Customization", _currentCustomization.ToString())) + + + foreach (CustomizationId customizationId in Enum.GetValues(typeof(CustomizationId))) { - foreach (CustomizationId customizationId in Enum.GetValues(typeof(CustomizationId))) + if (!set.IsAvailable(customizationId)) + continue; + + switch (customizationId.ToType(_currentSubRace.ToRace() == Race.Hrothgar)) { - if (!set.IsAvailable(customizationId)) - continue; - - if (ImGui.Selectable(customizationId.ToString(), customizationId == _currentCustomization)) - _currentCustomization = customizationId; + case CharaMakeParams.MenuType.ColorPicker: + ret |= DrawColorPicker(customizationId.ToString(), "", x, + customizationId, set); + break; + case CharaMakeParams.MenuType.ListSelector: + ret |= DrawListSelector(customizationId.ToString(), "", x, + customizationId, set); + break; + case CharaMakeParams.MenuType.IconSelector: + ret |= DrawIconSelector(customizationId.ToString(), "", x, customizationId, set); + break; + case CharaMakeParams.MenuType.MultiIconSelector: + ret |= DrawMultiSelector(x, set); + break; + case CharaMakeParams.MenuType.Percentage: + ret |= DrawPercentageSelector(customizationId.ToString(), "", x, customizationId, set); + break; } - - ImGui.EndCombo(); } - var count = set.Count(_currentCustomization); - var tmp = 0; - switch (_currentCustomization.ToType(_currentSubRace.ToRace() == Race.Hrothgar)) - { - case CharaMakeParams.MenuType.ColorPicker: - { - using var raii = new ImGuiRaii().PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero) - .PushStyle(ImGuiStyleVar.FrameRounding, 0f); - for (var i = 0; i < count; ++i) - { - var data = set.Data(_currentCustomization, i); - ImGui.ColorButton($"{data.Value}", ImGui.ColorConvertU32ToFloat4(data.Color)); - if (i % 8 != 7) - ImGui.SameLine(); - } - } - break; - case CharaMakeParams.MenuType.Percentage: - ImGui.SliderInt("Percentage", ref tmp, 0, 100); - break; - case CharaMakeParams.MenuType.ListSelector: - ImGui.Combo("List", ref tmp, Enumerable.Range(0, count).Select(i => $"{_currentCustomization} #{i}").ToArray(), count); - break; - case CharaMakeParams.MenuType.IconSelector: - case CharaMakeParams.MenuType.MultiIconSelector: - { - using var raii = new ImGuiRaii().PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero) - .PushStyle(ImGuiStyleVar.FrameRounding, 0f); - for (var i = 0; i < count; ++i) - { - var data = set.Data(_currentCustomization, i); - var texture = GlamourerPlugin.Customization.GetIcon(data.IconId); - ImGui.ImageButton(texture.ImGuiHandle, FeatureIconSize * ImGui.GetIO().FontGlobalScale); - if (ImGui.IsItemHovered()) - { - using var tooltip = ImGuiRaii.NewTooltip(); - ImGui.Image(texture.ImGuiHandle, new Vector2(texture.Width, texture.Height)); - } - - if (i % 4 != 3) - ImGui.SameLine(); - } - } - break; - } + return ret; } private void Draw() { ImGui.SetNextWindowSizeConstraints(Vector2.One * 600, Vector2.One * 5000); - if (!_visible || !ImGui.Begin(_glamourerHeader)) + if (!_visible || !ImGui.Begin(_glamourerHeader, ref _visible)) return; try @@ -311,11 +638,11 @@ namespace Glamourer.Gui changes |= DrawEquip(EquipSlot.RFinger, equip.RFinger); changes |= DrawEquip(EquipSlot.LFinger, equip.LFinger); + changes |= DrawStuff(); + if (changes) UpdateActors(_player); } - - DrawStuff(); } finally { diff --git a/repo.json b/repo.json index de6d45b..438abcd 100644 --- a/repo.json +++ b/repo.json @@ -4,8 +4,8 @@ "Name": "Glamourer", "Description": "Adds functionality to change appearance of actors. Requires Penumbra to be installed and activated to work.", "InternalName": "Glamourer", - "AssemblyVersion": "0.0.1.0", - "TestingAssemblyVersion": "0.0.1.0", + "AssemblyVersion": "0.0.1.1", + "TestingAssemblyVersion": "0.0.1.1", "RepoUrl": "https://github.com/Ottermandias/Glamourer", "ApplicableVersion": "any", "DalamudApiLevel": 3,