298 lines
9.3 KiB
C#
298 lines
9.3 KiB
C#
using System.Collections;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
using UnityEngine.InputSystem;
|
||
|
||
/// <summary>
|
||
/// Терминал лифта: ввод 4-значного кода доступа для перехода на 2-й уровень.
|
||
/// </summary>
|
||
public class ElevatorKeypadUI : MonoBehaviour
|
||
{
|
||
private static ElevatorKeypadUI _instance;
|
||
public static ElevatorKeypadUI Instance
|
||
{
|
||
get
|
||
{
|
||
if (_instance == null)
|
||
{
|
||
_instance = Object.FindAnyObjectByType<ElevatorKeypadUI>(FindObjectsInactive.Include);
|
||
}
|
||
return _instance;
|
||
}
|
||
}
|
||
|
||
[Header("Корневая панель")]
|
||
[SerializeField] private GameObject keypadPanelRoot;
|
||
|
||
[Header("Слоты для отображения цифр")]
|
||
[SerializeField] private Text[] digitSlots = new Text[4];
|
||
[SerializeField] private Image[] digitSlotBorders = new Image[4];
|
||
|
||
[Header("Статусная строка")]
|
||
[SerializeField] private Text statusText;
|
||
|
||
[Header("Кнопки клавиатуры")]
|
||
[SerializeField] private Button[] numberButtons; // 0..9
|
||
[SerializeField] private Button clearButton;
|
||
[SerializeField] private Button enterButton;
|
||
[SerializeField] private Button exitButton;
|
||
|
||
[Header("Цвета статуса")]
|
||
public Color normalStatusColor = new Color(1.0f, 0.85f, 0.1f, 1.0f);
|
||
public Color errorStatusColor = new Color(1.0f, 0.25f, 0.25f, 1.0f);
|
||
public Color successStatusColor = new Color(0.2f, 1.0f, 0.4f, 1.0f);
|
||
|
||
private string enteredCode = "";
|
||
private bool isOpen = false;
|
||
private bool isLockedSuccess = false;
|
||
|
||
public bool IsOpen => isOpen;
|
||
|
||
private void Awake()
|
||
{
|
||
_instance = this;
|
||
if (keypadPanelRoot == null)
|
||
keypadPanelRoot = gameObject;
|
||
|
||
SetupButtons();
|
||
}
|
||
|
||
private void SetupButtons()
|
||
{
|
||
if (numberButtons != null)
|
||
{
|
||
for (int i = 0; i < numberButtons.Length; i++)
|
||
{
|
||
int num = i;
|
||
if (numberButtons[i] != null)
|
||
{
|
||
numberButtons[i].onClick.RemoveAllListeners();
|
||
numberButtons[i].onClick.AddListener(() => OnNumberPressed(num));
|
||
}
|
||
}
|
||
}
|
||
|
||
if (clearButton != null)
|
||
{
|
||
clearButton.onClick.RemoveAllListeners();
|
||
clearButton.onClick.AddListener(OnClearPressed);
|
||
}
|
||
|
||
if (enterButton != null)
|
||
{
|
||
enterButton.onClick.RemoveAllListeners();
|
||
enterButton.onClick.AddListener(OnEnterPressed);
|
||
}
|
||
|
||
if (exitButton != null)
|
||
{
|
||
exitButton.onClick.RemoveAllListeners();
|
||
exitButton.onClick.AddListener(CloseKeypad);
|
||
}
|
||
}
|
||
|
||
private int openFrame = -1;
|
||
|
||
private void Update()
|
||
{
|
||
if (!isOpen) return;
|
||
if (Time.frameCount == openFrame) return;
|
||
|
||
HandleKeyboardInput();
|
||
}
|
||
|
||
private void HandleKeyboardInput()
|
||
{
|
||
var keyboard = Keyboard.current;
|
||
if (keyboard != null)
|
||
{
|
||
if (keyboard.escapeKey.wasPressedThisFrame)
|
||
{
|
||
CloseKeypad();
|
||
return;
|
||
}
|
||
|
||
if (!isLockedSuccess)
|
||
{
|
||
if (keyboard.digit0Key.wasPressedThisFrame || keyboard.numpad0Key.wasPressedThisFrame) OnNumberPressed(0);
|
||
else if (keyboard.digit1Key.wasPressedThisFrame || keyboard.numpad1Key.wasPressedThisFrame) OnNumberPressed(1);
|
||
else if (keyboard.digit2Key.wasPressedThisFrame || keyboard.numpad2Key.wasPressedThisFrame) OnNumberPressed(2);
|
||
else if (keyboard.digit3Key.wasPressedThisFrame || keyboard.numpad3Key.wasPressedThisFrame) OnNumberPressed(3);
|
||
else if (keyboard.digit4Key.wasPressedThisFrame || keyboard.numpad4Key.wasPressedThisFrame) OnNumberPressed(4);
|
||
else if (keyboard.digit5Key.wasPressedThisFrame || keyboard.numpad5Key.wasPressedThisFrame) OnNumberPressed(5);
|
||
else if (keyboard.digit6Key.wasPressedThisFrame || keyboard.numpad6Key.wasPressedThisFrame) OnNumberPressed(6);
|
||
else if (keyboard.digit7Key.wasPressedThisFrame || keyboard.numpad7Key.wasPressedThisFrame) OnNumberPressed(7);
|
||
else if (keyboard.digit8Key.wasPressedThisFrame || keyboard.numpad8Key.wasPressedThisFrame) OnNumberPressed(8);
|
||
else if (keyboard.digit9Key.wasPressedThisFrame || keyboard.numpad9Key.wasPressedThisFrame) OnNumberPressed(9);
|
||
|
||
if (keyboard.backspaceKey.wasPressedThisFrame || keyboard.deleteKey.wasPressedThisFrame || keyboard.cKey.wasPressedThisFrame)
|
||
{
|
||
OnBackspacePressed();
|
||
}
|
||
|
||
if (keyboard.enterKey.wasPressedThisFrame || keyboard.numpadEnterKey.wasPressedThisFrame)
|
||
{
|
||
OnEnterPressed();
|
||
}
|
||
}
|
||
}
|
||
|
||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||
if (Input.GetKeyDown(KeyCode.Escape))
|
||
{
|
||
CloseKeypad();
|
||
return;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
public void OpenKeypad()
|
||
{
|
||
openFrame = Time.frameCount;
|
||
|
||
if (!gameObject.activeSelf) gameObject.SetActive(true);
|
||
if (keypadPanelRoot != null && !keypadPanelRoot.activeSelf)
|
||
keypadPanelRoot.SetActive(true);
|
||
|
||
isOpen = true;
|
||
Time.timeScale = 0f;
|
||
Cursor.lockState = CursorLockMode.None;
|
||
Cursor.visible = true;
|
||
|
||
enteredCode = "";
|
||
UpdateDisplay();
|
||
SetStatus("ВВЕДИТЕ 4-ЗНАЧНЫЙ КОД ДОСТУПА", normalStatusColor);
|
||
|
||
GameAudioSynthesizer.PlayKeypadBeep();
|
||
}
|
||
|
||
public void CloseKeypad()
|
||
{
|
||
if (!isOpen) return;
|
||
|
||
isOpen = false;
|
||
if (keypadPanelRoot != null)
|
||
keypadPanelRoot.SetActive(false);
|
||
|
||
Time.timeScale = 1f;
|
||
Cursor.lockState = CursorLockMode.Locked;
|
||
Cursor.visible = false;
|
||
|
||
GameAudioSynthesizer.PlayKeypadClear();
|
||
}
|
||
|
||
public void OnNumberPressed(int number)
|
||
{
|
||
if (isLockedSuccess) return;
|
||
|
||
if (enteredCode.Length < 4)
|
||
{
|
||
enteredCode += number.ToString();
|
||
GameAudioSynthesizer.PlayKeypadBeep();
|
||
UpdateDisplay();
|
||
|
||
if (enteredCode.Length == 4)
|
||
{
|
||
SetStatus("НАЖМИТЕ [ВВОД / ENTER] ДЛЯ ПРОВЕРКИ", normalStatusColor);
|
||
}
|
||
}
|
||
}
|
||
|
||
public void OnBackspacePressed()
|
||
{
|
||
if (isLockedSuccess) return;
|
||
|
||
if (enteredCode.Length > 0)
|
||
{
|
||
enteredCode = enteredCode.Substring(0, enteredCode.Length - 1);
|
||
GameAudioSynthesizer.PlayKeypadClear();
|
||
UpdateDisplay();
|
||
SetStatus("ВВЕДИТЕ 4-ЗНАЧНЫЙ КОД ДОСТУПА", normalStatusColor);
|
||
}
|
||
}
|
||
|
||
public void OnClearPressed()
|
||
{
|
||
if (isLockedSuccess) return;
|
||
|
||
enteredCode = "";
|
||
GameAudioSynthesizer.PlayKeypadClear();
|
||
UpdateDisplay();
|
||
SetStatus("КОД СБРОШЕН. ВВЕДИТЕ ЗАНОВО", normalStatusColor);
|
||
}
|
||
|
||
public void OnEnterPressed()
|
||
{
|
||
if (isLockedSuccess) return;
|
||
|
||
if (enteredCode.Length != 4)
|
||
{
|
||
SetStatus("ОШИБКА: ТРЕБУЕТСЯ 4 ЦИФРЫ!", errorStatusColor);
|
||
GameAudioSynthesizer.PlayErrorCode();
|
||
return;
|
||
}
|
||
|
||
if (LevelCodeManager.Instance != null && LevelCodeManager.Instance.ValidateCode(enteredCode))
|
||
{
|
||
isLockedSuccess = true;
|
||
SetStatus("ДОСТУП РАЗРЕШЕН! ЗАПУСК ЛИФТА НА УРОВЕНЬ 2...", successStatusColor);
|
||
GameAudioSynthesizer.PlaySuccessChime();
|
||
StartCoroutine(RoutineSuccessTransition());
|
||
}
|
||
else
|
||
{
|
||
SetStatus("ОТКАЗ В ДОСТУПЕ! НЕВЕРНЫЙ КОД", errorStatusColor);
|
||
GameAudioSynthesizer.PlayErrorCode();
|
||
StartCoroutine(RoutineWrongCodeShake());
|
||
}
|
||
}
|
||
|
||
private IEnumerator RoutineWrongCodeShake()
|
||
{
|
||
yield return new WaitForSecondsRealtime(0.8f);
|
||
enteredCode = "";
|
||
UpdateDisplay();
|
||
SetStatus("ВВЕДИТЕ 4-ЗНАЧНЫЙ КОД ДОСТУПА", normalStatusColor);
|
||
}
|
||
|
||
private IEnumerator RoutineSuccessTransition()
|
||
{
|
||
yield return new WaitForSecondsRealtime(1.8f);
|
||
CloseKeypad();
|
||
|
||
if (LevelSuccessUI.Instance != null)
|
||
{
|
||
LevelSuccessUI.Instance.ShowSuccessScreen();
|
||
}
|
||
}
|
||
|
||
private void UpdateDisplay()
|
||
{
|
||
for (int i = 0; i < 4; i++)
|
||
{
|
||
if (digitSlots != null && i < digitSlots.Length && digitSlots[i] != null)
|
||
{
|
||
if (i < enteredCode.Length)
|
||
{
|
||
digitSlots[i].text = enteredCode[i].ToString();
|
||
digitSlots[i].color = new Color(1.0f, 0.85f, 0.1f, 1.0f);
|
||
}
|
||
else
|
||
{
|
||
digitSlots[i].text = "_";
|
||
digitSlots[i].color = new Color(0.4f, 0.4f, 0.4f, 0.7f);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void SetStatus(string text, Color color)
|
||
{
|
||
if (statusText != null)
|
||
{
|
||
statusText.text = text;
|
||
statusText.color = color;
|
||
}
|
||
}
|
||
}
|