Toggle session panel with Escape as in-game pause overlay
- Panel shows in Main while disconnected, auto-hides once a connection is established, and toggles open/closed with Escape in the Lobby or on a Map. - Escape now pauses gameplay (active mode exits, cursor freed, paint and movement disabled) instead of ending the match directly; closing restores the prior mode via SwitchTo. - Disconnect button is context-aware: leaves the session in the Lobby, acts as "Back to Lobby" (EndMatch) for the match authority on a Map, and stays a plain disconnect for non-authority clients on a Map. - Removed the Escape->EndMatch handler from MatchManager; match end now routes through RequestEndMatch with the same authority routing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
d27ee16004
commit
cdfec364b2
4 files changed
+248
-51
No files matched your search
@@ -1,7 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// uGUI binding for <see cref="OnlineSessionManager"/>. Drives the server-browser canvas - Host / Refresh /
|
||||
@@ -13,6 +17,13 @@ using UnityEngine.UI;
|
||||
/// Selection model: Refresh fills the list with clones of <see cref="entryTemplate"/> (each a clickable row
|
||||
/// showing name + player count). Clicking a row selects it; Join connects to the selected session. While
|
||||
/// connected, only Disconnect is interactable.
|
||||
///
|
||||
/// Overlay behaviour: the panel is always shown in Main (not connected). Once a connection is up it hides;
|
||||
/// in the lobby/map Esc toggles it back as a modal pause overlay (cursor freed, local gameplay suspended via
|
||||
/// <see cref="GameModeManager.SetPaused"/>). On the map the Disconnect button becomes "Back to Lobby" for the
|
||||
/// match authority (ends the match), while everyone else (in the lobby, or a non-authority client on the map)
|
||||
/// gets a plain disconnect. Only the visual <see cref="panelRoot"/> is toggled - this binder stays alive on
|
||||
/// its (always-active) canvas so it keeps reading Esc while the panel is hidden.
|
||||
/// </summary>
|
||||
public class OnlineSessionBrowserUI : MonoBehaviour
|
||||
{
|
||||
@@ -33,6 +44,11 @@ public class OnlineSessionBrowserUI : MonoBehaviour
|
||||
[Header("Status")]
|
||||
[SerializeField] private TMP_Text statusLabel;
|
||||
|
||||
[Header("Overlay")]
|
||||
[Tooltip("Visual container toggled by Esc while connected (the panel root). Must be a CHILD of this " +
|
||||
"binder's object so the binder keeps running - and reading Esc - while the panel is hidden.")]
|
||||
[SerializeField] private GameObject panelRoot;
|
||||
|
||||
[Tooltip("Background tint of the selected row.")]
|
||||
[SerializeField] private Color selectedTint = new Color(0.26f, 0.52f, 0.96f, 1f);
|
||||
[Tooltip("Background tint of an unselected row.")]
|
||||
@@ -42,10 +58,22 @@ public class OnlineSessionBrowserUI : MonoBehaviour
|
||||
private readonly List<Row> _rows = new List<Row>();
|
||||
private string _selectedId;
|
||||
|
||||
private MatchManager _match; // local match state (scene kind + authority); found at runtime
|
||||
private GameModeManager _gameMode; // pause hook for the modal overlay; found at runtime
|
||||
private TMP_Text _disconnectLabel; // disconnect button caption (relabelled to "Back to Lobby")
|
||||
|
||||
private bool _open; // Esc-toggled visibility while connected
|
||||
private bool _connected; // last-seen connection state (to detect transitions)
|
||||
private string _lastScene; // last-seen active scene name (to auto-close on a scene change)
|
||||
private string _disconnectText; // last applied caption (avoids per-frame TMP churn)
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// The template is the prototype, never shown itself - layout ignores it while disabled.
|
||||
if (entryTemplate) entryTemplate.SetActive(false);
|
||||
|
||||
_match = FindFirstObjectByType<MatchManager>();
|
||||
_gameMode = FindFirstObjectByType<GameModeManager>();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
@@ -53,7 +81,11 @@ public class OnlineSessionBrowserUI : MonoBehaviour
|
||||
if (hostButton) hostButton.onClick.AddListener(OnHost);
|
||||
if (refreshButton) refreshButton.onClick.AddListener(OnRefresh);
|
||||
if (joinButton) joinButton.onClick.AddListener(OnJoin);
|
||||
if (disconnectButton) disconnectButton.onClick.AddListener(OnDisconnect);
|
||||
if (disconnectButton)
|
||||
{
|
||||
disconnectButton.onClick.AddListener(OnDisconnect);
|
||||
_disconnectLabel = disconnectButton.GetComponentInChildren<TMP_Text>(true);
|
||||
}
|
||||
|
||||
if (manager)
|
||||
{
|
||||
@@ -61,8 +93,10 @@ public class OnlineSessionBrowserUI : MonoBehaviour
|
||||
manager.SessionsChanged += RebuildList;
|
||||
}
|
||||
|
||||
_connected = manager && manager.IsConnected;
|
||||
RebuildList();
|
||||
OnManagerChanged();
|
||||
ApplyVisibility();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
@@ -79,16 +113,92 @@ public class OnlineSessionBrowserUI : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!manager) return;
|
||||
bool connected = manager.IsConnected;
|
||||
|
||||
// Auto-close the overlay if the scene changed underneath it (a remote ended/started the match, or
|
||||
// we walked into Start Match) so it never lingers as a stale pause across a transition.
|
||||
string scene = SceneManager.GetActiveScene().name;
|
||||
if (connected && _open && _lastScene != null && scene != _lastScene)
|
||||
SetOpen(false);
|
||||
_lastScene = scene;
|
||||
|
||||
if (!connected) return; // Main: panel always shown, Esc ignored
|
||||
|
||||
bool inLobbyOrMap = _match && (_match.IsLocalSceneLobby || _match.IsLocalSceneMap);
|
||||
if (inLobbyOrMap && EscapePressed())
|
||||
SetOpen(!_open);
|
||||
|
||||
RefreshDisconnectLabel();
|
||||
}
|
||||
|
||||
private void OnHost() { if (manager) manager.Host(); }
|
||||
private void OnRefresh() { if (manager) manager.Refresh(); }
|
||||
private void OnJoin() { if (manager && !string.IsNullOrEmpty(_selectedId)) manager.Join(_selectedId); }
|
||||
private void OnDisconnect() { if (manager) manager.Disconnect(); }
|
||||
|
||||
private void OnDisconnect()
|
||||
{
|
||||
if (!manager) return;
|
||||
|
||||
// On the map, the match AUTHORITY's button means "Back to Lobby" (end the match for everyone)
|
||||
// rather than leaving the session. Everyone else - in the lobby, or a non-authority client on the
|
||||
// map - does a plain disconnect.
|
||||
if (_match && _match.IsLocalSceneMap && _match.IsLocalMatchAuthority)
|
||||
{
|
||||
_match.RequestEndMatch();
|
||||
SetOpen(false); // heading back to the lobby; close the overlay + resume input
|
||||
return;
|
||||
}
|
||||
|
||||
manager.Disconnect();
|
||||
}
|
||||
|
||||
private void OnManagerChanged()
|
||||
{
|
||||
if (!manager) return;
|
||||
|
||||
bool connected = manager.IsConnected;
|
||||
if (connected != _connected)
|
||||
{
|
||||
_connected = connected;
|
||||
// Connection up (hosted/joined) -> hide the panel; Esc reopens it in the lobby/map.
|
||||
// Back to Main (disconnect/shutdown) -> show it again and drop any pause.
|
||||
_open = false;
|
||||
if (!connected && _gameMode) _gameMode.SetPaused(false);
|
||||
ApplyVisibility();
|
||||
}
|
||||
|
||||
if (statusLabel) statusLabel.text = manager.Status;
|
||||
UpdateButtons();
|
||||
RefreshDisconnectLabel();
|
||||
}
|
||||
|
||||
private void SetOpen(bool open)
|
||||
{
|
||||
_open = open;
|
||||
ApplyVisibility();
|
||||
if (_gameMode) _gameMode.SetPaused(open);
|
||||
}
|
||||
|
||||
private void ApplyVisibility()
|
||||
{
|
||||
bool show = !(manager && manager.IsConnected) || _open;
|
||||
if (panelRoot && panelRoot.activeSelf != show)
|
||||
panelRoot.SetActive(show);
|
||||
}
|
||||
|
||||
private void RefreshDisconnectLabel()
|
||||
{
|
||||
if (!_disconnectLabel) return;
|
||||
bool backToLobby = _match && _match.IsLocalSceneMap && _match.IsLocalMatchAuthority;
|
||||
string text = backToLobby ? "Back to Lobby" : "Disconnect";
|
||||
if (text != _disconnectText)
|
||||
{
|
||||
_disconnectText = text;
|
||||
_disconnectLabel.text = text;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateButtons()
|
||||
@@ -165,4 +275,13 @@ public class OnlineSessionBrowserUI : MonoBehaviour
|
||||
var t = root.Find(childName);
|
||||
return t ? t.GetComponent<TMP_Text>() : null;
|
||||
}
|
||||
|
||||
private static bool EscapePressed()
|
||||
{
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
return Keyboard.current != null && Keyboard.current.escapeKey.wasPressedThisFrame;
|
||||
#else
|
||||
return Input.GetKeyDown(KeyCode.Escape);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user