Fade in/out window system windows

This commit is contained in:
goaaats 2025-05-09 23:40:49 +02:00
parent 2c735e9ec3
commit b1c874c123
2 changed files with 64 additions and 6 deletions

View file

@ -32,6 +32,9 @@ namespace Dalamud.Interface.Windowing;
/// </summary> /// </summary>
public abstract class Window public abstract class Window
{ {
private const float FadeInOutTime = 1f;
private const float FadeInOutStep = 0.09f;
private static readonly ModuleLog Log = new("WindowSystem"); private static readonly ModuleLog Log = new("WindowSystem");
private static bool wasEscPressedLastFrame = false; private static bool wasEscPressedLastFrame = false;
@ -48,6 +51,12 @@ public abstract class Window
private PresetModel.PresetWindow? presetWindow; private PresetModel.PresetWindow? presetWindow;
private bool presetDirty = false; private bool presetDirty = false;
private float fadeInTimer = 1f;
private float fadeOutTimer = 0f;
private IDrawListTextureWrap? fadeOutTexture = null;
private Vector2 fadeOutSize = Vector2.Zero;
private Vector2 fadeOutOrigin = Vector2.Zero;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Window"/> class. /// Initializes a new instance of the <see cref="Window"/> class.
/// </summary> /// </summary>
@ -89,6 +98,11 @@ public abstract class Window
/// Enable the built-in "additional options" menu on the title bar. /// Enable the built-in "additional options" menu on the title bar.
/// </summary> /// </summary>
UseAdditionalOptions = 1 << 2, UseAdditionalOptions = 1 << 2,
/// <summary>
/// Do not draw non-critical animations.
/// </summary>
IsReducedMotion = 1 << 3,
} }
/// <summary> /// <summary>
@ -316,6 +330,7 @@ public abstract class Window
internal void DrawInternal(WindowDrawFlags internalDrawFlags, WindowSystemPersistence? persistence) internal void DrawInternal(WindowDrawFlags internalDrawFlags, WindowSystemPersistence? persistence)
{ {
this.PreOpenCheck(); this.PreOpenCheck();
var isReducedMotion = internalDrawFlags.HasFlag(WindowDrawFlags.IsReducedMotion);
if (!this.IsOpen) if (!this.IsOpen)
{ {
@ -330,9 +345,35 @@ public abstract class Window
UIGlobals.PlaySoundEffect(this.OnCloseSfxId); UIGlobals.PlaySoundEffect(this.OnCloseSfxId);
} }
if (this.fadeOutTexture != null)
{
this.fadeOutTimer -= FadeInOutStep;
if (this.fadeOutTimer <= 0f)
{
this.fadeOutTexture.Dispose();
this.fadeOutTexture = null;
}
else
{
var dl = ImGui.GetBackgroundDrawList();
dl.AddImage(
this.fadeOutTexture.ImGuiHandle,
this.fadeOutOrigin,
this.fadeOutOrigin + this.fadeOutSize,
Vector2.Zero,
Vector2.One,
ImGui.ColorConvertFloat4ToU32(new(1f, 1f, 1f, Math.Clamp(this.fadeOutTimer / FadeInOutTime, 0f, 1f))));
}
}
this.fadeInTimer = !isReducedMotion ? 0f : FadeInOutTime;
return; return;
} }
this.fadeInTimer += FadeInOutStep;
if (this.fadeInTimer > FadeInOutTime)
this.fadeInTimer = FadeInOutTime;
this.Update(); this.Update();
if (!this.DrawConditions()) if (!this.DrawConditions())
return; return;
@ -546,8 +587,19 @@ public abstract class Window
} }
} }
this.fadeOutSize = ImGui.GetWindowSize();
this.fadeOutOrigin = ImGui.GetWindowPos();
ImGui.End(); ImGui.End();
if (!this.internalIsOpen && this.fadeOutTexture == null && !isReducedMotion)
{
this.fadeOutTexture = Service<TextureManager>.Get().CreateDrawListTexture(
"WindowFadeOutTexture");
this.fadeOutTexture.ResizeAndDrawWindow(this.WindowName, Vector2.One);
this.fadeOutTimer = FadeInOutTime;
}
if (printWindow) if (printWindow)
{ {
var tex = Service<TextureManager>.Get().CreateDrawListTexture( var tex = Service<TextureManager>.Get().CreateDrawListTexture(
@ -567,7 +619,7 @@ public abstract class Window
ImGui.PopID(); ImGui.PopID();
} }
private void ApplyConditionals() private unsafe void ApplyConditionals()
{ {
if (this.Position.HasValue) if (this.Position.HasValue)
{ {
@ -594,15 +646,18 @@ public abstract class Window
ImGui.SetNextWindowSizeConstraints(this.SizeConstraints.Value.MinimumSize * ImGuiHelpers.GlobalScale, this.SizeConstraints.Value.MaximumSize * ImGuiHelpers.GlobalScale); ImGui.SetNextWindowSizeConstraints(this.SizeConstraints.Value.MinimumSize * ImGuiHelpers.GlobalScale, this.SizeConstraints.Value.MaximumSize * ImGuiHelpers.GlobalScale);
} }
if (this.BgAlpha.HasValue) var maxBgAlpha = this.internalAlpha ?? this.BgAlpha;
var fadeInAlpha = this.fadeInTimer / FadeInOutTime;
if (fadeInAlpha < 1f)
{ {
ImGui.SetNextWindowBgAlpha(this.BgAlpha.Value); maxBgAlpha = maxBgAlpha.HasValue ?
Math.Clamp(maxBgAlpha.Value * fadeInAlpha, 0f, 1f) :
(*ImGui.GetStyleColorVec4(ImGuiCol.WindowBg)).W * fadeInAlpha;
} }
// Manually set alpha takes precedence, if devs don't want that, they should turn it off if (maxBgAlpha.HasValue)
if (this.internalAlpha.HasValue)
{ {
ImGui.SetNextWindowBgAlpha(this.internalAlpha.Value); ImGui.SetNextWindowBgAlpha(maxBgAlpha.Value);
} }
} }

View file

@ -119,6 +119,9 @@ public class WindowSystem
if (config?.IsFocusManagementEnabled ?? false) if (config?.IsFocusManagementEnabled ?? false)
flags |= Window.WindowDrawFlags.UseFocusManagement; flags |= Window.WindowDrawFlags.UseFocusManagement;
if (config?.ReduceMotions ?? false)
flags |= Window.WindowDrawFlags.IsReducedMotion;
// 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())
{ {