diff --git a/Dalamud.sln.DotSettings b/Dalamud.sln.DotSettings
index ba114a776..4653085d4 100644
--- a/Dalamud.sln.DotSettings
+++ b/Dalamud.sln.DotSettings
@@ -49,6 +49,7 @@
True
True
True
+ True
True
True
True
diff --git a/Dalamud/Game/Internal/Gui/FlyTextGui.cs b/Dalamud/Game/Internal/Gui/FlyTextGui.cs
new file mode 100644
index 000000000..5d7e9eef9
--- /dev/null
+++ b/Dalamud/Game/Internal/Gui/FlyTextGui.cs
@@ -0,0 +1,321 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+
+using Dalamud.Game.Text.SeStringHandling;
+using Dalamud.Hooking;
+using FFXIVClientStructs.FFXIV.Client.UI;
+using Serilog;
+
+namespace Dalamud.Game.Internal.Gui
+{
+ ///
+ /// This class facilitates interacting with and creating native in-game "fly text".
+ ///
+ public sealed class FlyTextGui : IDisposable
+ {
+ ///
+ /// The native function responsible for adding fly text to the UI. See .
+ ///
+ private readonly AddFlyTextDelegate addFlyTextNative;
+
+ ///
+ /// The hook that fires when the game creates a fly text element. See .
+ ///
+ private readonly Hook createFlyTextHook;
+
+ private readonly Stopwatch hookTimer;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The SigScanner instance.
+ /// The Dalamud instance.
+ internal FlyTextGui(SigScanner scanner, Dalamud dalamud)
+ {
+ this.Dalamud = dalamud;
+
+ this.hookTimer = new Stopwatch();
+
+ this.Address = new FlyTextGuiAddressResolver();
+ this.Address.Setup(scanner);
+
+ this.addFlyTextNative = Marshal.GetDelegateForFunctionPointer(this.Address.AddFlyText);
+ this.createFlyTextHook = new Hook(this.Address.CreateFlyText, this.CreateFlyTextDetour);
+ }
+
+ ///
+ /// The delegate defining the type for the FlyText event.
+ ///
+ /// The FlyTextKind. See .
+ /// Value1 passed to the native flytext function.
+ /// Value2 passed to the native flytext function. Seems unused.
+ /// Text1 passed to the native flytext function.
+ /// Text2 passed to the native flytext function.
+ /// Color passed to the native flytext function. Changes flytext color.
+ /// Icon ID passed to the native flytext function. Only displays with select FlyTextKind.
+ /// The vertical offset to place the flytext at. 0 is default. Negative values result
+ /// in text appearing higher on the screen. This does not change where the element begins to fade.
+ /// Whether this flytext has been handled. If a subscriber sets this to true, the FlyText will not appear.
+ public delegate void FlyTextDelegate(
+ ref FlyTextKind kind,
+ ref int val1,
+ ref int val2,
+ ref SeString text1,
+ ref SeString text2,
+ ref uint color,
+ ref uint icon,
+ ref float yOffset,
+ ref bool handled);
+
+ ///
+ /// Private delegate for the native CreateFlyText function's hook.
+ ///
+ private delegate IntPtr CreateFlyTextDelegate(
+ IntPtr addonFlyText,
+ int kind,
+ int val1,
+ int val2,
+ IntPtr text2,
+ uint color,
+ uint icon,
+ IntPtr text1,
+ float unk3);
+
+ ///
+ /// Private delegate for the native AddFlyText function pointer.
+ ///
+ private delegate void AddFlyTextDelegate(
+ IntPtr addonFlyText,
+ uint actorIndex,
+ uint messageMax,
+ IntPtr numbers,
+ uint offsetNum,
+ uint offsetNumMax,
+ IntPtr strings,
+ uint offsetStr,
+ uint offsetStrMax,
+ int unknown);
+
+ ///
+ /// The FlyText event that can be subscribed to.
+ ///
+ public event FlyTextDelegate? OnFlyText;
+
+ private Dalamud Dalamud { get; }
+
+ private FlyTextGuiAddressResolver Address { get; }
+
+ ///
+ /// Disposes of managed and unmanaged resources.
+ ///
+ public void Dispose()
+ {
+ this.createFlyTextHook.Disable();
+ this.createFlyTextHook.Dispose();
+ }
+
+ ///
+ /// Displays a fly text in-game on the local player.
+ ///
+ /// The FlyTextKind. See .
+ /// The index of the actor to place flytext on. Indexing unknown. 1 places flytext on local player.
+ /// Value1 passed to the native flytext function.
+ /// Value2 passed to the native flytext function. Seems unused.
+ /// Text1 passed to the native flytext function.
+ /// Text2 passed to the native flytext function.
+ /// Color passed to the native flytext function. Changes flytext color.
+ /// Icon ID passed to the native flytext function. Only displays with select FlyTextKind.
+ public unsafe void AddFlyText(FlyTextKind kind, uint actorIndex, uint val1, uint val2, SeString text1, SeString text2, uint color, uint icon)
+ {
+ // Known valid flytext region within the atk arrays
+ int numIndex = 28;
+ int strIndex = 25;
+ uint numOffset = 147;
+ uint strOffset = 28;
+
+ // Get the UI module and flytext addon pointers
+ var ui = (UIModule*)this.Dalamud.Framework.Gui.GetUIModule();
+ var flytext = this.Dalamud.Framework.Gui.GetUiObjectByName("_FlyText", 1);
+
+ if (ui == null || flytext == IntPtr.Zero)
+ return;
+
+ // Get the number and string arrays we need
+ var atkArrayDataHolder = ui->RaptureAtkModule.AtkModule.AtkArrayDataHolder;
+ var numArray = atkArrayDataHolder._NumberArrays[numIndex];
+ var strArray = atkArrayDataHolder._StringArrays[strIndex];
+
+ // Write the values to the arrays using a known valid flytext region
+
+ // Whether or not to enable this set of values for displaying flytext
+ numArray->IntArray[numOffset + 0] = 1; // Some kind of "Enabled" flag for this section
+ numArray->IntArray[numOffset + 1] = (int)kind;
+ numArray->IntArray[numOffset + 2] = unchecked((int)val1);
+ numArray->IntArray[numOffset + 3] = unchecked((int)val2);
+ numArray->IntArray[numOffset + 4] = 5; // Unknown
+ numArray->IntArray[numOffset + 5] = unchecked((int)color);
+ numArray->IntArray[numOffset + 6] = unchecked((int)icon);
+ numArray->IntArray[numOffset + 7] = 0; // Unknown
+ numArray->IntArray[numOffset + 8] = 0; // Unknown, has something to do with yOffset
+
+ fixed (byte* pText1 = text1.Encode())
+ {
+ fixed (byte* pText2 = text2.Encode())
+ {
+ strArray->StringArray[strOffset + 0] = pText1;
+ strArray->StringArray[strOffset + 1] = pText2;
+
+ this.addFlyTextNative(
+ flytext,
+ actorIndex,
+ 1,
+ (IntPtr)numArray,
+ numOffset,
+ 9,
+ (IntPtr)strArray,
+ strOffset,
+ 2,
+ 0);
+ }
+ }
+ }
+
+ ///
+ /// Enables this module.
+ ///
+ internal void Enable()
+ {
+ this.createFlyTextHook.Enable();
+ }
+
+ private IntPtr CreateFlyTextDetour(
+ IntPtr addonFlyText,
+ int kind,
+ int val1,
+ int val2,
+ IntPtr text2,
+ uint color,
+ uint icon,
+ IntPtr text1,
+ float yOffset)
+ {
+ var retVal = IntPtr.Zero;
+ try
+ {
+ this.hookTimer.Restart();
+ Log.Verbose("[FlyText] Enter CreateFlyText detour!");
+
+ var handled = false;
+
+ var tmpKind = (FlyTextKind)kind;
+ var tmpVal1 = val1;
+ var tmpVal2 = val2;
+ var tmpText1 = this.Dalamud.SeStringManager.Parse(text1);
+ var tmpText2 = this.Dalamud.SeStringManager.Parse(text2);
+ var tmpColor = color;
+ var tmpIcon = icon;
+ var tmpYOffset = yOffset;
+
+ var cmpText1 = tmpText1.ToString();
+ var cmpText2 = tmpText2.ToString();
+
+ Log.Verbose($"[FlyText] Called with addonFlyText({addonFlyText.ToInt64():X}) " +
+ $"kind({((FlyTextKind)kind).ToString()}) val1({val1}) val2({val2}) " +
+ $"text1({text1.ToInt64():X}, \"{tmpText1}\") text2({text2.ToInt64():X}, \"{tmpText2}\") " +
+ $"color({color:X}) icon({icon}) yOffset({yOffset})");
+ Log.Verbose("[FlyText] Calling flytext events!");
+ this.OnFlyText?.Invoke(
+ ref tmpKind,
+ ref tmpVal1,
+ ref tmpVal2,
+ ref tmpText1,
+ ref tmpText2,
+ ref tmpColor,
+ ref tmpIcon,
+ ref tmpYOffset,
+ ref handled);
+
+ // If handled, ignore the original call
+ if (handled)
+ {
+ Log.Verbose("[FlyText] FlyText was handled.");
+
+ // Returning null to AddFlyText from CreateFlyText will result
+ // in the operation being dropped entirely.
+ return IntPtr.Zero;
+ }
+
+ // Check if any values have changed
+ var dirty = tmpKind != (FlyTextKind)kind ||
+ tmpVal1 != val1 ||
+ tmpVal2 != val2 ||
+ tmpText1.ToString() != cmpText1 ||
+ tmpText2.ToString() != cmpText2 ||
+ tmpColor != color ||
+ tmpIcon != icon ||
+ Math.Abs(tmpYOffset - yOffset) > float.Epsilon;
+
+ // If not dirty, make the original call
+ if (!dirty)
+ {
+ Log.Verbose("[FlyText] Calling flytext with original args.");
+ return this.createFlyTextHook.Original(addonFlyText, kind, val1, val2, text2, color, icon, text1, yOffset);
+ }
+
+ var terminated1 = Terminate(tmpText1.Encode());
+ var terminated2 = Terminate(tmpText2.Encode());
+ var pText1 = Marshal.AllocHGlobal(terminated1.Length);
+ var pText2 = Marshal.AllocHGlobal(terminated2.Length);
+ Marshal.Copy(terminated1, 0, pText1, terminated1.Length);
+ Marshal.Copy(terminated2, 0, pText2, terminated2.Length);
+ Log.Verbose("[FlyText] Allocated and set strings.");
+
+ retVal = this.createFlyTextHook.Original(
+ addonFlyText,
+ (int)tmpKind,
+ tmpVal1,
+ tmpVal2,
+ pText2,
+ tmpColor,
+ tmpIcon,
+ pText1,
+ tmpYOffset);
+
+ Log.Verbose("[FlyText] Returned from original. Delaying free task.");
+
+ Task.Delay(2000).ContinueWith(_ =>
+ {
+ try
+ {
+ Marshal.FreeHGlobal(pText1);
+ Marshal.FreeHGlobal(pText2);
+ Log.Verbose("[FlyText] Freed strings.");
+ }
+ catch (Exception e)
+ {
+ Log.Verbose(e, "[FlyText] Exception occurred freeing strings in task.");
+ }
+ });
+ this.hookTimer.Stop();
+ Log.Verbose($"[FlyText] Hook took {this.hookTimer.ElapsedTicks} ticks, {this.hookTimer.ElapsedMilliseconds}ms.");
+ }
+ catch (Exception e)
+ {
+ Log.Error(e, "Exception occurred in CreateFlyTextDetour!");
+ }
+
+ return retVal;
+ }
+
+ private static byte[] Terminate(byte[] source)
+ {
+ var terminated = new byte[source.Length + 1];
+ Array.Copy(source, 0, terminated, 0, source.Length);
+ terminated[^1] = 0;
+
+ return terminated;
+ }
+ }
+}
diff --git a/Dalamud/Game/Internal/Gui/FlyTextGuiAddressResolver.cs b/Dalamud/Game/Internal/Gui/FlyTextGuiAddressResolver.cs
new file mode 100644
index 000000000..6d073b701
--- /dev/null
+++ b/Dalamud/Game/Internal/Gui/FlyTextGuiAddressResolver.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace Dalamud.Game.Internal.Gui
+{
+ ///
+ /// An address resolver for the class.
+ ///
+ public class FlyTextGuiAddressResolver : BaseAddressResolver
+ {
+ ///
+ /// Gets the address of the native AddFlyText method, which occurs
+ /// when the game adds fly text elements to the UI. Multiple fly text
+ /// elements can be added in a single AddFlyText call.
+ ///
+ public IntPtr AddFlyText { get; private set; }
+
+ ///
+ /// Gets the address of the native CreateFlyText method, which occurs
+ /// when the game creates a new fly text element. This method is called
+ /// once per fly text element, and can be called multiple times per
+ /// AddFlyText call.
+ ///
+ public IntPtr CreateFlyText { get; private set; }
+
+ ///
+ protected override void Setup64Bit(SigScanner sig)
+ {
+ this.AddFlyText = sig.ScanText("E8 ?? ?? ?? ?? FF C7 41 D1 C7");
+ this.CreateFlyText = sig.ScanText("48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 40 48 63 FA");
+ }
+ }
+}
diff --git a/Dalamud/Game/Internal/Gui/FlyTextKind.cs b/Dalamud/Game/Internal/Gui/FlyTextKind.cs
new file mode 100644
index 000000000..b9a222ac3
--- /dev/null
+++ b/Dalamud/Game/Internal/Gui/FlyTextKind.cs
@@ -0,0 +1,214 @@
+namespace Dalamud.Game.Internal.Gui
+{
+ ///
+ /// Enum of FlyTextKind values. Members suffixed with
+ /// a number seem to be a duplicate, or perform duplicate behavior.
+ ///
+ public enum FlyTextKind
+ {
+ ///
+ /// Val1 in serif font, Text2 in sans-serif as subtitle.
+ /// Used for autos and incoming DoTs.
+ ///
+ AutoAttack = 0,
+
+ ///
+ /// Val1 in serif font, Text2 in sans-serif as subtitle.
+ /// Does a bounce effect on appearance.
+ ///
+ DirectHit = 1,
+
+ ///
+ /// Val1 in larger serif font with exclamation, with Text2
+ /// in sans-serif as subtitle. Does a bigger bounce effect on appearance.
+ ///
+ CriticalHit = 2,
+
+ ///
+ /// Val1 in even larger serif font with 2 exclamations, Text2 in
+ /// sans-serif as subtitle. Does a large bounce effect on appearance.
+ /// Does not scroll up or down the screen.
+ ///
+ CriticalDirectHit = 3,
+
+ ///
+ /// AutoAttack with sans-serif Text1 to the left of the Val1.
+ ///
+ NamedAttack = 4,
+
+ ///
+ /// DirectHit with sans-serif Text1 to the left of the Val1.
+ ///
+ NamedDirectHit = 5,
+
+ ///
+ /// CriticalHit with sans-serif Text1 to the left of the Val1.
+ ///
+ NamedCriticalHit = 6,
+
+ ///
+ /// CriticalDirectHit with sans-serif Text1 to the left of the Val1.
+ ///
+ NamedCriticalDirectHit = 7,
+
+ ///
+ /// All caps, serif MISS.
+ ///
+ Miss = 8,
+
+ ///
+ /// Sans-serif Text1 next to all caps serif MISS.
+ ///
+ NamedMiss = 9,
+
+ ///
+ /// All caps serif DODGE.
+ ///
+ Dodge = 10,
+
+ ///
+ /// Sans-serif Text1 next to all caps serif DODGE.
+ ///
+ NamedDodge = 11,
+
+ ///
+ /// Icon next to sans-serif Text1.
+ ///
+ NamedIcon = 12,
+ NamedIcon2 = 13,
+
+ ///
+ /// Serif Val1 with all caps condensed font EXP with Text2 in sans-serif as subtitle.
+ ///
+ Exp = 14,
+
+ ///
+ /// Sans-serif Text1 next to serif Val1 with all caps condensed font MP with Text2 in sans-serif as subtitle.
+ ///
+ NamedMp = 15,
+
+ ///
+ /// Sans-serif Text1 next to serif Val1 with all caps condensed font TP with Text2 in sans-serif as subtitle.
+ ///
+ NamedTp = 16,
+
+ NamedAttack2 = 17,
+ NamedMp2 = 18,
+ NamedTp2 = 19,
+
+ ///
+ /// Sans-serif Text1 next to serif Val1 with all caps condensed font EP with Text2 in sans-serif as subtitle.
+ ///
+ NamedEp = 20,
+
+ ///
+ /// Displays nothing.
+ ///
+ None = 21,
+
+ ///
+ /// All caps serif INVULNERABLE.
+ ///
+ Invulnerable = 22,
+
+ ///
+ /// All caps sans-serif condensed font INTERRUPTED!
+ /// Does a large bounce effect on appearance.
+ /// Does not scroll up or down the screen.
+ ///
+ Interrupted = 23,
+
+ ///
+ /// AutoAttack with no Text2.
+ ///
+ AutoAttackNoText = 24,
+ AutoAttackNoText2 = 25,
+ CriticalHit2 = 26,
+ AutoAttackNoText3 = 27,
+ NamedCriticalHit2 = 28,
+
+ ///
+ /// Same as NamedCriticalHit with a green (cannot change) MP in condensed font to the right of Val1.
+ /// Does a jiggle effect to the right on appearance.
+ ///
+ NamedCriticalHitWithMp = 29,
+
+ ///
+ /// Same as NamedCriticalHit with a yellow (cannot change) TP in condensed font to the right of Val1.
+ /// Does a jiggle effect to the right on appearance.
+ ///
+ NamedCriticalHitWithTp = 30,
+
+ ///
+ /// Same as NamedIcon with sans-serif "has no effect!" to the right.
+ ///
+ NamedIconHasNoEffect = 31,
+
+ ///
+ /// Same as NamedIcon but Text1 is slightly faded. Used for buff expiration.
+ ///
+ NamedIconFaded = 32,
+ NamedIconFaded2 = 33,
+
+ ///
+ /// Text1 in sans-serif font.
+ ///
+ Named = 34,
+
+ ///
+ /// Same as NamedIcon with sans-serif "(fully resisted)" to the right.
+ ///
+ NamedIconFullyResisted = 35,
+
+ ///
+ /// All caps serif 'INCAPACITATED!'.
+ ///
+ Incapacitated = 36,
+
+ ///
+ /// Text1 with sans-serif "(fully resisted)" to the right.
+ ///
+ NamedFullyResisted = 37,
+
+ ///
+ /// Text1 with sans-serif "has no effect!" to the right.
+ ///
+ NamedHasNoEffect = 38,
+
+ NamedAttack3 = 39,
+ NamedMp3 = 40,
+ NamedTp3 = 41,
+
+ ///
+ /// Same as NamedIcon with serif "INVULNERABLE!" beneath the Text1.
+ ///
+ NamedIconInvulnerable = 42,
+
+ ///
+ /// All caps serif RESIST.
+ ///
+ Resist = 43,
+
+ ///
+ /// Same as NamedIcon but places the given icon in the item icon outline.
+ ///
+ NamedIconWithItemOutline = 44,
+
+ AutoAttackNoText4 = 45,
+ CriticalHit3 = 46,
+
+ ///
+ /// All caps serif REFLECT.
+ ///
+ Reflect = 47,
+
+ ///
+ /// All caps serif REFLECTED.
+ ///
+ Reflected = 48,
+
+ DirectHit2 = 49,
+ CriticalHit5 = 50,
+ CriticalDirectHit2 = 51,
+ }
+}
diff --git a/Dalamud/Game/Internal/Gui/GameGui.cs b/Dalamud/Game/Internal/Gui/GameGui.cs
index f27f75662..005a15da9 100644
--- a/Dalamud/Game/Internal/Gui/GameGui.cs
+++ b/Dalamud/Game/Internal/Gui/GameGui.cs
@@ -66,6 +66,7 @@ namespace Dalamud.Game.Internal.Gui
this.Chat = new ChatGui(this.address.ChatManager, scanner, dalamud);
this.PartyFinder = new PartyFinderGui(scanner, dalamud);
this.Toast = new ToastGui(scanner, dalamud);
+ this.FlyText = new FlyTextGui(scanner, dalamud);
this.setGlobalBgmHook = new Hook(this.address.SetGlobalBgm, this.HandleSetGlobalBgmDetour);
this.handleItemHoverHook = new Hook(this.address.HandleItemHover, this.HandleItemHoverDetour);
@@ -161,6 +162,11 @@ namespace Dalamud.Game.Internal.Gui
///
public ToastGui Toast { get; private set; }
+ ///
+ /// Gets the instance.
+ ///
+ public FlyTextGui FlyText { get; private set; }
+
///
/// Gets a value indicating whether the game UI is hidden.
///
@@ -452,6 +458,7 @@ namespace Dalamud.Game.Internal.Gui
{
this.Chat.Enable();
this.Toast.Enable();
+ this.FlyText.Enable();
this.PartyFinder.Enable();
this.setGlobalBgmHook.Enable();
this.handleItemHoverHook.Enable();
@@ -468,6 +475,7 @@ namespace Dalamud.Game.Internal.Gui
{
this.Chat.Dispose();
this.Toast.Dispose();
+ this.FlyText.Dispose();
this.PartyFinder.Dispose();
this.setGlobalBgmHook.Dispose();
this.handleItemHoverHook.Dispose();
diff --git a/Dalamud/Game/Text/SeStringHandling/SeStringManager.cs b/Dalamud/Game/Text/SeStringHandling/SeStringManager.cs
index ad805f528..ed9437d3d 100644
--- a/Dalamud/Game/Text/SeStringHandling/SeStringManager.cs
+++ b/Dalamud/Game/Text/SeStringHandling/SeStringManager.cs
@@ -1,6 +1,8 @@
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Runtime.InteropServices;
using Dalamud.Data;
using Dalamud.Game.Text.SeStringHandling.Payloads;
@@ -47,6 +49,24 @@ namespace Dalamud.Game.Text.SeStringHandling
return new SeString(payloads);
}
+ ///
+ /// Parse a binary game message into an SeString.
+ ///
+ /// Pointer to a binary message payload data in SE's internal format.
+ /// An SeString containing parsed Payload objects for each payload in the data.
+ public SeString Parse(IntPtr bytePtr)
+ {
+ var bytes = new List();
+ byte read = Marshal.ReadByte(bytePtr, 0);
+ for (int ofs = 1; read != 0; ofs++)
+ {
+ bytes.Add(read);
+ read = Marshal.ReadByte(bytePtr, ofs);
+ }
+
+ return this.Parse(bytes.ToArray());
+ }
+
///
/// Creates an SeString representing an entire Payload chain that can be used to link an item in the chat log.
///
diff --git a/Dalamud/Interface/Internal/Windows/DataWindow.cs b/Dalamud/Interface/Internal/Windows/DataWindow.cs
index 6b723098f..c2ad77d1b 100644
--- a/Dalamud/Interface/Internal/Windows/DataWindow.cs
+++ b/Dalamud/Interface/Internal/Windows/DataWindow.cs
@@ -9,6 +9,7 @@ using Dalamud.Game.ClientState.Actors.Types;
using Dalamud.Game.ClientState.Actors.Types.NonPlayer;
using Dalamud.Game.ClientState.Structs.JobGauge;
using Dalamud.Game.Internal;
+using Dalamud.Game.Internal.Gui;
using Dalamud.Game.Internal.Gui.Addon;
using Dalamud.Game.Internal.Gui.Toast;
using Dalamud.Game.Text;
@@ -49,6 +50,7 @@ namespace Dalamud.Interface.Internal.Windows
private UIDebug addonInspector = null;
+ // Toast fields
private string inputTextToast = string.Empty;
private int toastPosition = 0;
private int toastSpeed = 0;
@@ -57,6 +59,17 @@ namespace Dalamud.Interface.Internal.Windows
private int questToastIconId = 0;
private bool questToastCheckmark = false;
+ // Fly text fields
+ private int flyActor;
+ private FlyTextKind flyKind;
+ private int flyVal1;
+ private int flyVal2;
+ private string flyText1 = string.Empty;
+ private string flyText2 = string.Empty;
+ private int flyIcon;
+ private Vector4 flyColor = new(1, 0, 0, 1);
+
+ // ImGui fields
private string inputTexPath = string.Empty;
private TextureWrap debugTex = null;
private Vector2 inputTexUv0 = Vector2.Zero;
@@ -98,6 +111,7 @@ namespace Dalamud.Interface.Internal.Windows
StartInfo,
Target,
Toast,
+ FlyText,
ImGui,
Tex,
Gamepad,
@@ -226,6 +240,10 @@ namespace Dalamud.Interface.Internal.Windows
this.DrawToast();
break;
+ case DataKind.FlyText:
+ this.DrawFlyText();
+ break;
+
case DataKind.ImGui:
this.DrawImGui();
break;
@@ -687,6 +705,45 @@ namespace Dalamud.Interface.Internal.Windows
}
}
+ private void DrawFlyText()
+ {
+ if (ImGui.BeginCombo("Kind", this.flyKind.ToString()))
+ {
+ var names = Enum.GetNames(typeof(FlyTextKind));
+ for (int i = 0; i < names.Length; i++)
+ {
+ if (ImGui.Selectable($"{names[i]} ({i})"))
+ this.flyKind = (FlyTextKind)i;
+ }
+
+ ImGui.EndCombo();
+ }
+
+ ImGui.InputText("Text1", ref this.flyText1, 200);
+ ImGui.InputText("Text2", ref this.flyText2, 200);
+
+ ImGui.InputInt("Val1", ref this.flyVal1);
+ ImGui.InputInt("Val2", ref this.flyVal2);
+
+ ImGui.InputInt("Icon ID", ref this.flyIcon);
+ ImGui.ColorEdit4("Color", ref this.flyColor);
+ ImGui.InputInt("Actor Index", ref this.flyActor);
+ var sendColor = ImGui.ColorConvertFloat4ToU32(this.flyColor);
+
+ if (ImGui.Button("Send"))
+ {
+ this.dalamud.Framework.Gui.FlyText.AddFlyText(
+ this.flyKind,
+ unchecked((uint)this.flyActor),
+ unchecked((uint)this.flyVal1),
+ unchecked((uint)this.flyVal2),
+ this.flyText1,
+ this.flyText2,
+ sendColor,
+ unchecked((uint)this.flyIcon));
+ }
+ }
+
private void DrawImGui()
{
ImGui.Text("Monitor count: " + ImGui.GetPlatformIO().Monitors.Size);