feat: add custom dalamud link payload handling
This commit is contained in:
parent
58efbf5b59
commit
8ce62fa24e
|
@ -4,9 +4,11 @@ using Dalamud.Game.Text.SeStringHandling;
|
|||
namespace ChatTwo;
|
||||
|
||||
internal abstract class Chunk {
|
||||
internal SeString? Source { get; set; }
|
||||
internal Payload? Link { get; set; }
|
||||
|
||||
protected Chunk(Payload? link) {
|
||||
protected Chunk(SeString? source, Payload? link) {
|
||||
this.Source = source;
|
||||
this.Link = link;
|
||||
}
|
||||
}
|
||||
|
@ -18,11 +20,11 @@ internal class TextChunk : Chunk {
|
|||
internal bool Italic { get; set; }
|
||||
internal string Content { get; set; }
|
||||
|
||||
internal TextChunk(Payload? link, string content) : base(link) {
|
||||
internal TextChunk(SeString? source, Payload? link, string content) : base(source, link) {
|
||||
this.Content = content;
|
||||
}
|
||||
|
||||
internal TextChunk(Payload? link, ChatType? fallbackColour, uint? foreground, uint? glow, bool italic, string content) : base(link) {
|
||||
internal TextChunk(SeString? source, Payload? link, ChatType? fallbackColour, uint? foreground, uint? glow, bool italic, string content) : base(source, link) {
|
||||
this.FallbackColour = fallbackColour;
|
||||
this.Foreground = foreground;
|
||||
this.Glow = glow;
|
||||
|
@ -34,7 +36,7 @@ internal class TextChunk : Chunk {
|
|||
internal class IconChunk : Chunk {
|
||||
internal BitmapFontIcon Icon { get; set; }
|
||||
|
||||
public IconChunk(Payload? link, BitmapFontIcon icon) : base(link) {
|
||||
public IconChunk(SeString? source, Payload? link, BitmapFontIcon icon) : base(source, link) {
|
||||
this.Icon = icon;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using ChatTwo.Ui;
|
||||
using ChatTwo.Util;
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
|
@ -54,12 +55,12 @@ internal sealed class PayloadHandler {
|
|||
}
|
||||
}
|
||||
|
||||
internal void Click(Payload payload, ImGuiMouseButton button) {
|
||||
internal void Click(Chunk chunk, Payload payload, ImGuiMouseButton button) {
|
||||
PluginLog.Log($"clicked {payload} with {button}");
|
||||
|
||||
switch (button) {
|
||||
case ImGuiMouseButton.Left:
|
||||
this.LeftClickPayload(payload);
|
||||
this.LeftClickPayload(chunk, payload);
|
||||
break;
|
||||
case ImGuiMouseButton.Right:
|
||||
this.RightClickPayload(payload);
|
||||
|
@ -145,7 +146,7 @@ internal sealed class PayloadHandler {
|
|||
this.Log.DrawChunks(desc.ToList());
|
||||
}
|
||||
|
||||
private void LeftClickPayload(Payload payload) {
|
||||
private void LeftClickPayload(Chunk chunk, Payload payload) {
|
||||
switch (payload) {
|
||||
case MapLinkPayload map: {
|
||||
this.Ui.Plugin.GameGui.OpenMapWithMapLink(map);
|
||||
|
@ -156,11 +157,38 @@ internal sealed class PayloadHandler {
|
|||
break;
|
||||
}
|
||||
case DalamudLinkPayload link: {
|
||||
this.ClickLinkPayload(chunk, payload, link);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ClickLinkPayload(Chunk chunk, Payload payload, DalamudLinkPayload link) {
|
||||
if (chunk.Source is not { } source) {
|
||||
return;
|
||||
}
|
||||
|
||||
var start = source.Payloads.IndexOf(payload);
|
||||
var end = source.Payloads.IndexOf(RawPayload.LinkTerminator);
|
||||
if (start == -1 || end == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
var payloads = source.Payloads.Skip(start).Take(end - start + 1).ToList();
|
||||
|
||||
var chatGui = this.Ui.Plugin.ChatGui;
|
||||
var field = chatGui.GetType().GetField("dalamudLinkHandlers", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (field == null || field.GetValue(chatGui) is not Dictionary<(string PluginName, uint CommandId), Action<uint, SeString>> dict || !dict.TryGetValue((link.Plugin, link.CommandId), out var action)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
action(link.CommandId, new SeString(payloads));
|
||||
} catch (Exception ex) {
|
||||
PluginLog.LogError(ex, "Error executing DalamudLinkPayload handler");
|
||||
}
|
||||
}
|
||||
|
||||
private void RightClickPayload(Payload payload) {
|
||||
switch (payload) {
|
||||
case PlayerPayload player: {
|
||||
|
|
|
@ -86,11 +86,11 @@ internal class Store : IDisposable {
|
|||
|
||||
var senderChunks = new List<Chunk>();
|
||||
if (formatting is { IsPresent: true }) {
|
||||
senderChunks.Add(new TextChunk(null, formatting.Before) {
|
||||
senderChunks.Add(new TextChunk(null, null, formatting.Before) {
|
||||
FallbackColour = chatCode.Type,
|
||||
});
|
||||
senderChunks.AddRange(ChunkUtil.ToChunks(sender, chatCode.Type));
|
||||
senderChunks.Add(new TextChunk(null, formatting.After) {
|
||||
senderChunks.Add(new TextChunk(null, null, formatting.After) {
|
||||
FallbackColour = chatCode.Type,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ internal sealed class ChatLog : IUiComponent {
|
|||
|
||||
if (tab.DisplayTimestamp) {
|
||||
var timestamp = message.Date.ToLocalTime().ToString("t");
|
||||
this.DrawChunk(new TextChunk(null, $"[{timestamp}]") {
|
||||
this.DrawChunk(new TextChunk(null, null, $"[{timestamp}]") {
|
||||
Foreground = 0xFFFFFFFF,
|
||||
});
|
||||
ImGui.SameLine();
|
||||
|
@ -298,7 +298,7 @@ internal sealed class ChatLog : IUiComponent {
|
|||
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;
|
||||
ImGui.Image(this._fontIcon.ImGuiHandle, size, uv0, uv1);
|
||||
ImGuiUtil.PostPayload(chunk.Link, handler);
|
||||
ImGuiUtil.PostPayload(chunk, handler);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -325,7 +325,7 @@ internal sealed class ChatLog : IUiComponent {
|
|||
ImGui.PushFont(this.Ui.ItalicFont.Value);
|
||||
}
|
||||
|
||||
ImGuiUtil.WrapText(text.Content, chunk.Link, handler);
|
||||
ImGuiUtil.WrapText(text.Content, chunk, handler);
|
||||
|
||||
if (text.Italic && this.Ui.ItalicFont.HasValue) {
|
||||
ImGui.PopFont();
|
||||
|
|
|
@ -14,7 +14,7 @@ internal static class ChunkUtil {
|
|||
Payload? link = null;
|
||||
|
||||
void Append(string text) {
|
||||
chunks.Add(new TextChunk(link, text) {
|
||||
chunks.Add(new TextChunk(msg, link, text) {
|
||||
FallbackColour = defaultColour,
|
||||
Foreground = foreground.Count > 0 ? foreground.Peek() : null,
|
||||
Glow = glow.Count > 0 ? glow.Peek() : null,
|
||||
|
@ -47,13 +47,13 @@ internal static class ChunkUtil {
|
|||
|
||||
break;
|
||||
case PayloadType.AutoTranslateText:
|
||||
chunks.Add(new IconChunk(link, BitmapFontIcon.AutoTranslateBegin));
|
||||
chunks.Add(new IconChunk(msg, link, BitmapFontIcon.AutoTranslateBegin));
|
||||
var autoText = ((AutoTranslatePayload) payload).Text;
|
||||
Append(autoText.Substring(2, autoText.Length - 4));
|
||||
chunks.Add(new IconChunk(link, BitmapFontIcon.AutoTranslateEnd));
|
||||
chunks.Add(new IconChunk(msg, link, BitmapFontIcon.AutoTranslateEnd));
|
||||
break;
|
||||
case PayloadType.Icon:
|
||||
chunks.Add(new IconChunk(link, ((IconPayload) payload).Icon));
|
||||
chunks.Add(new IconChunk(msg, link, ((IconPayload) payload).Icon));
|
||||
break;
|
||||
case PayloadType.MapLink:
|
||||
case PayloadType.Quest:
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.Text;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Interface;
|
||||
using ImGuiNET;
|
||||
|
||||
|
@ -12,7 +11,8 @@ internal static class ImGuiUtil {
|
|||
ImGuiMouseButton.Right,
|
||||
};
|
||||
|
||||
internal static void PostPayload(Payload? payload, PayloadHandler? handler) {
|
||||
internal static void PostPayload(Chunk chunk, PayloadHandler? handler) {
|
||||
var payload = chunk.Link;
|
||||
if (payload != null && ImGui.IsItemHovered()) {
|
||||
ImGui.SetMouseCursor(ImGuiMouseCursor.Hand);
|
||||
handler?.Hover(payload);
|
||||
|
@ -24,15 +24,15 @@ internal static class ImGuiUtil {
|
|||
|
||||
foreach (var button in Buttons) {
|
||||
if (ImGui.IsItemClicked(button)) {
|
||||
handler.Click(payload, button);
|
||||
handler.Click(chunk, payload, button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static unsafe void WrapText(string csText, Payload? payload, PayloadHandler? handler) {
|
||||
internal static unsafe void WrapText(string csText, Chunk chunk, PayloadHandler? handler) {
|
||||
void Text(byte* text, byte* textEnd) {
|
||||
ImGuiNative.igTextUnformatted(text, textEnd);
|
||||
PostPayload(payload, handler);
|
||||
PostPayload(chunk, handler);
|
||||
}
|
||||
|
||||
if (csText.Length == 0) {
|
||||
|
|
Loading…
Reference in New Issue