257 lines
7.1 KiB
C#
Raw Permalink 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;
using System.Collections.Generic;
using UnityEngine;
public class TextInput : MonoBehaviour, ICompletable
{
[Header("Генерация")]
[SerializeField] private GameObject _letterSlotPrefab;
[SerializeField] private RectTransform _group;
[Header("Управление")]
[SerializeField] private InSignal _nextSlot;
[SerializeField] private InSignal _prevSlot;
[SerializeField] private InSignal _nextSymbol;
[SerializeField] private InSignal _prevSymbol;
[SerializeField] private List<InSignal> _exitSignals;
[SerializeField] private float _timeToExit = 2;
[SerializeField] private Instruction exitDisplay;
[Header("Ключ prefs")]
[SerializeField] private string key;
[SerializeField] private bool loadData;
[SerializeField] private bool saveDataOnClose;
[Header("Настройки генерации поля")]
[SerializeField] private int slotsCount = 11;
[Header("Звуки")]
[SerializeField] private AudioClip switchSlotSound;
[SerializeField] private AudioClip switchLetterSound;
[SerializeField] private AudioClip acceptSound;
[SerializeField] private AudioClip openSound;
[Header("Алфавит")]
[SerializeField] private string alphabetString = "0123456789";
[Header("Скорость переключения букв")]
[SerializeField] private float MaxSpeedLetterPerSecond = 8;
[SerializeField] private float MinSpeedLetterPerSecond = 3;
[SerializeField] private float MaxSpeedTime = 3;
[SerializeField] private float MinSpeedTime = 0.5f;
[SerializeField]
private float switchButtonPressedTime = 0;
private float letterSwitchSpeed = 0;
private float switchDelayRest = 1;
private int _slotIndex = 0;
private float exitTimer = 0;
private LetterSlot[] _slots;
public event Action OnComplete;
private LetterSlot _activeSlot => _slots[_slotIndex];
private bool exitRequested = false;
private bool ready;
public void Initialize()
{
Generate();
LoadSavedData();
exitDisplay.Init();
}
private void OnEnable()
{
ready = false;
}
private void Update()//условия завершения добавить
{
if (!ready)
{
ready = !(In.GetButton(_nextSlot) || In.GetButton(_prevSlot) || In.GetButton(_nextSymbol) || In.GetButton(_prevSymbol));
return;
}
if (exitRequested)
{
exitTimer = 0;
exitRequested = false;
Exit();
return;
}
int dir = 0;
if (In.GetButtonDown(_nextSlot)) dir += 1;
if (In.GetButtonDown(_prevSlot)) dir -= 1;
SwitchSlot(dir);
dir = 0;
if (In.GetButton(_nextSymbol)) dir += 1;
if (In.GetButton(_prevSymbol)) dir -= 1;
SwitchLetter(dir);
if (ExitCombinationPressed())
{
exitTimer += Time.deltaTime;
}
else
{
exitTimer -= Time.deltaTime;
}
exitTimer = Mathf.Clamp(exitTimer, 0f, _timeToExit);
exitDisplay?.SetProgress(exitTimer / _timeToExit);
exitRequested = exitTimer >= _timeToExit;
}
private void Exit()
{
SaveAndClose();
exitDisplay?.SetProgress(0);
OnComplete?.Invoke();
gameObject.SetActive(false);
}
public string SaveAndClose()
{
string result = GetText();
if (!string.IsNullOrEmpty(key) && saveDataOnClose)
{
PlayerPrefs.SetString(key, result);
}
Clear();
return result;
}
private void Generate()
{
_slots = new LetterSlot[slotsCount];
for (int i = 0; i < slotsCount; i++)
{
var go = Instantiate(_letterSlotPrefab.gameObject, _group);
_slots[i] = go.GetComponent<LetterSlot>();
_slots[i].Init(alphabetString[0], false);
}
_slotIndex = 0;
_slots[0].SetSelected(true);
}
private void LoadSavedData()//Тут надо проработать
{
string data = "";
if (loadData)
data = PlayerPrefs.GetString(key, "");
// Очищаем все слоты
for (int i = 0; i < slotsCount; i++)
{
_slots[i].SetSymbol(alphabetString[0]);
}
if (!string.IsNullOrEmpty(data))
{
int minLength = Mathf.Min(data.Length, slotsCount);
for (int i = 0; i < minLength; i++)
{
_slots[i].SetSymbol(data[i]);
}
}
}
public void SwitchSlot(int discreteDirection)
{
if (discreteDirection == 0) return;
_activeSlot.SetSelected(false);
ChangeIndexBounded(ref _slotIndex, delta: discreteDirection, length: slotsCount);
_activeSlot.SetSelected(true);
}
public void SwitchLetter(int continiousDirection)
{
continiousDirection = Mathf.Clamp(continiousDirection, -1, 1);
if (continiousDirection == 0)//сброс переключения
{
switchDelayRest = 0;
switchButtonPressedTime = 0;
return;
}
if (switchDelayRest < 0)
{
//переключение
int currentLetterindex = getSymbolIndex(_activeSlot.GetSymbol(), alphabetString);
ChangeIndexLooped(ref currentLetterindex, delta: continiousDirection, alphabetString.Length);
_activeSlot.SetSymbol(alphabetString[currentLetterindex]);
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;
}
int getSymbolIndex(char symbol, string alphabet) => alphabet.IndexOf(symbol);
}
public void Clear()
{
foreach (var slot in _slots)
{
Destroy(slot.gameObject);
}
_slots = null;
}
public string GetText()
{
System.Text.StringBuilder sb = new();
foreach (var slot in _slots)
sb.Append(slot.GetSymbol());
return sb.ToString().Trim();
}
private
static void ChangeIndexLooped(ref int index, int delta, int length)
=> index = (index + delta + length) % length;
static void ChangeIndexBounded(ref int index, int delta, int length)
=> index = Mathf.Clamp(index + delta, 0, length - 1);
private bool ExitCombinationPressed()
{
foreach (var signal in _exitSignals)
{
if (In.GetButton(signal) == false)
return false;
}
return true;
}
}