Tasharen Entertainment Forum

Support => NGUI 3 Support => Topic started by: wom on March 01, 2014, 07:23:51 PM

Title: v3.5.0 resizing a scroll view causes content to scroll down
Post by: wom on March 01, 2014, 07:23:51 PM
Since upgrading to 3.5.0 (and 3.5.1) - I get some strange behaviour where resizing my "window" component seems to scroll the contents of window downward.

As I drag the UIDragResize widget, the transform of the GameObject that has the UIScrollView decreases it's Y position - this causes the content of window to scroll down out of view (clipping happens correctly).

This seems to happen to two completely different kinds of "window" widgets that I've created (the content of one is laid out with a UITable, but the other is just hardcoded).

I'm certain it's the NGUI upgrade behaving differently in this way.  I've rolled the project back to 3.4.9 and seen the widgets working the way I intend, then did the upgrade again (this time direct to 3.5.1) and the same weird "scroll down on resize" thing happens again.

Has anyone else seen a similar change in behaviour with resizing scroll views?  Are there any known issues? 
I'd really like to avoid spending a bunch of time messing around with this if it's already known.



Title: Re: v3.5.0 resizing a scroll view causes content to scroll down
Post by: ArenMook on March 01, 2014, 09:04:42 PM
Recent versions of NGUI added the "origin" setting on scroll views. When you start resizing the scroll view, the scroll view's position will be reset to the origin point if you have no scroll bar, or it will be kept relative to the scroll bar's position if you do.
Title: Re: v3.5.0 resizing a scroll view causes content to scroll down
Post by: wom on March 01, 2014, 09:26:10 PM
Yes, looks like it's the content origin thing - when I set the origin to be bottom and resize the window, the content scrolls away upward.
My windows do not have scrollbars.

Quote
When you start resizing the scroll view, the scroll view's position will be reset to the origin point if you have no scroll bar
Ok, I can see how that makes sense.

But something seems to be wrong - it seems like instead of resetting the position to the same thing each time, it keeps resetting slightly more than it needs to and "pushing" the content away from the origin.  I've tried setting the content origin to centre, but that just pushes the content away up and left.  What can I do to stop this?
Title: Re: v3.5.0 resizing a scroll view causes content to scroll down
Post by: ArenMook on March 02, 2014, 06:26:47 PM
That sounds very odd. Can you create a simple repro case for me to look at? Just please don't attach it here... email me the download link instead (support at tasharen.com)
Title: Re: v3.5.0 resizing a scroll view causes content to scroll down
Post by: wom on March 04, 2014, 02:21:43 AM
Email sent.
Repro'd on 3.5.2 - same project working the way I think it should on 3.4.9.

