TouhouLS/Assets/RealCode/Menu/GameTransition.cs

226 lines
6.5 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System.Linq;
public enum GameState { Menu, SinglePlayer, Multiplayer, Lobby, SelectingRegion, ConnectionInProgress, InGame, Continue, Credits, Help }
public class GameTransition : MonoBehaviour {
[Header("Escape")]
public RectTransform escapeButton;
public Vector2 selectedEscapePosition = Vector2.zero;
private Vector2 baseEscapePosition;
public static GameTransition Instance { get; private set; }
[Header("Main")]
[SerializeField]
private GameState _state;
public GameState state {
get => _state;
set {
if (_state == value) return;
_state = value;
EventSystem.current.SetSelectedGameObject(null);
var select = rDisplays.FirstOrDefault(d => d.states.Contains(value) && d.firstSelectedGameObject != null);
if (select != null)
EventSystem.current.SetSelectedGameObject(select.firstSelectedGameObject);
}
}
public bool inMultiplayer;
public float lerpSpeed = 10f;
[System.Serializable]
private class RectTransformDisplay{
public RectTransform target = null;
public GameState[] states = new GameState[] { GameState.Menu };
[System.NonSerialized]
public Vector2 basePosition = Vector2.zero;
public Vector2 selectedPosition = Vector2.zero;
public GameObject firstSelectedGameObject = null;
}
[System.Serializable]
private class TransformDisplay : TransformDefault{
public GameState[] states = new GameState[] { GameState.Menu };
public int playerLoadedCount = 0;
public TransformDisplay(Transform t, Vector3 p, Vector3 r, Vector3 s) : base(t, p, r, s) { }
}
private class TransformDefault{
public Transform target = null;
public Vector3 position = Vector3.zero;
public Vector3 rotation = Vector3.zero;
public Vector3 scale = Vector3.one;
public TransformDefault(Transform t, Vector3 p, Vector3 r, Vector3 s){
target = t;
position = p;
rotation = r;
scale = s;
}
public void Set(float lerp){
target.localPosition = Vector3.Lerp(target.localPosition, position, lerp);
target.localRotation = Quaternion.Slerp(target.localRotation, Quaternion.Euler(rotation), lerp);
target.localScale = Vector3.Lerp(target.localScale, scale, lerp);
}
}
private TransformDefault[] tDefault;
[SerializeField]
private RectTransformDisplay[] rDisplays = new RectTransformDisplay[0];
[SerializeField]
private TransformDisplay[] tDisplays = new TransformDisplay[0];
public GameState[] selectedOrthoStates;
public float selectedCameraOrthoSize = 3f;
private float baseCameraOrthoSize;
private Camera baseCamera;
private void Awake() {
Instance = this;
}
private void Start() {
escapeButton.GetComponent<Button>().onClick.AddListener(Escape);
baseEscapePosition = escapeButton.anchoredPosition;
baseCamera = Camera.main;
baseCameraOrthoSize = baseCamera.orthographicSize;
foreach(var r in rDisplays){
r.basePosition = r.target.anchoredPosition;
}
tDefault = tDisplays.Select(t => t.target).Distinct().Select(t => new TransformDefault(t, t.localPosition, t.localEulerAngles, t.localScale)).ToArray();
}
private bool prevState;
private bool curState;
private void Update() {
// obscure fix to input field + esc
prevState = curState;
var sinputfield = EventSystem.current.currentSelectedGameObject;
if (sinputfield){
var comp = sinputfield.GetComponent<TMPro.TMP_InputField>();
curState = comp ? comp.isFocused : false;
} else {
curState = false;
}
// Escape handling
if (Input.GetKeyDown(KeyCode.Escape)) {
if (prevState && !curState) return;
Escape();
}
// in case the player disconnects during any weird times
if (inMultiplayer){
switch(NetworkManager.net.State){
case ExitGames.Client.Photon.LoadBalancing.ClientState.Disconnected:
case ExitGames.Client.Photon.LoadBalancing.ClientState.PeerCreated:
state = GameState.Menu;
inMultiplayer = false;
break;
case ExitGames.Client.Photon.LoadBalancing.ClientState.ConnectedToNameServer:
state = GameState.SelectingRegion;
break;
case ExitGames.Client.Photon.LoadBalancing.ClientState.JoinedLobby:
state = GameState.Multiplayer;
break;
case ExitGames.Client.Photon.LoadBalancing.ClientState.Joined:
if (state != GameState.InGame && state != GameState.Continue)
state = GameState.Lobby;
break;
}
}
// transform
var dist = Time.deltaTime * lerpSpeed;
var playersLoaded = NetworkManager.inRoom ? NetworkManager.net.CurrentRoom.PlayerCount : 2;
foreach(var d in rDisplays){
var selected = d.states.Contains(state);
var item = d.target;
if (item){
item.anchoredPosition = Vector3.Lerp(item.anchoredPosition, selected ? d.selectedPosition : d.basePosition, dist);
}
}
var set = new Dictionary<Transform, TransformDefault>();
foreach(var t in tDefault)
set.Add(t.target, t);
foreach(var d in tDisplays){
var selected = d.states.Contains(state);
if (selected && d.playerLoadedCount <= playersLoaded){
d.Set(dist);
set.Remove(d.target);
}
}
foreach(var d in set){
d.Value.Set(dist);
}
baseCamera.orthographicSize = Mathf.Lerp(baseCamera.orthographicSize, selectedOrthoStates.Contains(state) ? selectedCameraOrthoSize : baseCameraOrthoSize, dist);
escapeButton.anchoredPosition = Vector2.Lerp(escapeButton.anchoredPosition, ShowEscapeButton() ? selectedEscapePosition : baseEscapePosition, dist);
}
bool ShowEscapeButton(){
return state != GameState.Menu;
}
void Escape(){
if (!ShowEscapeButton()) return;
switch (state){
case GameState.Help:
case GameState.Credits:
state = GameState.Menu;
break;
// must disconnect
case GameState.Multiplayer:
case GameState.SelectingRegion:
state = GameState.ConnectionInProgress;
NetworkManager.net.Service();
NetworkManager.net.Disconnect();
break;
// special case, leave room
case GameState.Lobby:
state = GameState.ConnectionInProgress;
NetworkManager.net.OpLeaveRoom();
break;
// close game
case GameState.InGame:
GameBoardInstance.instance.ExitGame();
break;
case GameState.Continue:
GameBoardInstance.instance.ExitGame(true);
break;
}
}
}