diff --git a/Assets/Scripts/OpenTS2/UI/Skia/SkiaInputField.cs b/Assets/Scripts/OpenTS2/UI/Skia/SkiaInputField.cs index 92943b19..278b4375 100644 --- a/Assets/Scripts/OpenTS2/UI/Skia/SkiaInputField.cs +++ b/Assets/Scripts/OpenTS2/UI/Skia/SkiaInputField.cs @@ -17,8 +17,9 @@ public class SkiaInputField : Selectable [SerializeField] private SkiaLabel _label; - [SerializeField] private int _selectedCharacter = 0; + private float _caretTimer = 0f; + private float CaretTime => WinUtils.GetCaretBlinkTimer(); private void Update() { @@ -26,30 +27,100 @@ private void Update() SelectedUpdate(); } - private void SelectedUpdate() + private void OnGUI() { - if (Input.GetKeyDown(KeyCode.LeftArrow)) - MoveCaretLeft(); - if (Input.GetKeyDown(KeyCode.RightArrow)) - MoveCaretRight(); + SelectedGUIUpdate(); + } - if (Input.GetKeyDown(KeyCode.Backspace)) + private void SelectedGUIUpdate() + { + var currentInput = ""; + var currentKey = KeyCode.None; + var ev = Event.current; + if (ev.type != EventType.KeyDown) return; + if (ev.isKey) { - if (_selectedCharacter >= 0) + if (ev.character != 0 && ev.character != '\t') { - var strBuilder = new StringBuilder(_label.Text); - strBuilder.Remove(_selectedCharacter, 1); - _label.Text = strBuilder.ToString(); - MoveCaretLeft(); + currentInput = ev.character.ToString(); } + currentKey = ev.keyCode; } + switch (currentKey) + { + case KeyCode.LeftArrow: + MoveCaretLeft(); + break; + + case KeyCode.RightArrow: + MoveCaretRight(); + break; + + case KeyCode.Backspace: + Backspace(); + break; + } + + if (currentInput != "") + { + TypeCharacter(currentInput); + } + ev.Use(); + } + + private void SelectedUpdate() + { ValidateSelection(); UpdateCaretPosition(); + DoCaretAnimation(); + } + + private void DoCaretAnimation() + { + var caretTime = CaretTime; + _caretTimer += Time.deltaTime; + if (_caretTimer > CaretTime * 2f) + { + _caretTimer = 0f; + } + + if (_caretTimer > caretTime) + { + if (_caret.gameObject.activeSelf) + _caret.gameObject.SetActive(false); + } + else + { + if (!_caret.gameObject.activeSelf) + _caret.gameObject.SetActive(true); + } + } + + private void TypeCharacter(string character) + { + _caretTimer = 0f; + var strBuilder = new StringBuilder(_label.Text); + var pointInsertion = _selectedCharacter + 1; + strBuilder.Insert(pointInsertion, character); + _label.Text = strBuilder.ToString(); + MoveCaretRight(); + } + + private void Backspace() + { + if (_selectedCharacter >= 0) + { + var strBuilder = new StringBuilder(_label.Text); + strBuilder.Remove(_selectedCharacter, 1); + _label.Text = strBuilder.ToString(); + MoveCaretLeft(); + } } private void MoveCaretLeft() { + _caretTimer = 0f; _selectedCharacter--; if (_selectedCharacter < -1) { @@ -59,6 +130,7 @@ private void MoveCaretLeft() private void MoveCaretRight() { + _caretTimer = 0f; _selectedCharacter++; if (_selectedCharacter >= _label.Text.Length) _selectedCharacter = _label.Text.Length - 1; @@ -69,7 +141,8 @@ private void UpdateCaretPosition() _caret.sizeDelta = new Vector2(1, _label.FontSize + ((_label.LineSpacing - 1f) * _label.FontSize)); if (_selectedCharacter < 0) { - _caret.anchoredPosition = new Vector2(0f, 0f); + var firstLineY = -_label.GetLineY(0) + _label.FontSize; + _caret.anchoredPosition = new Vector2(0f, firstLineY); return; } var rect = _label.GetCharacterRect(_selectedCharacter); diff --git a/Assets/Scripts/OpenTS2/UI/Skia/SkiaLabel.cs b/Assets/Scripts/OpenTS2/UI/Skia/SkiaLabel.cs index 65883a93..88b54c5b 100644 --- a/Assets/Scripts/OpenTS2/UI/Skia/SkiaLabel.cs +++ b/Assets/Scripts/OpenTS2/UI/Skia/SkiaLabel.cs @@ -468,23 +468,17 @@ private void ParseText(SKImageInfo imageInfo) { var lineAtLastWord = new TextLine(textAtLastWord, lastLineIndex, lastWordIndex - 1); lines.Add(lineAtLastWord); - var nextWordSearchStart = lastWordIndex; lastLineIndex = lastWordIndex; lastWordIndex = -1; - for (var n = nextWordSearchStart; n < text.Length; n++) - { - if (text[n] != ' ') - { - lastLineIndex = n; - break; - } - } + } else { lines.Add(cutLine); lastLineIndex = i; lastWordIndex = -1; + if (c == ' ') + lastLineIndex++; } } else @@ -492,6 +486,8 @@ private void ParseText(SKImageInfo imageInfo) lines.Add(cutLine); lastLineIndex = i; lastWordIndex = -1; + if (c == ' ') + lastLineIndex++; } } } diff --git a/Assets/Scripts/OpenTS2/UI/Skia/WinUtils.cs b/Assets/Scripts/OpenTS2/UI/Skia/WinUtils.cs new file mode 100644 index 00000000..7bebdba8 --- /dev/null +++ b/Assets/Scripts/OpenTS2/UI/Skia/WinUtils.cs @@ -0,0 +1,22 @@ +using PlasticPipe.PlasticProtocol.Messages; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace OpenTS2.UI.Skia +{ + public unsafe static class WinUtils + { + [DllImport("user32.dll")] + private static extern uint GetCaretBlinkTime(); + + public static float GetCaretBlinkTimer() + { + return GetCaretBlinkTime() * 0.001f; + } + } +} diff --git a/Assets/Scripts/OpenTS2/UI/Skia/WinUtils.cs.meta b/Assets/Scripts/OpenTS2/UI/Skia/WinUtils.cs.meta new file mode 100644 index 00000000..e1b98765 --- /dev/null +++ b/Assets/Scripts/OpenTS2/UI/Skia/WinUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b81c9128f6f821b4d88f16d556af2a2a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: