mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-13 20:24:16 +01:00
Merge pull request #1763 from goatcorp/new_im_hooks-rollup
[new_im_hooks] Rollup changes from master
This commit is contained in:
commit
dba48b7d19
4 changed files with 105 additions and 5 deletions
|
|
@ -12,6 +12,8 @@ using Dalamud.Logging.Internal;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||||
|
|
||||||
using Lumina.Excel.GeneratedSheets;
|
using Lumina.Excel.GeneratedSheets;
|
||||||
|
|
||||||
using Action = System.Action;
|
using Action = System.Action;
|
||||||
|
|
@ -89,6 +91,16 @@ internal sealed class ClientState : IInternalDisposableService, IClientState
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ushort TerritoryType { get; private set; }
|
public ushort TerritoryType { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public unsafe uint MapId
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var agentMap = AgentMap.Instance();
|
||||||
|
return agentMap != null ? AgentMap.Instance()->CurrentMapId : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public PlayerCharacter? LocalPlayer => Service<ObjectTable>.GetNullable()?[0] as PlayerCharacter;
|
public PlayerCharacter? LocalPlayer => Service<ObjectTable>.GetNullable()?[0] as PlayerCharacter;
|
||||||
|
|
||||||
|
|
@ -238,6 +250,9 @@ internal class ClientStatePluginScoped : IInternalDisposableService, IClientStat
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ushort TerritoryType => this.clientStateService.TerritoryType;
|
public ushort TerritoryType => this.clientStateService.TerritoryType;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public uint MapId => this.clientStateService.MapId;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public PlayerCharacter? LocalPlayer => this.clientStateService.LocalPlayer;
|
public PlayerCharacter? LocalPlayer => this.clientStateService.LocalPlayer;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ using System.Text.Unicode;
|
||||||
using Dalamud.Game;
|
using Dalamud.Game;
|
||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
using Dalamud.Hooking.WndProcHook;
|
using Dalamud.Hooking.WndProcHook;
|
||||||
|
using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.GameFonts;
|
using Dalamud.Interface.GameFonts;
|
||||||
using Dalamud.Interface.Internal.ManagedAsserts;
|
using Dalamud.Interface.Internal.ManagedAsserts;
|
||||||
using Dalamud.Interface.ManagedFontAtlas.Internals;
|
using Dalamud.Interface.ManagedFontAtlas.Internals;
|
||||||
|
|
@ -82,7 +83,7 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
private readonly ImGuiSetPlatformImeDataDelegate setPlatformImeDataDelegate;
|
private readonly ImGuiSetPlatformImeDataDelegate setPlatformImeDataDelegate;
|
||||||
|
|
||||||
/// <summary>The candidates.</summary>
|
/// <summary>The candidates.</summary>
|
||||||
private readonly List<string> candidateStrings = new();
|
private readonly List<(string String, bool Supported)> candidateStrings = new();
|
||||||
|
|
||||||
/// <summary>The selected imm component.</summary>
|
/// <summary>The selected imm component.</summary>
|
||||||
private string compositionString = string.Empty;
|
private string compositionString = string.Empty;
|
||||||
|
|
@ -242,6 +243,42 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static (string String, bool Supported) ToUcs2(char* data, int nc = -1)
|
||||||
|
{
|
||||||
|
if (nc == -1)
|
||||||
|
{
|
||||||
|
nc = 0;
|
||||||
|
while (data[nc] != 0)
|
||||||
|
nc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var supported = true;
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.EnsureCapacity(nc);
|
||||||
|
for (var i = 0; i < nc; i++)
|
||||||
|
{
|
||||||
|
if (char.IsHighSurrogate(data[i]) && i + 1 < nc && char.IsLowSurrogate(data[i + 1]))
|
||||||
|
{
|
||||||
|
// Surrogate pair is found, but only UCS-2 characters are supported. Skip the next low surrogate.
|
||||||
|
sb.Append('\xFFFD');
|
||||||
|
supported = false;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if (char.IsSurrogate(data[i]) || !Rune.IsValid(data[i]))
|
||||||
|
{
|
||||||
|
// Lone surrogate pair, or an invalid codepoint.
|
||||||
|
sb.Append('\xFFFD');
|
||||||
|
supported = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (sb.ToString(), supported);
|
||||||
|
}
|
||||||
|
|
||||||
private static string ImmGetCompositionString(HIMC hImc, uint comp)
|
private static string ImmGetCompositionString(HIMC hImc, uint comp)
|
||||||
{
|
{
|
||||||
var numBytes = ImmGetCompositionStringW(hImc, comp, null, 0);
|
var numBytes = ImmGetCompositionStringW(hImc, comp, null, 0);
|
||||||
|
|
@ -250,7 +287,8 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
|
|
||||||
var data = stackalloc char[numBytes / 2];
|
var data = stackalloc char[numBytes / 2];
|
||||||
_ = ImmGetCompositionStringW(hImc, comp, data, (uint)numBytes);
|
_ = ImmGetCompositionStringW(hImc, comp, data, (uint)numBytes);
|
||||||
return new(data, 0, numBytes / 2);
|
|
||||||
|
return ToUcs2(data, numBytes / 2).String;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReleaseUnmanagedResources()
|
private void ReleaseUnmanagedResources()
|
||||||
|
|
@ -623,8 +661,8 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
(int)candlist.dwPageStart,
|
(int)candlist.dwPageStart,
|
||||||
(int)Math.Min(candlist.dwCount - candlist.dwPageStart, candlist.dwPageSize)))
|
(int)Math.Min(candlist.dwCount - candlist.dwPageStart, candlist.dwPageSize)))
|
||||||
{
|
{
|
||||||
this.candidateStrings.Add(new((char*)(pStorage + candlist.dwOffset[i])));
|
this.candidateStrings.Add(ToUcs2((char*)(pStorage + candlist.dwOffset[i])));
|
||||||
this.ReflectCharacterEncounters(this.candidateStrings[^1]);
|
this.ReflectCharacterEncounters(this.candidateStrings[^1].String);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -783,7 +821,15 @@ internal sealed unsafe class DalamudIme : IInternalDisposableService
|
||||||
if (selected)
|
if (selected)
|
||||||
color = ImGui.GetColorU32(ImGuiCol.NavHighlight);
|
color = ImGui.GetColorU32(ImGuiCol.NavHighlight);
|
||||||
|
|
||||||
drawList.AddText(cursor, color, $"{i + 1}. {ime.candidateStrings[i]}");
|
var s = $"{i + 1}. {ime.candidateStrings[i].String}";
|
||||||
|
drawList.AddText(cursor, color, s);
|
||||||
|
if (!ime.candidateStrings[i].Supported)
|
||||||
|
{
|
||||||
|
var pos = cursor + ImGui.CalcTextSize(s) with { Y = 0 } +
|
||||||
|
new Vector2(4 * ImGuiHelpers.GlobalScale, 0);
|
||||||
|
drawList.AddText(pos, ImGui.GetColorU32(ImGuiColors.DalamudRed), " (x)");
|
||||||
|
}
|
||||||
|
|
||||||
cursor.Y += candTextSize.Y + spaceY;
|
cursor.Y += candTextSize.Y + spaceY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,11 @@ public interface IClientState
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ushort TerritoryType { get; }
|
public ushort TerritoryType { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current Map the player resides in.
|
||||||
|
/// </summary>
|
||||||
|
public uint MapId { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the local player character, if one is present.
|
/// Gets the local player character, if one is present.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
using Dalamud.Data;
|
||||||
|
using Dalamud.Game.ClientState.Objects.Types;
|
||||||
|
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||||
|
|
||||||
|
using Lumina;
|
||||||
using Lumina.Excel.GeneratedSheets;
|
using Lumina.Excel.GeneratedSheets;
|
||||||
|
|
||||||
namespace Dalamud.Utility;
|
namespace Dalamud.Utility;
|
||||||
|
|
@ -128,4 +134,32 @@ public static class MapUtil
|
||||||
{
|
{
|
||||||
return WorldToMap(worldCoordinates, map.OffsetX, map.OffsetY, map.SizeFactor);
|
return WorldToMap(worldCoordinates, map.OffsetX, map.OffsetY, map.SizeFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension method to get the current position of a GameObject in Map Coordinates (visible to players in the
|
||||||
|
/// minimap or chat). A Z (height) value will always be returned, even on maps that do not natively show one.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="InvalidOperationException">Thrown if ClientState is unavailable.</exception>
|
||||||
|
/// <param name="go">The GameObject to get the position for.</param>
|
||||||
|
/// <param name="correctZOffset">Whether to "correct" a Z offset to sane values for maps that don't have one.</param>
|
||||||
|
/// <returns>A Vector3 that represents the X (east/west), Y (north/south), and Z (height) position of this object.</returns>
|
||||||
|
public static unsafe Vector3 GetMapCoordinates(this GameObject go, bool correctZOffset = false)
|
||||||
|
{
|
||||||
|
var agentMap = AgentMap.Instance();
|
||||||
|
|
||||||
|
if (agentMap == null || agentMap->CurrentMapId == 0)
|
||||||
|
throw new InvalidOperationException("Could not determine active map - data may not be loaded yet?");
|
||||||
|
|
||||||
|
var territoryTransient = Service<DataManager>.Get()
|
||||||
|
.GetExcelSheet<TerritoryTypeTransient>()!
|
||||||
|
.GetRow(agentMap->CurrentTerritoryId);
|
||||||
|
|
||||||
|
return WorldToMap(
|
||||||
|
go.Position,
|
||||||
|
agentMap->CurrentOffsetX,
|
||||||
|
agentMap->CurrentOffsetY,
|
||||||
|
territoryTransient?.OffsetZ ?? 0,
|
||||||
|
(uint)agentMap->CurrentMapSizeFactor,
|
||||||
|
correctZOffset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue