Tasharen Entertainment Forum

Support => NGUI 3 Support => Topic started by: Clicker on March 25, 2014, 04:07:31 AM

Title: NGUIText fits logic breaks a lot
Post by: Clicker on March 25, 2014, 04:07:31 AM
Hello. Since NGUI has been updated to 3.5.4 r2 (and now 3.5.5) it is having a bug with new fits logic in NGUIText script. For instance, you can check it in scene Example 12 - Chat Windows, just add a little bit more text in input field than it can fit in a row in the window and submit, so you will get an empty window (no text at all). For me, I just roll back the script to the previous version without that logic, and it works fine for now. Hope, it would help and the issue will be fixed till the next version of NGUI.
Title: Re: NGUIText fits logic breaks a lot
Post by: ArenMook on March 26, 2014, 02:11:00 AM
Doesn't happen in the Pro version, so I'm guessing it's related to changes in NGUIText. In NGUIText, line 880 is:
  1.                                         sb.Append(text.Substring(start, Mathf.Max(0, offset - start)));
  2.  
  3.                                         if (ch != ' ' && !eastern)
  4.                                         {
  5.                                                 fits = false;
  6.                                                 break;
  7.                                         }
Change it to:
  1.                                         sb.Append(text.Substring(start, Mathf.Max(0, offset - start)));
  2.                                         if (ch != ' ' && !eastern) fits = false;
Title: Re: NGUIText fits logic breaks a lot
Post by: gg67 on March 30, 2014, 05:16:45 PM
Same issue here in 3.5.5. The fix didn't seem to work.
Title: Re: NGUIText fits logic breaks a lot
Post by: ArenMook on March 31, 2014, 06:25:16 AM
It's the same version, gg67. Pro is 3.5.6.
Title: Re: NGUIText fits logic breaks a lot
Post by: gg67 on April 02, 2014, 12:51:41 PM
But shouldn't making the change you mention above fix the issue in 3.5.5?
Title: Re: NGUIText fits logic breaks a lot
Post by: ArenMook on April 02, 2014, 05:18:10 PM
There have been more changes than that. Let's revisit it when 3.5.6 ships (around this Friday).
Title: Re: NGUIText fits logic breaks a lot
Post by: Clicker on April 07, 2014, 03:25:34 AM
:( The issue stays in 3.5.6.
Title: Re: NGUIText fits logic breaks a lot
Post by: ArenMook on April 08, 2014, 12:51:27 AM
Alright, so how do I reproduce it on my end? The chat window example works fine for me, even if I type in a lot of text and then submit it.
Title: Re: NGUIText fits logic breaks a lot
Post by: Clicker on April 14, 2014, 06:20:48 AM
NGUI 3.5.7. Same issue. Just create an empty project, add NGUI 3.5.7 (current one) and launch example 12 - Chat Window, then add a lot of characters in input field and submit. The issue will appear and all text is gone.
Title: Re: NGUIText fits logic breaks a lot
Post by: ArenMook on April 15, 2014, 09:05:52 AM
Got a vid showing the issue today, so was able to repro and fix it. Use this UITextList:
  1. //----------------------------------------------
  2. //            NGUI: Next-Gen UI kit
  3. // Copyright © 2011-2014 Tasharen Entertainment
  4. //----------------------------------------------
  5.  
  6. #if !UNITY_3_5 && !UNITY_FLASH
  7. #define DYNAMIC_FONT
  8. #endif
  9.  
  10. using UnityEngine;
  11. using System.Collections.Generic;
  12. using System.Text;
  13.  
  14. /// <summary>
  15. /// Text list can be used with a UILabel to create a scrollable multi-line text field that's
  16. /// easy to add new entries to. Optimal use: chat window.
  17. /// </summary>
  18.  
  19. [AddComponentMenu("NGUI/UI/Text List")]
  20. public class UITextList : MonoBehaviour
  21. {
  22.         public enum Style
  23.         {
  24.                 Text,
  25.                 Chat,
  26.         }
  27.  
  28.         /// <summary>
  29.         /// Label the contents of which will be modified with the chat entries.
  30.         /// </summary>
  31.  
  32.         public UILabel textLabel;
  33.  
  34.         /// <summary>
  35.         /// Vertical scroll bar associated with the text list.
  36.         /// </summary>
  37.  
  38.         public UIProgressBar scrollBar;
  39.  
  40.         /// <summary>
  41.         /// Text style. Text entries go top to bottom. Chat entries go bottom to top.
  42.         /// </summary>
  43.  
  44.         public Style style = Style.Text;
  45.  
  46.         /// <summary>
  47.         /// Maximum number of chat log entries to keep before discarding them.
  48.         /// </summary>
  49.  
  50.         public int paragraphHistory = 50;
  51.  
  52.         // Text list is made up of paragraphs
  53.         protected class Paragraph
  54.         {
  55.                 public string text;             // Original text
  56.                 public string[] lines;  // Split lines
  57.         }
  58.  
  59.         protected char[] mSeparator = new char[] { '\n' };
  60.         protected BetterList<Paragraph> mParagraphs = new BetterList<Paragraph>();
  61.         protected float mScroll = 0f;
  62.         protected int mTotalLines = 0;
  63.         protected int mLastWidth = 0;
  64.         protected int mLastHeight = 0;
  65.  
  66.         /// <summary>
  67.         /// Whether the text list is usable.
  68.         /// </summary>
  69.  
  70. #if DYNAMIC_FONT
  71.         public bool isValid { get { return textLabel != null && textLabel.ambigiousFont != null; } }
  72. #else
  73.         public bool isValid { get { return textLabel != null && textLabel.bitmapFont != null; } }
  74. #endif
  75.  
  76.         /// <summary>
  77.         /// Relative (0-1 range) scroll value, with 0 being the oldest entry and 1 being the newest entry.
  78.         /// </summary>
  79.  
  80.         public float scrollValue
  81.         {
  82.                 get
  83.                 {
  84.                         return mScroll;
  85.                 }
  86.                 set
  87.                 {
  88.                         value = Mathf.Clamp01(value);
  89.  
  90.                         if (isValid && mScroll != value)
  91.                         {
  92.                                 if (scrollBar != null)
  93.                                 {
  94.                                         scrollBar.value = value;
  95.                                 }
  96.                                 else
  97.                                 {
  98.                                         mScroll = value;
  99.                                         UpdateVisibleText();
  100.                                 }
  101.                         }
  102.                 }
  103.         }
  104.  
  105.         /// <summary>
  106.         /// Height of each line.
  107.         /// </summary>
  108.  
  109.         protected float lineHeight { get { return (textLabel != null) ? textLabel.fontSize + textLabel.spacingY : 20f; } }
  110.  
  111.         /// <summary>
  112.         /// Height of the scrollable area (outside of the visible area's bounds).
  113.         /// </summary>
  114.  
  115.         protected int scrollHeight
  116.         {
  117.                 get
  118.                 {
  119.                         if (!isValid) return 0;
  120.                         int maxLines = Mathf.FloorToInt((float)textLabel.height / lineHeight);
  121.                         return Mathf.Max(0, mTotalLines - maxLines);
  122.                 }
  123.         }
  124.  
  125.         /// <summary>
  126.         /// Clear the text.
  127.         /// </summary>
  128.  
  129.         public void Clear ()
  130.         {
  131.                 mParagraphs.Clear();
  132.                 UpdateVisibleText();
  133.         }
  134.  
  135.         /// <summary>
  136.         /// Automatically find the values if none were specified.
  137.         /// </summary>
  138.  
  139.         void Start ()
  140.         {
  141.                 if (textLabel == null)
  142.                         textLabel = GetComponentInChildren<UILabel>();
  143.  
  144.                 if (scrollBar != null)
  145.                         EventDelegate.Add(scrollBar.onChange, OnScrollBar);
  146.  
  147.                 textLabel.overflowMethod = UILabel.Overflow.ClampContent;
  148.  
  149.                 if (style == Style.Chat)
  150.                 {
  151.                         textLabel.pivot = UIWidget.Pivot.BottomLeft;
  152.                         scrollValue = 1f;
  153.                 }
  154.                 else
  155.                 {
  156.                         textLabel.pivot = UIWidget.Pivot.TopLeft;
  157.                         scrollValue = 0f;
  158.                 }
  159.         }
  160.  
  161.         /// <summary>
  162.         /// Keep an eye on the size of the label, and if it changes -- rebuild everything.
  163.         /// </summary>
  164.  
  165.         void Update ()
  166.         {
  167.                 if (isValid)
  168.                 {
  169.                         if (textLabel.width != mLastWidth || textLabel.height != mLastHeight)
  170.                         {
  171.                                 mLastWidth = textLabel.width;
  172.                                 mLastHeight = textLabel.height;
  173.                                 Rebuild();
  174.                         }
  175.                 }
  176.         }
  177.  
  178.         /// <summary>
  179.         /// Allow scrolling of the text list.
  180.         /// </summary>
  181.  
  182.         public void OnScroll (float val)
  183.         {
  184.                 int sh = scrollHeight;
  185.  
  186.                 if (sh != 0)
  187.                 {
  188.                         val *= lineHeight;
  189.                         scrollValue = mScroll - val / sh;
  190.                 }
  191.         }
  192.  
  193.         /// <summary>
  194.         /// Allow dragging of the text list.
  195.         /// </summary>
  196.  
  197.         public void OnDrag (Vector2 delta)
  198.         {
  199.                 int sh = scrollHeight;
  200.  
  201.                 if (sh != 0)
  202.                 {
  203.                         float val = delta.y / lineHeight;
  204.                         scrollValue = mScroll + val / sh;
  205.                 }
  206.         }
  207.  
  208.         /// <summary>
  209.         /// Delegate function called when the scroll bar's value changes.
  210.         /// </summary>
  211.  
  212.         void OnScrollBar ()
  213.         {
  214.                 mScroll = UIScrollBar.current.value;
  215.                 UpdateVisibleText();
  216.         }
  217.  
  218.         /// <summary>
  219.         /// Add a new paragraph.
  220.         /// </summary>
  221.  
  222.         public void Add (string text) { Add(text, true); }
  223.  
  224.         /// <summary>
  225.         /// Add a new paragraph.
  226.         /// </summary>
  227.  
  228.         protected void Add (string text, bool updateVisible)
  229.         {
  230.                 Paragraph ce = null;
  231.  
  232.                 if (mParagraphs.size < paragraphHistory)
  233.                 {
  234.                         ce = new Paragraph();
  235.                 }
  236.                 else
  237.                 {
  238.                         ce = mParagraphs[0];
  239.                         mParagraphs.RemoveAt(0);
  240.                 }
  241.  
  242.                 ce.text = text;
  243.                 mParagraphs.Add(ce);
  244.                 Rebuild();
  245.         }
  246.  
  247.         /// <summary>
  248.         /// Rebuild the visible text.
  249.         /// </summary>
  250.  
  251.         protected void Rebuild ()
  252.         {
  253.                 if (isValid)
  254.                 {
  255.                         // Although we could simply use UILabel.Wrap, it would mean setting the same data
  256.                         // over and over every paragraph, which is not ideal. It's faster to only do it once
  257.                         // and then do wrapping ourselves in the 'for' loop below.
  258.                         textLabel.UpdateNGUIText();
  259.                         NGUIText.rectHeight = 1000000;
  260.                         mTotalLines = 0;
  261.  
  262.                         for (int i = 0; i < mParagraphs.size; ++i)
  263.                         {
  264.                                 string final;
  265.                                 Paragraph p = mParagraphs.buffer[i];
  266.                                 NGUIText.WrapText(p.text, out final);
  267.                                 p.lines = final.Split('\n');
  268.                                 mTotalLines += p.lines.Length;
  269.                         }
  270.  
  271.                         // Recalculate the total number of lines
  272.                         mTotalLines = 0;
  273.                         for (int i = 0, imax = mParagraphs.size; i < imax; ++i)
  274.                                 mTotalLines += mParagraphs.buffer[i].lines.Length;
  275.  
  276.                         // Update the bar's size
  277.                         if (scrollBar != null)
  278.                         {
  279.                                 UIScrollBar sb = scrollBar as UIScrollBar;
  280.                                 if (sb != null) sb.barSize = (mTotalLines == 0) ? 1f : 1f - (float)scrollHeight / mTotalLines;
  281.                         }
  282.  
  283.                         // Update the visible text
  284.                         UpdateVisibleText();
  285.                 }
  286.         }
  287.  
  288.         /// <summary>
  289.         /// Refill the text label based on what's currently visible.
  290.         /// </summary>
  291.  
  292.         protected void UpdateVisibleText ()
  293.         {
  294.                 if (isValid)
  295.                 {
  296.                         if (mTotalLines == 0)
  297.                         {
  298.                                 textLabel.text = "";
  299.                                 return;
  300.                         }
  301.  
  302.                         int maxLines = Mathf.FloorToInt((float)textLabel.height / lineHeight);
  303.                         int sh = Mathf.Max(0, mTotalLines - maxLines);
  304.                         int offset = Mathf.RoundToInt(mScroll * sh);
  305.                         if (offset < 0) offset = 0;
  306.  
  307.                         StringBuilder final = new StringBuilder();
  308.  
  309.                         for (int i = 0, imax = mParagraphs.size; maxLines > 0 && i < imax; ++i)
  310.                         {
  311.                                 Paragraph p = mParagraphs.buffer[i];
  312.  
  313.                                 for (int b = 0, bmax = p.lines.Length; maxLines > 0 && b < bmax; ++b)
  314.                                 {
  315.                                         string s = p.lines[b];
  316.  
  317.                                         if (offset > 0)
  318.                                         {
  319.                                                 --offset;
  320.                                         }
  321.                                         else
  322.                                         {
  323.                                                 if (final.Length > 0) final.Append("\n");
  324.                                                 final.Append(s);
  325.                                                 --maxLines;
  326.                                         }
  327.                                 }
  328.                         }
  329.                         textLabel.text = final.ToString();
  330.                 }
  331.         }
  332. }