Danro/Assets/Scripts/UI/LevelSelectModal.cs
Danil Iarosh 2f2d100eae feat(inputs): remove obsolete COM input system and update dependencies
- Removed deprecated ButtonPinMapping enum and related COM input classes- Updated ComInputToInputSystemAdapter with improved binding logic- Refactored GameManager to use new globals prefab path
- Enhanced GameEndUIController with event system focus management
- Modified Globals prefab to use pin-based input bindings
- Cleaned up obsolete COM system wrapper and native wrapper classes
- Adjusted input adapter to support pin bindings over action bindings
- Updated manufacturer name in virtual gamepad description
2025-11-04 17:06:51 +03:00

139 lines
5.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
namespace RR.Common.UI
{
public class LevelSelectModal : MonoBehaviour
{
[Header("Управление")]
[SerializeField] private InputActionReference close;
[Header("UI")]
[SerializeField] private CanvasGroup canvasGroup;
[SerializeField] private Transform content; // Grid parent
[SerializeField] private LevelButton levelButtonPrefab;
[SerializeField] private Button closeButton;
[SerializeField] private float fadeDuration = 0.15f;
private readonly List<LevelButton> _levelsPool = new();
void Awake()
{
if (closeButton) closeButton.onClick.AddListener(Close);
gameObject.SetActive(false);
}
// ==== ПУБЛИЧНЫЙ API ====
/// <summary>
/// Метод для открытия модального окна
/// </summary>
public void Open()
{
BuildIfNeeded();
gameObject.SetActive(true);
StopAllCoroutines();
StartCoroutine(Fade(0f, 1f, fadeDuration));
}
/// <summary>
/// Метод для закрытия модального окна
/// </summary>
private void Close()
{
StopAllCoroutines();
StartCoroutine(Fade(1f, 0f, fadeDuration, () => gameObject.SetActive(false)));
}
// ==== ВНУТРЕННЕЕ ====
/// <summary>
/// Метод для сборки кнопок уровней
/// </summary>
void BuildIfNeeded()
{
// Очистим/пересоберём
foreach (var b in _levelsPool) if (b) Destroy(b.gameObject);
_levelsPool.Clear();
var levels = EnumerateLevelScenesInBuild()
.OrderBy(e => e.world)
.ThenBy(e => e.stage)
.ToList();
foreach (var lv in levels)
{
var btn = Instantiate(levelButtonPrefab, content);
btn.Setup(lv.name, lv.world, lv.stage);
if (lv.world == 1) btn.SetColor(Color.green);
else if (lv.world == 2) btn.SetColor(Color.blue);
_levelsPool.Add(btn);
}
}
struct LevelEntry { public string name; public int world; public int stage; }
/// <summary>
/// Метод для перебора уровней в игре
/// </summary>
/// <returns>LevelEntry - текущий мир при переборе</returns>
IEnumerable<LevelEntry> EnumerateLevelScenesInBuild()
{
int n = SceneManager.sceneCountInBuildSettings;
for (int i = 0; i < n; i++)
{
string path = SceneUtility.GetScenePathByBuildIndex(i);
string buttonName = System.IO.Path.GetFileNameWithoutExtension(path);
// фильтр "только уровни" по формату имени W-S:
var parts = buttonName.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 (buttonName.Equals("Level UI", System.StringComparison.OrdinalIgnoreCase)) continue;
if (buttonName.Equals("MainMenu", System.StringComparison.OrdinalIgnoreCase)) continue;
yield return new LevelEntry { name = buttonName, world = world, stage = stage };
}
}
/// <summary>
/// Метод для плавного перехода (затухания)
/// </summary>
/// <param name="from">Начальная прозрачность</param>
/// <param name="to">Конечная прозрачнеость</param>
/// <param name="time">Время перехода</param>
/// <param name="onDone">Действие при выполнении перехода</param>
IEnumerator Fade(float from, float to, float time, System.Action onDone = null)
{
if (!canvasGroup) { onDone?.Invoke(); yield break; }
float t = 0f;
canvasGroup.alpha = from;
canvasGroup.blocksRaycasts = true;
while (t < time)
{
t += Time.unscaledDeltaTime;
canvasGroup.alpha = Mathf.Lerp(from, to, t / time);
yield return null;
}
canvasGroup.alpha = to;
canvasGroup.blocksRaycasts = to > 0.99f;
onDone?.Invoke();
}
void Update()
{
// ESC закрыть
if (gameObject.activeSelf && close.action.WasPressedThisFrame())
Close();
}
}
}