3DText - Change Text Through Script - Unity - unity3d

I have read lot of questions on how to change text of a 3DText from script.
Lot of them suggested the following :::
GetComponent(TextMesh).text = "blah";
But when I try to use this, I get an error Expression denotes atype', where a variable',value' or method group' was expected
I tried a lot of examples and couldn't really get it to work.
TextMesh textMesh;
textMesh = (TextMesh) descriptionObject.transform.GetComponent("Text Mesh");
textMesh.text = "Name : ABC";
The above code though Compiles without errors doesn't change the text. Can someone help me out with this? How do I change the TEXT of a 3DText Object.
Thanks...

This would be a prettier solution than one already given(C# script used in example) :
//define a Textmesh that we want to edit
public TextMesh tm;
// here in start method (run at instantiating of script) i find component of type
// TextMesh ( <TextMesh> ) of object named"nameOfTheObject" and reference it
// via tm variable;
void Start () {
tm = (TextMesh)GameObject.Find ("nameOfTheObject").GetComponent<TextMesh>();
// here we change the value of displayed text
tm.text = "new Text u want to see";
}
Or if u want to do it the shortest way possible (syntax wise):
//keep in mind this requires for the script to be attached to the object u
// are editing (the 3dText);
//same as above, the only difference is the note in the line above as this
// method is run from gameObject.GetComponent....
// gameObject is a variable which would be equivalent of this.GetComp...
// in some other programming languages
GetComponent<TextMesh>().text ="new Text u want";

This Works !!!!
textMesh = (TextMesh) descriptionObject.transform.GetComponent(typeof(TextMesh));
textMesh.text = "Name : ABC";

Related

How can I get text value of TMPro Text without markup tags in Unity?

I am trying to get text value in TMPro Text component without markup tags but haven't found any solutions.
Say, <b><color=red>Hello </color><b> world is the value in TMPro Text, and I just want Hello world in c# script.
Bear in mind that tag <b> and color will change, so I would love to remove tags dynamically, meaning I would like not to replacing each tag by text.replace("<b>", "") kind of things.
Does anyone know how to do it?
I dont know about the option of using HTML on tmp but you can attach the text to your script by create a new variable like that:
[SerializeField] TMP_Text textVar;
then you can drag you tmp game object to the component that include this script
and the you can change the text like that:
textVar.text = "what ever";
or get text like that:
string textString = textVar.text;
for the color you can use
Color color = textVar.color;
You can use TMP_Text.GetParsedText () to get the text after it has been parsed and rich text tags removed.
Alternatively you can also use regular expressions to search a string for rich text tags, and remove them while preserving the rest of the string.
using System.Text.RegularExpressions;
public static string GetString (string str)
{
Regex rich = new Regex (#"<[^>]*>");
if (rich.IsMatch (str))
{
str = rich.Replace (str, string.Empty);
}
return str;
}

How to search for and highlight a substring in Codemirror 6?

I'm building a simple code editor to help children learn HTML. One feature I'm trying to add is that when users mouseover their rendered code (in an iframe), the corresponding HTML code in the editor is highlighted. So, for example, if a user mouses-over an image of kittens, the actual code, , would be highlighted in the editor.
Mousing-over the iframe to get the html source for that element is the easy part, which I've done (using document.elementFromPoint(e.clientX, e.clientY in the iframe itself, and posting that up to the parent) - so that's not the part I need help with. The part I can't figure out is how to search for and highlight that string of selected code in the code editor.
I'm using Codemirror 6 for this project, as it seems as it will give me the most flexibility to create such a feature. However, as a Codemirror 6 novice, I'm struggling with the documentation to find out where I should start. It seems like the steps I need to complete to accomplish this are:
Search for a range in the editor's text that matches a string (ie.'<img src="kittens.gif"').
Highlight that range in the editor.
Can anyone out there give me some advice as to where in the Codemirror 6 API I should look to start implementing this? It seems like it should be easy, but my unfamiliarity with the Codemirror API and the terse documentation is making this difficult.
1. Search for a range in the editor's text that matches a string (ie.'<img src="kittens.gif"').
You can use SearchCursor class (iterator) to get the character's range where is located the DOM element in your editor.
// the import for SearchCursor class
import {SearchCursor} from "#codemirror/search"
// your editor's view
let main_view = new EditorView({ /* your code */ });
// will create a cursor based on the doc content and the DOM element as a string (outerHTML)
let cursor = new SearchCursor(main_view.state.doc, element.outerHTML);
// will search the first match of the string element.outerHTML in the editor view main_view.state.doc
cursor.next()
// display the range where is located your DOM element in your editor
console.log(cursor.value);
2. Highlight that range in the editor.
As described in the migration documentation here, marked text is replace by decoration. To highlight a range in the editor with codemirror 6, you need to create one decoration and apply it in a dispatch on your view. This decoration need to be provide by an extension that you add in the extensions of your editor view.
// the import for the 3 new classes
import {StateEffect, StateField} from "#codemirror/state"
import {Decoration} from "#codemirror/view"
// code mirror effect that you will use to define the effect you want (the decoration)
const highlight_effect = StateEffect.define();
// define a new field that will be attached to your view state as an extension, update will be called at each editor's change
const highlight_extension = StateField.define({
create() { return Decoration.none },
update(value, transaction) {
value = value.map(transaction.changes)
for (let effect of transaction.effects) {
if (effect.is(highlight_effect)) value = value.update({add: effect.value, sort: true})
}
return value
},
provide: f => EditorView.decorations.from(f)
});
// this is your decoration where you can define the change you want : a css class or directly css attributes
const highlight_decoration = Decoration.mark({
// attributes: {style: "background-color: red"}
class: 'red_back'
});
// your editor's view
let main_view = new EditorView({
extensions: [highlight_extension]
});
// this is where the change takes effect by the dispatch. The of method instanciate the effect. You need to put this code where you want the change to take place
main_view.dispatch({
effects: highlight_effect.of([highlight_decoration.range(cursor.value.from, cursor.value.to)])
});
Hope it will help you to implement what you want ;)
Have a look at #codemirror/search.
Specifically, the source code implementation of Selection Matching may be of use for you to adapt.
It uses Decoration.mark over a range of text.
You can use SearchCursor to iterate over ranges that match your pattern (or RegExpCursor)
Use getSearchCursor, something like this:
var cursor = cmEditor.getSearchCursor(keyword , CodeMirror.Pos(cmEditor.firstLine(), 0), {caseFold: true, multiline: true});
if(cursor.find(false)){ //move to that position.
cmEditor.setSelection(cursor.from(), cursor.to());
cmEditor.scrollIntoView({from: cursor.from(), to: cursor.to()}, 20);
}
Programmatically search and select a keyword
Take a look at getSearchCursor source code it it give some glow about how it works and its usage.
So use getSearchCursor for finding text and optionally use markText for highlighting text because you can mark text with setSelection method of editor.
Selection Marking Demo
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
styleSelectedText: true
});
editor.markText({line: 6, ch: 26}, {line: 6, ch: 42}, {className: "styled-background"});
And it seem this is what you are looking for:
codemirror: search and highlight multipule words without dialog
RegExpCursor is another option that you can use:
new RegExpCursor(
text: Text,
query: string,
options⁠?: {ignoreCase⁠?: boolean},
from⁠?: number = 0,
to⁠?: number = text.length
)
Sample usage at:
Replacing text between dollar signs for Mathml expression.

