#if ENABLE_INPUT_SYSTEM using UnityEngine.InputSystem; #endif namespace SRDebugger.UI.Controls { using System.Collections.Generic; using System.Collections.ObjectModel; using SRF; using UnityEngine; using UnityEngine.UI; public delegate void PinEntryControlCallback(IList result, bool didCancel); public class PinEntryControl : SRMonoBehaviourEx { private bool _isVisible = true; private List _numbers = new List(4); [RequiredField] public Image Background; public bool CanCancel = true; [RequiredField] public UnityEngine.UI.Button CancelButton; [RequiredField] public Text CancelButtonText; [RequiredField] public CanvasGroup CanvasGroup; [RequiredField] public Animator DotAnimator; public UnityEngine.UI.Button[] NumberButtons; public Toggle[] NumberDots; [RequiredField] public Text PromptText; public event PinEntryControlCallback Complete; protected override void Awake() { base.Awake(); for (var i = 0; i < NumberButtons.Length; i++) { var number = i; NumberButtons[i].onClick.AddListener(() => { PushNumber(number); }); } CancelButton.onClick.AddListener(CancelButtonPressed); RefreshState(); } protected override void OnEnable() { #if ENABLE_INPUT_SYSTEM Keyboard.current.onTextInput += HandleCharacter; #endif } protected override void OnDisable() { #if ENABLE_INPUT_SYSTEM Keyboard.current.onTextInput -= HandleCharacter; #endif } protected override void Update() { base.Update(); if (!_isVisible) { return; } #if ENABLE_INPUT_SYSTEM bool delete = Keyboard.current.deleteKey.wasPressedThisFrame || Keyboard.current.backspaceKey.wasPressedThisFrame; #else bool delete = (Input.GetKeyDown(KeyCode.Backspace) || Input.GetKeyDown(KeyCode.Delete)); #endif if (_numbers.Count > 0 && delete) { _numbers.PopLast(); RefreshState(); } #if !ENABLE_INPUT_SYSTEM var input = Input.inputString; for (var i = 0; i < input.Length; i++) { HandleCharacter(input[i]); } #endif } private void HandleCharacter(char i) { if (!_isVisible) { return; } if (!char.IsNumber(i)) { return; } var num = (int) char.GetNumericValue(i); if (num > 9 || num < 0) { return; } PushNumber(num); } public void Show() { CanvasGroup.alpha = 1f; CanvasGroup.blocksRaycasts = CanvasGroup.interactable = true; _isVisible = true; } public void Hide() { CanvasGroup.alpha = 0f; CanvasGroup.blocksRaycasts = CanvasGroup.interactable = false; _isVisible = false; } public void Clear() { _numbers.Clear(); RefreshState(); } public void PlayInvalidCodeAnimation() { DotAnimator.SetTrigger("Invalid"); } protected void OnComplete() { if (Complete != null) { Complete(new ReadOnlyCollection(_numbers), false); } } protected void OnCancel() { if (Complete != null) { Complete(new int[] {}, true); } } private void CancelButtonPressed() { if (_numbers.Count > 0) { _numbers.PopLast(); } else { OnCancel(); } RefreshState(); } public void PushNumber(int number) { if (_numbers.Count >= 4) { Debug.LogWarning("[PinEntry] Expected 4 numbers"); return; } _numbers.Add(number); if (_numbers.Count >= 4) { OnComplete(); } RefreshState(); } private void RefreshState() { for (var i = 0; i < NumberDots.Length; i++) { NumberDots[i].isOn = i < _numbers.Count; } if (_numbers.Count > 0) { CancelButtonText.text = "Delete"; } else { CancelButtonText.text = CanCancel ? "Cancel" : ""; } } } }