2025-11-09 13:23:03 +01:00
|
|
|
using Core;
|
|
|
|
|
using Core.Lifecycle;
|
|
|
|
|
using UI.Core;
|
2025-11-07 16:47:10 +01:00
|
|
|
using Cinematics;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.Playables;
|
2025-11-09 13:23:03 +01:00
|
|
|
using UnityEngine.UI;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Collections.Generic;
|
2025-11-07 16:47:10 +01:00
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
namespace UI
|
2025-11-07 16:47:10 +01:00
|
|
|
{
|
2025-11-09 13:23:03 +01:00
|
|
|
/// <summary>
|
|
|
|
|
/// Manages player HUD elements and their visibility.
|
|
|
|
|
/// Works alongside UIPageController (must be on same GameObject).
|
|
|
|
|
/// Automatically hides HUD when pages open, shows when all pages close.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class PlayerHudManager : ManagedBehaviour
|
|
|
|
|
{
|
|
|
|
|
public enum UIMode { Overworld, Puzzle, Minigame, HideAll };
|
2025-11-07 16:47:10 +01:00
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
public UIMode currentUIMode;
|
|
|
|
|
|
|
|
|
|
[Header("HUD Management")]
|
|
|
|
|
[SerializeField] private Transform hudButtonsContainer; // Parent object containing all HUD buttons
|
|
|
|
|
|
|
|
|
|
[Header("Cinematic References")]
|
|
|
|
|
public GameObject landscapeObject;
|
|
|
|
|
public GameObject portraitObject;
|
|
|
|
|
public GameObject cinematicsParentObject;
|
|
|
|
|
public GameObject CinematicBackground;
|
|
|
|
|
|
|
|
|
|
[Header("HUD Elements")]
|
|
|
|
|
public GameObject eagleEye;
|
2025-11-07 16:47:10 +01:00
|
|
|
|
|
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
[HideInInspector] public Image cinematicSprites;
|
|
|
|
|
[HideInInspector] public Image cinematicBackgroundSprites;
|
|
|
|
|
[HideInInspector] public GameObject currentCinematicPlayer;
|
|
|
|
|
[HideInInspector] public PlayableDirector playableDirector;
|
2025-11-07 16:47:10 +01:00
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
|
|
|
|
|
private static PlayerHudManager _instance;
|
|
|
|
|
public static PlayerHudManager Instance => _instance;
|
|
|
|
|
|
|
|
|
|
private UIPageController _uiPageController;
|
|
|
|
|
private AppSwitcher _appSwitcherComponent;
|
|
|
|
|
|
|
|
|
|
private new void Awake()
|
|
|
|
|
{
|
|
|
|
|
base.Awake();
|
|
|
|
|
if (Instance != null)
|
|
|
|
|
{
|
|
|
|
|
Destroy(this);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
_instance = this;
|
|
|
|
|
|
|
|
|
|
// Get UIPageController on same GameObject
|
|
|
|
|
_uiPageController = GetComponent<UIPageController>();
|
|
|
|
|
if (_uiPageController == null)
|
|
|
|
|
{
|
|
|
|
|
UnityEngine.Debug.LogError("[PlayerHudManager] UIPageController not found on same GameObject!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InitializeReferences();
|
|
|
|
|
}
|
2025-11-07 16:47:10 +01:00
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
protected override void OnManagedAwake()
|
2025-11-07 16:47:10 +01:00
|
|
|
{
|
2025-11-09 13:23:03 +01:00
|
|
|
// Subscribe to UIPageController page changes for auto HUD management
|
|
|
|
|
if (_uiPageController != null)
|
|
|
|
|
{
|
|
|
|
|
_uiPageController.OnPageChanged += HandlePageStackChanged;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Subscribe to CinematicsManager events for HUD management during cinematics
|
|
|
|
|
if (CinematicsManager.Instance != null)
|
|
|
|
|
{
|
|
|
|
|
CinematicsManager.Instance.OnCinematicStarted += HandleCinematicStarted;
|
|
|
|
|
CinematicsManager.Instance.OnCinematicStopped += HandleCinematicStopped;
|
|
|
|
|
|
|
|
|
|
// Check if a cinematic is already playing
|
|
|
|
|
if (CinematicsManager.Instance.IsCinematicPlaying)
|
|
|
|
|
{
|
|
|
|
|
HideAllHud();
|
|
|
|
|
Logging.Debug("[PlayerHudManager] Cinematic already playing on init, hiding HUD");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (SceneManagerService.Instance != null)
|
|
|
|
|
{
|
|
|
|
|
SceneManagerService.Instance.SceneLoadCompleted += NewSceneLoaded;
|
|
|
|
|
}
|
|
|
|
|
if (SceneManagerService.Instance.CurrentGameplayScene == "AppleHillsOverworld")
|
|
|
|
|
{
|
|
|
|
|
NewSceneLoaded("AppleHillsOverworld");
|
|
|
|
|
}
|
|
|
|
|
if (SceneManagerService.Instance.CurrentGameplayScene == "StartingScene")
|
|
|
|
|
{
|
|
|
|
|
// TODO: Hide all UI until cinematics have played
|
|
|
|
|
NewSceneLoaded("AppleHillsOverworld");
|
|
|
|
|
}
|
2025-11-07 16:47:10 +01:00
|
|
|
}
|
|
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
protected override void OnDestroy()
|
|
|
|
|
{
|
|
|
|
|
base.OnDestroy();
|
|
|
|
|
|
|
|
|
|
// Unsubscribe from events
|
|
|
|
|
if (_uiPageController != null)
|
|
|
|
|
{
|
|
|
|
|
_uiPageController.OnPageChanged -= HandlePageStackChanged;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (CinematicsManager.Instance != null)
|
|
|
|
|
{
|
|
|
|
|
CinematicsManager.Instance.OnCinematicStarted -= HandleCinematicStarted;
|
|
|
|
|
CinematicsManager.Instance.OnCinematicStopped -= HandleCinematicStopped;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (SceneManagerService.Instance != null)
|
|
|
|
|
{
|
|
|
|
|
SceneManagerService.Instance.SceneLoadCompleted -= NewSceneLoaded;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-11-07 16:47:10 +01:00
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
private void InitializeReferences()
|
|
|
|
|
{
|
|
|
|
|
currentCinematicPlayer = landscapeObject;
|
|
|
|
|
playableDirector = cinematicsParentObject.GetComponent<PlayableDirector>();
|
|
|
|
|
cinematicSprites = currentCinematicPlayer.GetComponent<Image>();
|
|
|
|
|
cinematicBackgroundSprites = CinematicBackground.GetComponent<Image>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpateCinematicReferences(GameObject newCinematicPlayer)
|
|
|
|
|
{
|
|
|
|
|
currentCinematicPlayer = newCinematicPlayer;
|
|
|
|
|
cinematicSprites = currentCinematicPlayer.GetComponent<Image>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetPortraitMode(bool portraitModeEnable)
|
|
|
|
|
{
|
|
|
|
|
if (portraitModeEnable)
|
|
|
|
|
{
|
|
|
|
|
UpateCinematicReferences(portraitObject);
|
2025-11-08 21:08:01 +01:00
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
UpateCinematicReferences(landscapeObject);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-11-08 21:08:01 +01:00
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
public void NewSceneLoaded(string sceneName)
|
|
|
|
|
{
|
|
|
|
|
switch (sceneName)
|
|
|
|
|
{
|
|
|
|
|
case "AppleHillsOverworld":
|
|
|
|
|
UpdateUIMode(UIMode.Overworld);
|
|
|
|
|
break;
|
|
|
|
|
case "Quarry":
|
|
|
|
|
UpdateUIMode(UIMode.Puzzle);
|
|
|
|
|
break;
|
|
|
|
|
case "DivingForPictures":
|
|
|
|
|
UpdateUIMode(UIMode.Minigame);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2025-11-08 21:08:01 +01:00
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
public void UpdateUIMode(UIMode mode)
|
2025-11-08 21:08:01 +01:00
|
|
|
{
|
2025-11-09 13:23:03 +01:00
|
|
|
switch (mode)
|
|
|
|
|
{
|
|
|
|
|
case UIMode.Overworld:
|
|
|
|
|
// Update currentUIMode var
|
|
|
|
|
currentUIMode = UIMode.Overworld;
|
|
|
|
|
// Hide eagle eye
|
|
|
|
|
eagleEye.SetActive(false);
|
|
|
|
|
break;
|
|
|
|
|
case UIMode.Puzzle:
|
|
|
|
|
// Update currentUIMode var
|
|
|
|
|
currentUIMode = UIMode.Puzzle;
|
|
|
|
|
// show eagle eye
|
|
|
|
|
eagleEye.SetActive(true);
|
|
|
|
|
break;
|
|
|
|
|
case UIMode.Minigame:
|
|
|
|
|
// Update currentUIMode var
|
|
|
|
|
currentUIMode = UIMode.Minigame;
|
|
|
|
|
// Hide birds eye
|
|
|
|
|
eagleEye.SetActive(false);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2025-11-08 21:08:01 +01:00
|
|
|
}
|
2025-11-09 13:23:03 +01:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Hides all HUD button elements
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void HideAllHud()
|
2025-11-08 21:08:01 +01:00
|
|
|
{
|
2025-11-09 13:23:03 +01:00
|
|
|
SetHudVisibility(false);
|
2025-11-08 21:08:01 +01:00
|
|
|
}
|
|
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
/// <summary>
|
|
|
|
|
/// Shows all HUD button elements
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void ShowAllHud()
|
|
|
|
|
{
|
|
|
|
|
SetHudVisibility(true);
|
|
|
|
|
}
|
2025-11-07 16:47:10 +01:00
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
/// <summary>
|
|
|
|
|
/// Hides all HUD elements except the specified exceptions
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="exceptions">GameObjects to keep visible</param>
|
|
|
|
|
public void HideAllHudExcept(params GameObject[] exceptions)
|
2025-11-07 16:47:10 +01:00
|
|
|
{
|
2025-11-09 13:23:03 +01:00
|
|
|
if (hudButtonsContainer == null)
|
|
|
|
|
{
|
|
|
|
|
Logging.Warning("[PlayerHudManager] HUD buttons container not assigned");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-11-07 16:47:10 +01:00
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
HashSet<GameObject> exceptionSet = new HashSet<GameObject>(exceptions);
|
|
|
|
|
|
|
|
|
|
foreach (Transform child in hudButtonsContainer)
|
|
|
|
|
{
|
|
|
|
|
bool shouldShow = exceptionSet.Contains(child.gameObject);
|
|
|
|
|
child.gameObject.SetActive(shouldShow);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Logging.Debug($"[PlayerHudManager] Hidden HUD except {exceptions.Length} exceptions");
|
2025-11-07 16:47:10 +01:00
|
|
|
}
|
2025-11-09 13:23:03 +01:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Common method to set visibility of all HUD elements
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void SetHudVisibility(bool visible)
|
2025-11-07 16:47:10 +01:00
|
|
|
{
|
2025-11-09 13:23:03 +01:00
|
|
|
if (hudButtonsContainer == null)
|
|
|
|
|
{
|
|
|
|
|
Logging.Warning("[PlayerHudManager] HUD buttons container not assigned");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (Transform child in hudButtonsContainer)
|
|
|
|
|
{
|
|
|
|
|
child.gameObject.SetActive(visible);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Logging.Debug($"[PlayerHudManager] {(visible ? "Shown" : "Hidden")} all HUD elements");
|
2025-11-07 16:47:10 +01:00
|
|
|
}
|
2025-11-08 21:08:01 +01:00
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
/// <summary>
|
|
|
|
|
/// Automatically manages HUD visibility based on page stack state
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void HandlePageStackChanged(UIPage currentPage)
|
|
|
|
|
{
|
|
|
|
|
if (_uiPageController == null) return;
|
|
|
|
|
|
|
|
|
|
// Use LINQ Count() on IEnumerable<UIPage> PageStack property
|
|
|
|
|
int stackCount = _uiPageController.PageStack.Count();
|
|
|
|
|
|
|
|
|
|
if (stackCount == 1 && currentPage != null)
|
|
|
|
|
{
|
|
|
|
|
// First page just opened - hide HUD
|
|
|
|
|
HideAllHud();
|
|
|
|
|
Logging.Debug("[PlayerHudManager] Page opened, hiding HUD");
|
|
|
|
|
}
|
|
|
|
|
else if (stackCount == 0)
|
|
|
|
|
{
|
|
|
|
|
// Last page closed - show HUD
|
|
|
|
|
ShowAllHud();
|
|
|
|
|
Logging.Debug("[PlayerHudManager] All pages closed, showing HUD");
|
|
|
|
|
}
|
|
|
|
|
// If stackCount > 1, we're navigating between pages, keep HUD hidden
|
2025-11-08 21:08:01 +01:00
|
|
|
}
|
|
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
/// <summary>
|
|
|
|
|
/// Called when a cinematic starts playing
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void HandleCinematicStarted()
|
|
|
|
|
{
|
|
|
|
|
HideAllHud();
|
|
|
|
|
Logging.Debug("[PlayerHudManager] Cinematic started, hiding HUD");
|
2025-11-08 21:08:01 +01:00
|
|
|
}
|
2025-11-08 22:16:43 +01:00
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
/// <summary>
|
|
|
|
|
/// Called when a cinematic stops playing
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void HandleCinematicStopped()
|
|
|
|
|
{
|
|
|
|
|
ShowAllHud();
|
|
|
|
|
Logging.Debug("[PlayerHudManager] Cinematic stopped, showing HUD");
|
|
|
|
|
}
|
2025-11-08 22:16:43 +01:00
|
|
|
|
2025-11-09 13:23:03 +01:00
|
|
|
/// <summary>
|
|
|
|
|
/// Convenience method to push a page from prefab using the UIPageController
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void PushPageFromPrefab(GameObject pagePrefab)
|
|
|
|
|
{
|
|
|
|
|
if (_uiPageController != null)
|
|
|
|
|
{
|
|
|
|
|
_uiPageController.PushPageFromPrefab(pagePrefab);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
UnityEngine.Debug.LogError("[PlayerHudManager] Cannot push page - UIPageController not found!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-11-07 16:47:10 +01:00
|
|
|
}
|
2025-11-09 13:23:03 +01:00
|
|
|
|