Unity Editor : How to resize and space value field of an inspector property field?

I am trying to implement my first unity editor code to make a custom array property drawer with indented named entries and indented and dynamicaly resized value fields.
I am using the following simple git solution as base for my code, which allows to set the labels of an array in the inspector : HERE
replacing the example shown in the gitHub solution, I am working with this enum as my array element name container:
[System.Serializable]
public enum HealthNames
{
General,
Head,
Body,
RightArm,
LeftArm,
Rightleg,
leftLeg,
}
and sets it up on a array in a monobehaviour class :
[ LabeledArray( typeof( HealthNames ) ) ]
public int[] m_aHealth = new int[ Enum.GetNames( typeof( HealthNames ) ).Length ];
I have added EditorGUI.indentLevel++; and EditorGUI.indentLevel--; at the start and end of the try statement to indent the label of the array elements, making them stand out from the size property.
Going from there, I have searched ways to add an indent on the elements' value fields or remove it from the size property's value field. but have found no answer using EditorGUI
I also looked to be able to resize all value fields dynamicaly, but there again, no answer came using EditorGUI only. there is no way to use EditorStyle.AnyField.WordWrap = true; on a propertyfield. Passing the PropertyField to an IntField, using a EditorStyles.NumberField and setting having its wrodwrapping set to true beforehand has no effect.
I also have found a small number of EditorGUILayout from a few years ago, but which do not work since the solution is built from the ground with EditorGUI
In hope of your enlightment on the matter
If I understand you correctly you want the labels and the value fields indented.
I think it could be done like e.g.
private const int INDENT = 15;
public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(rect, label, property);
var fieldsRect = new Rect(rect.x + INDENT, rect.y, rect.width - INDENT, rect.height);
try
{
var path = property.propertyPath;
int pos = int.Parse(path.Split('[').LastOrDefault().TrimEnd(']'));
EditorGUI.PropertyField(fieldRect, property, new GUIContent(ObjectNames.NicifyVariableName(((LabeledArrayAttribute)attribute).names[pos])), true);
}
catch
{
EditorGUI.PropertyField(fieldRect, property, label, true);
}
EditorGUI.EndProperty();
}

