using System; using UnityEngine; public class TextInput : MonoBehaviour, IControlable { public event Action OnComplete; [Header("Генерация")] [SerializeField] private LetterSlot _letterSlotPrefab; [SerializeField] private RectTransform _cellsRoot; [Header("Звуки")] [SerializeField] private AudioClip switchSlotSound; [SerializeField] private AudioClip switchLetterSound; [SerializeField] private AudioClip acceptSound; [SerializeField] private AudioClip openSound; [Header("Скорость переключения букв")] [SerializeField] private float MaxSpeedLetterPerSecond = 8; [SerializeField] private float MinSpeedLetterPerSecond = 3; [SerializeField] private float MaxSpeedTime = 3; [SerializeField] private float MinSpeedTime = 0.5f; private float switchButtonPressedTime = 0; private float letterSwitchSpeed = 0; private float switchDelayRest = 1; private int _slotIndex = 0; private LetterSlot[] _slots; private bool completionRequested = false; private bool completeUnpressed = false; public bool ControlsEnabled { get; set; } = true; private LetterSlot ActiveSlot => _slots[_slotIndex]; public void Initialize(int cellsAmount, string alphabet, string initialString = "") { Generate(cellsAmount, alphabet); InitializeSlots(initialString); } public void UpdateControls() { int dir_h = In.GetAxis(JoystickSide.Both, InteractMode.Discrete).x; SwitchSlot(dir_h); int dir_v = In.GetAxis(JoystickSide.Both, InteractMode.Continious).y; SwitchLetter(dir_v); if(In.GetAction(JoystickSide.Both, InteractMode.Continious) == false) completeUnpressed = true; completionRequested = In.GetAction(JoystickSide.Both, InteractMode.Continious); if (completionRequested && completeUnpressed) Complete(); } private void Complete() { string result = CollectText(); OnComplete?.Invoke(result); Destroy(gameObject); } private void Generate(int cellsAmount, string alphabet) { ClearCells(); _slots = new LetterSlot[cellsAmount]; for (int i = 0; i < cellsAmount; i++) { var cell = Instantiate(_letterSlotPrefab, _cellsRoot); cell.Init(alphabet[0], alphabet); _slots[i] = cell; } _slotIndex = 0; _slots[_slotIndex].SetSelected(true); } private void InitializeSlots(string initialString) { for (int i = 0; i < _slots.Length; i++) _slots[i].SetSymbol(0); if (string.IsNullOrEmpty(initialString)) return; int minLength = Mathf.Min(initialString.Length, _slots.Length); for (int i = 0; i < minLength; i++) _slots[i].SetSymbol(initialString[i]); } public void SwitchSlot(int dir) { if (dir == 0) return; ActiveSlot.SetSelected(false); _slotIndex = Mathf.Clamp(_slotIndex + dir, 0, _slots.Length); ActiveSlot.SetSelected(true); } public void SwitchLetter(int dir) { if (dir == 0) { switchDelayRest = 0; switchButtonPressedTime = 0; return; } if (switchDelayRest < 0) { ActiveSlot.ChangeSymbol(dir); recalculateRest(); } switchDelayRest -= Time.deltaTime; switchButtonPressedTime += Time.deltaTime; void recalculateRest() { float k = (MaxSpeedLetterPerSecond - MinSpeedLetterPerSecond) / (MaxSpeedTime - MinSpeedTime); float b = MinSpeedLetterPerSecond - k * MinSpeedTime; letterSwitchSpeed = k * switchButtonPressedTime + b; letterSwitchSpeed = Mathf.Clamp(letterSwitchSpeed, MinSpeedLetterPerSecond, MaxSpeedLetterPerSecond); switchDelayRest = 1 / letterSwitchSpeed; } } private void ClearCells() { for (int i = _cellsRoot.childCount - 1; i >= 0; i--) { var cell = _cellsRoot.GetChild(i).gameObject; Destroy(cell); } _slots = null; } public string CollectText() { System.Text.StringBuilder sb = new(); foreach (var slot in _slots) sb.Append(slot.Symbol); return sb.ToString().Trim(); } }