VanguardReMaster/client/Assets/Vanguard/Runtime/UI/CollectionView.cs

319 lines
11 KiB
C#
Raw 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 System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using Vanguard.Api;
using Vanguard.Api.Contracts;
using Vanguard.Meta;
using Vanguard.State;
namespace Vanguard.UI
{
/// <summary>Коллекция игрока и разбор карт в пыль.</summary>
public sealed class CollectionView : IDisposable
{
private readonly MetaService _meta;
private readonly PlayerState _player;
private readonly Action _onBack;
private bool _disposed;
private readonly RectTransform _root;
private readonly Text _balances;
private readonly Text _status;
private readonly RectTransform _confirm;
private Text _confirmText;
private RectTransform _content;
private CollectionItemDto _pending;
private bool _loading;
public CollectionView(
Transform parent,
MetaService meta,
PlayerState player,
Action onBack)
{
_meta = meta;
_player = player;
_onBack = onBack;
_root = UiKit.CreatePanel(parent, "CollectionScreen", new Color(0.035f, 0.045f, 0.065f, 1f));
var top = UiKit.CreatePanel(_root, "TopBar", new Color(0.07f, 0.085f, 0.115f, 1f));
top.anchorMin = new Vector2(0f, 1f);
top.anchorMax = new Vector2(1f, 1f);
top.pivot = new Vector2(0.5f, 1f);
top.anchoredPosition = Vector2.zero;
top.sizeDelta = new Vector2(0f, 88f);
UiKit.AddHorizontalLayout(top, 22, 16);
var back = UiKit.CreateButton(top, "Back", "← Назад", () => _onBack(), 18);
UiKit.SetPreferredHeight(back, 44f, 0f);
var title = UiKit.CreateText(top, "Title", "Коллекция", 32, Color.white, TextAnchor.MiddleLeft);
title.fontStyle = FontStyle.Bold;
UiKit.SetPreferredHeight(title, 46f);
_balances = UiKit.CreateText(
top, "Balances", string.Empty, 18,
new Color(0.70f, 0.76f, 0.90f), TextAnchor.MiddleRight);
UiKit.SetPreferredHeight(_balances, 36f);
var body = UiKit.CreatePanel(_root, "Body", new Color(0.035f, 0.045f, 0.065f, 0f));
body.anchorMin = Vector2.zero;
body.anchorMax = Vector2.one;
body.offsetMin = new Vector2(40f, 28f);
body.offsetMax = new Vector2(-40f, -110f);
UiKit.AddVerticalLayout(body, 8, 10);
var hint = UiKit.CreateText(
body,
"Hint",
"Разбор даёт пыль: C 5 · R 10 · RR 25 · RRR 100. SP не разбирается.",
17,
new Color(0.58f, 0.65f, 0.78f),
TextAnchor.MiddleLeft);
UiKit.SetPreferredHeight(hint, 26f);
var scroll = UiKit.CreateScrollView(body, "CollectionScroll", out _content, 8f);
var scrollElement = scroll.gameObject.AddComponent<LayoutElement>();
scrollElement.flexibleHeight = 1f;
scrollElement.minHeight = 200f;
_status = UiKit.CreateText(
body, "Status", string.Empty, 18,
new Color(0.62f, 0.68f, 0.82f), TextAnchor.MiddleLeft);
UiKit.SetPreferredHeight(_status, 34f);
_confirm = BuildConfirm(parent);
_confirm.gameObject.SetActive(false);
_root.gameObject.SetActive(false);
_player.Changed += OnPlayerChanged;
}
public void Show()
{
UiKit.SetActive(_root, true);
_confirm.gameObject.SetActive(false);
OnPlayerChanged();
_ = LoadAsync();
}
public void Hide()
{
UiKit.SetActive(_root, false);
_confirm.gameObject.SetActive(false);
}
public void Dispose()
{
if (_disposed)
return;
_disposed = true;
_player.Changed -= OnPlayerChanged;
}
private RectTransform BuildConfirm(Transform parent)
{
var overlay = UiKit.CreatePanel(parent, "DismantleConfirm", new Color(0f, 0f, 0f, 0.72f));
var card = UiKit.CreateCenteredCard(
overlay, "ConfirmCard", new Vector2(620f, 300f),
new Color(0.08f, 0.10f, 0.14f, 1f));
UiKit.AddVerticalLayout(card, 30, 12);
var title = UiKit.CreateText(card, "Title", "Разобрать карту?", 28, Color.white);
title.fontStyle = FontStyle.Bold;
UiKit.SetPreferredHeight(title, 42f);
_confirmText = UiKit.CreateText(
card, "Text", string.Empty, 19,
new Color(0.72f, 0.78f, 0.92f),
TextAnchor.MiddleCenter);
UiKit.SetPreferredHeight(_confirmText, 110f);
var yes = UiKit.CreateButton(card, "Yes", "Разобрать", OnConfirmDismantle, 20);
UiKit.SetPreferredHeight(yes, 48f);
var no = UiKit.CreateButton(card, "No", "Отмена", HideConfirm, 20);
UiKit.SetPreferredHeight(no, 44f);
overlay.gameObject.SetActive(false);
return overlay;
}
private async Task LoadAsync()
{
if (_loading)
return;
_loading = true;
SetStatus("Загружаем коллекцию…", new Color(0.62f, 0.68f, 0.82f));
try
{
var collection = await _meta.GetCollectionAsync();
if (_disposed)
return;
Rebuild(collection.Items ?? new List<CollectionItemDto>());
SetStatus(
collection.Items == null || collection.Items.Count == 0
? "Коллекция пуста. Пройдите онбординг."
: "Карт в коллекции: " + collection.Items.Sum(item => item.Count) + ".",
new Color(0.62f, 0.68f, 0.82f));
}
catch (ApiException exception)
{
SetStatus(exception.Message, new Color(1f, 0.55f, 0.45f));
}
catch (Exception exception)
{
Debug.LogException(exception);
SetStatus("Не удалось загрузить коллекцию.", new Color(1f, 0.55f, 0.45f));
}
finally
{
_loading = false;
}
}
private void Rebuild(IReadOnlyList<CollectionItemDto> items)
{
for (var i = _content.childCount - 1; i >= 0; i--)
UnityEngine.Object.Destroy(_content.GetChild(i).gameObject);
if (items.Count == 0)
return;
foreach (var item in items)
AddRow(item);
}
private void AddRow(CollectionItemDto item)
{
var row = UiKit.CreatePanel(_content, "Item_" + item.PrintingId, new Color(0.07f, 0.085f, 0.115f, 1f));
var rowElement = row.gameObject.AddComponent<LayoutElement>();
rowElement.preferredHeight = 64f;
UiKit.AddHorizontalLayout(row, 10, 10);
var name = UiKit.CreateText(
row, "Name", item.NameEn, 19, Color.white, TextAnchor.MiddleLeft);
var nameElement = name.gameObject.AddComponent<LayoutElement>();
nameElement.flexibleWidth = 1f;
nameElement.preferredHeight = 40f;
var printing = UiKit.CreateText(
row, "Printing", item.PrintingId, 16,
new Color(0.58f, 0.65f, 0.78f), TextAnchor.MiddleLeft);
var printingElement = printing.gameObject.AddComponent<LayoutElement>();
printingElement.preferredWidth = 190f;
printingElement.preferredHeight = 40f;
var rarity = UiKit.CreateText(
row, "Rarity", item.Rarity, 17,
new Color(0.78f, 0.82f, 0.95f));
var rarityElement = rarity.gameObject.AddComponent<LayoutElement>();
rarityElement.preferredWidth = 64f;
rarityElement.preferredHeight = 40f;
var count = UiKit.CreateText(
row, "Count", "×" + item.Count, 18,
new Color(0.78f, 0.82f, 0.95f));
var countElement = count.gameObject.AddComponent<LayoutElement>();
countElement.preferredWidth = 54f;
countElement.preferredHeight = 40f;
var canDismantle = item.Rarity != "SP" && item.Count > 0;
var dismantle = UiKit.CreateButton(
row,
"Dismantle",
canDismantle ? "Разобрать 1" : "SP",
() => ShowConfirm(item),
16);
dismantle.interactable = canDismantle;
var dismantleElement = dismantle.gameObject.AddComponent<LayoutElement>();
dismantleElement.preferredWidth = 150f;
dismantleElement.preferredHeight = 44f;
dismantleElement.flexibleWidth = 0f;
}
private void ShowConfirm(CollectionItemDto item)
{
_pending = item;
_confirmText.text = "«" + item.NameEn + "» (" + item.PrintingId + ")\n"
+ "Вы получите " + DustFor(item.Rarity) + " пыли. Осталось: " + item.Count + ".";
_confirm.SetAsLastSibling();
_confirm.gameObject.SetActive(true);
}
private void HideConfirm()
{
_pending = null;
_confirm.gameObject.SetActive(false);
}
private async void OnConfirmDismantle()
{
if (_pending == null)
return;
var item = _pending;
_confirm.gameObject.SetActive(false);
SetStatus("Разбираем " + item.PrintingId + "…", new Color(0.62f, 0.68f, 0.82f));
try
{
await _meta.DismantleAsync(item.PrintingId, 1);
SetStatus("Разобрано: " + item.PrintingId + ".", new Color(0.45f, 0.85f, 0.55f));
await LoadAsync();
}
catch (ApiException exception)
{
SetStatus(exception.Message, new Color(1f, 0.55f, 0.45f));
}
catch (Exception exception)
{
Debug.LogException(exception);
SetStatus("Не удалось разобрать карту.", new Color(1f, 0.55f, 0.45f));
}
finally
{
_pending = null;
}
}
private static int DustFor(string rarity)
{
switch (rarity)
{
case "C": return 5;
case "R": return 10;
case "RR": return 25;
case "RRR": return 100;
default: return 0;
}
}
private void OnPlayerChanged()
{
if (_disposed || _balances == null)
return;
_balances.text = "Gold " + _player.Gold + " · Пыль " + _player.Dust
+ " · Токены " + _player.Tokens;
}
private void SetStatus(string text, Color color)
{
if (_disposed || _status == null)
return;
_status.text = text ?? string.Empty;
_status.color = color;
}
}
}