- Home /
Setting a color to selected string letters in inspector
Hi, I'm building a dialogue system and I was wondering if it was possible through editor scripting to set certain parts of a string to a certain color. Specifically by selecting them through the click drag function like in word for example. So the idea is first I'll add a color picked, but then I need to somehow be able to click on that color picker and set the color of only the highlighted section of characters in the string.
From there I'll record the first and last character and update the non-editor script accordingly to remember the letters but that's not really relevant.
Again to be specific, I just want to be able to color in the highlighted part of a string.
Thank you.
Hey @Zuccinin are you using Text $$anonymous$$esh Pro? Are you selecting the text in the Text$$anonymous$$eshPro object or a custom editor unity text area / text field?
This is definitely achievable - I made a custom editor that does this for my game. Should be able to help if you give me a bit more info
Answer by flashframe · May 14, 2020 at 10:12 AM
Hey @Zuccinin I just went ahead and presumed you are using Text Mesh Pro (now built in to Unity). I put together this editor window script that does what you want. I'm sure you'll be able to adapt it to your needs. You can see how it can be extended to add any tags to the selected text - not just color.
To use it, you dock the window somewhere and select a Text Mesh Pro object in the inspector. Set the color with the color picker, then select the text you want to color in the text box and press the + button. It'll grab the selected text and add tags around the text.
using UnityEngine;
using System.Reflection;
using UnityEditor;
using TMPro;
namespace Zuccinin
{
public class TextUtilityWindow : EditorWindow
{
[MenuItem("Zuccinin/Text Utility", false, 0)]
public static void OpenTextUtilityWindow()
{
EditorWindow.GetWindow(typeof(TextUtilityWindow), false, "Text Utilities");
}
Color textColor = Color.white;
TMP_Text textObject;
private void OnGUI()
{
if(Selection.activeTransform != null)
{
textObject = Selection.activeTransform.GetComponent<TMP_Text>();
}
else
{
textObject = null;
}
DrawTextArea();
EditorGUILayout.BeginHorizontal();
textColor = EditorGUILayout.ColorField(textColor);
if (GUILayout.Button("+", EditorStyles.toolbarButton, GUILayout.Width(25), GUILayout.Height(15)))
{
AddColor();
}
EditorGUILayout.EndHorizontal();
}
void DrawTextArea()
{
//DIALOGUE ENTRY TEXT AREA
if(textObject == null)
{
EditorGUILayout.LabelField("SELECT A TEXT OBJECT IN THE INSPECTOR.");
}
else
{
string s = textObject.text;
EditorGUI.BeginChangeCheck();
s = EditorGUILayout.TextArea(s);
if (EditorGUI.EndChangeCheck())
{
Undo.SetCurrentGroupName("Changed Dialogue Text");
textObject.text = s;
Undo.CollapseUndoOperations(Undo.GetCurrentGroup());
}
}
}
void AddTag(string prefix, string suffix)
{
if (textObject == null) return;
TextEditor textEditor = typeof(EditorGUI)
.GetField("activeEditor", BindingFlags.Static | BindingFlags.NonPublic)
.GetValue(null) as TextEditor;
if (textEditor != null)
{
string selectedText = textEditor.SelectedText;
int index = (textEditor.selectIndex < textEditor.cursorIndex) ? textEditor.selectIndex : textEditor.cursorIndex;
int length = selectedText.Length;
string originalText = textObject.text;
string tagText = prefix + selectedText + suffix;
string newText = tagText;
if (length < originalText.Length)
{
string strippedText = originalText.Remove(index, length);
newText = strippedText.Insert(index, tagText);
}
textObject.text = newText;
ClearFocus();
}
}
void AddColor()
{
string color = ColorUtility.ToHtmlStringRGB(textColor);
string prefix = "<color=#" + color + ">";
string suffix = "</color>";
AddTag(prefix, suffix);
}
void ClearFocus()
{
GUIUtility.keyboardControl = 0;
GUIUtility.hotControl = 0;
}
}
}
Oh wow, I'm going to try it out right now! I'll be back with a response on how it worked out. Quite a bit to read through and understand.
I see now, right away I think I haven't been very clear I think. The idea is that the text changes color in the text box in the inspector rather than in the game view?
I'll just explain more clearly why I want this.
The plan is to color code segments of the text I type in because depending on where a player interrupts the npc while they talk they will get different narrative outcomes. So once I have segment of the textmeshpro window text colored in I will assign that color to a message, to easier see every single place you can interrupt an npc and get a different message. Is it possible to keep the selected text selected until you pick a color like wordpad/word/notepad etc? Not really necessary but I think it could be the most intuitive. No need if you don't have the time though, if there is a place where there is any documentation on selected text that would be great as well.
It also seems to only change once for me?
$$anonymous$$ight be quite a heavy project this early in my editor scripting. I'm not fully aware of what each part is doing, I'll sit with it for a while and figure things out though.
Oh I'm sorry, might have been a bit of user error as well. I see now what you mean. I select the text and it shows up in the text window in Text Utilities. In there I change the color. I see, however still, the hopes is for the textmeshpro text window to have colors in it to color code what segment leads where. Initially I was planning on color coding in a public string[] and then just send the text to a text mesh pro. I'm not sure if it is better to just have multiple text mesh pro windows.
Thank you were much, the more I use this the cooler it is. I'm sure I can adapt it somewhat in a week or so. Just so much to learn and understand.
Hey there! I'm not 100% clear still on whether you want the in game text to be coloured or just the text in the editor?
This tool adds the color codes around the selected text so that in the game it will be coloured. If you ONLY want it to be color coded in the editor and not at runtime, you'd need to use a custom tool to display and edit the text in the editor. This code could be the starting point for that editor. It would help to know how your data is structured for your dialogue system. If you have a data object for each "line", then you could add a field for color that you use in the editor to display the text in a different color in your custom tool. Or if you know in code that this line is "interruptible" you could use that information to display in a different color.
You can have the text box in the window display rich text by adapting the code for the DrawTextArea function:
void DrawTextArea()
{
//DIALOGUE ENTRY TEXT AREA
if(textObject == null)
{
EditorGUILayout.LabelField("SELECT A TEXT OBJECT IN THE INSPECTOR.");
}
else
{
GUIStyle textBoxStyle = new GUIStyle(EditorStyles.textArea);
textBoxStyle.richText = true;
string s = textObject.text;
EditorGUI.BeginChangeCheck();
s = EditorGUILayout.TextArea(s, textBoxStyle);
if (EditorGUI.EndChangeCheck())
{
Undo.SetCurrentGroupName("Changed Dialogue Text");
textObject.text = s;
Undo.CollapseUndoOperations(Undo.GetCurrentGroup());
}
}
}
Now you'll see that when you change the color of the text, it actually appears coloured in the editor.
I'll update my answer later with comments to help you understand what's going what.
The ingame text should pretty much be unaffected completely. I'm more or less just marking segments of string with different colors. Those segments will lead to different dialogue later on. I just want something that tracks segments visually in the inspector by color coding them in the string text visually.
Basically I want the strings for dialogue that I put in to look like the first part of this image that I made. So that I can specify what part of the string/text should lead where and color code it. https://imgur.com/a/ClIXAXx
This is specifically for the inspector, I don't want this stuff ingame. It's just to make a system for dialogue.