Использовать полную иконку персонажа и крестик для пустого приза. Добавить звук переключения, указатели выбора и анимацию добавленных призов за 0,3 секунды. Скрывать экран настроек на время работы с конфигуратором призов. Восстановить ссылку на префаб добавленного приза и оформить контекстные окна по макетам. Устранить повторное подтверждение QR-приза и исправить направление вертикальной навигации витрины. Проверено в Unity в режиме игры: ввод и сохранение значений, добавление и удаление пяти типов призов, анимация выбора и защита от повторного добавления. Ошибок в консоли нет.
134 lines
5.3 KiB
C#
134 lines
5.3 KiB
C#
using DG.Tweening;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
public sealed class AddedPrizeButton : PrizeButton
|
|
{
|
|
private const float TransitionDuration = 0.3f;
|
|
|
|
[SerializeField] private PrizeButton _notSelectedTemplate;
|
|
[SerializeField] private PrizeButton _selectedTemplate;
|
|
|
|
private RectTransform _buttonRect;
|
|
private RectTransform _backgroundRect;
|
|
private Image _backgroundImage;
|
|
private RectTransform _iconRect;
|
|
private RectTransform _labelRect;
|
|
private RectTransform _pointerRect;
|
|
private Image _pointerImage;
|
|
private Image _deleteSignImage;
|
|
private VisualState _notSelectedState;
|
|
private VisualState _selectedState;
|
|
private Sequence _selectionTween;
|
|
private bool _isSelected;
|
|
|
|
private struct VisualState
|
|
{
|
|
public Vector2 ButtonSize;
|
|
public Vector2 BackgroundPosition;
|
|
public Vector2 BackgroundSize;
|
|
public Color BackgroundColor;
|
|
public Vector2 IconPosition;
|
|
public Vector2 IconSize;
|
|
public Vector2 LabelPosition;
|
|
public Vector2 LabelSize;
|
|
public Vector2 PointerPosition;
|
|
public TextWrappingModes TextWrappingMode;
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
_buttonRect = (RectTransform)transform;
|
|
_backgroundRect = (RectTransform)transform.Find("bg");
|
|
_backgroundImage = _backgroundRect.GetComponent<Image>();
|
|
_iconRect = (RectTransform)_image.transform;
|
|
_labelRect = _textMeshPro.rectTransform;
|
|
_pointerRect = (RectTransform)transform.Find("pointer");
|
|
_pointerImage = _pointerRect.GetComponent<Image>();
|
|
_deleteSignImage = transform.Find("delete sign").GetComponent<Image>();
|
|
|
|
_notSelectedState = ReadState(_notSelectedTemplate);
|
|
_selectedState = ReadState(_selectedTemplate);
|
|
_deleteSignImage.raycastTarget = false;
|
|
ApplyState(_notSelectedState);
|
|
SetAlpha(_pointerImage, 0f);
|
|
SetAlpha(_deleteSignImage, 0f);
|
|
}
|
|
|
|
public override void SetSelected(bool selected)
|
|
{
|
|
if (_isSelected == selected)
|
|
return;
|
|
|
|
_isSelected = selected;
|
|
_selectionTween?.Kill();
|
|
VisualState state = selected ? _selectedState : _notSelectedState;
|
|
|
|
_selectionTween = DOTween.Sequence().SetUpdate(true);
|
|
_selectionTween.Join(_buttonRect.DOSizeDelta(state.ButtonSize, TransitionDuration));
|
|
_selectionTween.Join(_backgroundRect.DOAnchorPos(state.BackgroundPosition, TransitionDuration));
|
|
_selectionTween.Join(_backgroundRect.DOSizeDelta(state.BackgroundSize, TransitionDuration));
|
|
_selectionTween.Join(_backgroundImage.DOColor(state.BackgroundColor, TransitionDuration));
|
|
_selectionTween.Join(_iconRect.DOAnchorPos(state.IconPosition, TransitionDuration));
|
|
_selectionTween.Join(_iconRect.DOSizeDelta(state.IconSize, TransitionDuration));
|
|
_selectionTween.Join(_labelRect.DOAnchorPos(state.LabelPosition, TransitionDuration));
|
|
_selectionTween.Join(_labelRect.DOSizeDelta(state.LabelSize, TransitionDuration));
|
|
_selectionTween.Join(_pointerRect.DOAnchorPos(state.PointerPosition, TransitionDuration));
|
|
_selectionTween.Join(_pointerImage.DOFade(selected ? 1f : 0f, TransitionDuration));
|
|
_selectionTween.Join(_deleteSignImage.DOFade(selected ? 1f : 0f, TransitionDuration));
|
|
_selectionTween.InsertCallback(TransitionDuration * 0.5f,
|
|
() => _textMeshPro.textWrappingMode = state.TextWrappingMode);
|
|
_selectionTween.Play();
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
_selectionTween?.Kill();
|
|
}
|
|
|
|
private void ApplyState(VisualState state)
|
|
{
|
|
_buttonRect.sizeDelta = state.ButtonSize;
|
|
_backgroundRect.anchoredPosition = state.BackgroundPosition;
|
|
_backgroundRect.sizeDelta = state.BackgroundSize;
|
|
_backgroundImage.color = state.BackgroundColor;
|
|
_iconRect.anchoredPosition = state.IconPosition;
|
|
_iconRect.sizeDelta = state.IconSize;
|
|
_labelRect.anchoredPosition = state.LabelPosition;
|
|
_labelRect.sizeDelta = state.LabelSize;
|
|
_pointerRect.anchoredPosition = state.PointerPosition;
|
|
_textMeshPro.textWrappingMode = state.TextWrappingMode;
|
|
}
|
|
|
|
private static VisualState ReadState(PrizeButton template)
|
|
{
|
|
Transform root = template.transform;
|
|
RectTransform background = (RectTransform)root.Find("bg");
|
|
RectTransform icon = (RectTransform)root.Find("prizeIcon");
|
|
RectTransform label = (RectTransform)root.Find("Text (TMP)");
|
|
RectTransform pointer = (RectTransform)root.Find("pointer");
|
|
|
|
return new VisualState
|
|
{
|
|
ButtonSize = ((RectTransform)root).sizeDelta,
|
|
BackgroundPosition = background.anchoredPosition,
|
|
BackgroundSize = background.sizeDelta,
|
|
BackgroundColor = background.GetComponent<Image>().color,
|
|
IconPosition = icon.anchoredPosition,
|
|
IconSize = icon.sizeDelta,
|
|
LabelPosition = label.anchoredPosition,
|
|
LabelSize = label.sizeDelta,
|
|
PointerPosition = pointer.anchoredPosition,
|
|
TextWrappingMode = label.GetComponent<TextMeshProUGUI>().textWrappingMode
|
|
};
|
|
}
|
|
|
|
private static void SetAlpha(Image image, float alpha)
|
|
{
|
|
Color color = image.color;
|
|
color.a = alpha;
|
|
image.color = color;
|
|
}
|
|
}
|