Add IGameGui (#1282)

This commit is contained in:
MidoriKami 2023-06-24 23:34:45 -07:00 committed by GitHub
parent 2fe7cfb5ef
commit 8a6269c178
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 134 additions and 72 deletions

View file

@ -7,6 +7,7 @@ using Dalamud.Hooking;
using Dalamud.Interface;
using Dalamud.IoC;
using Dalamud.IoC.Internal;
using Dalamud.Plugin.Services;
using Dalamud.Utility;
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
using FFXIVClientStructs.FFXIV.Client.System.String;
@ -28,7 +29,10 @@ namespace Dalamud.Game.Gui;
[PluginInterface]
[InterfaceVersion("1.0")]
[ServiceManager.BlockingEarlyLoadedService]
public sealed unsafe class GameGui : IDisposable, IServiceType
#pragma warning disable SA1015
[ResolveVia<IGameGui>]
#pragma warning restore SA1015
public sealed unsafe class GameGui : IDisposable, IServiceType, IGameGui
{
private readonly GameGuiAddressResolver address;
@ -112,43 +116,26 @@ public sealed unsafe class GameGui : IDisposable, IServiceType
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate IntPtr ToggleUiHideDelegate(IntPtr thisPtr, byte unknownByte);
/// <summary>
/// Event which is fired when the game UI hiding is toggled.
/// </summary>
/// <inheritdoc/>
public event EventHandler<bool> UiHideToggled;
/// <summary>
/// Event that is fired when the currently hovered item changes.
/// </summary>
/// <inheritdoc/>
public event EventHandler<ulong> HoveredItemChanged;
/// <summary>
/// Event that is fired when the currently hovered action changes.
/// </summary>
/// <inheritdoc/>
public event EventHandler<HoveredAction> HoveredActionChanged;
/// <summary>
/// Gets a value indicating whether the game UI is hidden.
/// </summary>
/// <inheritdoc/>
public bool GameUiHidden { get; private set; }
/// <summary>
/// Gets or sets the item ID that is currently hovered by the player. 0 when no item is hovered.
/// If > 1.000.000, subtract 1.000.000 and treat it as HQ.
/// </summary>
/// <inheritdoc/>
public ulong HoveredItem { get; set; }
/// <summary>
/// Gets the action ID that is current hovered by the player. 0 when no action is hovered.
/// </summary>
/// <inheritdoc/>
public HoveredAction HoveredAction { get; } = new HoveredAction();
/// <summary>
/// Opens the in-game map with a flag on the location of the parameter.
/// </summary>
/// <param name="mapLink">Link to the map to be opened.</param>
/// <returns>True if there were no errors and it could open the map.</returns>
/// <inheritdoc/>
public bool OpenMapWithMapLink(MapLinkPayload mapLink)
{
var uiModule = this.GetUIModule();
@ -178,22 +165,11 @@ public sealed unsafe class GameGui : IDisposable, IServiceType
return this.openMapWithFlag(uiMapObjectPtr, mapLinkString);
}
/// <summary>
/// Converts in-world coordinates to screen coordinates (upper left corner origin).
/// </summary>
/// <param name="worldPos">Coordinates in the world.</param>
/// <param name="screenPos">Converted coordinates.</param>
/// <returns>True if worldPos corresponds to a position in front of the camera and screenPos is in the viewport.</returns>
/// <inheritdoc/>
public bool WorldToScreen(Vector3 worldPos, out Vector2 screenPos)
=> this.WorldToScreen(worldPos, out screenPos, out var inView) && inView;
/// <summary>
/// Converts in-world coordinates to screen coordinates (upper left corner origin).
/// </summary>
/// <param name="worldPos">Coordinates in the world.</param>
/// <param name="screenPos">Converted coordinates.</param>
/// <param name="inView">True if screenPos corresponds to a position inside the camera viewport.</param>
/// <returns>True if worldPos corresponds to a position in front of the camera.</returns>
/// <inheritdoc/>
public bool WorldToScreen(Vector3 worldPos, out Vector2 screenPos, out bool inView)
{
// Get base object with matrices
@ -220,13 +196,7 @@ public sealed unsafe class GameGui : IDisposable, IServiceType
return inFront;
}
/// <summary>
/// Converts screen coordinates to in-world coordinates via raycasting.
/// </summary>
/// <param name="screenPos">Screen coordinates.</param>
/// <param name="worldPos">Converted coordinates.</param>
/// <param name="rayDistance">How far to search for a collision.</param>
/// <returns>True if successful. On false, worldPos's contents are undefined.</returns>
/// <inheritdoc/>
public bool ScreenToWorld(Vector2 screenPos, out Vector3 worldPos, float rayDistance = 100000.0f)
{
// The game is only visible in the main viewport, so if the cursor is outside
@ -290,10 +260,7 @@ public sealed unsafe class GameGui : IDisposable, IServiceType
return isSuccess;
}
/// <summary>
/// Gets a pointer to the game's UI module.
/// </summary>
/// <returns>IntPtr pointing to UI module.</returns>
/// <inheritdoc/>
public IntPtr GetUIModule()
{
var framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework.Instance();
@ -307,12 +274,7 @@ public sealed unsafe class GameGui : IDisposable, IServiceType
return (IntPtr)uiModule;
}
/// <summary>
/// Gets the pointer to the Addon with the given name and index.
/// </summary>
/// <param name="name">Name of addon to find.</param>
/// <param name="index">Index of addon to find (1-indexed).</param>
/// <returns>IntPtr.Zero if unable to find UI, otherwise IntPtr pointing to the start of the addon.</returns>
/// <inheritdoc/>
public IntPtr GetAddonByName(string name, int index = 1)
{
var atkStage = AtkStage.GetSingleton();
@ -330,29 +292,17 @@ public sealed unsafe class GameGui : IDisposable, IServiceType
return (IntPtr)addon;
}
/// <summary>
/// Find the agent associated with an addon, if possible.
/// </summary>
/// <param name="addonName">The addon name.</param>
/// <returns>A pointer to the agent interface.</returns>
/// <inheritdoc/>
public IntPtr FindAgentInterface(string addonName)
{
var addon = this.GetAddonByName(addonName);
return this.FindAgentInterface(addon);
}
/// <summary>
/// Find the agent associated with an addon, if possible.
/// </summary>
/// <param name="addon">The addon address.</param>
/// <returns>A pointer to the agent interface.</returns>
/// <inheritdoc/>
public IntPtr FindAgentInterface(void* addon) => this.FindAgentInterface((IntPtr)addon);
/// <summary>
/// Find the agent associated with an addon, if possible.
/// </summary>
/// <param name="addonPtr">The addon address.</param>
/// <returns>A pointer to the agent interface.</returns>
/// <inheritdoc/>
public IntPtr FindAgentInterface(IntPtr addonPtr)
{
if (addonPtr == IntPtr.Zero)

View file

@ -0,0 +1,112 @@
using System;
using System.Numerics;
using Dalamud.Game.Gui;
using Dalamud.Game.Text.SeStringHandling.Payloads;
namespace Dalamud.Plugin.Services;
/// <summary>
/// A class handling many aspects of the in-game UI.
/// </summary>
public unsafe interface IGameGui
{
/// <summary>
/// Event which is fired when the game UI hiding is toggled.
/// </summary>
public event EventHandler<bool> UiHideToggled;
/// <summary>
/// Event that is fired when the currently hovered item changes.
/// </summary>
public event EventHandler<ulong> HoveredItemChanged;
/// <summary>
/// Event that is fired when the currently hovered action changes.
/// </summary>
public event EventHandler<HoveredAction> HoveredActionChanged;
/// <summary>
/// Gets a value indicating whether the game UI is hidden.
/// </summary>
public bool GameUiHidden { get; }
/// <summary>
/// Gets or sets the item ID that is currently hovered by the player. 0 when no item is hovered.
/// If > 1.000.000, subtract 1.000.000 and treat it as HQ.
/// </summary>
public ulong HoveredItem { get; set; }
/// <summary>
/// Gets the action ID that is current hovered by the player. 0 when no action is hovered.
/// </summary>
public HoveredAction HoveredAction { get; }
/// <summary>
/// Opens the in-game map with a flag on the location of the parameter.
/// </summary>
/// <param name="mapLink">Link to the map to be opened.</param>
/// <returns>True if there were no errors and it could open the map.</returns>
public bool OpenMapWithMapLink(MapLinkPayload mapLink);
/// <summary>
/// Converts in-world coordinates to screen coordinates (upper left corner origin).
/// </summary>
/// <param name="worldPos">Coordinates in the world.</param>
/// <param name="screenPos">Converted coordinates.</param>
/// <returns>True if worldPos corresponds to a position in front of the camera and screenPos is in the viewport.</returns>
public bool WorldToScreen(Vector3 worldPos, out Vector2 screenPos);
/// <summary>
/// Converts in-world coordinates to screen coordinates (upper left corner origin).
/// </summary>
/// <param name="worldPos">Coordinates in the world.</param>
/// <param name="screenPos">Converted coordinates.</param>
/// <param name="inView">True if screenPos corresponds to a position inside the camera viewport.</param>
/// <returns>True if worldPos corresponds to a position in front of the camera.</returns>
public bool WorldToScreen(Vector3 worldPos, out Vector2 screenPos, out bool inView);
/// <summary>
/// Converts screen coordinates to in-world coordinates via raycasting.
/// </summary>
/// <param name="screenPos">Screen coordinates.</param>
/// <param name="worldPos">Converted coordinates.</param>
/// <param name="rayDistance">How far to search for a collision.</param>
/// <returns>True if successful. On false, worldPos's contents are undefined.</returns>
public bool ScreenToWorld(Vector2 screenPos, out Vector3 worldPos, float rayDistance = 100000.0f);
/// <summary>
/// Gets a pointer to the game's UI module.
/// </summary>
/// <returns>IntPtr pointing to UI module.</returns>
public nint GetUIModule();
/// <summary>
/// Gets the pointer to the Addon with the given name and index.
/// </summary>
/// <param name="name">Name of addon to find.</param>
/// <param name="index">Index of addon to find (1-indexed).</param>
/// <returns>nint.Zero if unable to find UI, otherwise nint pointing to the start of the addon.</returns>
public nint GetAddonByName(string name, int index = 1);
/// <summary>
/// Find the agent associated with an addon, if possible.
/// </summary>
/// <param name="addonName">The addon name.</param>
/// <returns>A pointer to the agent interface.</returns>
public nint FindAgentInterface(string addonName);
/// <summary>
/// Find the agent associated with an addon, if possible.
/// </summary>
/// <param name="addon">The addon address.</param>
/// <returns>A pointer to the agent interface.</returns>
public nint FindAgentInterface(void* addon);
/// <summary>
/// Find the agent associated with an addon, if possible.
/// </summary>
/// <param name="addonPtr">The addon address.</param>
/// <returns>A pointer to the agent interface.</returns>
public IntPtr FindAgentInterface(IntPtr addonPtr);
}