Note that I'm not saying it's necessarily broken: just that the behaviour changed and I'd like to be able to get my widgets working the way they were in 3.4.9 if at all possible (and that the current behaviour the way I have the widgets set up is just plain weird).
Title: Re: v3.5.0 resizing a scroll view causes content to scroll down
Post by: ArenMook on March 04, 2014, 03:25:33 AM
Thanks, here is the fix. Replace NGUIText.WrapText function with this one:
  1.         /// <summary>
  2.         /// Text wrapping functionality. The 'width' and 'height' should be in pixels.
  3.         /// </summary>
  4.  
  5.         static public bool WrapText (string text, out string finalText, bool keepCharCount)
  6.         {
  7.                 if (rectWidth < 1 || rectHeight < 1 || finalLineHeight < 1f)
  8.                 {
  9.                         finalText = "";
  10.                         return false;
  11.                 }
  12.  
  13.                 float height = (maxLines > 0) ? Mathf.Min(rectHeight, finalLineHeight * maxLines) : rectHeight;
  14.                 int maxLineCount = (maxLines > 0) ? maxLines : 1000000;
  15.                 maxLineCount = Mathf.FloorToInt(Mathf.Min(maxLineCount, height / finalLineHeight) + 0.01f);
  16.  
  17.                 if (maxLineCount == 0)
  18.                 {
  19.                         finalText = "";
  20.                         return false;
  21.                 }
  22.  
  23.                 if (string.IsNullOrEmpty(text)) text = " ";
  24.                 Prepare(text);
  25.  
  26.                 StringBuilder sb = new StringBuilder();
  27.                 int textLength = text.Length;
  28.                 float remainingWidth = rectWidth;
  29.                 int start = 0, offset = 0, lineCount = 1, prev = 0;
  30.                 bool lineIsEmpty = true;
  31.  
  32.                 // Run through all characters
  33.                 for (; offset < textLength; ++offset)
  34.                 {
  35.                         char ch = text[offset];
  36.  
  37.                         // New line character -- start a new line
  38.                         if (ch == '\n')
  39.                         {
  40.                                 if (lineCount == maxLineCount) break;
  41.                                 remainingWidth = rectWidth;
  42.  
  43.                                 // Add the previous word to the final string
  44.                                 if (start < offset) sb.Append(text.Substring(start, offset - start + 1));
  45.                                 else sb.Append(ch);
  46.  
  47.                                 lineIsEmpty = true;
  48.                                 ++lineCount;
  49.                                 start = offset + 1;
  50.                                 prev = 0;
  51.                                 continue;
  52.                         }
  53.  
  54.                         // When encoded symbols such as [RrGgBb] or [-] are encountered, skip past them
  55.                         if (encoding && ParseSymbol(text, ref offset)) { --offset; continue; }
  56.  
  57.                         // See if there is a symbol matching this text
  58.                         BMSymbol symbol = useSymbols ? GetSymbol(text, offset, textLength) : null;
  59.  
  60.                         // Calculate how wide this symbol or character is going to be
  61.                         float glyphWidth;
  62.  
  63.                         if (symbol == null)
  64.                         {
  65.                                 // Find the glyph for this character
  66.                                 float w = GetGlyphWidth(ch, prev);
  67.                                 if (w == 0f) continue;
  68.                                 glyphWidth = finalSpacingX + w;
  69.                         }
  70.                         else glyphWidth = finalSpacingX + symbol.advance * fontScale;
  71.  
  72.                         // Reduce the width
  73.                         remainingWidth -= glyphWidth;
  74.  
  75.                         // If this marks the end of a word, add it to the final string.
  76.                         if (ch == ' ')
  77.                         {
  78.                                 if (prev == ' ')
  79.                                 {
  80.                                         sb.Append(' ');
  81.                                         start = offset + 1;
  82.                                 }
  83.                                 else if (prev != ' ' && start < offset)
  84.                                 {
  85.                                         int end = offset - start + 1;
  86.  
  87.                                         // Last word on the last line should not include an invisible character
  88.                                         if (lineCount == maxLineCount && remainingWidth <= 0f && offset < textLength && text[offset] <= ' ') --end;
  89.  
  90.                                         sb.Append(text.Substring(start, end));
  91.                                         lineIsEmpty = false;
  92.                                         start = offset + 1;
  93.                                         prev = ch;
  94.                                 }
  95.                         }
  96.  
  97.                         // Doesn't fit?
  98.                         if (remainingWidth < 0f)
  99.                         {
  100.                                 // Can't start a new line
  101.                                 if (lineIsEmpty || lineCount == maxLineCount)
  102.                                 {
  103.                                         // This is the first word on the line -- add it up to the character that fits
  104.                                         sb.Append(text.Substring(start, Mathf.Max(0, offset - start)));
  105.  
  106.                                         if (lineCount++ == maxLineCount)
  107.                                         {
  108.                                                 start = offset;
  109.                                                 break;
  110.                                         }
  111.  
  112.                                         if (keepCharCount) ReplaceSpaceWithNewline(ref sb);
  113.                                         else EndLine(ref sb);
  114.  
  115.                                         // Start a brand-new line
  116.                                         lineIsEmpty = true;
  117.  
  118.                                         if (ch == ' ')
  119.                                         {
  120.                                                 start = offset + 1;
  121.                                                 remainingWidth = rectWidth;
  122.                                         }
  123.                                         else
  124.                                         {
  125.                                                 start = offset;
  126.                                                 remainingWidth = rectWidth - glyphWidth;
  127.                                         }
  128.                                         prev = 0;
  129.                                 }
  130.                                 else
  131.                                 {
  132.                                         // Revert the position to the beginning of the word and reset the line
  133.                                         lineIsEmpty = true;
  134.                                         remainingWidth = rectWidth;
  135.                                         offset = start - 1;
  136.                                         prev = 0;
  137.  
  138.                                         if (lineCount++ == maxLineCount) break;
  139.                                         if (keepCharCount) ReplaceSpaceWithNewline(ref sb);
  140.                                         else EndLine(ref sb);
  141.                                         continue;
  142.                                 }
  143.                         }
  144.                         else prev = ch;
  145.  
  146.                         // Advance the offset past the symbol
  147.                         if (symbol != null)
  148.                         {
  149.                                 offset += symbol.length - 1;
  150.                                 prev = 0;
  151.                         }
  152.                 }
  153.  
  154.                 if (start < offset) sb.Append(text.Substring(start, offset - start));
  155.                 finalText = sb.ToString();
  156.                 return (offset == textLength) || (lineCount <= Mathf.Min(maxLines, maxLineCount));
  157.         }
