Initial Commit

master
Liza 2023-10-11 02:52:55 +02:00
commit a8861ce40a
Signed by: liza
GPG Key ID: 7199F8D727D55F67
7 changed files with 332 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
/.idea
*.user
/bin
/obj

113
DalamudReflector.cs Normal file
View File

@ -0,0 +1,113 @@
using Dalamud.Plugin;
using System;
using System.Collections.Generic;
using System.Reflection;
using Dalamud.Plugin.Services;
namespace LLib;
/// <summary>
/// Originally part of ECommons by NightmareXIV.
///
/// https://github.com/NightmareXIV/ECommons/blob/master/ECommons/Reflection/DalamudReflector.cs
/// </summary>
public sealed class DalamudReflector : IDisposable
{
private readonly DalamudPluginInterface _pluginInterface;
private readonly IFramework _framework;
private readonly IPluginLog _pluginLog;
private readonly Dictionary<string, IDalamudPlugin> _pluginCache = new();
private bool _pluginsChanged;
public DalamudReflector(DalamudPluginInterface pluginInterface, IFramework framework, IPluginLog pluginLog)
{
_pluginInterface = pluginInterface;
_framework = framework;
_pluginLog = pluginLog;
var pm = GetPluginManager();
pm.GetType().GetEvent("OnInstalledPluginsChanged")!.AddEventHandler(pm, OnInstalledPluginsChanged);
_framework.Update += FrameworkUpdate;
}
public void Dispose()
{
_framework.Update -= FrameworkUpdate;
var pm = GetPluginManager();
pm.GetType().GetEvent("OnInstalledPluginsChanged")!.RemoveEventHandler(pm, OnInstalledPluginsChanged);
}
private void FrameworkUpdate(IFramework framework)
{
if (_pluginsChanged)
{
_pluginsChanged = false;
_pluginCache.Clear();
}
}
private object GetPluginManager()
{
return _pluginInterface.GetType().Assembly.GetType("Dalamud.Service`1", true)!
.MakeGenericType(
_pluginInterface.GetType().Assembly.GetType("Dalamud.Plugin.Internal.PluginManager", true)!)
.GetMethod("Get")!.Invoke(null, BindingFlags.Default, null, Array.Empty<object>(), null)!;
}
public bool TryGetDalamudPlugin(string internalName, out IDalamudPlugin? instance, bool suppressErrors = false,
bool ignoreCache = false)
{
if (!ignoreCache && _pluginCache.TryGetValue(internalName, out instance))
{
return true;
}
try
{
var pluginManager = GetPluginManager();
var installedPlugins =
(System.Collections.IList)pluginManager.GetType().GetProperty("InstalledPlugins")!.GetValue(
pluginManager)!;
foreach (var t in installedPlugins)
{
if ((string?)t.GetType().GetProperty("Name")!.GetValue(t) == internalName)
{
var type = t.GetType().Name == "LocalDevPlugin" ? t.GetType().BaseType : t.GetType();
var plugin = (IDalamudPlugin?)type!
.GetField("instance", BindingFlags.NonPublic | BindingFlags.Instance)!.GetValue(t);
if (plugin == null)
{
_pluginLog.Warning($"[DalamudReflector] Found requested plugin {internalName} but it was null");
}
else
{
instance = plugin;
_pluginCache[internalName] = plugin;
return true;
}
}
}
instance = null;
return false;
}
catch (Exception e)
{
if (!suppressErrors)
{
_pluginLog.Error(e, $"Can't find {internalName} plugin: {e.Message}");
}
instance = null;
return false;
}
}
private void OnInstalledPluginsChanged()
{
_pluginLog.Verbose("Installed plugins changed event fired");
_pluginsChanged = true;
}
}

102
LImGui.HeaderIcon.cs Normal file
View File

