Update header icon logic for Dalamud changes

This commit is contained in:
Liza 2023-11-09 10:47:42 +01:00
parent 7f83ece6a0
commit 865a608031
Signed by: liza
GPG Key ID: 7199F8D727D55F67
2 changed files with 48 additions and 128 deletions

View File

@ -1,109 +0,0 @@
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;
if (!CurrentWindowHasCloseButton() &&
GetCurrentWindowFlags().HasFlag(ImGuiWindowFlags.NoCollapse) &&
GetCurrentWindowFlags().HasFlag(ImGuiWindowFlags.AlwaysAutoResize))
_headerImGuiButtonWidth += 5 * scale;
else
_headerImGuiButtonWidth += 10 * 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;
}
}

View File

@ -1,34 +1,63 @@
using System.Diagnostics;
using System.Numerics;
using Dalamud.Interface;
using Dalamud.Plugin;
using Dalamud.Interface.Windowing;
using ImGuiNET;
namespace LLib;
public static partial class LImGui
public static class LImGui
{
public static void AddPatreonIcon(DalamudPluginInterface pluginInterface)
public abstract class LWindow : Window
{
if (AddHeaderIcon(pluginInterface, "##Patreon", FontAwesomeIcon.Heart, new HeaderIconOptions
{
Tooltip = "Go to patreon.com/lizac",
Color = 0xFF3030D0,
}))
protected bool ClickedHeaderLastFrame;
protected bool ClickedHeaderCurrentFrame;
protected LWindow(string name, ImGuiWindowFlags flags = ImGuiWindowFlags.None, bool forceMainWindow = false)
: base(name, flags, forceMainWindow)
{
try
TitleBarButtons.Add(new TitleBarButton
{
Process.Start(new ProcessStartInfo
Icon = FontAwesomeIcon.Heart,
ShowTooltip = () =>
{
FileName = "https://www.patreon.com/lizac",
UseShellExecute = true,
Verb = string.Empty,
});
}
catch
{
// not sure what to do anyway
}
ImGui.BeginTooltip();
ImGui.Text("Go to patreon.com/lizac");
ImGui.EndTooltip();
},
Priority = int.MinValue,
IconOffset = new Vector2(1.5f, 1),
Click = _ =>
{
// when you make a window click-through, `Click` is triggered on each individual frame the mouse button is held down.
ClickedHeaderCurrentFrame = true;
if (ClickedHeaderLastFrame)
return;
try
{
Process.Start(new ProcessStartInfo
{
FileName = "https://www.patreon.com/lizac",
UseShellExecute = true,
Verb = string.Empty,
});
}
catch
{
// not sure what to do anyway
}
},
AvailableClickthrough = true,
});
}
public override void PreDraw()
{
base.PreDraw();
ClickedHeaderLastFrame = ClickedHeaderCurrentFrame;
ClickedHeaderCurrentFrame = false;
}
}
}