253 lines
6.9 KiB
C#
253 lines
6.9 KiB
C#
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;
|
||
|
||
[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();
|
||
}
|
||
|
||
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);
|
||
|
||
exitRequested = exitTimer >= _timeToExit;
|
||
}
|
||
|
||
private void Exit()
|
||
{
|
||
SaveAndClose();
|
||
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;
|
||
}
|
||
|
||
}
|