165 lines
5.7 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using DG.Tweening;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class RatingPanel : InfoPanel
{
[Header("Описание")]
[SerializeField] private RectTransform descriptionSign;
[SerializeField] private float descriptionOpenY, descriptionCloseY, descriptionDuration;
[Header("Топ рейтинга")]
[SerializeField] private GameObject _recordPrefab;
[SerializeField] private int _recordsCount = 3;
[SerializeField] private Vector2 _recordsSize = new(800f, 190f);
[SerializeField] private float _recordSpacing = 4f;
private RatingModal _modal;
private RectTransform _recordsRoot;
private const string DateFormat = "dd.MM.yy";
public override bool BlocksNavigation => _modal != null && _modal.IsOpen;
public override float closeDelay => (infoDuration + buttonDuration + descriptionDuration
- timeOffset * 3 + titleDuration)
/ closeSpeedMultiplier;
public override void Initialize()
{
}
public override void Interact()
{
if (_modal == null)
_modal = FindFirstObjectByType<RatingModal>(FindObjectsInactive.Include);
if (_modal == null)
{
Debug.LogWarning("Не найдено модальное окно рейтинга.");
return;
}
if (_modal.IsOpen)
{
_modal.Close();
return;
}
Canvas canvas = root.GetComponentInParent<Canvas>()?.rootCanvas;
_modal.Open(canvas != null ? canvas.transform : null);
}
public override void CloseModal()
{
_modal?.Close();
}
protected override void InitializeBeforeOpen()
{
BuildTopRecords();
}
protected override Sequence GetOpenSequence(float delay)
{
Sequence seq = DOTween.Sequence();
seq.AppendInterval(delay);
seq.Append(root.DOAnchorPos(Vector2.zero, titleDuration));
seq.Append(titleSign.DOAnchorPosY(titleOpenY, titleDuration));
float t = delay + titleDuration * 2;
seq.Insert(t, descriptionSign.DOAnchorPosY(descriptionOpenY, descriptionDuration));
seq.Insert(t, button.DOAnchorPosX(buttonOpenX, buttonDuration));
seq.Insert(t + buttonDuration - timeOffset, info.DOAnchorPosX(infoOpenX, infoDuration).SetEase(Ease.OutBack));
return seq;
}
protected override Sequence GetCloseSequence(Vector2 position)
{
Sequence seq = DOTween.Sequence();
float time = 0;
seq.Insert(time, info.DOAnchorPosX(infoCloseX, infoDuration));
time += infoDuration - timeOffset;
seq.Insert(time, button.DOAnchorPosX(buttonCloseX, buttonDuration));
time += buttonDuration - timeOffset;
seq.Insert(time, descriptionSign.DOAnchorPosY(descriptionCloseY, descriptionDuration));
time += descriptionDuration - timeOffset;
seq.Insert(time, titleSign.DOAnchorPosY(titleCloseY, titleDuration));
seq.Append(root.DOAnchorPos(position, titleDuration * 4));
seq.timeScale = closeSpeedMultiplier;
return seq;
}
private void BuildTopRecords()
{
_recordsRoot ??= transform.Find("Info/RecordsGroup") as RectTransform;
if (_recordsRoot == null || _recordPrefab == null)
{
Debug.LogWarning("Не настроен вывод топа рейтинга в главном меню.");
return;
}
ClearTopRecords();
_recordsRoot.sizeDelta = _recordsSize;
PlayerStatsService statsService = GameManager.Instance?.StatsService;
List<PlayerStatsRecord> records = statsService?.GetTopPlayers(_recordsCount)
?? new List<PlayerStatsRecord>();
RectTransform prefabRect = _recordPrefab.GetComponent<RectTransform>();
float prefabWidth = prefabRect != null ? prefabRect.rect.width : _recordsRoot.rect.width;
float prefabHeight = prefabRect != null ? prefabRect.rect.height : 66f;
float scale = prefabWidth > 0f ? _recordsRoot.rect.width / prefabWidth : 1f;
float rowHeight = prefabHeight * scale;
float rowStep = rowHeight + _recordSpacing;
float firstRowY = (records.Count - 1) * rowStep * 0.5f;
for (int i = 0; i < records.Count; i++)
{
RectTransform row = Instantiate(_recordPrefab, _recordsRoot).GetComponent<RectTransform>();
row.anchorMin = new Vector2(0.5f, 0.5f);
row.anchorMax = new Vector2(0.5f, 0.5f);
row.pivot = new Vector2(0.5f, 0.5f);
row.anchoredPosition = new Vector2(0f, firstRowY - i * rowStep);
row.localScale = Vector3.one * scale;
FillTopRecord(row, i + 1, records[i]);
}
}
private void ClearTopRecords()
{
for (int i = _recordsRoot.childCount - 1; i >= 0; i--)
{
GameObject child = _recordsRoot.GetChild(i).gameObject;
child.SetActive(false);
Destroy(child);
}
}
private void FillTopRecord(RectTransform row, int rank, PlayerStatsRecord record)
{
TextMeshProUGUI[] cells = row.GetComponentsInChildren<TextMeshProUGUI>(true);
if (cells.Length < 5)
return;
cells[0].text = rank.ToString();
cells[1].text = record.PlayerName;
cells[2].text = FormatTime(record.CompletionTimeSec);
cells[3].text = record.MovesCount.ToString();
cells[4].text = record.CompletedAt.ToString(DateFormat);
}
private string FormatTime(float seconds)
{
int totalSeconds = Mathf.Max(0, Mathf.RoundToInt(seconds));
return $"{totalSeconds / 60:D2}:{totalSeconds % 60:D2}";
}
}