Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

TextField in runtime : y position changing when modifying the content

Discussion in 'Immediate Mode GUI (IMGUI)' started by Avalion, Oct 20, 2014.

  1. Avalion

    Avalion

    Joined:
    May 2, 2012
    Posts:
    34
    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 :
    Code (CSharp):
    1.     private static Dictionary<string, List<GUIStyle>> ms_borders = new Dictionary<string, List<GUIStyle>>();
    2.     public static GUIStyle GetBorder(string type, string _border) {
    3.         if (ms_borders == null)
    4.             ms_borders = new Dictionary<string, List<GUIStyle>>();
    5.  
    6.         if (!ms_borders.ContainsKey(type)) {
    7.             List<GUIStyle> list = new List<GUIStyle>();
    8.             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" };
    9.             foreach (string text in bgs) {
    10.                 GUIStyle g = new GUIStyle();
    11.                 g.normal.background = (Texture2D)Resources.Load("boxes/" + type + "/" + text);
    12.                 g.wordWrap = true;
    13.  
    14.                 if (g.normal.background != null && (text.Contains("top") || text.Contains("bottom")))
    15.                     g.fixedHeight = g.normal.background.height;
    16.                 if (g.normal.background != null && (text.Contains("right") || text.Contains("left")))
    17.                     g.fixedWidth = g.normal.background.width;
    18.  
    19.                 g.stretchWidth = true;
    20.                 g.stretchHeight = true;
    21.  
    22.                 list.Add(g);
    23.             }
    24.             ms_borders.Add(type, list);
    25.         }
    26.  
    27.         switch (_border) {
    28.             case "top_left":
    29.                 return ms_borders[type][0];
    30.             case "top":
    31.                 return ms_borders[type][1];
    32.             case "top_right":
    33.                 return ms_borders[type][2];
    34.             case "left":
    35.                 return ms_borders[type][3];
    36.             case "background":
    37.                 return ms_borders[type][4];
    38.             case "right":
    39.                 return ms_borders[type][5];
    40.             case "bottom_left":
    41.                 return ms_borders[type][6];
    42.             case "bottom":
    43.                 return ms_borders[type][7];
    44.             case "bottom_right":
    45.                 return ms_borders[type][8];
    46.         }
    47.         return null;
    48.     }
    49.  
    50.     public static void BeginBox(string type, params GUILayoutOption[] _options) {
    51.         GUILayout.BeginVertical(_options);
    52.         GUILayout.BeginHorizontal();
    53.         GUILayout.Label("", GetBorder(type, "top_left"));
    54.         GUILayout.Label("", GetBorder(type, "top"));
    55.         GUILayout.Label("", GetBorder(type, "top_right"));
    56.         GUILayout.EndHorizontal();
    57.         GUILayout.BeginHorizontal();
    58.         GUILayout.Label("", GetBorder(type, "left"));
    59.         GUILayout.BeginHorizontal(GetBorder(type, "background"));
    60.         GUILayout.BeginVertical();
    61.     }
    62.     public static void EndBox(string type) {
    63.         GUILayout.EndVertical();
    64.         GUILayout.EndHorizontal();
    65.         GUILayout.Label("", GetBorder(type, "right"));
    66.         GUILayout.EndHorizontal();
    67.         GUILayout.BeginHorizontal();
    68.         GUILayout.Label("", GetBorder(type, "bottom_left"));
    69.         GUILayout.Label("", GetBorder(type, "bottom"));
    70.         GUILayout.Label("", GetBorder(type, "bottom_right"));
    71.         GUILayout.EndHorizontal();
    72.         GUILayout.EndVertical();
    73.     }
    So my comment is a customed "Box" which contains a TextField, dynamically placed from the 3D position of its GameObject :
    Code (CSharp):
    1.  
    2.         Vector2 screenCoords = Camera.main.WorldToScreenPoint(transform.position);
    3.         screenCoords.y = Screen.height - screenCoords.y;
    4.         // Don't display if out of the screen
    5.         if (!new Rect(0, 0, Screen.width, Screen.height).Contains(screenCoords))
    6.             return;
    7.         // Calculate the size of the content      
    8.         Vector2 size = Vector2.zero;
    9.         size.y = m_textStyle.CalcHeight(new GUIContent(m_content), MAX_PIXEL_WIDTH);
    10.         size.x = Mathf.Min(m_textStyle.CalcSize(new GUIContent(m_content)).x, MAX_PIXEL_WIDTH);
    11.  
    12.         Vector2 dateSize = m_dateStyle.CalcSize(new GUIContent(m_date));
    13.         dateSize.x = Mathf.Min(dateSize.x + 5, MAX_PIXEL_WIDTH);
    14.  
    15.         GUIStyle bgStyle = GetBorder("comments", "background");
    16.  
    17.         float width = Mathf.Max(size.x, dateSize.x) + CalcStyleWidth(GetBorder("comments", "left")) + CalcStyleWidth(GetBorder("comments", "right")) + bgStyle.padding.left + bgStyle.padding.right;
    18.         float height = size.y + dateSize.y + CalcStyleHeight(GetBorder("comments", "top")) + CalcStyleHeight(GetBorder("comments", "bottom")) + bgStyle.padding.top + bgStyle.padding.bottom;
    19.         // Place it on Screen
    20.         m_position = new Rect(screenCoords.x - width + 8, screenCoords.y - height, width, height);
    21.         // Display
    22.         GUI.BeginGroup(m_position);
    23.         BeginBox("comments", GUILayout.Width(m_position.width));
    24.         string value = GUILayout.TextArea(m_content, m_textStyle, GUILayout.Width(size.x), GUILayout.Height(size.y));
    25.         if (value.Length <= 100)
    26.             m_content = value;
    27.         GUILayout.BeginHorizontal();
    28.         GUILayout.FlexibleSpace();
    29.         GUILayout.Label(m_date, m_dateStyle);
    30.         GUILayout.Space(5);
    31.         GUILayout.EndHorizontal();
    32.         EndBox("comments");
    33.         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 :)
     
  2. Avalion

    Avalion

    Joined:
    May 2, 2012
    Posts:
    34
    I setted the GUIstyle.alignment to TextAnchor.LowerLeft.

    It minimized the problem but don't fix it... I send an error report (641263)

    thanks