Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
- Добавлен Editor-скрипт SpriteAssetGenerator для автоматической генерации TMP Sprite Asset'ов из текстур призов. - Сгенерированы TMP Sprite Asset'ы (Prize, Prize_Hopper, Prize_Marbles, Prize_QR, Prize_Tickets) в папке Assets/Resources/Sprite Assets. - Настроены FaceInfo и вертикальное центрирование спрайтов относительно текста. - Обновлен RulesPrizeListPage.cs: вместо текстовых названий призов выводятся соответствующие пиктограммы с помощью тегов <sprite>. - Добавлены новые файлы текстур призов и их мета-файлы в коммит.
197 lines
7.0 KiB
C#
197 lines
7.0 KiB
C#
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
using RR.Common.Managers;
|
|
using RR.Common.Prizes;
|
|
|
|
namespace RR.Common.UI
|
|
{
|
|
/// <summary>
|
|
/// Страница правил, которая динамически выводит призы за уровни из настроек призовой системы.
|
|
/// Повесьте компонент на GameObject страницы и назначьте TMP_Text либо оставьте поле пустым,
|
|
/// чтобы компонент нашёл первый TMP_Text в дочерних объектах.
|
|
/// </summary>
|
|
[DisallowMultipleComponent]
|
|
public sealed class RulesPrizeListPage : MonoBehaviour
|
|
{
|
|
[Header("Text")]
|
|
[SerializeField] private TMP_Text targetText;
|
|
|
|
[Header("Content")]
|
|
[SerializeField] private string title = "Призы за уровни";
|
|
[SerializeField] private string emptyPrizeText = "без приза";
|
|
[SerializeField] private string noLevelsText = "Уровни не найдены.";
|
|
[SerializeField] private string unavailableText = "Настройки призов недоступны.";
|
|
[SerializeField] private bool showTitle = true;
|
|
[SerializeField] private bool showLevelsWithoutPrize = true;
|
|
|
|
[Header("Levels")]
|
|
[SerializeField] private bool includeOnlyLevelsFolder = true;
|
|
[SerializeField] private string levelsFolderName = "Levels";
|
|
[SerializeField] private List<string> ignoredSceneNames = new() { "MainMenu", "Level UI" };
|
|
|
|
private void Awake()
|
|
{
|
|
ResolveText();
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
Refresh();
|
|
}
|
|
|
|
[ContextMenu("Refresh Prize List")]
|
|
public void Refresh()
|
|
{
|
|
ResolveText();
|
|
if (targetText == null)
|
|
{
|
|
Debug.LogWarning($"[{nameof(RulesPrizeListPage)}] TMP_Text не найден на странице правил.", this);
|
|
return;
|
|
}
|
|
|
|
PrizeSystemManager manager = PrizeSystemManager.Instance;
|
|
PrizeDatabase database = manager != null ? manager.Database : null;
|
|
if (database == null)
|
|
{
|
|
targetText.text = unavailableText;
|
|
return;
|
|
}
|
|
|
|
List<string> levels = GetLevelSceneNames();
|
|
if (levels.Count == 0)
|
|
{
|
|
levels.AddRange(database.GetAll().Keys);
|
|
levels.Sort();
|
|
}
|
|
|
|
if (levels.Count == 0)
|
|
{
|
|
targetText.text = noLevelsText;
|
|
return;
|
|
}
|
|
|
|
StringBuilder builder = new();
|
|
if (showTitle && !string.IsNullOrWhiteSpace(title))
|
|
{
|
|
builder.AppendLine(title);
|
|
builder.AppendLine();
|
|
}
|
|
|
|
for (int i = 0; i < levels.Count; i++)
|
|
{
|
|
string levelName = levels[i];
|
|
LevelPrizeConfig config = database.GetConfig(levelName);
|
|
|
|
if (!showLevelsWithoutPrize && (config == null || config.type == PrizeType.None))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
builder.Append(levelName);
|
|
builder.Append(" — ");
|
|
builder.Append(BuildPrizeText(manager, config));
|
|
|
|
if (i < levels.Count - 1)
|
|
{
|
|
builder.AppendLine();
|
|
}
|
|
}
|
|
|
|
string result = builder.ToString().TrimEnd();
|
|
targetText.text = string.IsNullOrWhiteSpace(result) ? noLevelsText : result;
|
|
}
|
|
|
|
private void ResolveText()
|
|
{
|
|
if (targetText == null)
|
|
{
|
|
targetText = GetComponent<TMP_Text>();
|
|
}
|
|
|
|
if (targetText == null)
|
|
{
|
|
targetText = GetComponentInChildren<TMP_Text>(true);
|
|
}
|
|
}
|
|
|
|
private List<string> GetLevelSceneNames()
|
|
{
|
|
List<string> result = new();
|
|
int sceneCount = SceneManager.sceneCountInBuildSettings;
|
|
|
|
for (int i = 0; i < sceneCount; i++)
|
|
{
|
|
string scenePath = SceneUtility.GetScenePathByBuildIndex(i);
|
|
if (string.IsNullOrWhiteSpace(scenePath))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
string normalizedPath = scenePath.Replace("\\", "/");
|
|
if (includeOnlyLevelsFolder)
|
|
{
|
|
string folderToken = $"/{levelsFolderName}/";
|
|
if (!normalizedPath.Contains(folderToken))
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
string sceneName = Path.GetFileNameWithoutExtension(scenePath);
|
|
if (ignoredSceneNames != null && ignoredSceneNames.Contains(sceneName))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
result.Add(sceneName);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private string BuildPrizeText(PrizeSystemManager manager, LevelPrizeConfig config)
|
|
{
|
|
if (config == null || config.type == PrizeType.None)
|
|
{
|
|
return emptyPrizeText;
|
|
}
|
|
|
|
return config.type switch
|
|
{
|
|
PrizeType.QRCode => BuildQrPrizeSpriteText(manager, config.qrTier),
|
|
PrizeType.Hopper => $"<sprite=\"Prize_Hopper\" name=\"Prize_Hopper_0\"> x{Mathf.Max(1, config.hopperCapsuleCount)}",
|
|
PrizeType.PrizeStand => BuildPrizeStandSpriteText(manager),
|
|
_ => config.type.ToString()
|
|
};
|
|
}
|
|
|
|
private static string BuildQrPrizeSpriteText(PrizeSystemManager manager, QRTier tier)
|
|
{
|
|
string prizeText = manager != null ? manager.GetQRCodeModalPrizeText(tier) : string.Empty;
|
|
bool isTicket = !string.IsNullOrEmpty(prizeText) &&
|
|
(prizeText.IndexOf("билет", System.StringComparison.OrdinalIgnoreCase) >= 0 ||
|
|
prizeText.IndexOf("ticket", System.StringComparison.OrdinalIgnoreCase) >= 0);
|
|
|
|
string spriteTag = isTicket
|
|
? "<sprite=\"Prize_Tickets\" name=\"Prize_Tickets_0\">"
|
|
: "<sprite=\"Prize_QR\" name=\"Prize_QR_0\">";
|
|
|
|
return string.IsNullOrWhiteSpace(prizeText)
|
|
? spriteTag
|
|
: $"{spriteTag} {prizeText.Trim()}";
|
|
}
|
|
|
|
private static string BuildPrizeStandSpriteText(PrizeSystemManager manager)
|
|
{
|
|
string spriteTag = "<sprite=\"Prize_Marbles\" name=\"Prize_Marbles_0\">";
|
|
PrizeStandSettings settings = manager != null ? manager.GetPrizeStandSettings() : null;
|
|
int boxCount = settings?.boxes != null ? settings.boxes.Count : 0;
|
|
return boxCount > 0 ? $"{spriteTag} (ячеек: {boxCount})" : spriteTag;
|
|
}
|
|
}
|
|
}
|