Использовать полную иконку персонажа и крестик для пустого приза. Добавить звук переключения, указатели выбора и анимацию добавленных призов за 0,3 секунды. Скрывать экран настроек на время работы с конфигуратором призов. Восстановить ссылку на префаб добавленного приза и оформить контекстные окна по макетам. Устранить повторное подтверждение QR-приза и исправить направление вертикальной навигации витрины. Проверено в Unity в режиме игры: ввод и сохранение значений, добавление и удаление пяти типов призов, анимация выбора и защита от повторного добавления. Ошибок в консоли нет.
107 lines
3.6 KiB
C#
107 lines
3.6 KiB
C#
using PrizeSystem;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
public class PrizeView : MonoBehaviour
|
||
{
|
||
[SerializeField] private Image _image;
|
||
[SerializeField] private TextMeshProUGUI _label;
|
||
|
||
|
||
|
||
public Prize Prize;
|
||
|
||
public void SetPrize(Prize prize)
|
||
{
|
||
if (prize == null || prize is EmptyPrize)
|
||
{
|
||
_image.sprite = prize is EmptyPrize ? PrizeSystemManager.GetPrizeIcon(PrizeType.None) : null;
|
||
_label.text = GetPrizeText(prize);
|
||
Prize = prize;
|
||
return;
|
||
}
|
||
|
||
_image.sprite = PrizeSystemManager.GetPrizeIcon(prize.PrizeType);
|
||
_label.text = GetText(prize);
|
||
_label.rectTransform.sizeDelta = new Vector2(_label.preferredWidth, _label.rectTransform.sizeDelta.y);
|
||
Prize = prize;
|
||
}
|
||
|
||
public void Clear()
|
||
{
|
||
_image.sprite = null;
|
||
_label.text = "";
|
||
Prize = null;
|
||
}
|
||
|
||
private string GetText(Prize prize) => GetPrizeText(prize);
|
||
|
||
public static string GetPrizeText(Prize prize)
|
||
{
|
||
if (prize == null || prize is EmptyPrize)
|
||
{
|
||
return "Пусто";
|
||
}
|
||
else if (prize is CountablePrize cp)
|
||
{
|
||
return prize.PrizeType switch
|
||
{
|
||
PrizeType.Hopper => $"{cp.Amount} {Pluralize(cp.Amount, "маленький приз", "маленьких приза", "маленьких призов")}",
|
||
PrizeType.Ticket => $"{cp.Amount} {Pluralize(cp.Amount, "билет", "билета", "билетов")}",
|
||
PrizeType.Marbles => $"{cp.Amount} марблс",
|
||
_ => "Приз"
|
||
};
|
||
}
|
||
else if (prize is VitrinaPrize vp)
|
||
{
|
||
return $"Витрина ячейки: {string.Join(" | ", vp.Boxes)}";
|
||
}
|
||
else if (prize is QrPrize qp)
|
||
{
|
||
return $"QR: {qp.PrizeText}";
|
||
}
|
||
return "";
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Возвращает правильную форму существительного для русского языка в зависимости от числа
|
||
/// </summary>
|
||
/// <param name="count">Количество предметов</param>
|
||
/// <param name="form1">Форма для 1 (именительный падеж, ед.ч.): "яблоко"</param>
|
||
/// <param name="form2">Форма для 2-4 (родительный падеж, ед.ч.): "яблока"</param>
|
||
/// <param name="form3">Форма для 5+ (родительный падеж, мн.ч.): "яблок"</param>
|
||
/// <returns>Правильная форма существительного</returns>
|
||
public static string Pluralize(int count, string form1, string form2, string form3)
|
||
{
|
||
// Приводим число к положительному виду для корректной работы с остатками
|
||
int absCount = Mathf.Abs(count);
|
||
|
||
// Определяем остатки для проверки правил
|
||
long lastTwoDigits = absCount % 100;
|
||
long lastDigit = absCount % 10;
|
||
|
||
// Особый случай: числа от 11 до 19 всегда используют форму 3
|
||
if (lastTwoDigits >= 11 && lastTwoDigits <= 19)
|
||
{
|
||
return form3;
|
||
}
|
||
|
||
// Обычные правила склонения
|
||
switch (lastDigit)
|
||
{
|
||
case 1:
|
||
return form1;
|
||
case 2:
|
||
case 3:
|
||
case 4:
|
||
return form2;
|
||
default:
|
||
return form3;
|
||
}
|
||
}
|
||
}
|