mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Add Emotes to Changed Items.
This commit is contained in:
parent
a890258cf5
commit
6cc89f3e7c
3 changed files with 115 additions and 37 deletions
|
|
@ -1 +1 @@
|
|||
Subproject commit 43f6737d4baa7988a5fe23096f20827bc54e6812
|
||||
Subproject commit bd7e79262a0db06e27e61b98ab0a31ebb881be2a
|
||||
|
|
@ -27,22 +27,23 @@ public class ChangedItemDrawer : IDisposable
|
|||
[Flags]
|
||||
public enum ChangedItemIcon : uint
|
||||
{
|
||||
Head = 0x0001,
|
||||
Body = 0x0002,
|
||||
Hands = 0x0004,
|
||||
Legs = 0x0008,
|
||||
Feet = 0x0010,
|
||||
Ears = 0x0020,
|
||||
Neck = 0x0040,
|
||||
Wrists = 0x0080,
|
||||
Finger = 0x0100,
|
||||
Monster = 0x0200,
|
||||
Demihuman = 0x0400,
|
||||
Customization = 0x0800,
|
||||
Action = 0x1000,
|
||||
Mainhand = 0x2000,
|
||||
Offhand = 0x4000,
|
||||
Unknown = 0x8000,
|
||||
Head = 0x00_00_01,
|
||||
Body = 0x00_00_02,
|
||||
Hands = 0x00_00_04,
|
||||
Legs = 0x00_00_08,
|
||||
Feet = 0x00_00_10,
|
||||
Ears = 0x00_00_20,
|
||||
Neck = 0x00_00_40,
|
||||
Wrists = 0x00_00_80,
|
||||
Finger = 0x00_01_00,
|
||||
Monster = 0x00_02_00,
|
||||
Demihuman = 0x00_04_00,
|
||||
Customization = 0x00_08_00,
|
||||
Action = 0x00_10_00,
|
||||
Mainhand = 0x00_20_00,
|
||||
Offhand = 0x00_40_00,
|
||||
Unknown = 0x00_80_00,
|
||||
Emote = 0x01_00_00,
|
||||
}
|
||||
|
||||
public const ChangedItemIcon AllFlags = (ChangedItemIcon)0xFFFF;
|
||||
|
|
@ -51,10 +52,11 @@ public class ChangedItemDrawer : IDisposable
|
|||
private readonly Configuration _config;
|
||||
private readonly ExcelSheet<Item> _items;
|
||||
private readonly CommunicatorService _communicator;
|
||||
private readonly Dictionary<ChangedItemIcon, TextureWrap> _icons = new(16);
|
||||
private readonly Dictionary<ChangedItemIcon, TextureWrap> _icons = new(16);
|
||||
private float _smallestIconWidth;
|
||||
|
||||
public ChangedItemDrawer(UiBuilder uiBuilder, IDataManager gameData, ITextureProvider textureProvider, CommunicatorService communicator, Configuration config)
|
||||
public ChangedItemDrawer(UiBuilder uiBuilder, IDataManager gameData, ITextureProvider textureProvider, CommunicatorService communicator,
|
||||
Configuration config)
|
||||
{
|
||||
_items = gameData.GetExcelSheet<Item>()!;
|
||||
uiBuilder.RunWhenUiPrepared(() => CreateEquipSlotIcons(uiBuilder, gameData, textureProvider), true);
|
||||
|
|
@ -164,6 +166,7 @@ public class ChangedItemDrawer : IDisposable
|
|||
ChangedItemIcon.Offhand,
|
||||
ChangedItemIcon.Customization,
|
||||
ChangedItemIcon.Action,
|
||||
ChangedItemIcon.Emote,
|
||||
ChangedItemIcon.Monster,
|
||||
ChangedItemIcon.Demihuman,
|
||||
ChangedItemIcon.Unknown,
|
||||
|
|
@ -182,14 +185,12 @@ public class ChangedItemDrawer : IDisposable
|
|||
|
||||
using var popup = ImRaii.ContextPopupItem(type.ToString());
|
||||
if (popup)
|
||||
{
|
||||
if (ImGui.MenuItem("Enable Only This"))
|
||||
{
|
||||
_config.ChangedItemFilter = type;
|
||||
_config.Save();
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
|
|
@ -238,6 +239,8 @@ public class ChangedItemDrawer : IDisposable
|
|||
{
|
||||
if (name.StartsWith("Action: "))
|
||||
iconType = ChangedItemIcon.Action;
|
||||
else if (name.StartsWith("Emote: "))
|
||||
iconType = ChangedItemIcon.Emote;
|
||||
else if (name.StartsWith("Customization: "))
|
||||
iconType = ChangedItemIcon.Customization;
|
||||
break;
|
||||
|
|
@ -306,6 +309,7 @@ public class ChangedItemDrawer : IDisposable
|
|||
ChangedItemIcon.Demihuman => "Demi-Human",
|
||||
ChangedItemIcon.Customization => "Customization",
|
||||
ChangedItemIcon.Action => "Action",
|
||||
ChangedItemIcon.Emote => "Emote",
|
||||
ChangedItemIcon.Mainhand => "Weapon (Mainhand)",
|
||||
ChangedItemIcon.Offhand => "Weapon (Offhand)",
|
||||
_ => "Other",
|
||||
|
|
@ -354,21 +358,47 @@ public class ChangedItemDrawer : IDisposable
|
|||
Add(ChangedItemIcon.Demihuman, textureProvider.GetTextureFromGame("ui/icon/062000/062041_hr1.tex", true));
|
||||
Add(ChangedItemIcon.Customization, textureProvider.GetTextureFromGame("ui/icon/062000/062043_hr1.tex", true));
|
||||
Add(ChangedItemIcon.Action, textureProvider.GetTextureFromGame("ui/icon/062000/062001_hr1.tex", true));
|
||||
Add(ChangedItemIcon.Emote, LoadEmoteTexture(gameData, uiBuilder));
|
||||
Add(ChangedItemIcon.Unknown, LoadUnknownTexture(gameData, uiBuilder));
|
||||
Add(AllFlags, textureProvider.GetTextureFromGame("ui/icon/114000/114052_hr1.tex", true));
|
||||
|
||||
_smallestIconWidth = _icons.Values.Min(i => i.Width);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static unsafe TextureWrap? LoadUnknownTexture(IDataManager gameData, UiBuilder uiBuilder)
|
||||
{
|
||||
var unk = gameData.GetFile<TexFile>("ui/uld/levelup2_hr1.tex");
|
||||
if (unk == null)
|
||||
return true;
|
||||
return null;
|
||||
|
||||
var image = unk.GetRgbaImageData();
|
||||
var bytes = new byte[unk.Header.Height * unk.Header.Height * 4];
|
||||
var diff = 2 * (unk.Header.Height - unk.Header.Width);
|
||||
for (var y = 0; y < unk.Header.Height; ++y)
|
||||
image.AsSpan(4 * y * unk.Header.Width, 4 * unk.Header.Width).CopyTo(bytes.AsSpan(4 * y * unk.Header.Height + diff));
|
||||
Add(ChangedItemIcon.Unknown, uiBuilder.LoadImageRaw(bytes, unk.Header.Height, unk.Header.Height, 4));
|
||||
|
||||
_smallestIconWidth = _icons.Values.Min(i => i.Width);
|
||||
return uiBuilder.LoadImageRaw(bytes, unk.Header.Height, unk.Header.Height, 4);
|
||||
}
|
||||
|
||||
return true;
|
||||
private static unsafe TextureWrap? LoadEmoteTexture(IDataManager gameData, UiBuilder uiBuilder)
|
||||
{
|
||||
var emote = gameData.GetFile<TexFile>("ui/icon/000000/000019_hr1.tex");
|
||||
if (emote == null)
|
||||
return null;
|
||||
|
||||
var image2 = emote.GetRgbaImageData();
|
||||
fixed (byte* ptr = image2)
|
||||
{
|
||||
var color = (uint*)ptr;
|
||||
for (var i = 0; i < image2.Length / 4; ++i)
|
||||
{
|
||||
if (color[i] == 0xFF000000)
|
||||
image2[i * 4 + 3] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return uiBuilder.LoadImageRaw(image2, emote.Header.Width, emote.Header.Height, 4);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using System.Numerics;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Utility;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Group;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
||||
|
|
@ -66,6 +67,7 @@ public class DebugTab : Window, ITab
|
|||
private readonly FrameworkManager _framework;
|
||||
private readonly TextureManager _textureManager;
|
||||
private readonly SkinFixer _skinFixer;
|
||||
private readonly IdentifierService _identifier;
|
||||
|
||||
public DebugTab(StartTracker timer, PerformanceTracker performance, Configuration config, CollectionManager collectionManager,
|
||||
ValidityChecker validityChecker, ModManager modManager, HttpApi httpApi, ActorService actorService,
|
||||
|
|
@ -73,7 +75,7 @@ public class DebugTab : Window, ITab
|
|||
ResourceManagerService resourceManager, PenumbraIpcProviders ipc, CollectionResolver collectionResolver,
|
||||
DrawObjectState drawObjectState, PathState pathState, SubfileHelper subfileHelper, IdentifiedCollectionCache identifiedCollectionCache,
|
||||
CutsceneService cutsceneService, ModImportManager modImporter, ImportPopup importPopup, FrameworkManager framework,
|
||||
TextureManager textureManager, SkinFixer skinFixer)
|
||||
TextureManager textureManager, SkinFixer skinFixer, IdentifierService identifier)
|
||||
: base("Penumbra Debug Window", ImGuiWindowFlags.NoCollapse, false)
|
||||
{
|
||||
IsOpen = true;
|
||||
|
|
@ -107,6 +109,7 @@ public class DebugTab : Window, ITab
|
|||
_framework = framework;
|
||||
_textureManager = textureManager;
|
||||
_skinFixer = skinFixer;
|
||||
_identifier = identifier;
|
||||
}
|
||||
|
||||
public ReadOnlySpan<byte> Label
|
||||
|
|
@ -138,12 +141,10 @@ public class DebugTab : Window, ITab
|
|||
ImGui.NewLine();
|
||||
DrawDebugCharacterUtility();
|
||||
ImGui.NewLine();
|
||||
DrawStainTemplates();
|
||||
DrawData();
|
||||
ImGui.NewLine();
|
||||
DrawDebugTabMetaLists();
|
||||
ImGui.NewLine();
|
||||
DrawDebugResidentResources();
|
||||
ImGui.NewLine();
|
||||
DrawResourceProblems();
|
||||
ImGui.NewLine();
|
||||
DrawPlayerModelInfo();
|
||||
|
|
@ -370,7 +371,9 @@ public class DebugTab : Window, ITab
|
|||
{
|
||||
ImGuiUtil.DrawTableColumn($"{((GameObject*)obj.Address)->ObjectIndex}");
|
||||
ImGuiUtil.DrawTableColumn($"0x{obj.Address:X}");
|
||||
ImGuiUtil.DrawTableColumn((obj.Address == nint.Zero) ? string.Empty : $"0x{(nint)((Character*)obj.Address)->GameObject.GetDrawObject():X}");
|
||||
ImGuiUtil.DrawTableColumn(obj.Address == nint.Zero
|
||||
? string.Empty
|
||||
: $"0x{(nint)((Character*)obj.Address)->GameObject.GetDrawObject():X}");
|
||||
var identifier = _actorService.AwaitedService.FromObject(obj, false, true, false);
|
||||
ImGuiUtil.DrawTableColumn(_actorService.AwaitedService.ToString(identifier));
|
||||
var id = obj.ObjectKind == ObjectKind.BattleNpc ? $"{identifier.DataId} | {obj.DataId}" : identifier.DataId.ToString();
|
||||
|
|
@ -546,9 +549,49 @@ public class DebugTab : Window, ITab
|
|||
}
|
||||
}
|
||||
|
||||
private void DrawData()
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Game Data"))
|
||||
return;
|
||||
|
||||
DrawEmotes();
|
||||
DrawStainTemplates();
|
||||
}
|
||||
|
||||
private string _emoteSearchFile = string.Empty;
|
||||
private string _emoteSearchName = string.Empty;
|
||||
|
||||
private void DrawEmotes()
|
||||
{
|
||||
using var mainTree = TreeNode("Emotes");
|
||||
if (!mainTree)
|
||||
return;
|
||||
|
||||
ImGui.InputText("File Name", ref _emoteSearchFile, 256);
|
||||
ImGui.InputText("Emote Name", ref _emoteSearchName, 256);
|
||||
using var table = Table("##table", 2, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY | ImGuiTableFlags.SizingFixedFit, new Vector2(-1, 12 * ImGui.GetTextLineHeightWithSpacing()));
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
var skips = ImGuiClip.GetNecessarySkips(ImGui.GetTextLineHeightWithSpacing());
|
||||
var dummy = ImGuiClip.FilteredClippedDraw(_identifier.AwaitedService.Emotes, skips,
|
||||
p => p.Key.Contains(_emoteSearchFile, StringComparison.OrdinalIgnoreCase)
|
||||
&& (_emoteSearchName.Length == 0
|
||||
|| p.Value.Any(s => s.Name.ToDalamudString().TextValue.Contains(_emoteSearchName, StringComparison.OrdinalIgnoreCase))),
|
||||
p =>
|
||||
{
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TextUnformatted(p.Key);
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TextUnformatted(string.Join(", ", p.Value.Select(v => v.Name.ToDalamudString().TextValue)));
|
||||
});
|
||||
ImGuiClip.DrawEndDummy(dummy, ImGui.GetTextLineHeightWithSpacing());
|
||||
}
|
||||
|
||||
private void DrawStainTemplates()
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Staining Templates"))
|
||||
using var mainTree = TreeNode("Staining Templates");
|
||||
if (!mainTree)
|
||||
return;
|
||||
|
||||
foreach (var (key, data) in _stains.StmFile.Entries)
|
||||
|
|
@ -625,16 +668,15 @@ public class DebugTab : Window, ITab
|
|||
ImGui.TableNextRow();
|
||||
continue;
|
||||
}
|
||||
|
||||
UiHelpers.Text(resource);
|
||||
ImGui.TableNextColumn();
|
||||
var data = (nint)ResourceHandle.GetData(resource);
|
||||
var data = (nint)ResourceHandle.GetData(resource);
|
||||
var length = ResourceHandle.GetLength(resource);
|
||||
if (ImGui.Selectable($"0x{data:X}"))
|
||||
{
|
||||
if (data != nint.Zero && length > 0)
|
||||
ImGui.SetClipboardText(string.Join("\n",
|
||||
new ReadOnlySpan<byte>((byte*)data, (int)length).ToArray().Select(b => b.ToString("X2"))));
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip("Click to copy bytes to clipboard.");
|
||||
ImGui.TableNextColumn();
|
||||
|
|
@ -655,7 +697,9 @@ public class DebugTab : Window, ITab
|
|||
ImGui.TextUnformatted($"{_characterUtility.DefaultResource(intern).Size}");
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.TableNextColumn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -679,7 +723,8 @@ public class DebugTab : Window, ITab
|
|||
/// <summary> Draw information about the resident resource files. </summary>
|
||||
private unsafe void DrawDebugResidentResources()
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Resident Resources"))
|
||||
using var tree = TreeNode("Resident Resources");
|
||||
if (!tree)
|
||||
return;
|
||||
|
||||
if (_residentResources.Address == null || _residentResources.Address->NumResources == 0)
|
||||
|
|
@ -703,8 +748,10 @@ public class DebugTab : Window, ITab
|
|||
private static void DrawCopyableAddress(string label, nint address)
|
||||
{
|
||||
using (var _ = PushFont(UiBuilder.MonoFont))
|
||||
{
|
||||
if (ImGui.Selectable($"0x{address:X16} {label}"))
|
||||
ImGui.SetClipboardText($"{address:X16}");
|
||||
}
|
||||
|
||||
ImGuiUtil.HoverTooltip("Click to copy address to clipboard.");
|
||||
}
|
||||
|
|
@ -789,9 +836,10 @@ public class DebugTab : Window, ITab
|
|||
if (!header)
|
||||
return;
|
||||
|
||||
DrawCopyableAddress("CharacterUtility", _characterUtility.Address);
|
||||
DrawCopyableAddress("CharacterUtility", _characterUtility.Address);
|
||||
DrawCopyableAddress("ResidentResourceManager", _residentResources.Address);
|
||||
DrawCopyableAddress("Device", Device.Instance());
|
||||
DrawCopyableAddress("Device", Device.Instance());
|
||||
DrawDebugResidentResources();
|
||||
}
|
||||
|
||||
/// <summary> Draw resources with unusual reference count. </summary>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue