Hello everybody !
I’m facing a little problem with TextField in Unity runtime.
I’m currently using Unity 4.5.1 but i’ve tested on 4.6 and it wasn’t fixed.
There is my problem :
I’ve attended to create some comments that can be created by users on my 3D application. Firstly, I decided to develop the GUI design.
I’ve developped a function which generate a box from textures place in the Resources folder. This was made because my comments have to be stretchable without losing its aspect Ratio on the corners. Here is the code to this functionnality :
private static Dictionary<string, List<GUIStyle>> ms_borders = new Dictionary<string, List<GUIStyle>>();
public static GUIStyle GetBorder(string type, string _border) {
if (ms_borders == null)
ms_borders = new Dictionary<string, List<GUIStyle>>();
if (!ms_borders.ContainsKey(type)) {
List<GUIStyle> list = new List<GUIStyle>();
string[] bgs = new string[9] { "border_top_left", "border_top", "border_top_right", "border_left", "background", "border_right", "border_bottom_left", "border_bottom", "border_bottom_right" };
foreach (string text in bgs) {
GUIStyle g = new GUIStyle();
g.normal.background = (Texture2D)Resources.Load("boxes/" + type + "/" + text);
g.wordWrap = true;
if (g.normal.background != null && (text.Contains("top") || text.Contains("bottom")))
g.fixedHeight = g.normal.background.height;
if (g.normal.background != null && (text.Contains("right") || text.Contains("left")))
g.fixedWidth = g.normal.background.width;
g.stretchWidth = true;
g.stretchHeight = true;
list.Add(g);
}
ms_borders.Add(type, list);
}
switch (_border) {
case "top_left":
return ms_borders[type][0];
case "top":
return ms_borders[type][1];
case "top_right":
return ms_borders[type][2];
case "left":
return ms_borders[type][3];
case "background":
return ms_borders[type][4];
case "right":
return ms_borders[type][5];
case "bottom_left":
return ms_borders[type][6];
case "bottom":
return ms_borders[type][7];
case "bottom_right":
return ms_borders[type][8];
}
return null;
}
public static void BeginBox(string type, params GUILayoutOption[] _options) {
GUILayout.BeginVertical(_options);
GUILayout.BeginHorizontal();
GUILayout.Label("", GetBorder(type, "top_left"));
GUILayout.Label("", GetBorder(type, "top"));
GUILayout.Label("", GetBorder(type, "top_right"));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("", GetBorder(type, "left"));
GUILayout.BeginHorizontal(GetBorder(type, "background"));
GUILayout.BeginVertical();
}
public static void EndBox(string type) {
GUILayout.EndVertical();
GUILayout.EndHorizontal();
GUILayout.Label("", GetBorder(type, "right"));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label("", GetBorder(type, "bottom_left"));
GUILayout.Label("", GetBorder(type, "bottom"));
GUILayout.Label("", GetBorder(type, "bottom_right"));
GUILayout.EndHorizontal();
GUILayout.EndVertical();
}
So my comment is a customed “Box” which contains a TextField, dynamically placed from the 3D position of its GameObject :
Vector2 screenCoords = Camera.main.WorldToScreenPoint(transform.position);
screenCoords.y = Screen.height - screenCoords.y;
// Don't display if out of the screen
if (!new Rect(0, 0, Screen.width, Screen.height).Contains(screenCoords))
return;
// Calculate the size of the content
Vector2 size = Vector2.zero;
size.y = m_textStyle.CalcHeight(new GUIContent(m_content), MAX_PIXEL_WIDTH);
size.x = Mathf.Min(m_textStyle.CalcSize(new GUIContent(m_content)).x, MAX_PIXEL_WIDTH);
Vector2 dateSize = m_dateStyle.CalcSize(new GUIContent(m_date));
dateSize.x = Mathf.Min(dateSize.x + 5, MAX_PIXEL_WIDTH);
GUIStyle bgStyle = GetBorder("comments", "background");
float width = Mathf.Max(size.x, dateSize.x) + CalcStyleWidth(GetBorder("comments", "left")) + CalcStyleWidth(GetBorder("comments", "right")) + bgStyle.padding.left + bgStyle.padding.right;
float height = size.y + dateSize.y + CalcStyleHeight(GetBorder("comments", "top")) + CalcStyleHeight(GetBorder("comments", "bottom")) + bgStyle.padding.top + bgStyle.padding.bottom;
// Place it on Screen
m_position = new Rect(screenCoords.x - width + 8, screenCoords.y - height, width, height);
// Display
GUI.BeginGroup(m_position);
BeginBox("comments", GUILayout.Width(m_position.width));
string value = GUILayout.TextArea(m_content, m_textStyle, GUILayout.Width(size.x), GUILayout.Height(size.y));
if (value.Length <= 100)
m_content = value;
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
GUILayout.Label(m_date, m_dateStyle);
GUILayout.Space(5);
GUILayout.EndHorizontal();
EndBox("comments");
GUI.EndGroup();
So, there is my problem : Where I modify text in runtime, the TextArea position Y value change as I put some texts. It only appears when Unity have focus on this TextArea…
Here is a demo
Thanks in advance and sorry for my English