using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UIElements; /// /// class to handles overall game ui state and transitions /// public class UIManager : MonoBehaviour { /// /// enum for available menus in the game, for use with ShowMenu() /// public enum DisplayState { UnassociatedState, DefaultView, GameView, ResultsView, LeaderboardView, AccountView } /// /// singleton pattern: define instance field for accessing the singleton elsewhere /// public static UIManager Instance; /// /// the current display state of the game /// [SerializeField] private DisplayState state = DisplayState.UnassociatedState; /// /// list of callbacks to invoke when the display state changes /// private readonly List> _onDisplayStateChangeCallbacks = new(); /// /// the visual element object for game ui /// public VisualElement UI; /// /// enforces singleton behaviour; sets doesn't destroy on load and checks for multiple instances /// private void Awake() { // check if instance hasn't been set yet if (Instance == null) { Debug.Log("awake as singleton instance, setting self as the forever-alive instance"); Instance = this; DontDestroyOnLoad(gameObject); } // check if instance is already set and it's not this instance else if (Instance != null && Instance != this) { Debug.Log("awake as non-singleton instance, destroying self"); Destroy(gameObject); } } /// /// modify state of initial variables /// private void Start() { SetDisplayState(DisplayState.DefaultView); } private void Update() { var gameplay = GameManager.Instance.Gameplay; if (gameplay == null) return; if (gameplay.Round >= 1) gameplay.Update(); } /// /// initialise variables and register callbacks /// private void OnEnable() { UI = GetComponent().rootVisualElement; } /// /// function to register a callback to be invoked when the display state changes /// /// /// callback function that takes two DisplayState parameters: /// public void RegisterOnDisplayStateChangeCallback(Action callback) { _onDisplayStateChangeCallbacks.Add(callback); } private void FireOnDisplayStateChange(DisplayState oldState, DisplayState newState) { foreach (var callback in _onDisplayStateChangeCallbacks) try { callback.Invoke(oldState, newState); } catch (Exception e) { Debug.LogError($"error invoking OnSignOutCallback: {e.Message}"); } } /// /// function to show a menu based on the enum passed, /// and any other necessary actions /// /// the game menu to show public void SetDisplayState(DisplayState newDisplayState) { // if the new state is the same as the current state, do nothing if (state == newDisplayState) { Debug.Log($"staying at {state} (illogical transition)"); return; } Debug.Log($"switching from {state} to {newDisplayState}"); var defaultView = UI.Q("DefaultView"); var gameView = UI.Q("GameView"); var resultsView = UI.Q("ResultsView"); var leaderboardView = UI.Q("LeaderboardView"); var accountView = UI.Q("AccountView"); defaultView.style.display = newDisplayState switch { DisplayState.DefaultView => DisplayStyle.Flex, _ => DisplayStyle.None }; gameView.style.display = newDisplayState switch { DisplayState.GameView => DisplayStyle.Flex, _ => DisplayStyle.None }; resultsView.style.display = newDisplayState switch { DisplayState.ResultsView => DisplayStyle.Flex, _ => DisplayStyle.None }; leaderboardView.style.display = newDisplayState switch { DisplayState.LeaderboardView => DisplayStyle.Flex, _ => DisplayStyle.None }; accountView.style.display = newDisplayState switch { DisplayState.AccountView => DisplayStyle.Flex, _ => DisplayStyle.None }; if (newDisplayState == DisplayState.GameView) { // if we're in the game view, everything except the account section/panel thing UI.Q