Files
Emberwild/Assets/GAME/Script/UI/HudVisibilityToggle.cs
2026-07-07 16:43:51 +02:00

92 lines
3.1 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
namespace Ashwild.UI
{
/// <summary>
/// Screenshot/capture utility: one keypress hides (and restores) every Canvas in the scene at
/// once, so the world can be photographed with no HUD, crosshair, notifications or menus on top.
/// It toggles each root Canvas's <see cref="Canvas.enabled"/> rather than deactivating GameObjects,
/// so animations, timers and gameplay keep running untouched behind the hidden UI.
///
/// This is a deliberate, isolated exception to the "InputManager owns all input" rule: it is not a
/// gameplay action and never goes through the Send-Messages path, so it reads the key straight from
/// <see cref="Keyboard"/> instead of the action asset. Canvases are re-queried on every toggle, so
/// windows opened after hiding are still caught the next time the state flips.
/// </summary>
[DisallowMultipleComponent]
public class HudVisibilityToggle : MonoBehaviour
{
#region Serialized Fields
[Header("Input")]
[Tooltip("Key that toggles all UI on/off (default F8).")]
[SerializeField] private Key toggleKey = Key.F8;
[Header("Exclusions")]
[Tooltip("Root canvases that must stay visible even when the HUD is hidden (e.g. a debug overlay).")]
[SerializeField] private List<Canvas> alwaysVisible = new List<Canvas>();
#endregion
#region State
/// <summary>
/// True while the UI is currently hidden — the next press restores it.
/// </summary>
private bool hidden;
#endregion
#region Unity Lifecycle
/// <summary>
/// Polls the toggle key each frame and flips UI visibility on a fresh press.
/// </summary>
private void Update()
{
Keyboard keyboard = Keyboard.current;
if (keyboard == null) return;
if (keyboard[toggleKey].wasPressedThisFrame)
ToggleHud();
}
#endregion
#region Public API
/// <summary>
/// Flips the hidden state and re-applies it to every root canvas in the scene.
/// </summary>
public void ToggleHud()
{
hidden = !hidden;
ApplyVisibility();
}
#endregion
#region Internal Helpers
/// <summary>
/// Enables or disables every root Canvas to match the current hidden state, skipping any
/// canvas listed in <see cref="alwaysVisible"/>. Only root canvases are touched — nested
/// canvases follow their parent's rendering, so toggling them too would be redundant.
/// </summary>
private void ApplyVisibility()
{
Canvas[] canvases = FindObjectsByType<Canvas>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
foreach (Canvas canvas in canvases)
{
if (canvas == null || !canvas.isRootCanvas) continue;
if (alwaysVisible.Contains(canvas)) continue;
canvas.enabled = !hidden;
}
}
#endregion
}
}