This repository has been archived on 2024-11-20. You can view files and clone it, but cannot push or open issues or pull requests.
colourmeok/ColourMeOKGame/Assets/Scripts/UIManager.cs

194 lines
No EOL
6.4 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
/// <summary>
/// class to handles overall game ui state and transitions
/// </summary>
public class UIManager : MonoBehaviour
{
/// <summary>
/// enum for available menus in the game, for use with <c>ShowMenu()</c>
/// </summary>
public enum DisplayState
{
UnassociatedState,
DefaultView,
GameView,
ResultsView,
LeaderboardView,
AccountView
}
/// <summary>
/// singleton pattern: define instance field for accessing the singleton elsewhere
/// </summary>
public static UIManager Instance;
/// <summary>
/// the current display state of the game
/// </summary>
[SerializeField] private DisplayState state = DisplayState.UnassociatedState;
/// <summary>
/// list of callbacks to invoke when the display state changes
/// </summary>
private readonly List<Action<DisplayState, DisplayState>> _onDisplayStateChangeCallbacks = new();
/// <summary>
/// the visual element object for game ui
/// </summary>
public VisualElement UI;
/// <summary>
/// enforces singleton behaviour; sets doesn't destroy on load and checks for multiple instances
/// </summary>
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);
}
}
/// <summary>
/// modify state of initial variables
/// </summary>
private void Start()
{
SetDisplayState(DisplayState.DefaultView);
}
private void Update()
{
var gameplay = GameManager.Instance.Gameplay;
if (gameplay == null) return;
if (gameplay.Round >= 1) gameplay.Update();
}
/// <summary>
/// initialise variables and register callbacks
/// </summary>
private void OnEnable()
{
UI = GetComponent<UIDocument>().rootVisualElement;
}
/// <summary>
/// function to register a callback to be invoked when the display state changes
/// </summary>
/// <param name="callback">
/// callback function that takes two <c>DisplayState</c> parameters:
/// </param>
public void RegisterOnDisplayStateChangeCallback(Action<DisplayState, DisplayState> 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}");
}
}
/// <summary>
/// function to show a menu based on the enum passed,
/// and any other necessary actions
/// </summary>
/// <param name="newDisplayState">the game menu to show</param>
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<VisualElement>("DefaultView");
var gameView = UI.Q<VisualElement>("GameView");
var resultsView = UI.Q<VisualElement>("ResultsView");
var leaderboardView = UI.Q<VisualElement>("LeaderboardView");
var accountView = UI.Q<VisualElement>("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<Button>("PlayButton").style.display = DisplayStyle.None;
UI.Q<Button>("LeaderboardButton").style.display = DisplayStyle.None;
UI.Q<Button>("AccountButton").style.display = DisplayStyle.None;
UI.Q<VisualElement>("AccountSection").style.display = DisplayStyle.Flex;
UI.Q<VisualElement>("ConnectionStatus").style.display = DisplayStyle.None;
// start the game
GameManager.Instance.Gameplay.StartGame();
}
else
{
// if we're not in the game view, show everything!
UI.Q<Button>("PlayButton").style.display = DisplayStyle.Flex;
UI.Q<Button>("LeaderboardButton").style.display =
GameManager.Instance.Backend.Status == Backend.FirebaseConnectionStatus.Connected
? DisplayStyle.Flex
: DisplayStyle.None;
UI.Q<Button>("AccountButton").style.display =
GameManager.Instance.Backend.Status == Backend.FirebaseConnectionStatus.Connected
? DisplayStyle.Flex
: DisplayStyle.None;
UI.Q<VisualElement>("AccountSection").style.display = DisplayStyle.Flex;
UI.Q<VisualElement>("ConnectionStatus").style.display = DisplayStyle.Flex;
}
FireOnDisplayStateChange(state, newDisplayState);
state = newDisplayState;
}
}