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 { /// /// Страница правил, которая динамически выводит призы за уровни из настроек призовой системы. /// Повесьте компонент на GameObject страницы и назначьте TMP_Text либо оставьте поле пустым, /// чтобы компонент нашёл первый TMP_Text в дочерних объектах. /// [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 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 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(); } if (targetText == null) { targetText = GetComponentInChildren(true); } } private List GetLevelSceneNames() { List 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 => $" 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 ? "" : ""; return string.IsNullOrWhiteSpace(prizeText) ? spriteTag : $"{spriteTag} {prizeText.Trim()}"; } private static string BuildPrizeStandSpriteText(PrizeSystemManager manager) { string spriteTag = ""; PrizeStandSettings settings = manager != null ? manager.GetPrizeStandSettings() : null; int boxCount = settings?.boxes != null ? settings.boxes.Count : 0; return boxCount > 0 ? $"{spriteTag} (ячеек: {boxCount})" : spriteTag; } } }