using System.Linq; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; namespace RR.Common.UI { /// /// Модальное окно выбора уровня. /// Наследуется от Modal для автоматического управления фокусом и блокировки фона. /// public class LevelSelectModal : Modal { [Header("Контент")] [SerializeField] private Transform content; // Grid parent [SerializeField] private LevelButton levelButtonPrefab; private readonly List _levelsPool = new(); /// /// Метод для открытия модального окна. /// Переопределяет базовый метод для сборки кнопок перед открытием. /// public override void Open() { BuildIfNeeded(); base.Open(); } // ==== ВНУТРЕННЕЕ ==== /// /// Метод для сборки кнопок уровней /// private void BuildIfNeeded() { // Очистим/пересоберём foreach (LevelButton b in _levelsPool.Where(b => b)) { Destroy(b.gameObject); } _levelsPool.Clear(); List levels = EnumerateLevelScenesInBuild() .OrderBy(e => e.world) .ThenBy(e => e.stage) .ToList(); foreach (LevelEntry _ in levels) { LevelButton btn = Instantiate(levelButtonPrefab, content); _levelsPool.Add(btn); } for (int index = 0; index < _levelsPool.Count; index++) { LevelButton btn = _levelsPool[index]; btn.Setup( $"{levels[index].world}-{levels[index].stage}", levels[index].world, levels[index].stage); switch (levels[index].world) { case 1: btn.SetColor(Color.green); break; case 2: btn.SetColor(Color.blue); break; } } } private struct LevelEntry { public int world; public int stage; } /// /// Метод для перебора уровней в игре /// /// LevelEntry - текущий мир при переборе private static IEnumerable EnumerateLevelScenesInBuild() { int n = SceneManager.sceneCountInBuildSettings; for (int i = 0; i < n; i++) { string path = SceneUtility.GetScenePathByBuildIndex(i); string sceneName = System.IO.Path.GetFileNameWithoutExtension(path); // фильтр "только уровни" по формату имени W-S: string[] parts = sceneName.Split('-'); if (parts.Length != 2) continue; if (!int.TryParse(parts[0], out int world)) continue; if (!int.TryParse(parts[1], out int stage)) continue; // Исключим служебные сцены if (sceneName.Equals("Level UI", System.StringComparison.OrdinalIgnoreCase)) continue; if (sceneName.Equals("MainMenu", System.StringComparison.OrdinalIgnoreCase)) continue; yield return new LevelEntry { world = world, stage = stage }; } } } }