Title: Re: v3.5.0 resizing a scroll view causes content to scroll down
Post by: wom on March 05, 2014, 03:56:32 AM
Quote
Replace NGUIText.WrapText function with this one
Is that a mis-post? (wrong code in this topic, or maybe you posted in the wrong topic?)

I tried it and it seemed to have no effect.  To be honest, I'm not sure how text wrapping would relate to the scrollview's transform position changing.
In any case, I tried removing the content labels and replacing with a sprite: same result (and the WrapText() function doesn't get called at all).


In your email, you said:
Quote
This happens because you have the "BgSprite" inside your scroll view anchored to something outside of it. You can't have elements inside your scroll view be anchored to elements outside of it.
Move the background outside the scroll view, or don't anchor it. Either one will fix the problem.
I want the background inside the scroll view because I want the user to be able to scroll the content of the window by dragging their finger anywhere within the window.  It's much easier to use in a touch environment and I actually like it better when I'm using my game on the desktop with a mouse (with the old 3.4.9 code-base).

I tried setting the anchor of the background to the scroll view instead of the window, but it still has the "push down" effect when you resize the window.  And when I set the anchor of the background of the window to none, the background doesn't resize with the window.
I'm anchoring the background to the window so that it will resize when the window resizes.   Resizing the background lets the user drag from anywhere within the window and the scrolling of the background sprite gives visual feedback as the scroll is occurring.

I also tried adding a scroll bar - but it still has the same problem.

Assuming there is no change and the answer is "nope - you can't do that any more" - do you have a suggestion on how I should lay out the widgets to achieve the functionality I've outlined?  I'm trying a different approach where the background is outside the scroll view and there's a container around the content inside the scroll view for dragging - bit it has a fair few visual and input problems so far.

Additionally - you might consider adding some kind of input validation to make sure the developer doesn't anchor to anything outside the scroll view. 
I thought it was the obvious way to do what I am trying to do and was very happy when it "just worked" - it'd be good to have some feedback that it won't work. 

Title: Re: v3.5.0 resizing a scroll view causes content to scroll down
Post by: ArenMook on March 05, 2014, 07:18:31 AM
Whoops, yes, wrong thread. Different submitted project.

Quote
I want the background inside the scroll view because I want the user to be able to scroll the content of the window by dragging their finger anywhere within the window.
So create an invisible collider covering your scroll view. ALT+SHIFT+W, ALT+SHIFT+C, then add UIDragScrollView to it. Anchor this widget.
Title: Re: v3.5.0 resizing a scroll view causes content to scroll down
Post by: wom on March 06, 2014, 03:11:32 AM
So create an invisible collider covering your scroll view. ALT+SHIFT+W, ALT+SHIFT+C, then add UIDragScrollView to it. Anchor this widget.

Ahhh - I gotcha now.
Thanks for the help.

For anyone else who is doing this and is confused like I was (tried a couple of times before I got it working):
Following Aren's instructions, you need to have the window selected when you create the container widget with the collider.  Then, change the anchor setting to point downward in the component hierarchy to the scroll view (it will default to pointing upwards at the window). 


UIDragResize script (targeted at the window) will resize the scroll view and container at the same time (because both are anchored to window) and dragging anywhere in the window will scroll the content (because UIDragScrollView targeted as scroll view).


Next up: pinch resizing, god help me.