using System; using UnityEngine; using UnityEngine.UI; using Vanguard.App; using Vanguard.State; namespace Vanguard.UI { /// /// Верхняя панель игрока, общая для Lobby и DeckBuilder: аватар-инициалы, /// ник, MMR, сезон, Rating/Community и гамбургер-меню. /// public sealed class PlayerTopBar : IDisposable { public const string RootName = "PlayerTopBar"; private const float Margin = 24f; private const float Height = 96f; private static readonly Color Border = new Color(0.18f, 0.49f, 1f, 0.55f); private static readonly Color BorderStrong = new Color(0.34f, 0.72f, 1f, 0.9f); private static readonly Color TextPrimary = new Color(0.88f, 0.93f, 1f); private static readonly Color TextMuted = new Color(0.58f, 0.69f, 0.88f); private static readonly Color TextDim = new Color(0.44f, 0.55f, 0.75f); private static readonly Color Accent = new Color(0.37f, 0.69f, 1f); private readonly PlayerState _player; private readonly HamburgerMenu _menu; private readonly RectTransform _root; private Text _avatar; private Text _playerName; private Text _mmr; private bool _disposed; public PlayerTopBar( Transform parent, AppConfig config, PlayerState player, Action onLoggedOut, Action onHistory, Action onRating, Action onCommunity, Action onLobby = null, Transform overlayParent = null) { _player = player; var top = Surface(parent, RootName, new Color(0.012f, 0.03f, 0.08f, 0.94f), 0); _root = top; top.anchorMin = new Vector2(0f, 1f); top.anchorMax = new Vector2(1f, 1f); top.pivot = new Vector2(0.5f, 1f); top.offsetMin = new Vector2(Margin, -Height); top.offsetMax = new Vector2(-Margin, 0f); var avatarRect = Surface( top, "Avatar", new Color(0.05f, 0.13f, 0.3f, 0.95f), 14); avatarRect.anchorMin = new Vector2(0f, 0.5f); avatarRect.anchorMax = new Vector2(0f, 0.5f); avatarRect.pivot = new Vector2(0f, 0.5f); avatarRect.sizeDelta = new Vector2(64f, 64f); avatarRect.anchoredPosition = new Vector2(20f, 0f); _avatar = UiKit.CreateText(avatarRect, "Initials", "?", 26, TextPrimary); _avatar.fontStyle = FontStyle.Bold; UiKit.Stretch(_avatar.rectTransform); UiKit.MakeLiteral(_avatar); _playerName = UiKit.CreateText( top, "PlayerName", "…", 22, TextPrimary, TextAnchor.MiddleLeft); _playerName.fontStyle = FontStyle.Bold; var nameRect = _playerName.rectTransform; nameRect.anchorMin = new Vector2(0f, 0.5f); nameRect.anchorMax = new Vector2(0f, 0.5f); nameRect.pivot = new Vector2(0f, 0.5f); nameRect.sizeDelta = new Vector2(420f, 30f); nameRect.anchoredPosition = new Vector2(104f, 14f); UiKit.MakeLiteral(_playerName); _mmr = UiKit.CreateText( top, "Mmr", string.Empty, 14, TextMuted, TextAnchor.MiddleLeft); var mmrRect = _mmr.rectTransform; mmrRect.anchorMin = new Vector2(0f, 0.5f); mmrRect.anchorMax = new Vector2(0f, 0.5f); mmrRect.pivot = new Vector2(0f, 0.5f); mmrRect.sizeDelta = new Vector2(460f, 22f); mmrRect.anchoredPosition = new Vector2(104f, -16f); UiKit.MakeLiteral(_mmr); var season = UiKit.CreateText( top, "Season", "Сезон — скоро", 14, TextDim, TextAnchor.MiddleCenter); var seasonRect = season.rectTransform; seasonRect.anchorMin = new Vector2(0.5f, 0.5f); seasonRect.anchorMax = new Vector2(0.5f, 0.5f); seasonRect.sizeDelta = new Vector2(280f, 30f); seasonRect.anchoredPosition = Vector2.zero; AddAction(top, "Rating", "Рейтинг", -312f, 180f, onRating, LobbyIcon.Chart); AddAction(top, "Community", "Сообщество", -96f, 200f, onCommunity, LobbyIcon.Friends); if (onLobby != null) AddAction(top, "ToLobby", "← В лобби", -508f, 160f, onLobby, null); _menu = new HamburgerMenu( top, config, onLoggedOut, onHistory, onLobby, "Меню", overlayParent); _player.Changed += UpdateTexts; Loc.LanguageChanged += UpdateTexts; UpdateTexts(); } public bool IsMenuOpen => _menu != null && _menu.IsOpen; public RectTransform Root => _root; public void CloseMenu() { if (_menu != null) _menu.Close(); } public void Dispose() { if (_disposed) return; _disposed = true; _player.Changed -= UpdateTexts; Loc.LanguageChanged -= UpdateTexts; } private void UpdateTexts() { if (_disposed) return; var name = string.IsNullOrEmpty(_player.UserName) ? "…" : _player.UserName; _playerName.text = name; _avatar.text = Initial(name); _mmr.text = "MMR " + _player.RankedMmr + " · " + Loc.Translate("матчей") + " " + _player.Matches + " · " + Loc.Translate("побед") + " " + WinsPercent(); } private string WinsPercent() { if (_player.Matches <= 0) return "0%"; return Mathf.RoundToInt(_player.Wins * 100f / _player.Matches) + "%"; } private static string Initial(string name) { foreach (var character in name) { if (char.IsLetterOrDigit(character)) return char.ToUpperInvariant(character).ToString(); } return "?"; } private static void AddAction( RectTransform parent, string name, string label, float rightOffset, float width, Action onClick, Action icon) { var buttonRect = Surface(parent, name, new Color(0.035f, 0.09f, 0.21f, 0.85f), 12); buttonRect.anchorMin = new Vector2(1f, 0.5f); buttonRect.anchorMax = new Vector2(1f, 0.5f); buttonRect.pivot = new Vector2(1f, 0.5f); buttonRect.sizeDelta = new Vector2(width, 52f); buttonRect.anchoredPosition = new Vector2(rightOffset, 0f); var image = buttonRect.GetComponent(); image.raycastTarget = true; var button = buttonRect.gameObject.AddComponent