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() { 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(); 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(); 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; } public void Escape(){ if (!ShowEscapeButton()) return; switch (state){ case GameState.Help: case GameState.Credits: case GameState.SinglePlayer: 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; } } }