diff --git a/Glamourer.GameData/GameData.cs b/Glamourer.GameData/GameData.cs index b2766d5..2878c91 100644 --- a/Glamourer.GameData/GameData.cs +++ b/Glamourer.GameData/GameData.cs @@ -51,7 +51,7 @@ namespace Glamourer => new(sheet.First(), "Nothing", slot); static Item EmptyNpc(EquipSlot slot) - => new(new Lumina.Excel.GeneratedSheets.Item() { ModelMain = 9903 }, "Smallclothes (NPC)", slot); + => new(new Lumina.Excel.GeneratedSheets.Item() { ModelMain = 9903, RowId = 1 }, "Smallclothes (NPC)", slot); _itemsBySlot = new Dictionary>() { diff --git a/Glamourer.zip b/Glamourer.zip index ef86c1f..52101bb 100644 Binary files a/Glamourer.zip and b/Glamourer.zip differ diff --git a/Glamourer/Glamourer.csproj b/Glamourer/Glamourer.csproj index 71e7305..f9042b4 100644 --- a/Glamourer/Glamourer.csproj +++ b/Glamourer/Glamourer.csproj @@ -5,8 +5,8 @@ x64 Glamourer Glamourer - 0.1.3.0 - 0.1.3.0 + 0.1.3.1 + 0.1.3.1 SoftOtter Glamourer Copyright © 2020 diff --git a/Glamourer/Glamourer.json b/Glamourer/Glamourer.json index 0c1c024..13db08a 100644 --- a/Glamourer/Glamourer.json +++ b/Glamourer/Glamourer.json @@ -5,7 +5,7 @@ "Description": "Adds functionality to change and store appearance of players, customization and equip. Requires Penumbra to be installed and activated to work. Can also add preview options to the Changed Items tab for Penumbra.", "Tags": [ "Appearance", "Glamour", "Race", "Outfit", "Armor", "Clothes", "Skins", "Customization", "Design", "Character" ], "InternalName": "Glamourer", - "AssemblyVersion": "0.1.3.0", + "AssemblyVersion": "0.1.3.1", "RepoUrl": "https://github.com/Ottermandias/Glamourer", "ApplicableVersion": "any", "DalamudApiLevel": 8, diff --git a/Glamourer/Gui/InterfaceActorPanel.cs b/Glamourer/Gui/InterfaceActorPanel.cs index 3ff2f14..701fc5a 100644 --- a/Glamourer/Gui/InterfaceActorPanel.cs +++ b/Glamourer/Gui/InterfaceActorPanel.cs @@ -1,9 +1,6 @@ using System; using System.Linq; using System.Numerics; -using System.Reflection; -using Dalamud.Game.ClientState.Objects.Enums; -using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Interface; using Dalamud.Logging; @@ -11,7 +8,6 @@ using Glamourer.Customization; using Glamourer.Designs; using Glamourer.FileSystem; using ImGuiNET; -using Penumbra.GameData.Structs; using Penumbra.PlayerWatch; namespace Glamourer.Gui diff --git a/Glamourer/Gui/InterfaceEquipment.cs b/Glamourer/Gui/InterfaceEquipment.cs index 3bd94c4..28667a6 100644 --- a/Glamourer/Gui/InterfaceEquipment.cs +++ b/Glamourer/Gui/InterfaceEquipment.cs @@ -1,237 +1,237 @@ -using System.Collections; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using ImGuiNET; -using Lumina.Text; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; using Penumbra.PlayerWatch; -namespace Glamourer.Gui +namespace Glamourer.Gui; + +internal partial class Interface { - internal partial class Interface + private bool DrawStainSelector(ComboWithFilter stainCombo, EquipSlot slot, StainId stainIdx) { - private bool DrawStainSelector(ComboWithFilter stainCombo, EquipSlot slot, StainId stainIdx) + stainCombo.PostPreview = null; + if (_stains.TryGetValue((byte)stainIdx, out var stain)) { - stainCombo.PostPreview = null; - if (_stains.TryGetValue((byte) stainIdx, out var stain)) - { - var previewPush = PushColor(stain, ImGuiCol.FrameBg); - stainCombo.PostPreview = () => ImGui.PopStyleColor(previewPush); - } - - var change = stainCombo.Draw(string.Empty, out var newStain) && !newStain.RowIndex.Equals(stainIdx); - if (!change && (byte) stainIdx != 0) - { - ImGuiCustom.HoverTooltip("Right-click to clear."); - if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) - { - change = true; - newStain = Stain.None; - } - } - - if (!change) - return false; - - if (_player == null) - return _inDesignMode && (_selection?.Data.WriteStain(slot, newStain.RowIndex) ?? false); - - Glamourer.RevertableDesigns.Add(_player); - newStain.Write(_player.Address, slot); - return true; - + var previewPush = PushColor(stain, ImGuiCol.FrameBg); + stainCombo.PostPreview = () => ImGui.PopStyleColor(previewPush); } - private bool DrawGlobalStainSelector(ComboWithFilter stainCombo) + var change = stainCombo.Draw(string.Empty, out var newStain) && !newStain.RowIndex.Equals(stainIdx); + if (!change && (byte)stainIdx != 0) { - stainCombo.PostPreview = null; - - var change = stainCombo.Draw(string.Empty, out var newStain); - ImGui.SameLine(); - ImGui.TextUnformatted("Dye All Slots"); - if (!change) + ImGuiCustom.HoverTooltip("Right-click to clear."); + if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) { - ImGuiCustom.HoverTooltip("Right-click to clear."); - if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) - { - change = true; - newStain = Stain.None; - } + change = true; + newStain = Stain.None; } + } - if (!change) - return false; + if (!change) + return false; - if (_player == null) + if (_player == null) + return _inDesignMode && (_selection?.Data.WriteStain(slot, newStain.RowIndex) ?? false); + + Glamourer.RevertableDesigns.Add(_player); + newStain.Write(_player.Address, slot); + return true; + } + + private bool DrawGlobalStainSelector(ComboWithFilter stainCombo) + { + stainCombo.PostPreview = null; + + var change = stainCombo.Draw(string.Empty, out var newStain); + ImGui.SameLine(); + ImGui.TextUnformatted("Dye All Slots"); + if (!change) + { + ImGuiCustom.HoverTooltip("Right-click to clear."); + if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) { - foreach (var key in GetEquipSlotNames().Keys) - { - if (key is EquipSlot.OffHand && _selection?.Data.Equipment.OffHand.Set.Value == 0) - continue; - _selection?.Data.WriteStain(key, newStain.RowIndex); - } - return _inDesignMode; + change = true; + newStain = Stain.None; } + } - Glamourer.RevertableDesigns.Add(_player); + if (!change) + return false; + + if (_player == null) + { foreach (var key in GetEquipSlotNames().Keys) { - newStain.Write(_player.Address, key); - } - - return true; - } + if (key is EquipSlot.OffHand && _selection?.Data.Equipment.OffHand.Set.Value == 0) + continue; - private bool DrawItemSelector(ComboWithFilter equipCombo, Lumina.Excel.GeneratedSheets.Item item, EquipSlot slot = EquipSlot.Unknown) - { - var currentName = item.Name.ToString(); - var change = equipCombo.Draw(currentName, out var newItem, _itemComboWidth) && newItem.Base.RowId != item.RowId; - if (!change && !ReferenceEquals(item, SmallClothes)) - { - ImGuiCustom.HoverTooltip("Right-click to clear."); - if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) - { - change = true; - newItem = Item.Nothing(slot); - } + _selection?.Data.WriteStain(key, newStain.RowIndex); } - if (!change) - return false; - - newItem = new Item(newItem.Base, newItem.Name, slot); - if (_player == null) - return _inDesignMode && (_selection?.Data.WriteItem(newItem) ?? false); - - Glamourer.RevertableDesigns.Add(_player); - newItem.Write(_player.Address); - return true; - + return _inDesignMode; } - private static bool DrawCheckbox(CharacterEquipMask flag, ref CharacterEquipMask mask) + Glamourer.RevertableDesigns.Add(_player); + foreach (var key in GetEquipSlotNames().Keys) + newStain.Write(_player.Address, key); + + return true; + } + + private bool DrawItemSelector(ComboWithFilter equipCombo, EquipItem item, EquipSlot slot = EquipSlot.Unknown) + { + var currentName = item.Name; + var change = equipCombo.Draw(currentName, out var newItem, _itemComboWidth) && newItem.Base.RowId != item.Id; + if (!change && item.Name != SmallClothes.Name) { - var tmp = (uint) mask; - var ret = false; - if (ImGui.CheckboxFlags($"##flag_{(uint) flag}", ref tmp, (uint) flag) && tmp != (uint) mask) + ImGuiCustom.HoverTooltip("Right-click to clear."); + if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) { - mask = (CharacterEquipMask) tmp; - ret = true; + change = true; + newItem = Item.Nothing(slot); } - - if (ImGui.IsItemHovered()) - ImGui.SetTooltip("Enable writing this slot in this save."); - return ret; } - private static readonly Lumina.Excel.GeneratedSheets.Item SmallClothes = new(){ Name = new SeString("Nothing"), RowId = 0 }; - private static readonly Lumina.Excel.GeneratedSheets.Item SmallClothesNpc = new(){ Name = new SeString("Smallclothes (NPC)"), RowId = 1 }; - private static readonly Lumina.Excel.GeneratedSheets.Item Unknown = new(){ Name = new SeString("Unknown"), RowId = 2 }; + if (!change) + return false; - private Lumina.Excel.GeneratedSheets.Item Identify(SetId set, WeaponType weapon, ushort variant, EquipSlot slot) + newItem = new Item(newItem.Base, newItem.Name, slot); + if (_player == null) + return _inDesignMode && (_selection?.Data.WriteItem(newItem) ?? false); + + Glamourer.RevertableDesigns.Add(_player); + newItem.Write(_player.Address); + return true; + } + + private static bool DrawCheckbox(CharacterEquipMask flag, ref CharacterEquipMask mask) + { + var tmp = (uint)mask; + var ret = false; + if (ImGui.CheckboxFlags($"##flag_{(uint)flag}", ref tmp, (uint)flag) && tmp != (uint)mask) { - return (uint) set switch - { - 0 => SmallClothes, - 9903 => SmallClothesNpc, - _ => ToItem(_identifier.Identify(set, weapon, variant, slot.ToSlot())), - }; + mask = (CharacterEquipMask)tmp; + ret = true; } - private Lumina.Excel.GeneratedSheets.Item ToItem(IEnumerable items) + if (ImGui.IsItemHovered()) + ImGui.SetTooltip("Enable writing this slot in this save."); + return ret; + } + + private static readonly EquipItem SmallClothes = new("Nothing", 0, 0, 0, 0, 0, 0, EquipSlot.Unknown); + private static readonly EquipItem SmallClothesNpc = new("Smallclothes (NPC)", 1, 0, 9903, 0, 1, 0, EquipSlot.Unknown); + private static readonly EquipItem Unknown = new("Unknown", 3, 0, 0, 0, 0, 0, EquipSlot.Unknown); + + private EquipItem Identify(SetId set, WeaponType weapon, ushort variant, EquipSlot slot) + { + return (uint)set switch { - var item = items.FirstOrDefault(); - if (item.Valid) - return Dalamud.GameData.GetExcelSheet()!.GetRow(item.Id) ?? Unknown; + 0 => SmallClothes, + 9903 => SmallClothesNpc, + _ => ToItem(_identifier.Identify(set, weapon, variant, slot.ToSlot())), + }; + } - return Unknown; - } + private static EquipItem ToItem(IEnumerable items) + { + var item = items.FirstOrDefault(); + if (item.Valid) + return item; - private bool DrawEquipSlot(EquipSlot slot, CharacterArmor equip) + return Unknown; + } + + private bool DrawEquipSlot(EquipSlot slot, CharacterArmor equip) + { + var (equipCombo, stainCombo) = _combos[slot]; + + var ret = DrawStainSelector(stainCombo, slot, equip.Stain); + ImGui.SameLine(); + var item = Identify(equip.Set, new WeaponType(), equip.Variant, slot); + if (item.Name == Unknown.Name) + item = new EquipItem($"Unknown ({item.ModelId.Value}, {item.Variant})", 0, 0, equip.Set, 0, equip.Variant, + FullEquipType.Unknown, slot); + ret |= DrawItemSelector(equipCombo, item, slot); + + return ret; + } + + private bool DrawEquipSlotWithCheck(EquipSlot slot, CharacterArmor equip, CharacterEquipMask flag, ref CharacterEquipMask mask) + { + var ret = DrawCheckbox(flag, ref mask); + ImGui.SameLine(); + ret |= DrawEquipSlot(slot, equip); + return ret; + } + + private bool DrawWeapon(EquipSlot slot, CharacterWeapon weapon) + { + var (equipCombo, stainCombo) = _combos[slot]; + + var ret = DrawStainSelector(stainCombo, slot, weapon.Stain); + ImGui.SameLine(); + var item = Identify(weapon.Set, weapon.Type, weapon.Variant, slot); + if (item.Name == Unknown.Name) + item = new EquipItem($"Unknown ({weapon.Set.Value}, {weapon.Type.Value}, {weapon.Variant})", 0, 0, weapon.Set, weapon.Type, (byte) weapon.Variant, FullEquipType.Unknown, slot); + ret |= DrawItemSelector(equipCombo, item, slot); + + return ret; + } + + private bool DrawWeaponWithCheck(EquipSlot slot, CharacterWeapon weapon, CharacterEquipMask flag, ref CharacterEquipMask mask) + { + var ret = DrawCheckbox(flag, ref mask); + ImGui.SameLine(); + ret |= DrawWeapon(slot, weapon); + return ret; + } + + private bool DrawEquip(CharacterEquipment equip) + { + var ret = false; + if (ImGui.CollapsingHeader("Character Equipment")) { - var (equipCombo, stainCombo) = _combos[slot]; - - var ret = DrawStainSelector(stainCombo, slot, equip.Stain); - ImGui.SameLine(); - var item = Identify(equip.Set, new WeaponType(), equip.Variant, slot); - ret |= DrawItemSelector(equipCombo, item, slot); - - return ret; + ret |= DrawGlobalStainSelector(_globalStainCombo); + ret |= DrawWeapon(EquipSlot.MainHand, equip.MainHand); + ret |= DrawWeapon(EquipSlot.OffHand, equip.OffHand); + ret |= DrawEquipSlot(EquipSlot.Head, equip.Head); + ret |= DrawEquipSlot(EquipSlot.Body, equip.Body); + ret |= DrawEquipSlot(EquipSlot.Hands, equip.Hands); + ret |= DrawEquipSlot(EquipSlot.Legs, equip.Legs); + ret |= DrawEquipSlot(EquipSlot.Feet, equip.Feet); + ret |= DrawEquipSlot(EquipSlot.Ears, equip.Ears); + ret |= DrawEquipSlot(EquipSlot.Neck, equip.Neck); + ret |= DrawEquipSlot(EquipSlot.Wrists, equip.Wrists); + ret |= DrawEquipSlot(EquipSlot.RFinger, equip.RFinger); + ret |= DrawEquipSlot(EquipSlot.LFinger, equip.LFinger); } - private bool DrawEquipSlotWithCheck(EquipSlot slot, CharacterArmor equip, CharacterEquipMask flag, ref CharacterEquipMask mask) + return ret; + } + + private bool DrawEquip(CharacterEquipment equip, ref CharacterEquipMask mask) + { + var ret = false; + if (ImGui.CollapsingHeader("Character Equipment")) { - var ret = DrawCheckbox(flag, ref mask); - ImGui.SameLine(); - ret |= DrawEquipSlot(slot, equip); - return ret; + ret |= DrawGlobalStainSelector(_globalStainCombo); + ret |= DrawWeaponWithCheck(EquipSlot.MainHand, equip.MainHand, CharacterEquipMask.MainHand, ref mask); + ret |= DrawWeaponWithCheck(EquipSlot.OffHand, equip.OffHand, CharacterEquipMask.OffHand, ref mask); + ret |= DrawEquipSlotWithCheck(EquipSlot.Head, equip.Head, CharacterEquipMask.Head, ref mask); + ret |= DrawEquipSlotWithCheck(EquipSlot.Body, equip.Body, CharacterEquipMask.Body, ref mask); + ret |= DrawEquipSlotWithCheck(EquipSlot.Hands, equip.Hands, CharacterEquipMask.Hands, ref mask); + ret |= DrawEquipSlotWithCheck(EquipSlot.Legs, equip.Legs, CharacterEquipMask.Legs, ref mask); + ret |= DrawEquipSlotWithCheck(EquipSlot.Feet, equip.Feet, CharacterEquipMask.Feet, ref mask); + ret |= DrawEquipSlotWithCheck(EquipSlot.Ears, equip.Ears, CharacterEquipMask.Ears, ref mask); + ret |= DrawEquipSlotWithCheck(EquipSlot.Neck, equip.Neck, CharacterEquipMask.Neck, ref mask); + ret |= DrawEquipSlotWithCheck(EquipSlot.Wrists, equip.Wrists, CharacterEquipMask.Wrists, ref mask); + ret |= DrawEquipSlotWithCheck(EquipSlot.RFinger, equip.RFinger, CharacterEquipMask.RFinger, ref mask); + ret |= DrawEquipSlotWithCheck(EquipSlot.LFinger, equip.LFinger, CharacterEquipMask.LFinger, ref mask); } - private bool DrawWeapon(EquipSlot slot, CharacterWeapon weapon) - { - var (equipCombo, stainCombo) = _combos[slot]; - - var ret = DrawStainSelector(stainCombo, slot, weapon.Stain); - ImGui.SameLine(); - var item = Identify(weapon.Set, weapon.Type, weapon.Variant, slot); - ret |= DrawItemSelector(equipCombo, item, slot); - - return ret; - } - - private bool DrawWeaponWithCheck(EquipSlot slot, CharacterWeapon weapon, CharacterEquipMask flag, ref CharacterEquipMask mask) - { - var ret = DrawCheckbox(flag, ref mask); - ImGui.SameLine(); - ret |= DrawWeapon(slot, weapon); - return ret; - } - - private bool DrawEquip(CharacterEquipment equip) - { - var ret = false; - if (ImGui.CollapsingHeader("Character Equipment")) - { - ret |= DrawGlobalStainSelector(_globalStainCombo); - ret |= DrawWeapon(EquipSlot.MainHand, equip.MainHand); - ret |= DrawWeapon(EquipSlot.OffHand, equip.OffHand); - ret |= DrawEquipSlot(EquipSlot.Head, equip.Head); - ret |= DrawEquipSlot(EquipSlot.Body, equip.Body); - ret |= DrawEquipSlot(EquipSlot.Hands, equip.Hands); - ret |= DrawEquipSlot(EquipSlot.Legs, equip.Legs); - ret |= DrawEquipSlot(EquipSlot.Feet, equip.Feet); - ret |= DrawEquipSlot(EquipSlot.Ears, equip.Ears); - ret |= DrawEquipSlot(EquipSlot.Neck, equip.Neck); - ret |= DrawEquipSlot(EquipSlot.Wrists, equip.Wrists); - ret |= DrawEquipSlot(EquipSlot.RFinger, equip.RFinger); - ret |= DrawEquipSlot(EquipSlot.LFinger, equip.LFinger); - } - - return ret; - } - - private bool DrawEquip(CharacterEquipment equip, ref CharacterEquipMask mask) - { - var ret = false; - if (ImGui.CollapsingHeader("Character Equipment")) - { - ret |= DrawGlobalStainSelector(_globalStainCombo); - ret |= DrawWeaponWithCheck(EquipSlot.MainHand, equip.MainHand, CharacterEquipMask.MainHand, ref mask); - ret |= DrawWeaponWithCheck(EquipSlot.OffHand, equip.OffHand, CharacterEquipMask.OffHand, ref mask); - ret |= DrawEquipSlotWithCheck(EquipSlot.Head, equip.Head, CharacterEquipMask.Head, ref mask); - ret |= DrawEquipSlotWithCheck(EquipSlot.Body, equip.Body, CharacterEquipMask.Body, ref mask); - ret |= DrawEquipSlotWithCheck(EquipSlot.Hands, equip.Hands, CharacterEquipMask.Hands, ref mask); - ret |= DrawEquipSlotWithCheck(EquipSlot.Legs, equip.Legs, CharacterEquipMask.Legs, ref mask); - ret |= DrawEquipSlotWithCheck(EquipSlot.Feet, equip.Feet, CharacterEquipMask.Feet, ref mask); - ret |= DrawEquipSlotWithCheck(EquipSlot.Ears, equip.Ears, CharacterEquipMask.Ears, ref mask); - ret |= DrawEquipSlotWithCheck(EquipSlot.Neck, equip.Neck, CharacterEquipMask.Neck, ref mask); - ret |= DrawEquipSlotWithCheck(EquipSlot.Wrists, equip.Wrists, CharacterEquipMask.Wrists, ref mask); - ret |= DrawEquipSlotWithCheck(EquipSlot.RFinger, equip.RFinger, CharacterEquipMask.RFinger, ref mask); - ret |= DrawEquipSlotWithCheck(EquipSlot.LFinger, equip.LFinger, CharacterEquipMask.LFinger, ref mask); - } - - return ret; - } + return ret; } } diff --git a/repo.json b/repo.json index 12957eb..014c650 100644 --- a/repo.json +++ b/repo.json @@ -6,8 +6,8 @@ "Description": "Adds functionality to change and store appearance of players, customization and equip. Requires Penumbra to be installed and activated to work. Can also add preview options to the Changed Items tab for Penumbra.", "Tags": [ "Appearance", "Glamour", "Race", "Outfit", "Armor", "Clothes", "Skins", "Customization", "Design", "Character" ], "InternalName": "Glamourer", - "AssemblyVersion": "0.1.3.0", - "TestingAssemblyVersion": "0.1.3.0", + "AssemblyVersion": "0.1.3.1", + "TestingAssemblyVersion": "0.1.3.1", "RepoUrl": "https://github.com/Ottermandias/Glamourer", "ApplicableVersion": "any", "DalamudApiLevel": 8,