using System.Collections; using UnityEngine; using UnityEngine.UI; using UnityEngine.InputSystem; /// /// Терминал лифта: ввод 4-значного кода доступа для перехода на 2-й уровень. /// public class ElevatorKeypadUI : MonoBehaviour { private static ElevatorKeypadUI _instance; public static ElevatorKeypadUI Instance { get { if (_instance == null) { _instance = Object.FindAnyObjectByType(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() { SetStatus("ДОСТУП РАЗРЕШЕН! СПУСК НА УРОВЕНЬ 2...", successStatusColor); yield return new WaitForSecondsRealtime(1.2f); if (LevelSuccessUI.Instance != null) { LevelSuccessUI.Instance.ShowSuccessScreen(); } yield return new WaitForSecondsRealtime(1.2f); Time.timeScale = 1f; UnityEngine.SceneManagement.SceneManager.LoadScene("Level2"); } 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; } } }