105 lines
3.8 KiB
C#
105 lines
3.8 KiB
C#
using System.Linq;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using UnityEngine.SceneManagement;
|
||
|
||
namespace RR.Common.UI
|
||
{
|
||
/// <summary>
|
||
/// Модальное окно выбора уровня.
|
||
/// Наследуется от Modal для автоматического управления фокусом и блокировки фона.
|
||
/// </summary>
|
||
public class LevelSelectModal : Modal
|
||
{
|
||
[Header("Контент")]
|
||
[SerializeField] private Transform content; // Grid parent
|
||
[SerializeField] private LevelButton levelButtonPrefab;
|
||
|
||
private readonly List<LevelButton> _levelsPool = new();
|
||
|
||
/// <summary>
|
||
/// Метод для открытия модального окна.
|
||
/// Переопределяет базовый метод для сборки кнопок перед открытием.
|
||
/// </summary>
|
||
public override void Open()
|
||
{
|
||
BuildIfNeeded();
|
||
base.Open();
|
||
}
|
||
|
||
// ==== ВНУТРЕННЕЕ ====
|
||
/// <summary>
|
||
/// Метод для сборки кнопок уровней
|
||
/// </summary>
|
||
private void BuildIfNeeded()
|
||
{
|
||
// Очистим/пересоберём
|
||
foreach (LevelButton b in _levelsPool.Where(b => b))
|
||
{
|
||
Destroy(b.gameObject);
|
||
}
|
||
|
||
_levelsPool.Clear();
|
||
|
||
List<LevelEntry> 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; }
|
||
|
||
/// <summary>
|
||
/// Метод для перебора уровней в игре
|
||
/// </summary>
|
||
/// <returns>LevelEntry - текущий мир при переборе</returns>
|
||
private static IEnumerable<LevelEntry> 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 };
|
||
}
|
||
}
|
||
}
|
||
}
|