How to validate Text mesh pro input field text in unity

I have tried to use text mesh pro input field in my project but I have face one series issue with that. i.e If try to validate empty or null text in input field it fails. For example when user without typing any text in tmp input field and click done button I have set a validation like not allowed to save null empty values but when user click done button without typing any text, those validations are fails. Please suggest any idea to fix this issue. Thanks in advance.
Here is the code I have tried :
var text = TextMeshProText.text; // here "TextMeshProText" is 'TMP_Text'
if(!string.IsNullOrEmpty(text))
{
//do required functionality
}
else
{
// Show alert to the user.
}
I have set the validation like this but without giving any text click on done button it fails null or empty condition and enter in to if.
I found the problem. It fails because you use TMP_Text instead TMP_InputField.
Note that: Use the code for TMP_InputField; not for TMP_Text that is inside it as a child.
Change your code to this:
TMP_InputField TextMeshProText;
...
public void OnClick ()
{
var text = TextMeshProText.text; // here "TextMeshProText" is 'TMP_InputField'
if (!string.IsNullOrEmpty(text))
{
//do required functionality
}
else
{
// Show alert to the user.
}
}
I hope it helps you

Gtk (mm) limit width of combobox

Because I use Comboboxes that may contain text entries of very long size,
which leads to the combobox increasing its width far beyond reasonable size,
I am trying to give a maximum width to the combobox.
If I am doing this like this:
class MyCombo : public Gtk::ComboBox {
private:
CellRendererText render;
public:
MyCombo() {
render.property_width_chars() = 10;
render.property_ellipsize() = Pango::ELLIPSIZE_END;
pack_start(render, true);
}
};
The result will be an empty cell of the desired width, which seems logical since I did not specify which column to show. But how can I do this with that attempt? Using pack_start will just bypass the renderer...
Another approach is this one:
class MyCombo : public Gtk::ComboBox {
private:
CellRendererText render;
public:
MyCombo() {
pack_start(render, true);
set_cell_data_func(render, sigc::mem_fun(*this, &MyCombo::render_iter));
}
void render_iter(const TreeModel::const_iterator& iter) {
Glib::ustring data = get_string_from_iter(iter);
int desired_width_chars = 10; //for example
render.property_text() = ellipsize_string(data, desired_width_chars);
}
};
Using that approach, it works, but the text in the popup (what opens up when u click the combobox) is also shortened which is not what I want (obviously the user should be able to read the whole string and I dont care about the popup widht.)
Can you please help me with this? I would be happy for any advice/alternative solutions.
Regards tagelicht
NOTE: set_wrap_width is a function that wraps the total number of entries in the combo box over a number of columns specified; it does not answer the question.
Using set_wrap_width(1) | Using set_wrap_width(5)
Following Noup's answer as a guide I managed to get the below code; which directly answers the question and its requirements (C++/Gtkmm).
// Get the first cell renderer of the ComboBox.
auto v_cellRenderer = (Gtk::CellRendererText*)v_comboBox.get_first_cell();
// Probably obsolete; Sets character width to 1.
v_cellRenderer->property_width_chars() = 1;
// Sets the ellipses ("...") to be at the end, where text overflows.
// See Pango::ELLIPSIZE enum for other values.
v_cellRenderer->property_ellipsize() = Pango::ELLIPSIZE_END;
// Sets the size of the box, change this to suit your needs.
// -1 sets it to automatic scaling: (width, height).
v_cellRenderer->set_fixed_size(200, -1);
Result (image):
Result of code
BE AWARE: Depending on where you perform the above code; either all the cells will be the same size, or just the box itself (intended).
From experimenting, I've found:
In the parent object constructor: All cell sizes are the same.
In a separate function: Only the first cell (the box) is affected.
I'd recommend you put the code in a function that's connected to the comboBox's changed signal, such as:
v_comboBox.signal_changed().connect(sigc::mem_fun(*this, &YourClass::comboBox_changedFunction));
This may be what you are looking for:
cell_renderer_text.set_wrap_width(10)
This is for Python, but you get the idea :-)
Unfortunately, the documentation is scarce. I found this by poking around in Anjuta/Glade.
Edit:
the docs are here. They are not overly helpful, but they do exist.
As an alternative, the following works for me without having to set wrap_width nor to subclass ComboBox (in Gtk#):
ComboBoxText cb = new ComboBoxText();
cb.Hexpand = true; //If there's available space, we use it
CellRendererText renderer = (cb.Cells[0] as CellRendererText); //Get the ComboBoxText only renderer
renderer.WidthChars = 20; //Always show at least 20 chars
renderer.Ellipsize = Pango.EllipsizeMode.End;
Note: I'm using Expand to use space if it's available. If you just want to keep the combo box on a fixed width, just remove that bit.