How to properly update caret position when modifying TMP input field with Rich Text ?
I am working on a game where players have to type code to interact with the environment. I wanted to implement syntax highlighting as they are typing. However, when I insert new rich text tags into the input filed, the caret position takes one blink in the wrong position before updating to the correct one. This is really annoying for someone typing since letters will go in the wrong place.
I have tried some of the solutions suggested here: https://forum.unity.com/threads/cant-change-caret-position.431105/
But with no success. Here is my code:
void ChangeColors(IEnumerable<IToken> original_token_list, string input_text)
{
string output = input_text;
//HashSet<IToken> unique_tokens = new HashSet<IToken>(original_token_list);
List<string> token_text = new List<string>();
foreach (IToken t in original_token_list)
{
if (keywords.Contains(t.Type))
{
token_text.Add("<color=#F67599>");
token_text.Add(t.Text);
token_text.Add("</color>");
input.GetComponent<TMP_InputField>().caretPosition = caretPos + 1;
}
else if (parens.Contains(t.Type))
{
token_text.Add("<color=#9EC651>");
token_text.Add(t.Text);
token_text.Add("</color>");
input.GetComponent<TMP_InputField>().caretPosition = caretPos + 1;
}
else if (brackets.Contains(t.Type))
{
token_text.Add("<color=#6FE1CD>");
token_text.Add(t.Text);
token_text.Add("</color>");
input.GetComponent<TMP_InputField>().caretPosition = caretPos + 1;
}
else if (t.Text != "<EOF>")
{
token_text.Add(t.Text);
}
}
output = "";
foreach (string s in token_text)
{
output += s;
}
//input.GetComponent<InputFieldWithHideableCaret>().HideCaret();
//CaretHidden = true;
input.GetComponent<InputFieldWithHideableCaret>().text = output;
//ChangeCaretPos();
Invoke("ChangeCaretPos", 0.05f);
}
and :
void ChangeCaretPos()
{
input.GetComponent<InputFieldWithHideableCaret>().caretPosition = caretPos + 1;
}
InputFieldWithHideableCaret is the same as TMP_InputField but with extra classes:
public class InputFieldWithHideableCaret : TMP_InputField
{
// using same name conventions as the InputField for consistency
private float m_CachedCaretBlinkRate;
/// <summary>
/// Caches BlinkRate, sets it to 0, hides the caret indefinitely.
/// </summary>
public void HideCaret()
{
m_CachedCaretBlinkRate = caretBlinkRate;
caretBlinkRate = 0f;
m_CaretVisible = false;
}
/// <summary>
/// Sets the caretBlinkRate back to original value, existing logic will do the rest.
/// </summary>
public void UnhideCaret()
{
caretBlinkRate = m_CachedCaretBlinkRate;
}
}
Did anyone ever find a solution to this?
Thanks!
Your answer
Follow this Question
Related Questions
How to set the position of these Texts ?? 0 Answers
[Solved] Saving data from Input Field 1 Answer
Input Field Problem 0 Answers
Find screen position of a specific word in a RichText? 1 Answer