feat: MVP pinning, clickthrough, alpha menu for Window System windows

Needs saving, an actual button in the title bar
This commit is contained in:
goat 2023-10-30 21:40:46 +01:00
parent e30c904ad6
commit 36364576a8
No known key found for this signature in database
GPG key ID: 49E2AA8C6A76498B

View file

@ -1,7 +1,10 @@
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using System.Runtime.InteropServices;
using CheapLoc;
using Dalamud.Configuration.Internal;
using Dalamud.Game.ClientState.Keys;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Utility;
using Dalamud.Logging.Internal;
using FFXIVClientStructs.FFXIV.Client.UI;
@ -20,6 +23,11 @@ public abstract class Window
private bool internalLastIsOpen = false;
private bool internalIsOpen = false;
private bool internalIsPinned = false;
private bool internalIsClickthrough = false;
private DateTimeOffset internalLastDisableClick = DateTimeOffset.MinValue;
private bool didPushInternalAlpha = false;
private float? internalAlpha = null;
private bool nextFrameBringToFront = false;
/// <summary>
@ -130,6 +138,16 @@ public abstract class Window
/// </summary>
public bool ShowCloseButton { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether or not this window should offer to be pinned via the window's titlebar context menu.
/// </summary>
public bool AllowPinning { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether or not this window should offer to be made click-through via the window's titlebar context menu.
/// </summary>
public bool AllowClickthrough { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether or not this window will stay open.
/// </summary>
@ -185,6 +203,11 @@ public abstract class Window
/// </summary>
public virtual void PreDraw()
{
if (this.internalAlpha.HasValue)
{
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, this.internalAlpha.Value);
this.didPushInternalAlpha = true;
}
}
/// <summary>
@ -192,6 +215,11 @@ public abstract class Window
/// </summary>
public virtual void PostDraw()
{
if (this.didPushInternalAlpha)
{
ImGui.PopStyleVar();
this.didPushInternalAlpha = false;
}
}
/// <summary>
@ -286,7 +314,15 @@ public abstract class Window
this.nextFrameBringToFront = false;
}
if (this.ShowCloseButton ? ImGui.Begin(this.WindowName, ref this.internalIsOpen, this.Flags) : ImGui.Begin(this.WindowName, this.Flags))
var flags = this.Flags;
if (this.internalIsPinned)
flags |= ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoResize;
if (this.internalIsClickthrough)
flags |= ImGuiWindowFlags.NoInputs | ImGuiWindowFlags.NoNav | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoScrollWithMouse | ImGuiWindowFlags.NoMouseInputs;
if (this.ShowCloseButton ? ImGui.Begin(this.WindowName, ref this.internalIsOpen, flags) : ImGui.Begin(this.WindowName, flags))
{
// Draw the actual window contents
try
@ -297,6 +333,80 @@ public abstract class Window
{
Log.Error(ex, $"Error during Draw(): {this.WindowName}");
}
if (this.AllowPinning || this.AllowClickthrough)
{
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 1f);
var popupName = "WindowSystemContextActions";
if (ImGui.BeginPopup(popupName))
{
if (this.internalIsClickthrough)
ImGui.BeginDisabled();
if (this.AllowPinning)
ImGui.Checkbox(Loc.Localize("WindowSystemContextActionPin", "Pin Window"), ref this.internalIsPinned);
if (this.internalIsClickthrough)
ImGui.EndDisabled();
if (this.AllowClickthrough)
{
if (ImGui.Checkbox(Loc.Localize("WindowSystemContextActionClickthrough", "Make clickthrough"),
ref this.internalIsClickthrough))
{
if (this.internalIsClickthrough)
this.internalIsPinned = true;
}
}
var alpha = (this.internalAlpha ?? ImGui.GetStyle().Alpha) * 100f;
if (ImGui.SliderFloat(Loc.Localize("WindowSystemContextActionAlpha", "Opacity"), ref alpha, 20f,
100f))
{
this.internalAlpha = alpha / 100f;
}
ImGui.SameLine();
if (ImGui.Button(Loc.Localize("WindowSystemContextActionReset", "Reset")))
{
this.internalAlpha = null;
}
ImGui.TextColored(ImGuiColors.DalamudGrey, Loc.Localize("WindowSystemContextActionDoubleClick", "Double click the title bar to disable clickthrough."));
ImGui.TextColored(ImGuiColors.DalamudGrey, Loc.Localize("WindowSystemContextActionDisclaimer", "These options may not work for all plugins at the moment."));
ImGui.EndPopup();
}
ImGui.PopStyleVar();
var titleBarRect = Vector4.Zero;
unsafe
{
var window = ImGuiNativeAdditions.igGetCurrentWindow();
ImGuiNativeAdditions.ImGuiWindow_TitleBarRect(&titleBarRect, window);
}
if (ImGui.IsMouseHoveringRect(new Vector2(titleBarRect.X, titleBarRect.Y), new Vector2(titleBarRect.Z, titleBarRect.W), false))
{
if (ImGui.IsWindowHovered() && ImGui.IsMouseClicked(ImGuiMouseButton.Right))
{
ImGui.OpenPopup(popupName);
}
if (ImGui.IsMouseDown(ImGuiMouseButton.Left))
{
if (DateTime.Now - this.internalLastDisableClick < TimeSpan.FromMilliseconds(100))
{
this.internalIsPinned = false;
this.internalIsClickthrough = false;
}
this.internalLastDisableClick = DateTime.Now;
}
}
}
}
if (wasFocused)
@ -375,6 +485,12 @@ public abstract class Window
{
ImGui.SetNextWindowBgAlpha(this.BgAlpha.Value);
}
// Manually set alpha takes precedence, if devs don't want that, they should turn it off
if (this.internalAlpha.HasValue)
{
ImGui.SetNextWindowBgAlpha(this.internalAlpha.Value);
}
}
/// <summary>
@ -392,4 +508,14 @@ public abstract class Window
/// </summary>
public Vector2 MaximumSize { get; set; }
}
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "imports")]
private static unsafe class ImGuiNativeAdditions
{
[DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)]
public static extern unsafe void* igGetCurrentWindow();
[DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)]
public static extern unsafe void ImGuiWindow_TitleBarRect(Vector4* pOut, void* window);
}
}