您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
340 行
12 KiB
340 行
12 KiB
// Add Platforms here that exclude Quit Menu option
|
|
|
|
using System.Collections.Generic;
|
|
using System.Text.RegularExpressions;
|
|
using Unity.MegaCity.Audio;
|
|
using UnityEngine;
|
|
using Unity.MegaCity.CameraManagement;
|
|
using Unity.MegaCity.Gameplay;
|
|
using UnityEngine.SceneManagement;
|
|
using UnityEngine.UIElements;
|
|
using UnityEngine.UIElements.Experimental;
|
|
using Random = UnityEngine.Random;
|
|
|
|
namespace Unity.MegaCity.UI
|
|
{
|
|
public enum MultiplayerMode
|
|
{
|
|
Matchmaker = 0,
|
|
Connect = 1
|
|
}
|
|
|
|
/// <summary>
|
|
/// Manages the UI for the main menu.
|
|
/// This sets the audio settings for the city.
|
|
/// Defines if the player should be manual or automatic.
|
|
/// Allows the execution to exiting by pressing Escape
|
|
/// Has access to the UI game settings
|
|
/// </summary>
|
|
public class MainMenu : MonoBehaviour
|
|
{
|
|
public HybridCameraManager m_HybridCameraManager;
|
|
[SerializeField] private AudioMaster m_AudioMaster;
|
|
[SerializeField] private UIGameSettings m_GameSettings;
|
|
[SerializeField] private GameObject m_LobbyPanel;
|
|
[SerializeField] private GameObject m_IPConnectorPanel;
|
|
|
|
[field: SerializeField]
|
|
public MultiplayerMode SelectedMultiplayerMode { get; private set; } = MultiplayerMode.Matchmaker;
|
|
|
|
public AudioMaster AudioMaster => m_AudioMaster;
|
|
private int m_CurrentMenuItem;
|
|
private int m_PrevMenuItem;
|
|
|
|
private Button m_PlayerControllerButton;
|
|
private Button m_IPConnectorControllerButton;
|
|
private Button m_QuitButton;
|
|
private Button m_GameSettingsButton;
|
|
private VisualElement m_VisualMenu;
|
|
private VisualElement m_OverlayMenu;
|
|
private VisualElement m_MainMenuContainer;
|
|
private List<Button> m_Options;
|
|
|
|
// 进度条控制
|
|
private float _mockProgress = -1;
|
|
private float _deltaTime = 0;
|
|
|
|
public static MainMenu Instance { get; private set; }
|
|
|
|
public bool IsVisible => m_VisualMenu.style.display == DisplayStyle.Flex;
|
|
|
|
private void Awake()
|
|
{
|
|
if (Instance == null)
|
|
{
|
|
Instance = this;
|
|
}
|
|
else
|
|
{
|
|
Destroy(gameObject);
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (Instance == this)
|
|
Instance = null;
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
// too strongly coupled to the ui so there we go :(
|
|
// In Awake() the AudioManager is not present (before OnEnable()) so we would run into a null-ref exception.
|
|
#if UNITY_SERVER && !UNITY_EDITOR
|
|
Debug.Log("Beginning server mode");
|
|
gameObject.SetActive(false);
|
|
return;
|
|
#else
|
|
MultiverseRoomAPI.Instance.ClientIsInGame = false;
|
|
InitUI();
|
|
#endif
|
|
}
|
|
|
|
private void InitUI()
|
|
{
|
|
m_Options = new List<Button>();
|
|
m_MainMenuContainer = GetComponent<UIDocument>().rootVisualElement;
|
|
m_PlayerControllerButton = m_MainMenuContainer.Q<Button>("lobby-controller-button");
|
|
m_IPConnectorControllerButton = m_MainMenuContainer.Q<Button>("ip-controller-button");
|
|
m_GameSettingsButton = m_MainMenuContainer.Q<Button>("settings-button");
|
|
m_QuitButton = m_MainMenuContainer.Q<Button>("quit-button");
|
|
m_VisualMenu = m_MainMenuContainer.Q<VisualElement>("visual-menu");
|
|
m_OverlayMenu = m_MainMenuContainer.Q<VisualElement>("overlay");
|
|
|
|
|
|
m_VisualMenu.style.display = DisplayStyle.Flex;
|
|
|
|
var userName = MultiverseRoomAPI.Instance.PlayerName;
|
|
Debug.Log($"Initializing UI as {userName}");
|
|
if (!string.IsNullOrEmpty(userName))
|
|
{
|
|
PlayerInfoController.Instance.Name = userName;
|
|
}
|
|
|
|
m_PlayerControllerButton.clicked += () =>
|
|
{
|
|
m_CurrentMenuItem = 0;
|
|
SelectItem();
|
|
};
|
|
|
|
m_IPConnectorControllerButton.clicked += () =>
|
|
{
|
|
m_CurrentMenuItem = 3;
|
|
SelectItem();
|
|
};
|
|
m_GameSettingsButton.clicked += () =>
|
|
{
|
|
m_CurrentMenuItem = 1;
|
|
SelectItem();
|
|
};
|
|
m_QuitButton.clicked += () =>
|
|
{
|
|
m_CurrentMenuItem = 2;
|
|
SelectItem();
|
|
};
|
|
|
|
m_PlayerControllerButton.RegisterCallback<MouseOverEvent>(e => { m_CurrentMenuItem = 0; });
|
|
m_GameSettingsButton.RegisterCallback<MouseOverEvent>(e => { m_CurrentMenuItem = 1; });
|
|
m_QuitButton.RegisterCallback<MouseOverEvent>(e => { m_CurrentMenuItem = 2; });
|
|
|
|
m_Options.Add(m_PlayerControllerButton);
|
|
m_Options.Add(m_GameSettingsButton);
|
|
m_Options.Add(m_QuitButton);
|
|
SetMenuOptionUIElements(m_CurrentMenuItem);
|
|
SetConnectionMode(SelectedMultiplayerMode);
|
|
SetupCosmeticFlickering(m_MainMenuContainer);
|
|
}
|
|
|
|
private string FilterNonAlphanumeric(string input)
|
|
{
|
|
return Regex.Replace(input, @"[^a-zA-Z0-9-_]", string.Empty);
|
|
}
|
|
|
|
private void SetConnectionMode(MultiplayerMode mode)
|
|
{
|
|
SelectedMultiplayerMode = mode;
|
|
var isMatchMaking = mode == MultiplayerMode.Matchmaker;
|
|
}
|
|
|
|
private void OnLobbyPanelSelected()
|
|
{
|
|
if (MultiverseRoomAPI.Instance.ClientIsInGame)
|
|
{
|
|
Debug.LogWarning("Cant hit play while already in-game!");
|
|
return;
|
|
}
|
|
|
|
// show lobby panel
|
|
m_LobbyPanel.SetActive(true);
|
|
}
|
|
|
|
private void OnIPConnectorPanelSelected()
|
|
{
|
|
if (MultiverseRoomAPI.Instance.ClientIsInGame)
|
|
{
|
|
Debug.LogWarning("Cant hit play while already in-game!");
|
|
return;
|
|
}
|
|
|
|
// show lobby panel
|
|
m_IPConnectorPanel.SetActive(true);
|
|
}
|
|
|
|
public void ConnectionSucceeded()
|
|
{
|
|
m_HybridCameraManager.m_CameraTargetMode = HybridCameraManager.CameraTargetMode.FollowPlayer;
|
|
m_LobbyPanel.SetActive(false);
|
|
m_IPConnectorPanel.SetActive(false);
|
|
MultiverseRoomAPI.Instance.ConnectionSucceeded();
|
|
AnimateOut();
|
|
}
|
|
|
|
public void ConnectionFailed()
|
|
{
|
|
MultiverseRoomAPI.Instance.ConnectionFailed();
|
|
SceneManager.LoadScene("MegaCity");
|
|
m_IPConnectorPanel.SetActive(false);
|
|
m_LobbyPanel.SetActive(false);
|
|
HideLoading();
|
|
}
|
|
|
|
public void Show()
|
|
{
|
|
m_VisualMenu.style.display = DisplayStyle.Flex;
|
|
m_VisualMenu.visible = true;
|
|
MultiverseRoomAPI.Instance.ClientIsInGame = false;
|
|
CursorUtils.ShowCursor(true);
|
|
}
|
|
|
|
private void AnimateOut()
|
|
{
|
|
HideLoading();
|
|
//LoadAudioSettings();
|
|
m_OverlayMenu.style.display = DisplayStyle.Flex;
|
|
|
|
m_OverlayMenu.experimental.animation
|
|
.Start(new StyleValues { opacity = 1 }, 1000)
|
|
.Ease(Easing.Linear)
|
|
.OnCompleted(() =>
|
|
{
|
|
m_VisualMenu.style.display = DisplayStyle.None;
|
|
m_VisualMenu.visible = false;
|
|
m_OverlayMenu.experimental.animation
|
|
.Start(new StyleValues { opacity = 0f }, 2000)
|
|
.Ease(Easing.Linear)
|
|
.OnCompleted(() => { m_OverlayMenu.style.display = DisplayStyle.None; });
|
|
|
|
// Show HUD
|
|
TutorialScreen.Instance.ShowTutorial();
|
|
});
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (_mockProgress >= 0 && _mockProgress < 95)
|
|
{
|
|
_deltaTime += Time.deltaTime;
|
|
|
|
if (_deltaTime > 1)
|
|
{
|
|
_deltaTime = 0;
|
|
_mockProgress += Random.Range(0, 7);
|
|
// 每秒进度 + 1 或 + 2
|
|
LoadingScreen.Instance.UpdateProgressBar(_mockProgress / 100);
|
|
}
|
|
}
|
|
|
|
if (!IsVisible)
|
|
return;
|
|
|
|
if (Input.GetKeyDown(KeyCode.Escape) && !m_GameSettings.IsVisible)
|
|
QuitSystem.WantsToQuit = true;
|
|
|
|
// Only restrict update interval with respect to moving, not selecting
|
|
if (Input.GetKeyDown(KeyCode.DownArrow))
|
|
++m_CurrentMenuItem;
|
|
else if (Input.GetKeyDown(KeyCode.UpArrow))
|
|
--m_CurrentMenuItem;
|
|
else if (Input.GetKeyDown(KeyCode.Return))
|
|
SelectItem();
|
|
|
|
m_CurrentMenuItem =
|
|
Mathf.Clamp(m_CurrentMenuItem, 0, m_Options.Count > 0 ? m_Options.Count - 1 : 0);
|
|
|
|
if (m_CurrentMenuItem != m_PrevMenuItem)
|
|
{
|
|
SetMenuOptionUIElements(m_CurrentMenuItem);
|
|
m_PrevMenuItem = m_CurrentMenuItem;
|
|
}
|
|
}
|
|
|
|
private void SetMenuOptionUIElements(int optionActive)
|
|
{
|
|
foreach (var buttonOption in m_Options)
|
|
buttonOption.RemoveFromClassList("button-menu-active");
|
|
|
|
m_Options[optionActive].AddToClassList("button-menu-active");
|
|
}
|
|
|
|
private void SelectItem()
|
|
{
|
|
switch (m_CurrentMenuItem)
|
|
{
|
|
case 0:
|
|
OnLobbyPanelSelected();
|
|
break;
|
|
case 1:
|
|
ShowGameSettings();
|
|
break;
|
|
case 2:
|
|
QuitDemo();
|
|
break;
|
|
case 3:
|
|
OnIPConnectorPanelSelected();
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void QuitDemo()
|
|
{
|
|
QuitSystem.WantsToQuit = true;
|
|
}
|
|
|
|
private void ShowGameSettings()
|
|
{
|
|
m_GameSettings.Show(m_VisualMenu);
|
|
m_VisualMenu.style.display = DisplayStyle.None;
|
|
}
|
|
|
|
private void SetupCosmeticFlickering(VisualElement root)
|
|
{
|
|
var flickeringElements = root.Query(className: "flicker").ToList();
|
|
foreach (var flickeringElement in flickeringElements)
|
|
{
|
|
var randomDelay = Random.Range(1, 4);
|
|
flickeringElement.AddToClassList($"transition-{randomDelay}");
|
|
flickeringElement.RegisterCallback<TransitionEndEvent>(_ =>
|
|
flickeringElement.ToggleInClassList("flicker-loop"));
|
|
root.schedule.Execute(() => flickeringElement.ToggleInClassList("flicker-loop")).StartingIn(100);
|
|
}
|
|
}
|
|
|
|
public void ShowLoading()
|
|
{
|
|
LoadingScreen.Instance.UpdateProgressBar(0);
|
|
LoadingScreen.Instance.Show();
|
|
LoadingScreen.Instance.UpdateProgressBar(0);
|
|
_mockProgress = 0;
|
|
m_LobbyPanel.SetActive(false);
|
|
m_IPConnectorPanel.SetActive(false);
|
|
}
|
|
|
|
public void HideLoading()
|
|
{
|
|
_mockProgress = -1;
|
|
LoadingScreen.Instance.UpdateProgressBar(1);
|
|
LoadingScreen.Instance.Hide();
|
|
}
|
|
}
|
|
}
|