Initial Commit
This commit is contained in:
commit
a8861ce40a
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/.idea
|
||||||
|
*.user
|
||||||
|
|
||||||
|
/bin
|
||||||
|
/obj
|
113
DalamudReflector.cs
Normal file
113
DalamudReflector.cs
Normal 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
102
LImGui.HeaderIcon.cs
Normal 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
36
LImGui.cs
Normal 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
53
LLib.csproj
Normal 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
16
LLib.sln
Normal 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
7
global.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"sdk": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"rollForward": "latestMinor",
|
||||||
|
"allowPrerelease": false
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user