mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 10:17:22 +01:00
Merge pull request #2161 from goaaats/feat/stabilize_window_additions
Stabilize WindowSystem additional options menu
This commit is contained in:
commit
be252bacc0
9 changed files with 301 additions and 80 deletions
|
|
@ -12,6 +12,7 @@ using Dalamud.Interface.FontIdentifier;
|
||||||
using Dalamud.Interface.Internal;
|
using Dalamud.Interface.Internal;
|
||||||
using Dalamud.Interface.Internal.ReShadeHandling;
|
using Dalamud.Interface.Internal.ReShadeHandling;
|
||||||
using Dalamud.Interface.Style;
|
using Dalamud.Interface.Style;
|
||||||
|
using Dalamud.Interface.Windowing.Persistence;
|
||||||
using Dalamud.IoC.Internal;
|
using Dalamud.IoC.Internal;
|
||||||
using Dalamud.Plugin.Internal.AutoUpdate;
|
using Dalamud.Plugin.Internal.AutoUpdate;
|
||||||
using Dalamud.Plugin.Internal.Profiles;
|
using Dalamud.Plugin.Internal.Profiles;
|
||||||
|
|
@ -264,8 +265,7 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
|
||||||
/// Gets or sets a value indicating whether or not an additional button allowing pinning and clickthrough options should be shown
|
/// Gets or sets a value indicating whether or not an additional button allowing pinning and clickthrough options should be shown
|
||||||
/// on plugin title bars when using the Window System.
|
/// on plugin title bars when using the Window System.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonProperty("EnablePluginUiAdditionalOptionsExperimental")]
|
public bool EnablePluginUiAdditionalOptions { get; set; } = true;
|
||||||
public bool EnablePluginUiAdditionalOptions { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether viewports should always be disabled.
|
/// Gets or sets a value indicating whether viewports should always be disabled.
|
||||||
|
|
@ -351,6 +351,11 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ProfilesHasSeenTutorial { get; set; } = false;
|
public bool ProfilesHasSeenTutorial { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the default UI preset.
|
||||||
|
/// </summary>
|
||||||
|
public PresetModel DefaultUiPreset { get; set; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the order of DTR elements, by title.
|
/// Gets or sets the order of DTR elements, by title.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ using Dalamud.Interface.ManagedFontAtlas.Internals;
|
||||||
using Dalamud.Interface.Style;
|
using Dalamud.Interface.Style;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
|
using Dalamud.Interface.Windowing.Persistence;
|
||||||
|
using Dalamud.IoC.Internal;
|
||||||
using Dalamud.Logging.Internal;
|
using Dalamud.Logging.Internal;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using Dalamud.Utility.Timing;
|
using Dalamud.Utility.Timing;
|
||||||
|
|
@ -60,6 +62,7 @@ namespace Dalamud.Interface.Internal;
|
||||||
/// This class manages interaction with the ImGui interface.
|
/// This class manages interaction with the ImGui interface.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
|
[InherentDependency<WindowSystemPersistence>] // Used by window system windows to restore state from the configuration
|
||||||
internal partial class InterfaceManager : IInternalDisposableService
|
internal partial class InterfaceManager : IInternalDisposableService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -39,18 +39,6 @@ public class SettingsTabExperimental : SettingsTab
|
||||||
|
|
||||||
new GapSettingsEntry(5),
|
new GapSettingsEntry(5),
|
||||||
|
|
||||||
new SettingsEntry<bool>(
|
|
||||||
Loc.Localize(
|
|
||||||
"DalamudSettingEnablePluginUIAdditionalOptions",
|
|
||||||
"Add a button to the title bar of plugin windows to open additional options"),
|
|
||||||
Loc.Localize(
|
|
||||||
"DalamudSettingEnablePluginUIAdditionalOptionsHint",
|
|
||||||
"This will allow you to pin certain plugin windows, make them clickthrough or adjust their opacity.\nThis may not be supported by all of your plugins. Contact the plugin author if you want them to support this feature."),
|
|
||||||
c => c.EnablePluginUiAdditionalOptions,
|
|
||||||
(v, c) => c.EnablePluginUiAdditionalOptions = v),
|
|
||||||
|
|
||||||
new GapSettingsEntry(5),
|
|
||||||
|
|
||||||
new ButtonSettingsEntry(
|
new ButtonSettingsEntry(
|
||||||
Loc.Localize("DalamudSettingsClearHidden", "Clear hidden plugins"),
|
Loc.Localize("DalamudSettingsClearHidden", "Clear hidden plugins"),
|
||||||
Loc.Localize(
|
Loc.Localize(
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,16 @@ public class SettingsTabLook : SettingsTab
|
||||||
c => c.IsDocking,
|
c => c.IsDocking,
|
||||||
(v, c) => c.IsDocking = v),
|
(v, c) => c.IsDocking = v),
|
||||||
|
|
||||||
|
new SettingsEntry<bool>(
|
||||||
|
Loc.Localize(
|
||||||
|
"DalamudSettingEnablePluginUIAdditionalOptions",
|
||||||
|
"Add a button to the title bar of plugin windows to open additional options"),
|
||||||
|
Loc.Localize(
|
||||||
|
"DalamudSettingEnablePluginUIAdditionalOptionsHint",
|
||||||
|
"This will allow you to pin certain plugin windows, make them clickthrough or adjust their opacity.\nThis may not be supported by all of your plugins. Contact the plugin author if you want them to support this feature."),
|
||||||
|
c => c.EnablePluginUiAdditionalOptions,
|
||||||
|
(v, c) => c.EnablePluginUiAdditionalOptions = v),
|
||||||
|
|
||||||
new SettingsEntry<bool>(
|
new SettingsEntry<bool>(
|
||||||
Loc.Localize("DalamudSettingEnablePluginUISoundEffects", "Enable sound effects for plugin windows"),
|
Loc.Localize("DalamudSettingEnablePluginUISoundEffects", "Enable sound effects for plugin windows"),
|
||||||
Loc.Localize("DalamudSettingEnablePluginUISoundEffectsHint", "This will allow you to enable or disable sound effects generated by plugin user interfaces.\nThis is affected by your in-game `System Sounds` volume settings."),
|
Loc.Localize("DalamudSettingEnablePluginUISoundEffectsHint", "This will allow you to enable or disable sound effects generated by plugin user interfaces.\nThis is affected by your in-game `System Sounds` volume settings."),
|
||||||
|
|
|
||||||
53
Dalamud/Interface/Windowing/Persistence/PresetModel.cs
Normal file
53
Dalamud/Interface/Windowing/Persistence/PresetModel.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.Windowing.Persistence;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Class representing a Window System preset.
|
||||||
|
/// </summary>
|
||||||
|
internal class PresetModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the ID of this preset.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("id")]
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of this preset.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("n")]
|
||||||
|
public string Name { get; set; } = "New Preset";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a dictionary containing the windows in the preset, mapping their ID to the preset.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("w")]
|
||||||
|
public Dictionary<uint, PresetWindow> Windows { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Class representing a window in a preset.
|
||||||
|
/// </summary>
|
||||||
|
internal class PresetWindow
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether the window is pinned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("p")]
|
||||||
|
public bool IsPinned { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether the window is clickthrough.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("ct")]
|
||||||
|
public bool IsClickThrough { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the window's opacity override.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("a")]
|
||||||
|
public float? Alpha { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
using Dalamud.Configuration.Internal;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.Windowing.Persistence;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Class handling persistence for window system windows.
|
||||||
|
/// </summary>
|
||||||
|
[ServiceManager.EarlyLoadedService]
|
||||||
|
internal class WindowSystemPersistence : IServiceType
|
||||||
|
{
|
||||||
|
[ServiceManager.ServiceDependency]
|
||||||
|
private readonly DalamudConfiguration config = Service<DalamudConfiguration>.Get();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="WindowSystemPersistence"/> class.
|
||||||
|
/// </summary>
|
||||||
|
[ServiceManager.ServiceConstructor]
|
||||||
|
public WindowSystemPersistence()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the active window system preset.
|
||||||
|
/// </summary>
|
||||||
|
public PresetModel ActivePreset => this.config.DefaultUiPreset;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or add a window to the active preset.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The ID of the window.</param>
|
||||||
|
/// <returns>The preset window instance, or null if the preset does not contain this window.</returns>
|
||||||
|
public PresetModel.PresetWindow? GetWindow(uint id)
|
||||||
|
{
|
||||||
|
return this.ActivePreset.Windows.TryGetValue(id, out var window) ? window : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Persist the state of a window to the active preset.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The ID of the window.</param>
|
||||||
|
/// <param name="window">The preset window instance.</param>
|
||||||
|
public void SaveWindow(uint id, PresetModel.PresetWindow window)
|
||||||
|
{
|
||||||
|
this.ActivePreset.Windows[id] = window;
|
||||||
|
this.config.QueueSave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
using CheapLoc;
|
using CheapLoc;
|
||||||
using Dalamud.Configuration.Internal;
|
|
||||||
using Dalamud.Game.ClientState.Keys;
|
using Dalamud.Game.ClientState.Keys;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
|
using Dalamud.Interface.Components;
|
||||||
using Dalamud.Interface.Internal;
|
using Dalamud.Interface.Internal;
|
||||||
using Dalamud.Interface.Utility;
|
using Dalamud.Interface.Utility;
|
||||||
|
using Dalamud.Interface.Windowing.Persistence;
|
||||||
using Dalamud.Logging.Internal;
|
using Dalamud.Logging.Internal;
|
||||||
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
|
|
@ -35,15 +37,19 @@ public abstract class Window
|
||||||
private float? internalAlpha = null;
|
private float? internalAlpha = null;
|
||||||
private bool nextFrameBringToFront = false;
|
private bool nextFrameBringToFront = false;
|
||||||
|
|
||||||
|
private bool hasInitializedFromPreset = false;
|
||||||
|
private PresetModel.PresetWindow? presetWindow;
|
||||||
|
private bool presetDirty = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Window"/> class.
|
/// Initializes a new instance of the <see cref="Window"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">The name/ID of this window.
|
/// <param name="name">The name/ID of this window.
|
||||||
/// If you have multiple windows with the same name, you will need to
|
/// If you have multiple windows with the same name, you will need to
|
||||||
/// append an unique ID to it by specifying it after "###" behind the window title.
|
/// append a unique ID to it by specifying it after "###" behind the window title.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="flags">The <see cref="ImGuiWindowFlags"/> of this window.</param>
|
/// <param name="flags">The <see cref="ImGuiWindowFlags"/> of this window.</param>
|
||||||
/// <param name="forceMainWindow">Whether or not this window should be limited to the main game window.</param>
|
/// <param name="forceMainWindow">Whether this window should be limited to the main game window.</param>
|
||||||
protected Window(string name, ImGuiWindowFlags flags = ImGuiWindowFlags.None, bool forceMainWindow = false)
|
protected Window(string name, ImGuiWindowFlags flags = ImGuiWindowFlags.None, bool forceMainWindow = false)
|
||||||
{
|
{
|
||||||
this.WindowName = name;
|
this.WindowName = name;
|
||||||
|
|
@ -51,6 +57,33 @@ public abstract class Window
|
||||||
this.ForceMainWindow = forceMainWindow;
|
this.ForceMainWindow = forceMainWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flags to control window behavior.
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
internal enum WindowDrawFlags
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Nothing.
|
||||||
|
/// </summary>
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable window opening/closing sound effects.
|
||||||
|
/// </summary>
|
||||||
|
UseSoundEffects = 1 << 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hook into the game's focus management.
|
||||||
|
/// </summary>
|
||||||
|
UseFocusManagement = 1 << 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable the built-in "additional options" menu on the title bar.
|
||||||
|
/// </summary>
|
||||||
|
UseAdditionalOptions = 1 << 2,
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the namespace of the window.
|
/// Gets or sets the namespace of the window.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -271,13 +304,12 @@ public abstract class Window
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Draw the window via ImGui.
|
/// Draw the window via ImGui.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="configuration">Configuration instance used to check if certain window management features should be enabled.</param>
|
/// <param name="internalDrawFlags">Flags controlling window behavior.</param>
|
||||||
internal void DrawInternal(DalamudConfiguration? configuration)
|
/// <param name="persistence">Handler for window persistence data.</param>
|
||||||
|
internal void DrawInternal(WindowDrawFlags internalDrawFlags, WindowSystemPersistence? persistence)
|
||||||
{
|
{
|
||||||
this.PreOpenCheck();
|
this.PreOpenCheck();
|
||||||
|
|
||||||
var doSoundEffects = configuration?.EnablePluginUISoundEffects ?? false;
|
|
||||||
|
|
||||||
if (!this.IsOpen)
|
if (!this.IsOpen)
|
||||||
{
|
{
|
||||||
if (this.internalIsOpen != this.internalLastIsOpen)
|
if (this.internalIsOpen != this.internalLastIsOpen)
|
||||||
|
|
@ -287,7 +319,8 @@ public abstract class Window
|
||||||
|
|
||||||
this.IsFocused = false;
|
this.IsFocused = false;
|
||||||
|
|
||||||
if (doSoundEffects && !this.DisableWindowSounds) UIGlobals.PlaySoundEffect(this.OnCloseSfxId);
|
if (internalDrawFlags.HasFlag(WindowDrawFlags.UseSoundEffects) && !this.DisableWindowSounds)
|
||||||
|
UIGlobals.PlaySoundEffect(this.OnCloseSfxId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -302,12 +335,15 @@ public abstract class Window
|
||||||
if (hasNamespace)
|
if (hasNamespace)
|
||||||
ImGui.PushID(this.Namespace);
|
ImGui.PushID(this.Namespace);
|
||||||
|
|
||||||
|
this.PreHandlePreset(persistence);
|
||||||
|
|
||||||
if (this.internalLastIsOpen != this.internalIsOpen && this.internalIsOpen)
|
if (this.internalLastIsOpen != this.internalIsOpen && this.internalIsOpen)
|
||||||
{
|
{
|
||||||
this.internalLastIsOpen = this.internalIsOpen;
|
this.internalLastIsOpen = this.internalIsOpen;
|
||||||
this.OnOpen();
|
this.OnOpen();
|
||||||
|
|
||||||
if (doSoundEffects && !this.DisableWindowSounds) UIGlobals.PlaySoundEffect(this.OnOpenSfxId);
|
if (internalDrawFlags.HasFlag(WindowDrawFlags.UseSoundEffects) && !this.DisableWindowSounds)
|
||||||
|
UIGlobals.PlaySoundEffect(this.OnOpenSfxId);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.PreDraw();
|
this.PreDraw();
|
||||||
|
|
@ -340,6 +376,8 @@ public abstract class Window
|
||||||
|
|
||||||
if (this.CanShowCloseButton ? ImGui.Begin(this.WindowName, ref this.internalIsOpen, flags) : ImGui.Begin(this.WindowName, flags))
|
if (this.CanShowCloseButton ? ImGui.Begin(this.WindowName, ref this.internalIsOpen, flags) : ImGui.Begin(this.WindowName, flags))
|
||||||
{
|
{
|
||||||
|
ImGuiNativeAdditions.igCustom_WindowSetInheritNoInputs(this.internalIsClickthrough);
|
||||||
|
|
||||||
// Draw the actual window contents
|
// Draw the actual window contents
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -355,7 +393,7 @@ public abstract class Window
|
||||||
var flagsApplicableForTitleBarIcons = !flags.HasFlag(ImGuiWindowFlags.NoDecoration) &&
|
var flagsApplicableForTitleBarIcons = !flags.HasFlag(ImGuiWindowFlags.NoDecoration) &&
|
||||||
!flags.HasFlag(ImGuiWindowFlags.NoTitleBar);
|
!flags.HasFlag(ImGuiWindowFlags.NoTitleBar);
|
||||||
var showAdditions = (this.AllowPinning || this.AllowClickthrough) &&
|
var showAdditions = (this.AllowPinning || this.AllowClickthrough) &&
|
||||||
(configuration?.EnablePluginUiAdditionalOptions ?? true) &&
|
internalDrawFlags.HasFlag(WindowDrawFlags.UseAdditionalOptions) &&
|
||||||
flagsApplicableForTitleBarIcons;
|
flagsApplicableForTitleBarIcons;
|
||||||
if (showAdditions)
|
if (showAdditions)
|
||||||
{
|
{
|
||||||
|
|
@ -375,36 +413,51 @@ public abstract class Window
|
||||||
{
|
{
|
||||||
var showAsPinned = this.internalIsPinned || this.internalIsClickthrough;
|
var showAsPinned = this.internalIsPinned || this.internalIsClickthrough;
|
||||||
if (ImGui.Checkbox(Loc.Localize("WindowSystemContextActionPin", "Pin Window"), ref showAsPinned))
|
if (ImGui.Checkbox(Loc.Localize("WindowSystemContextActionPin", "Pin Window"), ref showAsPinned))
|
||||||
|
{
|
||||||
this.internalIsPinned = showAsPinned;
|
this.internalIsPinned = showAsPinned;
|
||||||
|
this.presetDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGuiComponents.HelpMarker(
|
||||||
|
Loc.Localize("WindowSystemContextActionPinHint", "Pinned windows will not move or resize when you click and drag them."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.internalIsClickthrough)
|
if (this.internalIsClickthrough)
|
||||||
ImGui.EndDisabled();
|
ImGui.EndDisabled();
|
||||||
|
|
||||||
if (this.AllowClickthrough)
|
if (this.AllowClickthrough)
|
||||||
ImGui.Checkbox(Loc.Localize("WindowSystemContextActionClickthrough", "Make clickthrough"), ref this.internalIsClickthrough);
|
{
|
||||||
|
if (ImGui.Checkbox(
|
||||||
|
Loc.Localize("WindowSystemContextActionClickthrough", "Make clickthrough"),
|
||||||
|
ref this.internalIsClickthrough))
|
||||||
|
{
|
||||||
|
this.presetDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGuiComponents.HelpMarker(
|
||||||
|
Loc.Localize("WindowSystemContextActionClickthroughHint", "Clickthrough windows will not receive mouse input, move or resize. They are completely inert."));
|
||||||
|
}
|
||||||
|
|
||||||
var alpha = (this.internalAlpha ?? ImGui.GetStyle().Alpha) * 100f;
|
var alpha = (this.internalAlpha ?? ImGui.GetStyle().Alpha) * 100f;
|
||||||
if (ImGui.SliderFloat(Loc.Localize("WindowSystemContextActionAlpha", "Opacity"), ref alpha, 20f,
|
if (ImGui.SliderFloat(Loc.Localize("WindowSystemContextActionAlpha", "Opacity"), ref alpha, 20f,
|
||||||
100f))
|
100f))
|
||||||
{
|
{
|
||||||
this.internalAlpha = alpha / 100f;
|
this.internalAlpha = alpha / 100f;
|
||||||
|
this.presetDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
if (ImGui.Button(Loc.Localize("WindowSystemContextActionReset", "Reset")))
|
if (ImGui.Button(Loc.Localize("WindowSystemContextActionReset", "Reset")))
|
||||||
{
|
{
|
||||||
this.internalAlpha = null;
|
this.internalAlpha = null;
|
||||||
|
this.presetDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAvailable)
|
if (isAvailable)
|
||||||
{
|
{
|
||||||
ImGui.TextColored(ImGuiColors.DalamudGrey,
|
ImGui.TextColored(ImGuiColors.DalamudGrey,
|
||||||
Loc.Localize("WindowSystemContextActionClickthroughDisclaimer",
|
Loc.Localize("WindowSystemContextActionClickthroughDisclaimer",
|
||||||
"Open this menu again to disable clickthrough."));
|
"Open this menu again by clicking the three dashes to disable clickthrough."));
|
||||||
ImGui.TextColored(ImGuiColors.DalamudGrey,
|
|
||||||
Loc.Localize("WindowSystemContextActionDisclaimer",
|
|
||||||
"These options may not work for all plugins at the moment."));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -457,8 +510,7 @@ public abstract class Window
|
||||||
|
|
||||||
this.IsFocused = ImGui.IsWindowFocused(ImGuiFocusedFlags.RootAndChildWindows);
|
this.IsFocused = ImGui.IsWindowFocused(ImGuiFocusedFlags.RootAndChildWindows);
|
||||||
|
|
||||||
var isAllowed = configuration?.IsFocusManagementEnabled ?? false;
|
if (internalDrawFlags.HasFlag(WindowDrawFlags.UseFocusManagement))
|
||||||
if (isAllowed)
|
|
||||||
{
|
{
|
||||||
var escapeDown = Service<KeyState>.Get()[VirtualKey.ESCAPE];
|
var escapeDown = Service<KeyState>.Get()[VirtualKey.ESCAPE];
|
||||||
if (escapeDown && this.IsFocused && !wasEscPressedLastFrame && this.RespectCloseHotkey)
|
if (escapeDown && this.IsFocused && !wasEscPressedLastFrame && this.RespectCloseHotkey)
|
||||||
|
|
@ -476,6 +528,8 @@ public abstract class Window
|
||||||
|
|
||||||
this.PostDraw();
|
this.PostDraw();
|
||||||
|
|
||||||
|
this.PostHandlePreset(persistence);
|
||||||
|
|
||||||
if (hasNamespace)
|
if (hasNamespace)
|
||||||
ImGui.PopID();
|
ImGui.PopID();
|
||||||
}
|
}
|
||||||
|
|
@ -519,6 +573,50 @@ public abstract class Window
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PreHandlePreset(WindowSystemPersistence? persistence)
|
||||||
|
{
|
||||||
|
if (persistence == null || this.hasInitializedFromPreset)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var id = ImGui.GetID(this.WindowName);
|
||||||
|
this.presetWindow = persistence.GetWindow(id);
|
||||||
|
|
||||||
|
this.hasInitializedFromPreset = true;
|
||||||
|
|
||||||
|
// Fresh preset - don't apply anything
|
||||||
|
if (this.presetWindow == null)
|
||||||
|
{
|
||||||
|
this.presetWindow = new PresetModel.PresetWindow();
|
||||||
|
this.presetDirty = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.internalIsPinned = this.presetWindow.IsPinned;
|
||||||
|
this.internalIsClickthrough = this.presetWindow.IsClickThrough;
|
||||||
|
this.internalAlpha = this.presetWindow.Alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PostHandlePreset(WindowSystemPersistence? persistence)
|
||||||
|
{
|
||||||
|
if (persistence == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Debug.Assert(this.presetWindow != null, "this.presetWindow != null");
|
||||||
|
|
||||||
|
if (this.presetDirty)
|
||||||
|
{
|
||||||
|
this.presetWindow.IsPinned = this.internalIsPinned;
|
||||||
|
this.presetWindow.IsClickThrough = this.internalIsClickthrough;
|
||||||
|
this.presetWindow.Alpha = this.internalAlpha;
|
||||||
|
|
||||||
|
var id = ImGui.GetID(this.WindowName);
|
||||||
|
persistence.SaveWindow(id, this.presetWindow!);
|
||||||
|
this.presetDirty = false;
|
||||||
|
|
||||||
|
Log.Verbose("Saved preset for {WindowName}", this.WindowName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private unsafe void DrawTitleBarButtons(void* window, ImGuiWindowFlags flags, Vector4 titleBarRect, IEnumerable<TitleBarButton> buttons)
|
private unsafe void DrawTitleBarButtons(void* window, ImGuiWindowFlags flags, Vector4 titleBarRect, IEnumerable<TitleBarButton> buttons)
|
||||||
{
|
{
|
||||||
ImGui.PushClipRect(ImGui.GetWindowPos(), ImGui.GetWindowPos() + ImGui.GetWindowSize(), false);
|
ImGui.PushClipRect(ImGui.GetWindowPos(), ImGui.GetWindowPos() + ImGui.GetWindowSize(), false);
|
||||||
|
|
@ -715,5 +813,8 @@ public abstract class Window
|
||||||
|
|
||||||
[DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern void ImGuiWindow_TitleBarRect(Vector4* pOut, void* window);
|
public static extern void ImGuiWindow_TitleBarRect(Vector4* pOut, void* window);
|
||||||
|
|
||||||
|
[DllImport("cimgui", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern void igCustom_WindowSetInheritNoInputs(bool inherit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
using Dalamud.Configuration.Internal;
|
using Dalamud.Configuration.Internal;
|
||||||
|
using Dalamud.Interface.Windowing.Persistence;
|
||||||
|
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
@ -103,7 +104,20 @@ public class WindowSystem
|
||||||
if (hasNamespace)
|
if (hasNamespace)
|
||||||
ImGui.PushID(this.Namespace);
|
ImGui.PushID(this.Namespace);
|
||||||
|
|
||||||
|
// These must be nullable, people are using stock WindowSystems and Windows without Dalamud for tests
|
||||||
var config = Service<DalamudConfiguration>.GetNullable();
|
var config = Service<DalamudConfiguration>.GetNullable();
|
||||||
|
var persistence = Service<WindowSystemPersistence>.GetNullable();
|
||||||
|
|
||||||
|
var flags = Window.WindowDrawFlags.None;
|
||||||
|
|
||||||
|
if (config?.EnablePluginUISoundEffects ?? false)
|
||||||
|
flags |= Window.WindowDrawFlags.UseSoundEffects;
|
||||||
|
|
||||||
|
if (config?.EnablePluginUiAdditionalOptions ?? false)
|
||||||
|
flags |= Window.WindowDrawFlags.UseAdditionalOptions;
|
||||||
|
|
||||||
|
if (config?.IsFocusManagementEnabled ?? false)
|
||||||
|
flags |= Window.WindowDrawFlags.UseFocusManagement;
|
||||||
|
|
||||||
// Shallow clone the list of windows so that we can edit it without modifying it while the loop is iterating
|
// Shallow clone the list of windows so that we can edit it without modifying it while the loop is iterating
|
||||||
foreach (var window in this.windows.ToArray())
|
foreach (var window in this.windows.ToArray())
|
||||||
|
|
@ -111,7 +125,7 @@ public class WindowSystem
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
// Log.Verbose($"[WS{(hasNamespace ? "/" + this.Namespace : string.Empty)}] Drawing {window.WindowName}");
|
// Log.Verbose($"[WS{(hasNamespace ? "/" + this.Namespace : string.Empty)}] Drawing {window.WindowName}");
|
||||||
#endif
|
#endif
|
||||||
window.DrawInternal(config);
|
window.DrawInternal(flags, persistence);
|
||||||
}
|
}
|
||||||
|
|
||||||
var focusedWindow = this.windows.FirstOrDefault(window => window.IsFocused && window.RespectCloseHotkey);
|
var focusedWindow = this.windows.FirstOrDefault(window => window.IsFocused && window.RespectCloseHotkey);
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7002b2884e9216d8bef3e792722d88abe31788f8
|
Subproject commit 122ee16819437eea7eefe0c04398b44174106d86
|
||||||
Loading…
Add table
Add a link
Reference in a new issue