feat: partially handle some payloads

This commit is contained in:
Anna
2021-12-29 21:53:44 -05:00
parent 1d9581abca
commit 0b9d617021
14 changed files with 341 additions and 50 deletions
+2 -2
View File
@@ -4,7 +4,7 @@ using Dalamud.Game.Text.SeStringHandling;
namespace ChatTwo; namespace ChatTwo;
internal abstract class Chunk { internal abstract class Chunk {
internal Payload? Link; internal Payload? Link { get; set; }
protected Chunk(Payload? link) { protected Chunk(Payload? link) {
this.Link = link; this.Link = link;
@@ -32,7 +32,7 @@ internal class TextChunk : Chunk {
} }
internal class IconChunk : Chunk { internal class IconChunk : Chunk {
internal BitmapFontIcon Icon; internal BitmapFontIcon Icon { get; set; }
public IconChunk(Payload? link, BitmapFontIcon icon) : base(link) { public IconChunk(Payload? link, BitmapFontIcon icon) : base(link) {
this.Icon = icon; this.Icon = icon;
+1 -1
View File
@@ -1,4 +1,4 @@
namespace ChatTwo.Code; namespace ChatTwo.Code;
internal enum InputChannel : uint { internal enum InputChannel : uint {
Tell = 0, Tell = 0,
+1 -1
View File
@@ -1,4 +1,4 @@
namespace ChatTwo.Code; namespace ChatTwo.Code;
internal static class InputChannelExt { internal static class InputChannelExt {
internal static ChatType ToChatType(this InputChannel input) { internal static ChatType ToChatType(this InputChannel input) {
+3 -1
View File
@@ -1,13 +1,14 @@
using ChatTwo.Code; using ChatTwo.Code;
using Dalamud.Configuration; using Dalamud.Configuration;
namespace ChatTwo; namespace ChatTwo;
[Serializable] [Serializable]
internal class Configuration : IPluginConfiguration { internal class Configuration : IPluginConfiguration {
public int Version { get; set; } = 1; public int Version { get; set; } = 1;
public bool HideChat = true; public bool HideChat = true;
public bool NativeItemTooltips = true;
public float FontSize = 17f; public float FontSize = 17f;
public Dictionary<ChatType, uint> ChatColours = new(); public Dictionary<ChatType, uint> ChatColours = new();
public List<Tab> Tabs = new(); public List<Tab> Tabs = new();
@@ -43,6 +44,7 @@ internal class Tab {
if (this.Messages.Count > 1000) { if (this.Messages.Count > 1000) {
this.Messages.RemoveAt(0); this.Messages.RemoveAt(0);
} }
this.MessagesMutex.ReleaseMutex(); this.MessagesMutex.ReleaseMutex();
this.Unread += 1; this.Unread += 1;
+54 -1
View File
@@ -102,6 +102,59 @@ internal unsafe class GameFunctions : IDisposable {
return (*flags & (1 << 22)) == 0; return (*flags & (1 << 22)) == 0;
} }
internal void OpenItemTooltip(uint id) {
var atkStage = AtkStage.GetSingleton();
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ItemDetail);
var addon = atkStage->RaptureAtkUnitManager->GetAddonByName("ItemDetail");
if (agent == null || addon == null) {
// atkStage ain't gonna be null or we have bigger problems
return;
}
var agentPtr = (IntPtr) agent;
// addresses mentioned here are 6.01
// see the call near the end of AgentItemDetail.Update
// offsets valid as of 6.01
// 8BFC49: sets some shit
*(uint*) (agentPtr + 0x20) = 22;
// 8C04C8: switch goes down to default, which is what we want
*(byte*) (agentPtr + 0x118) = 1;
// 8BFCF6: item id when hovering over item in chat
*(uint*) (agentPtr + 0x11C) = id;
// 8BFCE4: always 0 when hovering over item in chat
*(uint*) (agentPtr + 0x120) = 0;
// 8C0B55: skips a check to do with inventory
*(byte*) (agentPtr + 0x128) &= 0xEF;
// 8BFC7C: when set to 1, lets everything continue (one frame)
*(byte*) (agentPtr + 0x146) = 1;
// 8BFC89: skips early return
*(byte*) (agentPtr + 0x14A) = 0;
// this just probably needs to be set
agent->AddonId = (uint) addon->ID;
// vcall from E8 ?? ?? ?? ?? 0F B7 C0 48 83 C4 60
var vf5 = (delegate*<AtkUnitBase*, byte, uint, void>*) ((IntPtr) addon->VTable + 40);
// E8872D: lets vf5 actually run
*(byte*) ((IntPtr) atkStage + 0x2B4) |= 2;
(*vf5)(addon, 0, 15);
}
internal void CloseItemTooltip() {
// hide addon first to prevent the "addon close" sound
var addon = AtkStage.GetSingleton()->RaptureAtkUnitManager->GetAddonByName("ItemDetail");
if (addon != null) {
addon->Hide(true);
}
var agent = Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.ItemDetail);
if (agent != null) {
agent->Hide();
}
}
private byte ChatLogRefreshDetour(IntPtr log, ushort eventId, AtkValue* value) { private byte ChatLogRefreshDetour(IntPtr log, ushort eventId, AtkValue* value) {
if (eventId == 0x31 && value != null && value->UInt is 0x05 or 0x0C) { if (eventId == 0x31 && value != null && value->UInt is 0x05 or 0x0C) {
string? eventInput = null; string? eventInput = null;
@@ -144,7 +197,7 @@ internal unsafe class GameFunctions : IDisposable {
} }
var channel = *(uint*) (shellModule + 0xFD0); var channel = *(uint*) (shellModule + 0xFD0);
// var channel = *(uint*) (agent + 0x40); // var channel = *(uint*) (agent + 0x40);
if (channel is 17 or 18) { if (channel is 17 or 18) {
channel = 0; channel = 0;
+1 -1
View File
@@ -1,6 +1,6 @@
using ChatTwo.Code; using ChatTwo.Code;
namespace ChatTwo; namespace ChatTwo;
internal class Message { internal class Message {
internal DateTime Date { get; } internal DateTime Date { get; }
+190
View File
@@ -0,0 +1,190 @@
using System.Numerics;
using ChatTwo.Ui;
using ChatTwo.Util;
using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Game.Text.SeStringHandling.Payloads;
using Dalamud.Logging;
using Dalamud.Utility;
using ImGuiNET;
namespace ChatTwo;
internal sealed class PayloadHandler {
private PluginUi Ui { get; }
private ChatLog Log { get; }
private HashSet<PlayerPayload> Popups { get; set; } = new();
private uint _hoveredItem;
private uint _hoverCounter;
private uint _lastHoverCounter;
internal PayloadHandler(PluginUi ui, ChatLog log) {
this.Ui = ui;
this.Log = log;
}
internal void Draw() {
var newPopups = new HashSet<PlayerPayload>();
foreach (var player in this.Popups) {
var id = PopupId(player);
if (!ImGui.BeginPopup(id)) {
continue;
}
newPopups.Add(player);
ImGui.PushID(id);
this.DrawPlayerPopup(player);
ImGui.PopID();
ImGui.EndPopup();
}
this.Popups = newPopups;
if (++this._hoverCounter - this._lastHoverCounter > 1) {
this.Ui.Plugin.Functions.CloseItemTooltip();
this._hoveredItem = 0;
this._hoverCounter = this._lastHoverCounter = 0;
}
}
internal void Click(Payload payload, ImGuiMouseButton button) {
PluginLog.Log($"clicked {payload} with {button}");
switch (button) {
case ImGuiMouseButton.Left:
this.LeftClickPayload(payload);
break;
case ImGuiMouseButton.Right:
this.RightClickPayload(payload);
break;
}
}
internal void Hover(Payload payload) {
switch (payload) {
case StatusPayload status: {
this.DoHover(() => this.HoverStatus(status), 250f);
break;
}
case ItemPayload item: {
if (this.Ui.Plugin.Config.NativeItemTooltips) {
this.Ui.Plugin.Functions.OpenItemTooltip(item.ItemId);
if (this._hoveredItem != item.ItemId) {
this._hoveredItem = item.ItemId;
this._hoverCounter = this._lastHoverCounter = 0;
} else {
this._lastHoverCounter = this._hoverCounter;
}
break;
}
this.DoHover(() => this.HoverItem(item), 250f);
break;
}
}
}
private void DoHover(Action inside, float width) {
ImGui.SetNextWindowSize(new Vector2(width, -1f));
ImGui.BeginTooltip();
ImGui.PushTextWrapPos();
ImGui.PushStyleColor(ImGuiCol.Text, this.Ui.DefaultText);
try {
inside();
} finally {
ImGui.PopStyleColor();
ImGui.PopTextWrapPos();
ImGui.EndTooltip();
}
}
private void HoverStatus(StatusPayload status) {
var name = ChunkUtil.ToChunks(status.Status.Name.ToDalamudString(), null);
this.Log.DrawChunks(name.ToList());
ImGui.Separator();
var desc = ChunkUtil.ToChunks(status.Status.Description.ToDalamudString(), null);
this.Log.DrawChunks(desc.ToList());
}
private void HoverItem(ItemPayload item) {
var name = ChunkUtil.ToChunks(item.Item.Name.ToDalamudString(), null);
this.Log.DrawChunks(name.ToList());
ImGui.Separator();
var desc = ChunkUtil.ToChunks(item.Item.Description.ToDalamudString(), null);
this.Log.DrawChunks(desc.ToList());
}
private void LeftClickPayload(Payload payload) {
switch (payload) {
case MapLinkPayload map: {
this.Ui.Plugin.GameGui.OpenMapWithMapLink(map);
break;
}
case QuestPayload quest: {
this.Ui.Plugin.Common.Functions.Journal.OpenQuest(quest.Quest);
break;
}
case DalamudLinkPayload link: {
break;
}
}
}
private void RightClickPayload(Payload payload) {
switch (payload) {
case PlayerPayload player: {
this.Popups.Add(player);
ImGui.OpenPopup(PopupId(player));
break;
}
}
}
private void DrawPlayerPopup(PlayerPayload player) {
var name = player.PlayerName;
if (player.World.IsPublic) {
name += $"{player.World.Name}";
}
ImGui.TextUnformatted(name);
ImGui.Separator();
if (player.World.IsPublic && ImGui.Selectable("Send Tell")) {
this.Log.Chat = $"/tell {player.PlayerName}@{player.World.Name} ";
this.Log.Activate = true;
}
if (ImGui.Selectable("Target")) {
foreach (var obj in this.Ui.Plugin.ObjectTable) {
if (obj is not PlayerCharacter character) {
continue;
}
if (character.Name.TextValue != player.PlayerName) {
continue;
}
if (player.World.IsPublic && character.HomeWorld.Id != player.World.RowId) {
continue;
}
this.Ui.Plugin.TargetManager.SetTarget(obj);
break;
}
}
}
private static string PopupId(PlayerPayload player) {
return $"###player-{player.PlayerName}@{player.World}";
}
}
+12 -2
View File
@@ -1,6 +1,7 @@
using Dalamud.Data; using Dalamud.Data;
using Dalamud.Game; using Dalamud.Game;
using Dalamud.Game.ClientState; using Dalamud.Game.ClientState;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.Command; using Dalamud.Game.Command;
using Dalamud.Game.Gui; using Dalamud.Game.Gui;
using Dalamud.IoC; using Dalamud.IoC;
@@ -21,7 +22,7 @@ public sealed class Plugin : IDalamudPlugin {
[PluginService] [PluginService]
internal ClientState ClientState { get; init; } internal ClientState ClientState { get; init; }
[PluginService] [PluginService]
internal CommandManager CommandManager { get; init; } internal CommandManager CommandManager { get; init; }
@@ -31,9 +32,18 @@ public sealed class Plugin : IDalamudPlugin {
[PluginService] [PluginService]
internal Framework Framework { get; init; } internal Framework Framework { get; init; }
[PluginService]
internal GameGui GameGui { get; init; }
[PluginService]
internal ObjectTable ObjectTable { get; init; }
[PluginService] [PluginService]
internal SigScanner SigScanner { get; init; } internal SigScanner SigScanner { get; init; }
[PluginService]
internal TargetManager TargetManager { get; init; }
internal Configuration Config { get; } internal Configuration Config { get; }
internal XivCommonBase Common { get; } internal XivCommonBase Common { get; }
internal GameFunctions Functions { get; } internal GameFunctions Functions { get; }
@@ -78,7 +88,7 @@ public sealed class Plugin : IDalamudPlugin {
if (!this.Config.HideChat) { if (!this.Config.HideChat) {
return; return;
} }
foreach (var name in ChatAddonNames) { foreach (var name in ChatAddonNames) {
if (GameFunctions.IsAddonInteractable(name)) { if (GameFunctions.IsAddonInteractable(name)) {
GameFunctions.SetAddonInteractable(name, false); GameFunctions.SetAddonInteractable(name, false);
+5 -1
View File
@@ -1,4 +1,5 @@
using System.Runtime.InteropServices; using System.Numerics;
using System.Runtime.InteropServices;
using ChatTwo.Ui; using ChatTwo.Ui;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Logging; using Dalamud.Logging;
@@ -10,6 +11,7 @@ internal sealed class PluginUi : IDisposable {
internal Plugin Plugin { get; } internal Plugin Plugin { get; }
internal ImFontPtr? RegularFont { get; private set; } internal ImFontPtr? RegularFont { get; private set; }
internal ImFontPtr? ItalicFont { get; private set; } internal ImFontPtr? ItalicFont { get; private set; }
internal Vector4 DefaultText { get; private set; }
private List<IUiComponent> Components { get; } private List<IUiComponent> Components { get; }
private ImFontConfigPtr _fontCfg; private ImFontConfigPtr _fontCfg;
@@ -104,6 +106,8 @@ internal sealed class PluginUi : IDisposable {
} }
private void Draw() { private void Draw() {
this.DefaultText = ImGui.GetStyle().Colors[(int) ImGuiCol.Text];
var font = this.RegularFont.HasValue; var font = this.RegularFont.HasValue;
if (font) { if (font) {
+33 -27
View File
@@ -9,15 +9,18 @@ namespace ChatTwo.Ui;
internal sealed class ChatLog : IUiComponent { internal sealed class ChatLog : IUiComponent {
private PluginUi Ui { get; } private PluginUi Ui { get; }
private bool _activate; internal bool Activate;
private string _chat = string.Empty; internal string Chat = string.Empty;
private readonly TextureWrap? _fontIcon; private readonly TextureWrap? _fontIcon;
private readonly List<string> _inputBacklog = new(); private readonly List<string> _inputBacklog = new();
private int _inputBacklogIdx = -1; private int _inputBacklogIdx = -1;
private int _lastTab; private int _lastTab;
private PayloadHandler PayloadHandler { get; }
internal ChatLog(PluginUi ui) { internal ChatLog(PluginUi ui) {
this.Ui = ui; this.Ui = ui;
this.PayloadHandler = new PayloadHandler(this.Ui, this);
this._fontIcon = this.Ui.Plugin.DataManager.GetImGuiTexture("common/font/fonticon_ps5.tex"); this._fontIcon = this.Ui.Plugin.DataManager.GetImGuiTexture("common/font/fonticon_ps5.tex");
@@ -30,9 +33,9 @@ internal sealed class ChatLog : IUiComponent {
} }
private void ChatActivated(string? input) { private void ChatActivated(string? input) {
this._activate = true; this.Activate = true;
if (input != null && !this._chat.Contains(input)) { if (input != null && !this.Chat.Contains(input)) {
this._chat += input; this.Chat += input;
} }
} }
@@ -80,7 +83,7 @@ internal sealed class ChatLog : IUiComponent {
// int numMessages; // int numMessages;
try { try {
tab.MessagesMutex.WaitOne(); tab.MessagesMutex.WaitOne();
for (var i = 0; i < tab.Messages.Count; i++) { for (var i = 0; i < tab.Messages.Count; i++) {
// numDrawn += 1; // numDrawn += 1;
var message = tab.Messages[i]; var message = tab.Messages[i];
@@ -94,11 +97,11 @@ internal sealed class ChatLog : IUiComponent {
} }
if (message.Sender.Count > 0) { if (message.Sender.Count > 0) {
this.DrawChunks(message.Sender); this.DrawChunks(message.Sender, this.PayloadHandler);
ImGui.SameLine(); ImGui.SameLine();
} }
this.DrawChunks(message.Content); this.DrawChunks(message.Content, this.PayloadHandler);
// drawnHeight += ImGui.GetCursorPosY() - lastPos; // drawnHeight += ImGui.GetCursorPosY() - lastPos;
// lastPos = ImGui.GetCursorPosY(); // lastPos = ImGui.GetCursorPosY();
@@ -115,7 +118,7 @@ internal sealed class ChatLog : IUiComponent {
} }
// PluginLog.Log($"numDrawn: {numDrawn}"); // PluginLog.Log($"numDrawn: {numDrawn}");
if (switchedTab || ImGui.GetScrollY() >= ImGui.GetScrollMaxY()) { if (switchedTab || ImGui.GetScrollY() >= ImGui.GetScrollMaxY()) {
// PluginLog.Log($"drawnHeight: {drawnHeight}"); // PluginLog.Log($"drawnHeight: {drawnHeight}");
// var itemPosY = clipper.StartPosY + drawnHeight; // var itemPosY = clipper.StartPosY + drawnHeight;
@@ -125,6 +128,8 @@ internal sealed class ChatLog : IUiComponent {
} }
} }
this.PayloadHandler.Draw();
ImGui.EndChild(); ImGui.EndChild();
ImGui.EndTabItem(); ImGui.EndTabItem();
@@ -134,7 +139,7 @@ internal sealed class ChatLog : IUiComponent {
ImGui.EndTabBar(); ImGui.EndTabBar();
} }
if (this._activate) { if (this.Activate) {
ImGui.SetKeyboardFocusHere(); ImGui.SetKeyboardFocusHere();
} }
@@ -148,23 +153,23 @@ internal sealed class ChatLog : IUiComponent {
if (inputColour != null) { if (inputColour != null) {
ImGui.PushStyleColor(ImGuiCol.Text, ColourUtil.RgbaToAbgr(inputColour.Value)); ImGui.PushStyleColor(ImGuiCol.Text, ColourUtil.RgbaToAbgr(inputColour.Value));
} }
ImGui.SetNextItemWidth(-1); ImGui.SetNextItemWidth(-1);
const ImGuiInputTextFlags inputFlags = ImGuiInputTextFlags.EnterReturnsTrue const ImGuiInputTextFlags inputFlags = ImGuiInputTextFlags.EnterReturnsTrue
| ImGuiInputTextFlags.CallbackAlways | ImGuiInputTextFlags.CallbackAlways
| ImGuiInputTextFlags.CallbackHistory; | ImGuiInputTextFlags.CallbackHistory;
if (ImGui.InputText("##chat2-input", ref this._chat, 500, inputFlags, this.Callback)) { if (ImGui.InputText("##chat2-input", ref this.Chat, 500, inputFlags, this.Callback)) {
if (!string.IsNullOrWhiteSpace(this._chat)) { if (!string.IsNullOrWhiteSpace(this.Chat)) {
var trimmed = this._chat.Trim(); var trimmed = this.Chat.Trim();
this.AddBacklog(trimmed); this.AddBacklog(trimmed);
this._inputBacklogIdx = -1; this._inputBacklogIdx = -1;
this.Ui.Plugin.Common.Functions.Chat.SendMessage(trimmed); this.Ui.Plugin.Common.Functions.Chat.SendMessage(trimmed);
} }
this._chat = string.Empty; this.Chat = string.Empty;
} }
if (inputColour != null) { if (inputColour != null) {
ImGui.PopStyleColor(); ImGui.PopStyleColor();
} }
@@ -175,9 +180,9 @@ internal sealed class ChatLog : IUiComponent {
private unsafe int Callback(ImGuiInputTextCallbackData* data) { private unsafe int Callback(ImGuiInputTextCallbackData* data) {
var ptr = new ImGuiInputTextCallbackDataPtr(data); var ptr = new ImGuiInputTextCallbackDataPtr(data);
if (this._activate) { if (this.Activate) {
this._activate = false; this.Activate = false;
data->CursorPos = this._chat.Length; data->CursorPos = this.Chat.Length;
data->SelectionStart = data->SelectionEnd = data->CursorPos; data->SelectionStart = data->SelectionEnd = data->CursorPos;
} }
@@ -192,12 +197,12 @@ internal sealed class ChatLog : IUiComponent {
switch (this._inputBacklogIdx) { switch (this._inputBacklogIdx) {
case -1: case -1:
var offset = 0; var offset = 0;
if (!string.IsNullOrWhiteSpace(this._chat)) { if (!string.IsNullOrWhiteSpace(this.Chat)) {
this.AddBacklog(this._chat); this.AddBacklog(this.Chat);
offset = 1; offset = 1;
} }
this._inputBacklogIdx = this._inputBacklog.Count - 1 - offset; this._inputBacklogIdx = this._inputBacklog.Count - 1 - offset;
break; break;
case > 0: case > 0:
@@ -229,9 +234,9 @@ internal sealed class ChatLog : IUiComponent {
return 0; return 0;
} }
private void DrawChunks(IReadOnlyList<Chunk> chunks) { internal void DrawChunks(IReadOnlyList<Chunk> chunks, PayloadHandler? handler = null) {
for (var i = 0; i < chunks.Count; i++) { for (var i = 0; i < chunks.Count; i++) {
this.DrawChunk(chunks[i]); this.DrawChunk(chunks[i], handler);
if (i < chunks.Count - 1) { if (i < chunks.Count - 1) {
ImGui.SameLine(); ImGui.SameLine();
@@ -239,7 +244,7 @@ internal sealed class ChatLog : IUiComponent {
} }
} }
private void DrawChunk(Chunk chunk) { private void DrawChunk(Chunk chunk, PayloadHandler? handler = null) {
if (chunk is IconChunk icon && this._fontIcon != null) { if (chunk is IconChunk icon && this._fontIcon != null) {
var bounds = IconUtil.GetBounds((byte) icon.Icon); var bounds = IconUtil.GetBounds((byte) icon.Icon);
if (bounds != null) { if (bounds != null) {
@@ -251,6 +256,7 @@ internal sealed class ChatLog : IUiComponent {
var uv0 = new Vector2(bounds.Value.X, bounds.Value.Y - 2) / texSize; var uv0 = new Vector2(bounds.Value.X, bounds.Value.Y - 2) / texSize;
var uv1 = new Vector2(bounds.Value.X + bounds.Value.Z, bounds.Value.Y - 2 + bounds.Value.W) / texSize; var uv1 = new Vector2(bounds.Value.X + bounds.Value.Z, bounds.Value.Y - 2 + bounds.Value.W) / texSize;
ImGui.Image(this._fontIcon.ImGuiHandle, size, uv0, uv1); ImGui.Image(this._fontIcon.ImGuiHandle, size, uv0, uv1);
ImGuiUtil.PostPayload(chunk.Link, handler);
} }
return; return;
@@ -277,7 +283,7 @@ internal sealed class ChatLog : IUiComponent {
ImGui.PushFont(this.Ui.ItalicFont.Value); ImGui.PushFont(this.Ui.ItalicFont.Value);
} }
ImGuiUtil.WrapText(text.Content); ImGuiUtil.WrapText(text.Content, chunk.Link, handler);
if (text.Italic && this.Ui.ItalicFont.HasValue) { if (text.Italic && this.Ui.ItalicFont.HasValue) {
ImGui.PopFont(); ImGui.PopFont();
+4
View File
@@ -12,6 +12,7 @@ internal sealed class Settings : IUiComponent {
private bool _visible; private bool _visible;
private bool _hideChat; private bool _hideChat;
private bool _nativeItemTooltips;
private float _fontSize; private float _fontSize;
private Dictionary<ChatType, uint> _chatColours = new(); private Dictionary<ChatType, uint> _chatColours = new();
private List<Tab> _tabs = new(); private List<Tab> _tabs = new();
@@ -34,6 +35,7 @@ internal sealed class Settings : IUiComponent {
private void Initialise() { private void Initialise() {
var config = this.Ui.Plugin.Config; var config = this.Ui.Plugin.Config;
this._hideChat = config.HideChat; this._hideChat = config.HideChat;
this._nativeItemTooltips = config.NativeItemTooltips;
this._fontSize = config.FontSize; this._fontSize = config.FontSize;
this._chatColours = config.ChatColours.ToDictionary(entry => entry.Key, entry => entry.Value); this._chatColours = config.ChatColours.ToDictionary(entry => entry.Key, entry => entry.Value);
this._tabs = config.Tabs.Select(tab => tab.Clone()).ToList(); this._tabs = config.Tabs.Select(tab => tab.Clone()).ToList();
@@ -60,6 +62,7 @@ internal sealed class Settings : IUiComponent {
- ImGui.CalcTextSize("A").Y; - ImGui.CalcTextSize("A").Y;
if (ImGui.BeginChild("##chat2-settings", new Vector2(-1, height))) { if (ImGui.BeginChild("##chat2-settings", new Vector2(-1, height))) {
ImGui.Checkbox("Hide chat", ref this._hideChat); ImGui.Checkbox("Hide chat", ref this._hideChat);
ImGui.Checkbox("Show native item tooltips", ref this._nativeItemTooltips);
ImGui.DragFloat("Font size", ref this._fontSize, .5f, 12f, 36f); ImGui.DragFloat("Font size", ref this._fontSize, .5f, 12f, 36f);
if (ImGui.TreeNodeEx("Chat colours")) { if (ImGui.TreeNodeEx("Chat colours")) {
@@ -163,6 +166,7 @@ internal sealed class Settings : IUiComponent {
var fontSizeChanged = Math.Abs(this._fontSize - this.Ui.Plugin.Config.FontSize) > float.Epsilon; var fontSizeChanged = Math.Abs(this._fontSize - this.Ui.Plugin.Config.FontSize) > float.Epsilon;
config.HideChat = this._hideChat; config.HideChat = this._hideChat;
config.NativeItemTooltips = this._nativeItemTooltips;
config.FontSize = this._fontSize; config.FontSize = this._fontSize;
config.ChatColours = this._chatColours; config.ChatColours = this._chatColours;
config.Tabs = this._tabs; config.Tabs = this._tabs;
+1 -1
View File
@@ -1,4 +1,4 @@
namespace ChatTwo.Ui; namespace ChatTwo.Ui;
internal interface IUiComponent : IDisposable { internal interface IUiComponent : IDisposable {
void Draw(); void Draw();
+1 -8
View File
@@ -1,7 +1,6 @@
using ChatTwo.Code; using ChatTwo.Code;
using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Game.Text.SeStringHandling.Payloads;
using Dalamud.Logging;
namespace ChatTwo.Util; namespace ChatTwo.Util;
@@ -23,13 +22,7 @@ internal static class ChunkUtil {
}); });
} }
PluginLog.Log("");
foreach (var payload in msg.Payloads) { foreach (var payload in msg.Payloads) {
PluginLog.Log(payload.Type.ToString());
if (payload.Type == PayloadType.Unknown) {
PluginLog.Log(payload.Encode().Select(b => b.ToString("x2")).Aggregate(string.Concat));
}
switch (payload.Type) { switch (payload.Type) {
case PayloadType.EmphasisItalic: case PayloadType.EmphasisItalic:
var newStatus = ((EmphasisItalicPayload) payload).IsEnabled; var newStatus = ((EmphasisItalicPayload) payload).IsEnabled;
@@ -75,7 +68,7 @@ internal static class ChunkUtil {
if (rawPayload.Data[1] == 0x13) { if (rawPayload.Data[1] == 0x13) {
foreground.Pop(); foreground.Pop();
glow.Pop(); glow.Pop();
} else if (rawPayload == RawPayload.LinkTerminator) { } else if (Equals(rawPayload, RawPayload.LinkTerminator)) {
link = null; link = null;
} }
+33 -4
View File
@@ -1,10 +1,39 @@
using System.Text; using System.Text;
using Dalamud.Game.Text.SeStringHandling;
using ImGuiNET; using ImGuiNET;
namespace ChatTwo.Util; namespace ChatTwo.Util;
internal static class ImGuiUtil { internal static class ImGuiUtil {
internal static unsafe void WrapText(string csText) { private static readonly ImGuiMouseButton[] Buttons = {
ImGuiMouseButton.Left,
ImGuiMouseButton.Middle,
ImGuiMouseButton.Right,
};
internal static void PostPayload(Payload? payload, PayloadHandler? handler) {
if (payload != null && ImGui.IsItemHovered()) {
ImGui.SetMouseCursor(ImGuiMouseCursor.Hand);
handler?.Hover(payload);
}
if (payload == null || handler == null) {
return;
}
foreach (var button in Buttons) {
if (ImGui.IsItemClicked(button)) {
handler.Click(payload, button);
}
}
}
internal static unsafe void WrapText(string csText, Payload? payload, PayloadHandler? handler) {
void Text(byte* text, byte* textEnd) {
ImGuiNative.igTextUnformatted(text, textEnd);
PostPayload(payload, handler);
}
foreach (var part in csText.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)) { foreach (var part in csText.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)) {
var bytes = Encoding.UTF8.GetBytes(part); var bytes = Encoding.UTF8.GetBytes(part);
fixed (byte* rawText = bytes) { fixed (byte* rawText = bytes) {
@@ -23,7 +52,7 @@ internal static class ImGuiUtil {
return; return;
} }
ImGuiNative.igTextUnformatted(text, endPrevLine); Text(text, endPrevLine);
widthLeft = ImGui.GetContentRegionAvail().X; widthLeft = ImGui.GetContentRegionAvail().X;
while (endPrevLine < textEnd) { while (endPrevLine < textEnd) {
@@ -37,7 +66,7 @@ internal static class ImGuiUtil {
break; break;
} }
ImGuiNative.igTextUnformatted(text, endPrevLine); Text(text, endPrevLine);
} }
} }
} }