From 923dd8b11fd2d2881ffbd36735184200fc77d4f7 Mon Sep 17 00:00:00 2001 From: pmgr <26606291+pmgr@users.noreply.github.com> Date: Wed, 29 Apr 2020 06:42:11 +0100 Subject: [PATCH] Added WorldToScreen and a prototype for ScreenToWorld. --- Dalamud/Game/Internal/Gui/GameGui.cs | 48 +++++++++++++++++++ .../Internal/Gui/GameGuiAddressResolver.cs | 4 ++ 2 files changed, 52 insertions(+) diff --git a/Dalamud/Game/Internal/Gui/GameGui.cs b/Dalamud/Game/Internal/Gui/GameGui.cs index 89f64eb2e..764b49d39 100644 --- a/Dalamud/Game/Internal/Gui/GameGui.cs +++ b/Dalamud/Game/Internal/Gui/GameGui.cs @@ -3,6 +3,7 @@ using System.Runtime.InteropServices; using Dalamud.Game.Chat.SeStringHandling.Payloads; using Dalamud.Hooking; using Serilog; +using SharpDX; namespace Dalamud.Game.Internal.Gui { public sealed class GameGui : IDisposable { @@ -34,6 +35,14 @@ namespace Dalamud.Game.Internal.Gui { private delegate bool OpenMapWithFlagDelegate(IntPtr UIMapObject, string flag); private OpenMapWithFlagDelegate openMapWithFlag; + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate IntPtr GetMatrixSingletonDelegate(); + internal readonly GetMatrixSingletonDelegate getMatrixSingleton; + + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + private unsafe delegate IntPtr ScreenToWorldNativeDelegate(float *camPosition, float *clipCoords, float rayDistance, float *worldCoords, float *unknown); + private readonly ScreenToWorldNativeDelegate screenToWorldNative; + /// /// 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 @@ -74,6 +83,12 @@ namespace Dalamud.Game.Internal.Gui { this); this.getUIObject = Marshal.GetDelegateForFunctionPointer(Address.GetUIObject); + + this.getMatrixSingleton = + Marshal.GetDelegateForFunctionPointer(Address.GetMatrixSingleton); + + this.screenToWorldNative = + Marshal.GetDelegateForFunctionPointer(Address.ScreenToWorld); } private IntPtr HandleSetGlobalBgmDetour(UInt16 bgmKey, byte a2, UInt32 a3, UInt32 a4, UInt32 a5, byte a6) { @@ -159,6 +174,39 @@ namespace Dalamud.Game.Internal.Gui { return this.openMapWithFlag(uiMapObjectPtr, mapLinkString); } + public Vector2 WorldToScreen(Vector3 worldCoords) + { + // Get base object with matrices + var matrixSingleton = this.getMatrixSingleton(); + + // Read current ViewProjectionMatrix plus game window size + var viewProjectionMatrix = new Matrix(); + float width, height; + unsafe { + var rawMatrix = (float*) (matrixSingleton + 0x1b4).ToPointer(); + + for (var i = 0; i < 16; i++, rawMatrix += 1) { + viewProjectionMatrix[i] = *rawMatrix; + } + + width = *rawMatrix; + height = *(rawMatrix + 1); + } + + Vector3.Transform(ref worldCoords, ref viewProjectionMatrix, out Vector3 pCoords); + + var normalProjCoords = new Vector2(pCoords.X / pCoords.Z, pCoords.Y / pCoords.Z); + + normalProjCoords.X = 0.5f * width * (normalProjCoords.X + 1f); + normalProjCoords.Y = 0.5f * height * (1f - normalProjCoords.Y); + + return normalProjCoords; + } + + public Vector3 ScreenToWorld(Vector2 screenCoords) { + return new Vector3(); + } + public void SetBgm(ushort bgmKey) => this.setGlobalBgmHook.Original(bgmKey, 0, 0, 0, 0, 0); public void Enable() { diff --git a/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs b/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs index 5142d0d41..0b092fdf6 100644 --- a/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs +++ b/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs @@ -12,6 +12,8 @@ namespace Dalamud.Game.Internal.Gui { public IntPtr HandleItemHover { get; set; } public IntPtr HandleItemOut { get; set; } public IntPtr GetUIObject { get; private set; } + public IntPtr GetMatrixSingleton { get; private set; } + public IntPtr ScreenToWorld { get; private set; } public GameGuiAddressResolver(IntPtr baseAddress) { BaseAddress = baseAddress; @@ -31,6 +33,8 @@ namespace Dalamud.Game.Internal.Gui { HandleItemHover = sig.ScanText("E8 ?? ?? ?? ?? 48 8B 5C 24 ?? 48 89 AE ?? ?? ?? ??"); HandleItemOut = sig.ScanText("48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 4D"); GetUIObject = sig.ScanText("E8 ?? ?? ?? ?? 48 8B C8 48 8B 10 FF 52 40 80 88 ?? ?? ?? ?? 01 E9"); + GetMatrixSingleton = sig.ScanText("E8 ?? ?? ?? ?? 48 8D 4C 24 ?? 48 89 4c 24 ?? 4C 8D 4D ?? 4C 8D 44 24 ??"); + ScreenToWorld = sig.ScanText("48 83 EC 48 48 8B 05 ?? ?? ?? ?? 4D 8B D1"); } } }