@ -0,0 +1,102 @@
using System.Numerics;
using System.Runtime.InteropServices;
using Dalamud.Interface;
using Dalamud.Interface.Utility;
using Dalamud.Plugin;
using ImGuiNET;
namespace LLib;
/// <summary>
/// Originally part of ECommons by NightmareXIV.
///
/// https://github.com/NightmareXIV/ECommons/blob/master/ECommons/ImGuiMethods/ImGuiEx.cs
/// </summary>
partial class LImGui
{
public sealed record HeaderIconOptions
{
public Vector2 Offset { get; init; } = Vector2.Zero;
public ImGuiMouseButton MouseButton { get; init; } = ImGuiMouseButton.Left;
public string Tooltip { get; init; } = string.Empty;
public uint Color { get; init; } = 0xFFFFFFFF;
}
private static uint _headerLastWindowId = 0;
private static ulong _headerLastFrame = 0;
private static float _headerCurrentPos = 0;
private static float _headerImGuiButtonWidth = 0;
public static bool AddHeaderIcon(DalamudPluginInterface pluginInterface, string id, FontAwesomeIcon icon, HeaderIconOptions options = null)
{
if (ImGui.IsWindowCollapsed()) return false;
var scale = ImGuiHelpers.GlobalScale;
var currentID = ImGui.GetID(0);
if (currentID != _headerLastWindowId || _headerLastFrame != pluginInterface.UiBuilder.FrameCount)
{
_headerLastWindowId = currentID;
_headerLastFrame = pluginInterface.UiBuilder.FrameCount;
_headerCurrentPos = 0.25f * ImGui.GetStyle().FramePadding.Length();
if (!GetCurrentWindowFlags().HasFlag(ImGuiWindowFlags.NoTitleBar))
_headerCurrentPos = 1;
_headerImGuiButtonWidth = 0f;
if (CurrentWindowHasCloseButton())
_headerImGuiButtonWidth += 17 * scale;
if (!GetCurrentWindowFlags().HasFlag(ImGuiWindowFlags.NoCollapse))
_headerImGuiButtonWidth += 17 * scale;
}
options ??= new();
var prevCursorPos = ImGui.GetCursorPos();
var buttonSize = new Vector2(20 * scale);
var buttonPos = new Vector2((ImGui.GetWindowWidth() - buttonSize.X - _headerImGuiButtonWidth * scale * _headerCurrentPos) - (ImGui.GetStyle().FramePadding.X * scale), ImGui.GetScrollY() + 1);
ImGui.SetCursorPos(buttonPos);
var drawList = ImGui.GetWindowDrawList();
drawList.PushClipRectFullScreen();
var pressed = false;
ImGui.InvisibleButton(id, buttonSize);
var itemMin = ImGui.GetItemRectMin();
var itemMax = ImGui.GetItemRectMax();
var halfSize = ImGui.GetItemRectSize() / 2;
var center = itemMin + halfSize;
if (ImGui.IsWindowHovered() && ImGui.IsMouseHoveringRect(itemMin, itemMax, false))
{
if (!string.IsNullOrEmpty(options.Tooltip))
ImGui.SetTooltip(options.Tooltip);
ImGui.GetWindowDrawList().AddCircleFilled(center, halfSize.X, ImGui.GetColorU32(ImGui.IsMouseDown(ImGuiMouseButton.Left) ? ImGuiCol.ButtonActive : ImGuiCol.ButtonHovered));
if (ImGui.IsMouseReleased(options.MouseButton))
pressed = true;
}
ImGui.SetCursorPos(buttonPos);
ImGui.PushFont(UiBuilder.IconFont);
var iconString = icon.ToIconString();
drawList.AddText(UiBuilder.IconFont, ImGui.GetFontSize(), itemMin + halfSize - ImGui.CalcTextSize(iconString) / 2 + options.Offset, options.Color, iconString);
ImGui.PopFont();
ImGui.PopClipRect();
ImGui.SetCursorPos(prevCursorPos);
return pressed;
}
[LibraryImport("cimgui")]
[UnmanagedCallConv(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })]
private static partial nint igGetCurrentWindow();
private static unsafe ImGuiWindow* GetCurrentWindow() => (ImGuiWindow*)igGetCurrentWindow();
private static unsafe ImGuiWindowFlags GetCurrentWindowFlags() => GetCurrentWindow()->Flags;
private static unsafe bool CurrentWindowHasCloseButton() => GetCurrentWindow()->HasCloseButton != 0;
[StructLayout(LayoutKind.Explicit)]
private struct ImGuiWindow
{
[FieldOffset(0xC)] public ImGuiWindowFlags Flags;
[FieldOffset(0xD5)] public byte HasCloseButton;
// 0x118 is the start of ImGuiWindowTempData
[FieldOffset(0x130)] public Vector2 CursorMaxPos;
}
}

36
LImGui.cs Normal file
View File

@ -0,0 +1,36 @@
using System.Diagnostics;
using System.Numerics;
using Dalamud.Interface;
using Dalamud.Plugin;
using ImGuiNET;
namespace LLib;
public static partial class LImGui
{
public static void AddPatreonIcon(DalamudPluginInterface pluginInterface)
{
if (AddHeaderIcon(pluginInterface, "##Patreon", FontAwesomeIcon.Heart, new HeaderIconOptions
{
Tooltip = "Open Liza's page on Patreon",
Color = 0xFF000FF,
Offset = Vector2.Zero,
MouseButton = ImGuiMouseButton.Left
}))
{
try
{
Process.Start(new ProcessStartInfo
{
FileName = "http://patreon.com/lizac",
UseShellExecute = true,
Verb = string.Empty,
});
}
catch
{
// not sure what to do anyway
}
}
}
}

53
LLib.csproj Normal file
View File

@ -0,0 +1,53 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework>
<Version>1.0</Version>
<LangVersion>11.0</LangVersion>
<Nullable>enable</Nullable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<DebugType>portable</DebugType>
<PathMap Condition="$(SolutionDir) != ''">$(SolutionDir)=X:\</PathMap>
</PropertyGroup>
<PropertyGroup>
<DalamudLibPath>$(appdata)\XIVLauncher\addon\Hooks\dev\</DalamudLibPath>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))'">
<DalamudLibPath>$(DALAMUD_HOME)/</DalamudLibPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="Dalamud">
<HintPath>$(DalamudLibPath)Dalamud.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="ImGui.NET">
<HintPath>$(DalamudLibPath)ImGui.NET.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Lumina">
<HintPath>$(DalamudLibPath)Lumina.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Lumina.Excel">
<HintPath>$(DalamudLibPath)Lumina.Excel.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>$(DalamudLibPath)Newtonsoft.Json.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="FFXIVClientStructs">
<HintPath>$(DalamudLibPath)FFXIVClientStructs.dll</HintPath>
<Private>false</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Folder Include="ImGui\" />
</ItemGroup>
</Project>

16
LLib.sln Normal file
View File

@ -0,0 +1,16 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LLib", "LLib.csproj", "{FCC925E1-A583-4C9E-B3BE-B92210BEEAC6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FCC925E1-A583-4C9E-B3BE-B92210BEEAC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FCC925E1-A583-4C9E-B3BE-B92210BEEAC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FCC925E1-A583-4C9E-B3BE-B92210BEEAC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FCC925E1-A583-4C9E-B3BE-B92210BEEAC6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

7
global.json Normal file
View File

@ -0,0 +1,7 @@
{
"sdk": {
"version": "7.0.0",
"rollForward": "latestMinor",
"allowPrerelease": false
}
}