Complete Match Results modal: standalone overlay, auto-open on resolution
MatchResultScreen becomes a self-contained modal (IsOpen/Open/Close, _panelRoot, pause handling); resolution auto-open moves there from the session browser. OverviewMenu integrates it into the Esc chain and hides the Match Results button until results exist (same pattern as the role-scoped mode buttons). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
fdb562bba5
commit
7669ae1b66
3 files changed
+101
-28
No files matched your search
@@ -1,18 +1,28 @@
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
/// <summary>
|
||||
/// Binds the match scoreboard section inside the pause/session panel (Online Session Manager) to the
|
||||
/// result rows <see cref="MatchManager"/> replicates: LIVE while a match runs (roster from Hide start,
|
||||
/// re-sent on every hit / mid-match leave; winner still None -> pending hiders read "Hiding") and frozen
|
||||
/// with the winner banner when Seek ends (the browser UI auto-opens the panel then). The section root is
|
||||
/// hidden while no result data exists (Main / lobby). Rows are pooled clones of the disabled row
|
||||
/// template, rebuilt only when a new result version arrives (<see cref="MatchManager.ResultVersion"/>).
|
||||
/// The standalone match results menu (modal pause overlay, same pattern as
|
||||
/// <see cref="OnlineSessionBrowserUI"/>): opened via the overview menu's Match Results button
|
||||
/// (<see cref="Open"/>), auto-opened when the Resolution sub-phase begins, closed by Esc through
|
||||
/// <see cref="OverviewMenu"/> (all Esc handling lives there). Binds the scoreboard to the result rows
|
||||
/// <see cref="MatchManager"/> replicates: LIVE while a match runs (roster from Hide start, re-sent on
|
||||
/// every hit / mid-match leave; winner still None -> pending hiders read "Hiding") and frozen with the
|
||||
/// winner banner when Seek ends. Rows are pooled clones of the disabled row template, rebuilt only when
|
||||
/// a new result version arrives (<see cref="MatchManager.ResultVersion"/>). Only the visual
|
||||
/// <see cref="_panelRoot"/> is toggled - this binder stays alive on its (always-active) object so it
|
||||
/// keeps tracking match state while the panel is hidden.
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class MatchResultScreen : MonoBehaviour
|
||||
{
|
||||
[Header("Overlay")]
|
||||
[Tooltip("Visual container toggled via Open/Close. Must be a CHILD of this binder's object so the " +
|
||||
"binder keeps tracking match state while the panel is hidden.")]
|
||||
[SerializeField] private GameObject _panelRoot;
|
||||
|
||||
[Tooltip("Big winner banner (\"Hunters win!\" / \"Hiders win!\").")]
|
||||
[SerializeField] private TMP_Text _winnerText;
|
||||
|
||||
@@ -38,6 +48,11 @@ public class MatchResultScreen : MonoBehaviour
|
||||
private readonly List<Row> _rows = new List<Row>();
|
||||
private int _boundVersion = -1;
|
||||
|
||||
private GameModeManager _gameMode; // pause hook for the modal overlay; found at runtime
|
||||
private bool _open; // overlay visibility (toggled via Open/Close)
|
||||
private Scene _lastScene; // last-seen active scene (to auto-close on a scene change)
|
||||
private MatchManager.MatchSubPhase _lastSubPhase; // last-seen sub-phase (auto-open on Resolution)
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
bool templateOk = _rowTemplate && FindText(_rowTemplate, "Name") && FindText(_rowTemplate, "Outcome") &&
|
||||
@@ -49,16 +64,65 @@ public class MatchResultScreen : MonoBehaviour
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_gameMode = FindFirstObjectByType<GameModeManager>();
|
||||
if (_panelRoot) _panelRoot.SetActive(false);
|
||||
}
|
||||
|
||||
/// <summary>True while the modal overlay is open. The overview menu yields Esc to this overlay
|
||||
/// (close-only) while it is open.</summary>
|
||||
public bool IsOpen => _open;
|
||||
|
||||
/// <summary>True once any result data exists (LIVE mid-match roster or the frozen final scoreboard) -
|
||||
/// there is nothing to show before the first Hide phase.</summary>
|
||||
public bool HasResults => MatchManager.Instance && MatchManager.Instance.LocalResults.Count > 0;
|
||||
|
||||
/// <summary>Opens the modal overlay (used by the overview menu's Match Results button); false while
|
||||
/// no result data exists, so the caller can drop the pause instead of stranding it.</summary>
|
||||
public bool Open()
|
||||
{
|
||||
if (!enabled || !HasResults) return false;
|
||||
SetOpen(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Closes the modal overlay and resumes gameplay (Esc handling in <see cref="OverviewMenu"/>).</summary>
|
||||
public void Close() => SetOpen(false);
|
||||
|
||||
private void SetOpen(bool open)
|
||||
{
|
||||
_open = open;
|
||||
if (_panelRoot) _panelRoot.SetActive(open);
|
||||
if (_gameMode) _gameMode.SetPaused(open);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// Auto-close if the scene changed underneath the open overlay (match ended -> lobby swap, or a
|
||||
// remote started the match) so it never lingers as a stale pause across a transition.
|
||||
Scene scene = SceneManager.GetActiveScene();
|
||||
if (_open && _lastScene.IsValid() && scene != _lastScene)
|
||||
SetOpen(false);
|
||||
_lastScene = scene;
|
||||
|
||||
var match = MatchManager.Instance;
|
||||
bool hasResults = match && match.LocalResults.Count > 0;
|
||||
|
||||
// Resolution just began -> auto-open so the final scoreboard is presented (this used to live on
|
||||
// the session browser while the scoreboard was a section of its panel). Esc can still close it.
|
||||
MatchManager.MatchSubPhase subPhase = match ? match.LocalSubPhase : MatchManager.MatchSubPhase.None;
|
||||
if (subPhase != _lastSubPhase)
|
||||
{
|
||||
_lastSubPhase = subPhase;
|
||||
if (subPhase == MatchManager.MatchSubPhase.Resolution && !_open && hasResults)
|
||||
SetOpen(true);
|
||||
}
|
||||
|
||||
if (_content && _content.activeSelf != hasResults) _content.SetActive(hasResults);
|
||||
if (!hasResults)
|
||||
{
|
||||
_boundVersion = -1;
|
||||
if (_open) SetOpen(false); // data vanished (disconnect) -> don't linger as an empty pause
|
||||
return;
|
||||
}
|
||||
if (_boundVersion != match.ResultVersion) Bind(match);
|
||||
|
||||
@@ -13,9 +13,7 @@ using UnityEngine.UI;
|
||||
/// lobby/map the overview (Esc) menu reopens it via <see cref="Open"/> as a modal pause overlay
|
||||
/// (cursor freed, gameplay suspended via <see cref="GameModeManager.SetPaused"/>) - all Esc key
|
||||
/// handling lives in <see cref="OverviewMenu"/>, which closes this overlay through <see cref="Close"/>.
|
||||
/// It also auto-opens when the Resolution sub-phase begins so
|
||||
/// the final match scoreboard (a section of this panel) is presented. The Disconnect button is
|
||||
/// context-sensitive: in Main it is an
|
||||
/// The Disconnect button is context-sensitive: in Main it is an
|
||||
/// application "Exit"; on the map it becomes "Back to Lobby" for the match authority (ends the match);
|
||||
/// everyone else gets a plain disconnect. Only the visual <see cref="panelRoot"/> is toggled - this binder
|
||||
/// stays alive on its (always-active) canvas so it keeps tracking state while the panel is hidden.
|
||||
@@ -61,7 +59,6 @@ public class OnlineSessionBrowserUI : MonoBehaviour
|
||||
private bool _connected; // last-seen connection state (to detect transitions)
|
||||
private Scene _lastScene; // last-seen active scene (to auto-close on a scene change)
|
||||
private string _disconnectText; // last applied caption (avoids per-frame TMP churn)
|
||||
private MatchManager.MatchSubPhase _lastSubPhase; // last-seen sub-phase (auto-open on Resolution)
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
@@ -124,16 +121,6 @@ public class OnlineSessionBrowserUI : MonoBehaviour
|
||||
|
||||
if (!connected) return; // Main: panel always shown
|
||||
|
||||
// Resolution just began -> auto-open the overlay so the final scoreboard is presented. Esc can
|
||||
// still close it (via the overview menu); the lobby scene swap afterwards auto-closes it (see above).
|
||||
MatchManager.MatchSubPhase subPhase = _match ? _match.LocalSubPhase : MatchManager.MatchSubPhase.None;
|
||||
if (subPhase != _lastSubPhase)
|
||||
{
|
||||
_lastSubPhase = subPhase;
|
||||
if (subPhase == MatchManager.MatchSubPhase.Resolution && !_open)
|
||||
SetOpen(true);
|
||||
}
|
||||
|
||||
RefreshDisconnectLabel();
|
||||
}
|
||||
|
||||
@@ -202,7 +189,6 @@ public class OnlineSessionBrowserUI : MonoBehaviour
|
||||
// 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;
|
||||
_lastSubPhase = MatchManager.MatchSubPhase.None; // rejoining into Resolution must re-trigger
|
||||
if (!connected && _gameMode) _gameMode.SetPaused(false);
|
||||
ApplyVisibility();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user