-
-
Save shoffing/5d304ff858d25546e7e7 to your computer and use it in GitHub Desktop.
Hacky workaround to fix some stuff with InputField
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEngine.UI; | |
using UnityEngine.EventSystems; | |
using System; | |
using System.Collections; | |
using System.IO; | |
public class ScriptEditor : InputField { | |
public Text lineNumbers; | |
private RectTransform rectTransform; | |
protected override void Start() { | |
rectTransform = GetComponent<RectTransform>(); | |
onValueChange.AddListener(new UnityEngine.Events.UnityAction<string>(TextChanged)); | |
onValueChange.AddListener(new UnityEngine.Events.UnityAction<string>(ResizeInput)); | |
onValueChange.AddListener(new UnityEngine.Events.UnityAction<string>(UpdateLineNumbers)); | |
onValidateInput = AutoIndent; | |
} | |
// Fix InputField not setting Text component's text | |
private void TextChanged(string iText) { | |
m_Text = iText; | |
UpdateLabel(); | |
m_TextComponent.text = iText; | |
} | |
// Resize input field as new lines get added | |
private void ResizeInput(string iText) { | |
string fullText = text; | |
Vector2 extents = textComponent.rectTransform.rect.size; | |
var settings = textComponent.GetGenerationSettings(extents); | |
settings.generateOutOfBounds = false; | |
var prefHeight = new TextGenerator().GetPreferredHeight(fullText, settings) + 16; | |
if(prefHeight > textComponent.rectTransform.rect.height - 16 || prefHeight < textComponent.rectTransform.rect.height + 16) { | |
rectTransform.sizeDelta = new Vector2(rectTransform.sizeDelta.x, prefHeight); | |
} | |
} | |
// Update the line numbers | |
private void UpdateLineNumbers(string text) { | |
int numLines = 0; | |
foreach(char c in text) { | |
if(c == '\n') numLines++; | |
} | |
string lineNumText = ""; | |
for(int i = 0; i <= numLines; i++) { | |
lineNumText += (i + 1) + "\n"; | |
} | |
lineNumbers.text = lineNumText; | |
} | |
// Automatic indentation matching | |
private char AutoIndent(string input, int charIndex, char addedChar) { | |
if(addedChar == '\n') { | |
string prevLine; | |
int prevLineStart = input.LastIndexOf('\n', Mathf.Max(charIndex - 1, 0)) + 1; | |
prevLine = input.Substring(prevLineStart, charIndex - prevLineStart); | |
int numWhitespace = 0; | |
string autoWhitespace = ""; | |
while(numWhitespace < prevLine.Length && (prevLine[numWhitespace] == '\t' || prevLine[numWhitespace] == ' ')) { | |
autoWhitespace += prevLine[numWhitespace]; | |
numWhitespace++; | |
} | |
text = input.Insert(charIndex, '\n' + autoWhitespace); | |
caretPosition = charIndex + 1 + numWhitespace; | |
return '\0'; | |
} | |
return addedChar; | |
} | |
//Returns string on given line number | |
public string GetTextOnLineNumber( int lineNumber ) { | |
using ( StringReader reader = new StringReader( text ) ) { | |
int currLine = 0; | |
string line; | |
while ( (line = reader.ReadLine()) != null ) { | |
if ( currLine == lineNumber ) { | |
return line; | |
} else { | |
currLine++; | |
} | |
} | |
return null; | |
} | |
} | |
// Overriding InputField | |
// InputField source: https://bitbucket.org/Unity-Technologies/ui/src/7c219d27562749b5581b017103c6947cebca6536/UnityEngine.UI/UI/Core/InputField.cs | |
// this code, is bananas. B.A.N.A.N.A.S. | |
public void SetText(string value) { | |
// Try | |
try { | |
m_Text = value; | |
UpdateLabel(); | |
if(onValueChange != null) | |
onValueChange.Invoke(m_Text); | |
} catch { | |
SetTextForReal(value); | |
} | |
} | |
private void SetTextForReal(string value) { | |
// Try harder | |
m_Text = value; | |
UpdateLabel(); | |
if(onValueChange != null) | |
onValueChange.Invoke(m_Text); | |
} | |
private int GetUnclampedCharacterLineFromPosition(Vector2 pos, TextGenerator generator) | |
{ | |
if (!multiLine) | |
return 0; | |
float height = m_TextComponent.rectTransform.rect.yMax; | |
// Position is above first line. | |
if (pos.y > height) | |
return -1; | |
for (int i = 0; i < generator.lineCount; ++i) | |
{ | |
float lineHeight = generator.lines[i].height / m_TextComponent.pixelsPerUnit; | |
if (pos.y <= height && pos.y > (height - lineHeight)) | |
return i; | |
height -= lineHeight; | |
} | |
// Position is after last line. | |
return generator.lineCount; | |
} | |
private static int GetLineEndPosition(TextGenerator gen, int line) | |
{ | |
line = Mathf.Max(line, 0); | |
if (line + 1 < gen.lines.Count) | |
return gen.lines[line + 1].startCharIdx - 1; | |
return gen.characterCountVisible; | |
} | |
protected new int GetCharacterIndexFromPosition(Vector2 pos) | |
{ | |
TextGenerator gen = m_TextComponent.cachedTextGenerator; | |
if (gen.lineCount == 0) | |
return 0; | |
int line = GetUnclampedCharacterLineFromPosition(pos, gen); | |
if (line < 0) | |
return 0; | |
if (line >= gen.lineCount) | |
return gen.characterCountVisible; | |
int startCharIndex = gen.lines[line].startCharIdx; | |
int endCharIndex = GetLineEndPosition(gen, line); | |
for (int i = startCharIndex; i < endCharIndex; i++) | |
{ | |
if (i >= gen.characterCountVisible) | |
break; | |
UICharInfo charInfo = gen.characters[i]; | |
Vector2 charPos = charInfo.cursorPos / m_TextComponent.pixelsPerUnit; | |
float distToCharStart = pos.x - charPos.x; | |
float distToCharEnd = charPos.x + (charInfo.charWidth / m_TextComponent.pixelsPerUnit) - pos.x; | |
if (distToCharStart < distToCharEnd) | |
return i; | |
} | |
return endCharIndex; | |
} | |
public override void OnPointerDown(PointerEventData eventData) | |
{ | |
EventSystem.current.SetSelectedGameObject(gameObject, eventData); | |
base.OnPointerDown(eventData); | |
Vector2 pos = ScreenToLocal(eventData.position); | |
caretPosition = GetCharacterIndexFromPosition(pos) + m_DrawStart; | |
UpdateLabel(); | |
eventData.Use(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment