mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
bl
This commit is contained in:
parent
cfd9000303
commit
1fbd43fea2
12 changed files with 470 additions and 184 deletions
|
|
@ -24,11 +24,17 @@ public unsafe struct Customize
|
||||||
set => Data->Data[1] = (byte)(value - 1);
|
set => Data->Data[1] = (byte)(value - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref byte BodyType
|
public byte BodyType
|
||||||
=> ref Data->Data[2];
|
{
|
||||||
|
get => Data->Data[2];
|
||||||
|
set => Data->Data[2] = value;
|
||||||
|
}
|
||||||
|
|
||||||
public ref byte Height
|
public byte Height
|
||||||
=> ref Data->Data[3];
|
{
|
||||||
|
get => Data->Data[3];
|
||||||
|
set => Data->Data[3] = value;
|
||||||
|
}
|
||||||
|
|
||||||
public SubRace Clan
|
public SubRace Clan
|
||||||
{
|
{
|
||||||
|
|
@ -36,11 +42,17 @@ public unsafe struct Customize
|
||||||
set => Data->Data[4] = (byte)value;
|
set => Data->Data[4] = (byte)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref byte Face
|
public byte Face
|
||||||
=> ref Data->Data[5];
|
{
|
||||||
|
get => Data->Data[5];
|
||||||
|
set => Data->Data[5] = value;
|
||||||
|
}
|
||||||
|
|
||||||
public ref byte Hairstyle
|
public byte Hairstyle
|
||||||
=> ref Data->Data[6];
|
{
|
||||||
|
get => Data->Data[6];
|
||||||
|
set => Data->Data[6] = value;
|
||||||
|
}
|
||||||
|
|
||||||
public bool HighlightsOn
|
public bool HighlightsOn
|
||||||
{
|
{
|
||||||
|
|
@ -48,17 +60,29 @@ public unsafe struct Customize
|
||||||
set => Data->Data[7] = (byte)(value ? Data->Data[7] | 0x80 : Data->Data[7] & 0x7F);
|
set => Data->Data[7] = (byte)(value ? Data->Data[7] | 0x80 : Data->Data[7] & 0x7F);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref byte SkinColor
|
public byte SkinColor
|
||||||
=> ref Data->Data[8];
|
{
|
||||||
|
get => Data->Data[8];
|
||||||
|
set => Data->Data[8] = value;
|
||||||
|
}
|
||||||
|
|
||||||
public ref byte EyeColorRight
|
public byte EyeColorRight
|
||||||
=> ref Data->Data[9];
|
{
|
||||||
|
get => Data->Data[9];
|
||||||
|
set => Data->Data[9] = value;
|
||||||
|
}
|
||||||
|
|
||||||
public ref byte HairColor
|
public byte HairColor
|
||||||
=> ref Data->Data[10];
|
{
|
||||||
|
get => Data->Data[10];
|
||||||
|
set => Data->Data[10] = value;
|
||||||
|
}
|
||||||
|
|
||||||
public ref byte HighlightsColor
|
public byte HighlightsColor
|
||||||
=> ref Data->Data[11];
|
{
|
||||||
|
get => Data->Data[11];
|
||||||
|
set => Data->Data[11] = value;
|
||||||
|
}
|
||||||
|
|
||||||
public readonly ref struct FacialFeatureStruct
|
public readonly ref struct FacialFeatureStruct
|
||||||
{
|
{
|
||||||
|
|
@ -86,14 +110,23 @@ public unsafe struct Customize
|
||||||
public FacialFeatureStruct FacialFeatures
|
public FacialFeatureStruct FacialFeatures
|
||||||
=> new(Data->Data + 12);
|
=> new(Data->Data + 12);
|
||||||
|
|
||||||
public ref byte TattooColor
|
public byte TattooColor
|
||||||
=> ref Data->Data[13];
|
{
|
||||||
|
get => Data->Data[13];
|
||||||
|
set => Data->Data[13] = value;
|
||||||
|
}
|
||||||
|
|
||||||
public ref byte Eyebrows
|
public byte Eyebrows
|
||||||
=> ref Data->Data[14];
|
{
|
||||||
|
get => Data->Data[14];
|
||||||
|
set => Data->Data[14] = value;
|
||||||
|
}
|
||||||
|
|
||||||
public ref byte EyeColorLeft
|
public byte EyeColorLeft
|
||||||
=> ref Data->Data[15];
|
{
|
||||||
|
get => Data->Data[15];
|
||||||
|
set => Data->Data[15] = value;
|
||||||
|
}
|
||||||
|
|
||||||
public byte EyeShape
|
public byte EyeShape
|
||||||
{
|
{
|
||||||
|
|
@ -107,11 +140,17 @@ public unsafe struct Customize
|
||||||
set => Data->Data[16] = (byte)(value ? Data->Data[16] | 0x80 : Data->Data[16] & 0x7F);
|
set => Data->Data[16] = (byte)(value ? Data->Data[16] | 0x80 : Data->Data[16] & 0x7F);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref byte Nose
|
public byte Nose
|
||||||
=> ref Data->Data[17];
|
{
|
||||||
|
get => Data->Data[17];
|
||||||
|
set => Data->Data[17] = value;
|
||||||
|
}
|
||||||
|
|
||||||
public ref byte Jaw
|
public byte Jaw
|
||||||
=> ref Data->Data[18];
|
{
|
||||||
|
get => Data->Data[18];
|
||||||
|
set => Data->Data[18] = value;
|
||||||
|
}
|
||||||
|
|
||||||
public byte Mouth
|
public byte Mouth
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -52,42 +52,54 @@ public class Glamourer : IDalamudPlugin
|
||||||
|
|
||||||
public unsafe Glamourer(DalamudPluginInterface pluginInterface)
|
public unsafe Glamourer(DalamudPluginInterface pluginInterface)
|
||||||
{
|
{
|
||||||
Dalamud.Initialize(pluginInterface);
|
try
|
||||||
Customization = CustomizationManager.Create(Dalamud.PluginInterface, Dalamud.GameData, Dalamud.ClientState.ClientLanguage);
|
|
||||||
RestrictedGear = GameData.RestrictedGear(Dalamud.GameData);
|
|
||||||
Models = GameData.Models(Dalamud.GameData);
|
|
||||||
Identifier = global::Penumbra.GameData.GameData.GetIdentifier(Dalamud.GameData);
|
|
||||||
Config = GlamourerConfig.Load();
|
|
||||||
Penumbra = new PenumbraAttach(Config.AttachToPenumbra);
|
|
||||||
FixedDesigns = new FixedDesigns();
|
|
||||||
CurrentManipulations = new CurrentManipulations();
|
|
||||||
//Designs = new DesignManager();
|
|
||||||
|
|
||||||
//GlamourerIpc = new GlamourerIpc(Dalamud.ClientState, Dalamud.Objects, Dalamud.PluginInterface);
|
|
||||||
RedrawManager = new RedrawManager(FixedDesigns, CurrentManipulations);
|
|
||||||
|
|
||||||
Dalamud.Commands.AddHandler(MainCommandString, new CommandInfo(OnGlamourer)
|
|
||||||
{
|
{
|
||||||
HelpMessage = "Open or close the Glamourer window.",
|
Dalamud.Initialize(pluginInterface);
|
||||||
});
|
|
||||||
Dalamud.Commands.AddHandler(ApplyCommandString, new CommandInfo(OnGlamour)
|
|
||||||
{
|
|
||||||
HelpMessage = $"Use Glamourer Functions: {HelpString}",
|
|
||||||
});
|
|
||||||
|
|
||||||
_interface = new Interface(this);
|
Customization = CustomizationManager.Create(Dalamud.PluginInterface, Dalamud.GameData, Dalamud.ClientState.ClientLanguage);
|
||||||
_windowSystem.AddWindow(_interface);
|
RestrictedGear = GameData.RestrictedGear(Dalamud.GameData);
|
||||||
Dalamud.PluginInterface.UiBuilder.Draw += _windowSystem.Draw;
|
Models = GameData.Models(Dalamud.GameData);
|
||||||
//FixedDesignManager.Flag((Human*)((Actor)Dalamud.ClientState.LocalPlayer?.Address).Pointer->GameObject.DrawObject, 0, &x);
|
|
||||||
|
Config = GlamourerConfig.Load();
|
||||||
|
|
||||||
|
Identifier = global::Penumbra.GameData.GameData.GetIdentifier(Dalamud.GameData);
|
||||||
|
Penumbra = new PenumbraAttach(Config.AttachToPenumbra);
|
||||||
|
FixedDesigns = new FixedDesigns();
|
||||||
|
CurrentManipulations = new CurrentManipulations();
|
||||||
|
//Designs = new DesignManager();
|
||||||
|
|
||||||
|
//GlamourerIpc = new GlamourerIpc(Dalamud.ClientState, Dalamud.Objects, Dalamud.PluginInterface);
|
||||||
|
RedrawManager = new RedrawManager(FixedDesigns, CurrentManipulations);
|
||||||
|
|
||||||
|
Dalamud.Commands.AddHandler(MainCommandString, new CommandInfo(OnGlamourer)
|
||||||
|
{
|
||||||
|
HelpMessage = "Open or close the Glamourer window.",
|
||||||
|
});
|
||||||
|
Dalamud.Commands.AddHandler(ApplyCommandString, new CommandInfo(OnGlamour)
|
||||||
|
{
|
||||||
|
HelpMessage = $"Use Glamourer Functions: {HelpString}",
|
||||||
|
});
|
||||||
|
|
||||||
|
_interface = new Interface(this);
|
||||||
|
_windowSystem.AddWindow(_interface);
|
||||||
|
Dalamud.PluginInterface.UiBuilder.Draw += _windowSystem.Draw;
|
||||||
|
//FixedDesignManager.Flag((Human*)((Actor)Dalamud.ClientState.LocalPlayer?.Address).Pointer->GameObject.DrawObject, 0, &x);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
RedrawManager.Dispose();
|
RedrawManager?.Dispose();
|
||||||
Penumbra.Dispose();
|
Penumbra?.Dispose();
|
||||||
Dalamud.PluginInterface.UiBuilder.Draw -= _windowSystem.Draw;
|
if (_windowSystem != null)
|
||||||
_interface.Dispose();
|
Dalamud.PluginInterface.UiBuilder.Draw -= _windowSystem.Draw;
|
||||||
|
_interface?.Dispose();
|
||||||
//GlamourerIpc.Dispose();
|
//GlamourerIpc.Dispose();
|
||||||
Dalamud.Commands.RemoveHandler(ApplyCommandString);
|
Dalamud.Commands.RemoveHandler(ApplyCommandString);
|
||||||
Dalamud.Commands.RemoveHandler(MainCommandString);
|
Dalamud.Commands.RemoveHandler(MainCommandString);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ internal partial class Interface
|
||||||
_equip = equip,
|
_equip = equip,
|
||||||
_actors = actors,
|
_actors = actors,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if (!ImGui.CollapsingHeader("Character Customization"))
|
if (!ImGui.CollapsingHeader("Character Customization"))
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
99
Glamourer/Gui/Interface.DebugStateTab.cs
Normal file
99
Glamourer/Gui/Interface.DebugStateTab.cs
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Numerics;
|
||||||
|
using Glamourer.Interop;
|
||||||
|
using Glamourer.State;
|
||||||
|
using ImGuiNET;
|
||||||
|
using OtterGui;
|
||||||
|
using OtterGui.Classes;
|
||||||
|
using OtterGui.Raii;
|
||||||
|
|
||||||
|
namespace Glamourer.Gui;
|
||||||
|
|
||||||
|
internal partial class Interface
|
||||||
|
{
|
||||||
|
private class DebugStateTab
|
||||||
|
{
|
||||||
|
private readonly CurrentManipulations _currentManipulations;
|
||||||
|
|
||||||
|
private LowerString _manipulationFilter = LowerString.Empty;
|
||||||
|
private Actor.IIdentifier _selection = Actor.IIdentifier.Invalid;
|
||||||
|
private CurrentDesign? _save = null;
|
||||||
|
private bool _delete = false;
|
||||||
|
|
||||||
|
public DebugStateTab(CurrentManipulations currentManipulations)
|
||||||
|
=> _currentManipulations = currentManipulations;
|
||||||
|
|
||||||
|
[Conditional("DEBUG")]
|
||||||
|
public void Draw()
|
||||||
|
{
|
||||||
|
using var tab = ImRaii.TabItem("Current Manipulations");
|
||||||
|
if (!tab)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DrawManipulationSelector();
|
||||||
|
if (_save == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
DrawActorPanel();
|
||||||
|
if (_delete)
|
||||||
|
{
|
||||||
|
_delete = false;
|
||||||
|
_currentManipulations.DeleteSave(_selection);
|
||||||
|
_selection = Actor.IIdentifier.Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawSelector(Vector2 oldSpacing)
|
||||||
|
{
|
||||||
|
using var child = ImRaii.Child("##actorSelector", new Vector2(_actorSelectorWidth, -1), true);
|
||||||
|
if (!child)
|
||||||
|
return;
|
||||||
|
|
||||||
|
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, oldSpacing);
|
||||||
|
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeight());
|
||||||
|
var remainder = ImGuiClip.FilteredClippedDraw(_currentManipulations, skips, CheckFilter, DrawSelectable);
|
||||||
|
ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawManipulationSelector()
|
||||||
|
{
|
||||||
|
using var group = ImRaii.Group();
|
||||||
|
var oldSpacing = ImGui.GetStyle().ItemSpacing;
|
||||||
|
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||||
|
.Push(ImGuiStyleVar.FrameRounding, 0);
|
||||||
|
ImGui.SetNextItemWidth(_actorSelectorWidth);
|
||||||
|
LowerString.InputWithHint("##actorFilter", "Filter...", ref _manipulationFilter, 64);
|
||||||
|
|
||||||
|
_save = null;
|
||||||
|
DrawSelector(oldSpacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckFilter(KeyValuePair<Actor.IIdentifier, CurrentDesign> data)
|
||||||
|
{
|
||||||
|
if (data.Key.Equals(_selection))
|
||||||
|
_save = data.Value;
|
||||||
|
return _manipulationFilter.Length == 0 || _manipulationFilter.IsContained(data.Key.ToString()!);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawSelectable(KeyValuePair<Actor.IIdentifier, CurrentDesign> data)
|
||||||
|
{
|
||||||
|
var equal = data.Key.Equals(_selection);
|
||||||
|
if (ImGui.Selectable(data.Key.ToString(), equal))
|
||||||
|
{
|
||||||
|
_selection = data.Key;
|
||||||
|
_save = data.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawActorPanel()
|
||||||
|
{
|
||||||
|
using var group = ImRaii.Group();
|
||||||
|
if (ImGui.Button("Delete"))
|
||||||
|
_delete = true;
|
||||||
|
CustomizationDrawer.Draw(_save!.Data.Customize, _save.Data.Equipment, Array.Empty<Actor>(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
228
Glamourer/Gui/Interface.Equipment.cs
Normal file
228
Glamourer/Gui/Interface.Equipment.cs
Normal file
|
|
@ -0,0 +1,228 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Dalamud.Interface;
|
||||||
|
using Glamourer.Customization;
|
||||||
|
using Glamourer.Interop;
|
||||||
|
using Glamourer.Structs;
|
||||||
|
using ImGuiNET;
|
||||||
|
using Lumina.Text;
|
||||||
|
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;
|
||||||
|
|
||||||
|
internal partial class Interface
|
||||||
|
{
|
||||||
|
//public class EquipmentDrawer
|
||||||
|
//{
|
||||||
|
// private static
|
||||||
|
//
|
||||||
|
// private Race _race;
|
||||||
|
// private Gender _gender;
|
||||||
|
// private CharacterEquip _equip;
|
||||||
|
// private IReadOnlyCollection<Actor> _actors = Array.Empty<Actor>();
|
||||||
|
//
|
||||||
|
// public static void Draw(Customize customize, CharacterEquip equip, IReadOnlyCollection<Actor> actors, bool locked)
|
||||||
|
// {
|
||||||
|
// var d = new EquipmentDrawer()
|
||||||
|
// {
|
||||||
|
// _race = customize.Race,
|
||||||
|
// _gender = customize.Gender,
|
||||||
|
// _actors = actors,
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// if (!ImGui.CollapsingHeader("Character Equipment"))
|
||||||
|
// return;
|
||||||
|
//
|
||||||
|
// using var disabled = ImRaii.Disabled(locked);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private bool DrawStainSelector(ComboWithFilter<Stain> stainCombo, EquipSlot slot, StainId stainIdx)
|
||||||
|
// {
|
||||||
|
// stainCombo.PostPreview = null;
|
||||||
|
// if (_stains.TryGetValue((byte)stainIdx, out var stain))
|
||||||
|
// {
|
||||||
|
// var previewPush = PushColor(stain, ImGuiCol.FrameBg);
|
||||||
|
// stainCombo.PostPreview = () => ImGui.PopStyleColor(previewPush);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// var change = stainCombo.Draw(string.Empty, out var newStain) && !newStain.RowIndex.Equals(stainIdx);
|
||||||
|
// if (!change && (byte)stainIdx != 0)
|
||||||
|
// {
|
||||||
|
// ImGuiUtil.HoverTooltip("Right-click to clear.");
|
||||||
|
// if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||||
|
// {
|
||||||
|
// change = true;
|
||||||
|
// newStain = Stain.None;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!change)
|
||||||
|
// return false;
|
||||||
|
//
|
||||||
|
// if (_player == null)
|
||||||
|
// return _inDesignMode && (_selection?.Data.WriteStain(slot, newStain.RowIndex) ?? false);
|
||||||
|
//
|
||||||
|
// Glamourer.RevertableDesigns.Add(_player);
|
||||||
|
// newStain.Write(_player.Address, slot);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private bool DrawItemSelector(ComboWithFilter<Item> equipCombo, Lumina.Excel.GeneratedSheets.Item item, EquipSlot slot = EquipSlot.Unknown)
|
||||||
|
// {
|
||||||
|
// var currentName = item.Name.ToString();
|
||||||
|
// var change = equipCombo.Draw(currentName, out var newItem, _itemComboWidth) && newItem.Base.RowId != item.RowId;
|
||||||
|
// if (!change && !ReferenceEquals(item, SmallClothes))
|
||||||
|
// {
|
||||||
|
// ImGuiUtil.HoverTooltip("Right-click to clear.");
|
||||||
|
// if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||||
|
// {
|
||||||
|
// change = true;
|
||||||
|
// newItem = Item.Nothing(slot);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (!change)
|
||||||
|
// return false;
|
||||||
|
//
|
||||||
|
// newItem = new Item(newItem.Base, newItem.Name, slot);
|
||||||
|
// if (_player == null)
|
||||||
|
// return _inDesignMode && (_selection?.Data.WriteItem(newItem) ?? false);
|
||||||
|
//
|
||||||
|
// Glamourer.RevertableDesigns.Add(_player);
|
||||||
|
// newItem.Write(_player.Address);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private static bool DrawCheckbox(CharacterEquipMask flag, ref CharacterEquipMask mask)
|
||||||
|
// {
|
||||||
|
// var tmp = (uint)mask;
|
||||||
|
// var ret = false;
|
||||||
|
// if (ImGui.CheckboxFlags($"##flag_{(uint)flag}", ref tmp, (uint)flag) && tmp != (uint)mask)
|
||||||
|
// {
|
||||||
|
// mask = (CharacterEquipMask)tmp;
|
||||||
|
// ret = true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (ImGui.IsItemHovered())
|
||||||
|
// ImGui.SetTooltip("Enable writing this slot in this save.");
|
||||||
|
// return ret;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private static readonly Lumina.Excel.GeneratedSheets.Item SmallClothes = new()
|
||||||
|
// {
|
||||||
|
// Name = new SeString("Nothing"),
|
||||||
|
// RowId = 0,
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// private static readonly Lumina.Excel.GeneratedSheets.Item SmallClothesNpc = new()
|
||||||
|
// {
|
||||||
|
// Name = new SeString("Smallclothes (NPC)"),
|
||||||
|
// RowId = 1,
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// private static readonly Lumina.Excel.GeneratedSheets.Item Unknown = new()
|
||||||
|
// {
|
||||||
|
// Name = new SeString("Unknown"),
|
||||||
|
// RowId = 2,
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// private Lumina.Excel.GeneratedSheets.Item Identify(SetId set, WeaponType weapon, ushort variant, EquipSlot slot)
|
||||||
|
// {
|
||||||
|
// return (uint)set switch
|
||||||
|
// {
|
||||||
|
// 0 => SmallClothes,
|
||||||
|
// 9903 => SmallClothesNpc,
|
||||||
|
// _ => _identifier.Identify(set, weapon, variant, slot) ?? Unknown,
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private bool DrawEquipSlot(EquipSlot slot, CharacterArmor equip)
|
||||||
|
// {
|
||||||
|
// var (equipCombo, stainCombo) = _combos[slot];
|
||||||
|
//
|
||||||
|
// var ret = DrawStainSelector(stainCombo, slot, equip.Stain);
|
||||||
|
// ImGui.SameLine();
|
||||||
|
// var item = Identify(equip.Set, new WeaponType(), equip.Variant, slot);
|
||||||
|
// ret |= DrawItemSelector(equipCombo, item, slot);
|
||||||
|
//
|
||||||
|
// return ret;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private bool DrawEquipSlotWithCheck(EquipSlot slot, CharacterArmor equip, CharacterEquipMask flag, ref CharacterEquipMask mask)
|
||||||
|
// {
|
||||||
|
// var ret = DrawCheckbox(flag, ref mask);
|
||||||
|
// ImGui.SameLine();
|
||||||
|
// ret |= DrawEquipSlot(slot, equip);
|
||||||
|
// return ret;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private bool DrawWeapon(EquipSlot slot, CharacterWeapon weapon)
|
||||||
|
// {
|
||||||
|
// var (equipCombo, stainCombo) = _combos[slot];
|
||||||
|
//
|
||||||
|
// var ret = DrawStainSelector(stainCombo, slot, weapon.Stain);
|
||||||
|
// ImGui.SameLine();
|
||||||
|
// var item = Identify(weapon.Set, weapon.Type, weapon.Variant, slot);
|
||||||
|
// ret |= DrawItemSelector(equipCombo, item, slot);
|
||||||
|
//
|
||||||
|
// return ret;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private bool DrawWeaponWithCheck(EquipSlot slot, CharacterWeapon weapon, CharacterEquipMask flag, ref CharacterEquipMask mask)
|
||||||
|
// {
|
||||||
|
// var ret = DrawCheckbox(flag, ref mask);
|
||||||
|
// ImGui.SameLine();
|
||||||
|
// ret |= DrawWeapon(slot, weapon);
|
||||||
|
// return ret;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private bool DrawEquip(CharacterEquipment equip)
|
||||||
|
// {
|
||||||
|
// var ret = false;
|
||||||
|
// if (ImGui.CollapsingHeader("Character Equipment"))
|
||||||
|
// {
|
||||||
|
// ret |= DrawWeapon(EquipSlot.MainHand, equip.MainHand);
|
||||||
|
// ret |= DrawWeapon(EquipSlot.OffHand, equip.OffHand);
|
||||||
|
// ret |= DrawEquipSlot(EquipSlot.Head, equip.Head);
|
||||||
|
// ret |= DrawEquipSlot(EquipSlot.Body, equip.Body);
|
||||||
|
// ret |= DrawEquipSlot(EquipSlot.Hands, equip.Hands);
|
||||||
|
// ret |= DrawEquipSlot(EquipSlot.Legs, equip.Legs);
|
||||||
|
// ret |= DrawEquipSlot(EquipSlot.Feet, equip.Feet);
|
||||||
|
// ret |= DrawEquipSlot(EquipSlot.Ears, equip.Ears);
|
||||||
|
// ret |= DrawEquipSlot(EquipSlot.Neck, equip.Neck);
|
||||||
|
// ret |= DrawEquipSlot(EquipSlot.Wrists, equip.Wrists);
|
||||||
|
// ret |= DrawEquipSlot(EquipSlot.RFinger, equip.RFinger);
|
||||||
|
// ret |= DrawEquipSlot(EquipSlot.LFinger, equip.LFinger);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return ret;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private bool DrawEquip(CharacterEquipment equip, ref CharacterEquipMask mask)
|
||||||
|
// {
|
||||||
|
// var ret = false;
|
||||||
|
// if (ImGui.CollapsingHeader("Character Equipment"))
|
||||||
|
// {
|
||||||
|
// ret |= DrawWeaponWithCheck(EquipSlot.MainHand, equip.MainHand, CharacterEquipMask.MainHand, ref mask);
|
||||||
|
// ret |= DrawWeaponWithCheck(EquipSlot.OffHand, equip.OffHand, CharacterEquipMask.OffHand, ref mask);
|
||||||
|
// ret |= DrawEquipSlotWithCheck(EquipSlot.Head, equip.Head, CharacterEquipMask.Head, ref mask);
|
||||||
|
// ret |= DrawEquipSlotWithCheck(EquipSlot.Body, equip.Body, CharacterEquipMask.Body, ref mask);
|
||||||
|
// ret |= DrawEquipSlotWithCheck(EquipSlot.Hands, equip.Hands, CharacterEquipMask.Hands, ref mask);
|
||||||
|
// ret |= DrawEquipSlotWithCheck(EquipSlot.Legs, equip.Legs, CharacterEquipMask.Legs, ref mask);
|
||||||
|
// ret |= DrawEquipSlotWithCheck(EquipSlot.Feet, equip.Feet, CharacterEquipMask.Feet, ref mask);
|
||||||
|
// ret |= DrawEquipSlotWithCheck(EquipSlot.Ears, equip.Ears, CharacterEquipMask.Ears, ref mask);
|
||||||
|
// ret |= DrawEquipSlotWithCheck(EquipSlot.Neck, equip.Neck, CharacterEquipMask.Neck, ref mask);
|
||||||
|
// ret |= DrawEquipSlotWithCheck(EquipSlot.Wrists, equip.Wrists, CharacterEquipMask.Wrists, ref mask);
|
||||||
|
// ret |= DrawEquipSlotWithCheck(EquipSlot.RFinger, equip.RFinger, CharacterEquipMask.RFinger, ref mask);
|
||||||
|
// ret |= DrawEquipSlotWithCheck(EquipSlot.LFinger, equip.LFinger, CharacterEquipMask.LFinger, ref mask);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return ret;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Glamourer.Customization;
|
|
||||||
using Glamourer.Interop;
|
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
|
||||||
namespace Glamourer.Gui;
|
namespace Glamourer.Gui;
|
||||||
|
|
@ -13,7 +11,6 @@ internal partial class Interface
|
||||||
private static readonly ImGuiScene.TextureWrap? LegacyTattoo = GetLegacyTattooIcon();
|
private static readonly ImGuiScene.TextureWrap? LegacyTattoo = GetLegacyTattooIcon();
|
||||||
private static readonly Vector4 RedTint = new(0.6f, 0.3f, 0.3f, 1f);
|
private static readonly Vector4 RedTint = new(0.6f, 0.3f, 0.3f, 1f);
|
||||||
|
|
||||||
|
|
||||||
private static Vector2 _iconSize = Vector2.Zero;
|
private static Vector2 _iconSize = Vector2.Zero;
|
||||||
private static Vector2 _framedIconSize = Vector2.Zero;
|
private static Vector2 _framedIconSize = Vector2.Zero;
|
||||||
private static Vector2 _spacing = Vector2.Zero;
|
private static Vector2 _spacing = Vector2.Zero;
|
||||||
|
|
@ -22,7 +19,6 @@ internal partial class Interface
|
||||||
private static float _comboSelectorSize;
|
private static float _comboSelectorSize;
|
||||||
private static float _raceSelectorWidth;
|
private static float _raceSelectorWidth;
|
||||||
|
|
||||||
|
|
||||||
private static void UpdateState()
|
private static void UpdateState()
|
||||||
{
|
{
|
||||||
// General
|
// General
|
||||||
|
|
@ -35,23 +31,18 @@ internal partial class Interface
|
||||||
_inputIntSize = 2 * _framedIconSize.X + ImGui.GetStyle().ItemSpacing.X;
|
_inputIntSize = 2 * _framedIconSize.X + ImGui.GetStyle().ItemSpacing.X;
|
||||||
_comboSelectorSize = 4 * _framedIconSize.X + 3 * ImGui.GetStyle().ItemSpacing.X;
|
_comboSelectorSize = 4 * _framedIconSize.X + 3 * ImGui.GetStyle().ItemSpacing.X;
|
||||||
_raceSelectorWidth = _inputIntSize + _comboSelectorSize - _framedIconSize.X;
|
_raceSelectorWidth = _inputIntSize + _comboSelectorSize - _framedIconSize.X;
|
||||||
|
|
||||||
// _itemComboWidth = 6 * _actualIconSize.X + 4 * ImGui.GetStyle().ItemSpacing.X - ColorButtonWidth + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ImGuiScene.TextureWrap? GetLegacyTattooIcon()
|
private static ImGuiScene.TextureWrap? GetLegacyTattooIcon()
|
||||||
{
|
{
|
||||||
using var resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("Glamourer.LegacyTattoo.raw");
|
using var resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("Glamourer.LegacyTattoo.raw");
|
||||||
if (resource != null)
|
if (resource == null)
|
||||||
{
|
return null;
|
||||||
var rawImage = new byte[resource.Length];
|
|
||||||
var length = resource.Read(rawImage, 0, (int)resource.Length);
|
|
||||||
if (length != resource.Length)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return Dalamud.PluginInterface.UiBuilder.LoadImageRaw(rawImage, 192, 192, 4);
|
var rawImage = new byte[resource.Length];
|
||||||
}
|
var length = resource.Read(rawImage, 0, (int)resource.Length);
|
||||||
|
return length == resource.Length
|
||||||
return null;
|
? Dalamud.PluginInterface.UiBuilder.LoadImageRaw(rawImage, 192, 192, 4)
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,103 +1,15 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Logging;
|
||||||
using Glamourer.Interop;
|
|
||||||
using Glamourer.State;
|
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using OtterGui;
|
|
||||||
using OtterGui.Classes;
|
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
|
|
||||||
namespace Glamourer.Gui;
|
namespace Glamourer.Gui;
|
||||||
|
|
||||||
internal partial class Interface : Window, IDisposable
|
internal partial class Interface : Window, IDisposable
|
||||||
{
|
{
|
||||||
private class DebugStateTab
|
|
||||||
{
|
|
||||||
private readonly CurrentManipulations _currentManipulations;
|
|
||||||
|
|
||||||
private LowerString _manipulationFilter = LowerString.Empty;
|
|
||||||
private Actor.IIdentifier _selection = Actor.IIdentifier.Invalid;
|
|
||||||
private CurrentDesign? _save = null;
|
|
||||||
private bool _delete = false;
|
|
||||||
|
|
||||||
public DebugStateTab(CurrentManipulations currentManipulations)
|
|
||||||
=> _currentManipulations = currentManipulations;
|
|
||||||
|
|
||||||
public void Draw()
|
|
||||||
{
|
|
||||||
using var tab = ImRaii.TabItem("Current Manipulations");
|
|
||||||
if (!tab)
|
|
||||||
return;
|
|
||||||
|
|
||||||
DrawManipulationSelector();
|
|
||||||
if (_save == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImGui.SameLine();
|
|
||||||
DrawActorPanel();
|
|
||||||
if (_delete)
|
|
||||||
{
|
|
||||||
_delete = false;
|
|
||||||
_currentManipulations.DeleteSave(_selection);
|
|
||||||
_selection = Actor.IIdentifier.Invalid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawSelector(Vector2 oldSpacing)
|
|
||||||
{
|
|
||||||
using var child = ImRaii.Child("##actorSelector", new Vector2(_actorSelectorWidth, -1), true);
|
|
||||||
if (!child)
|
|
||||||
return;
|
|
||||||
|
|
||||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, oldSpacing);
|
|
||||||
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeight());
|
|
||||||
var remainder = ImGuiClip.FilteredClippedDraw(_currentManipulations, skips, CheckFilter, DrawSelectable);
|
|
||||||
ImGuiClip.DrawEndDummy(remainder, ImGui.GetTextLineHeight());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawManipulationSelector()
|
|
||||||
{
|
|
||||||
using var group = ImRaii.Group();
|
|
||||||
var oldSpacing = ImGui.GetStyle().ItemSpacing;
|
|
||||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
|
||||||
.Push(ImGuiStyleVar.FrameRounding, 0);
|
|
||||||
ImGui.SetNextItemWidth(_actorSelectorWidth);
|
|
||||||
LowerString.InputWithHint("##actorFilter", "Filter...", ref _manipulationFilter, 64);
|
|
||||||
|
|
||||||
_save = null;
|
|
||||||
DrawSelector(oldSpacing);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CheckFilter(KeyValuePair<Actor.IIdentifier, CurrentDesign> data)
|
|
||||||
{
|
|
||||||
if (data.Key.Equals(_selection))
|
|
||||||
_save = data.Value;
|
|
||||||
return _manipulationFilter.Length == 0 || _manipulationFilter.IsContained(data.Key.ToString()!);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawSelectable(KeyValuePair<Actor.IIdentifier, CurrentDesign> data)
|
|
||||||
{
|
|
||||||
var equal = data.Key.Equals(_selection);
|
|
||||||
if (ImGui.Selectable(data.Key.ToString(), equal))
|
|
||||||
{
|
|
||||||
_selection = data.Key;
|
|
||||||
_save = data.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawActorPanel()
|
|
||||||
{
|
|
||||||
using var group = ImRaii.Group();
|
|
||||||
if (ImGui.Button("Delete"))
|
|
||||||
_delete = true;
|
|
||||||
CustomizationDrawer.Draw(_save!.Data.Customize, _save.Data.Equipment, Array.Empty<Actor>(), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly Glamourer _plugin;
|
private readonly Glamourer _plugin;
|
||||||
|
|
||||||
private readonly ActorTab _actorTab;
|
private readonly ActorTab _actorTab;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ using Lumina.Text;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
using Penumbra.PlayerWatch;
|
|
||||||
|
|
||||||
namespace Glamourer.Gui;
|
namespace Glamourer.Gui;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ public unsafe partial class RedrawManager
|
||||||
{
|
{
|
||||||
PluginLog.Information($"Updated {slot} from current designs for {identifier}.");
|
PluginLog.Information($"Updated {slot} from current designs for {identifier}.");
|
||||||
(var replaced, *data) =
|
(var replaced, *data) =
|
||||||
Glamourer.RestrictedGear.ResolveRestricted(*data, slot, (Race)drawObject->Race, (Gender)drawObject->Sex);
|
Glamourer.RestrictedGear.ResolveRestricted(*data, slot, (Race)drawObject->Race, (Gender)(drawObject->Sex + 1));
|
||||||
save2.Data.Equipment[slot] = *data;
|
save2.Data.Equipment[slot] = *data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -214,25 +214,24 @@ public unsafe partial class RedrawManager : IDisposable
|
||||||
if (!(_currentManipulations.TryGetDesign(identifier, out var save) || _fixedDesigns.TryGetDesign(identifier, out var save2)))
|
if (!(_currentManipulations.TryGetDesign(identifier, out var save) || _fixedDesigns.TryGetDesign(identifier, out var save2)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
// Compare game object customize data against draw object customize data for transformations.
|
// Compare game object customize data against draw object customize data for transformations.
|
||||||
// Apply customization if they correspond and there is customization to apply.
|
// Apply customization if they correspond and there is customization to apply.
|
||||||
//var gameObjectCustomize = new Customize((CustomizeData*)actor.Pointer->CustomizeData);
|
var gameObjectCustomize = new Customize((CustomizeData*)actor.Pointer->CustomizeData);
|
||||||
//if (gameObjectCustomize.Equals(customize))
|
if (gameObjectCustomize.Equals(customize))
|
||||||
// customize.Load(save.Customize);
|
customize.Load(save.Data.Customize);
|
||||||
//
|
|
||||||
//// Compare game object equip data against draw object equip data for transformations.
|
// Compare game object equip data against draw object equip data for transformations.
|
||||||
//// Apply each piece of equip that should be applied if they correspond.
|
// Apply each piece of equip that should be applied if they correspond.
|
||||||
//var gameObjectEquip = new CharacterEquip((CharacterArmor*)actor.Pointer->EquipSlotData);
|
var gameObjectEquip = new CharacterEquip((CharacterArmor*)actor.Pointer->EquipSlotData);
|
||||||
//if (gameObjectEquip.Equals(equip))
|
if (gameObjectEquip.Equals(equip))
|
||||||
//{
|
{
|
||||||
// var saveEquip = save.Equipment;
|
var saveEquip = save.Data.Equipment;
|
||||||
// foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||||
// {
|
{
|
||||||
// (var _, equip[slot]) =
|
(var _, equip[slot]) =
|
||||||
// Glamourer.RestrictedGear.ResolveRestricted(true ? equip[slot] : saveEquip[slot], slot, customize.Race, customize.Gender);
|
Glamourer.RestrictedGear.ResolveRestricted(true ? equip[slot] : saveEquip[slot], slot, customize.Race, customize.Gender);
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnCharacterRedraw(IntPtr gameObject, IntPtr modelId, IntPtr customize, IntPtr equipData)
|
private void OnCharacterRedraw(IntPtr gameObject, IntPtr modelId, IntPtr customize, IntPtr equipData)
|
||||||
|
|
@ -267,7 +266,7 @@ public unsafe partial class RedrawManager : IDisposable
|
||||||
{
|
{
|
||||||
if (!drawObject.Valid)
|
if (!drawObject.Valid)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return _changeCustomize(drawObject.Pointer, (byte*)customize.Data, 1);
|
return _changeCustomize(drawObject.Pointer, (byte*)customize.Data, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
using Glamourer.Interop;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Glamourer.Customization;
|
||||||
|
using Glamourer.Interop;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
|
|
||||||
namespace Glamourer.State;
|
namespace Glamourer.State;
|
||||||
|
|
@ -25,6 +28,13 @@ public unsafe class CurrentDesign : ICharacterData
|
||||||
_drawData = _initialData.Clone();
|
_drawData = _initialData.Clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SaveCustomization(Customize customize, IReadOnlyCollection<Actor> actors)
|
||||||
|
{
|
||||||
|
_drawData.Customize.Load(customize);
|
||||||
|
foreach (var actor in actors.Where(a => a && a.DrawObject))
|
||||||
|
Glamourer.RedrawManager.UpdateCustomize(actor.DrawObject, _drawData.Customize);
|
||||||
|
}
|
||||||
|
|
||||||
public void Update(Actor actor)
|
public void Update(Actor actor)
|
||||||
{
|
{
|
||||||
if (!actor)
|
if (!actor)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Net.Http;
|
|
||||||
using Glamourer.Customization;
|
using Glamourer.Customization;
|
||||||
using Glamourer.State;
|
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue