Tasharen Entertainment Forum

Support => NGUI 3 Documentation => Topic started by: ArenMook on November 20, 2013, 07:43:17 PM

Title: UIWidget
Post by: ArenMook on November 20, 2013, 07:43:17 PM
Overview

UIWidget is a basic NGUI component. In simplest terms, it's just a rectangle that you can position on the screen however you like. This widget, while has an area, is also completely invisible at run-time -- making it ideal for use as a container holding other components.

(http://www.tasharen.com/ngui/uiwidget.jpg)

UIWidget also happens to be the base class for all drawn NGUI elements -- including sprites and labels that you use to create your user interfaces. UILabel, UISprite, UITexture and UI2DSprite classes all derive from UIWidget.
In the code, the widget's position is specified using the Transform component -- just like any other game object. The position is always relative to the widget's Pivot point. A pivot point basically means "the point widget rotates around".

Widgets also have Depth that controls their order when clicking on them (and in case of derived classes such as Sprite and Label -- their draw order). This order can be observed by right-clicking on the widget in the Scene View and choosing the Select menu. Doing so will give you a list of all the selectable widgets underneath the mouse in the same order that they will be drawn / receive events -- top to bottom.

(http://www.tasharen.com/ngui/rclick.jpg)

The same context menu can also be used to add siblings and children to your widgets as well as attach scripts and create new elements.

If you are looking for the documentation regarding the Anchors section, you can find it in the base class -- UIRect (http://www.tasharen.com/forum/index.php?topic=7013).

Class Documentation

http://tasharen.com/ngui/docs/class_u_i_widget.html

If you have a question regarding this component or would like me to clarify something, just post a reply here.
Title: Re: UIWidget - UpdateWidgetCollider
Post by: kasparlund on December 30, 2013, 01:09:52 PM
Hi

In NGUITools.cs line 290 there is the following statement
if (!w.isVisible) return;

I believe this is inconvenient because it prevents you to calculate layout and sizes before display including setting the right collider area using the UIWidget feature to update the collider.

Could this be improved in a future version. Alternatively UIWidget could update the collider area when it becomes visible ?
Title: Re: UIWidget
Post by: ArenMook on December 30, 2013, 01:42:59 PM
Fair enough. I can remove it.
Title: Re: UIWidget
Post by: heeroz on January 02, 2014, 05:32:05 AM
"aspect ratio" is helpful, but how about one more aspect ratio options, "Fill" ? Just same as UIStretch "FillKeepingRatio" Style.
Useful for which I want it to fill the screen like splash screen.
Title: Re: UIWidget
Post by: PoN on February 11, 2014, 08:48:12 PM
What is better(performance, decrease drawcalls) to use if i would like to make a window in a game - UIPanel or UIWidget ?
Title: Re: UIWidget
Post by: ArenMook on February 11, 2014, 09:08:27 PM
Panel is what draws widgets. That's like asking what's better to use -- a file or a folder -- just doesn't make much sense.

It's generally a good idea to have one panel per window.
Title: Re: UIWidget
Post by: Lautaro on February 12, 2014, 08:52:42 PM
Hi! I have a prefab with a hierachy of different gameobject with NGUI widgets. They are inventory slots. I have 8 of them as the inventory. Then i have another one that follows the mouse to show what you have picked up from the inventory. This hand-slot is rendered behind then inventory slot. How can i make it render in front?
Title: Re: UIWidget
Post by: ArenMook on February 13, 2014, 03:20:19 AM
Put it underneath a different panel that has a higher depth.
Title: Re: UIWidget
Post by: Lautaro on February 13, 2014, 05:24:36 AM
Brilliant! Thanks.
Title: Re: UIWidget
Post by: VapapeurTeam on February 25, 2014, 09:46:48 AM
Hello,

The documentation page for UIStretch (this one (http://www.tasharen.com/forum/index.php?topic=6713)) says that UIStretch is now deprecated and invites you to visit the Widget or Panel documentation instead.

However, I don't see how I can mimic the behaviour of the old UIStretch using the Anchor features of a Widget. It seems to be replacing the functionality of the old UIAnchor script (like, I want my sprite to be 10px from the bottom of the screen no matter what), but for example if I want my sprite to always have a vertical size equal to 10% of my screen vertical resolution, how can I specify that in the Widget ? I would have used a UIStretch to do that, but here, all the input seems to be in pixel so I can't do relative sizes.

Thanks in advance.
Title: Re: UIWidget
Post by: ArenMook on February 26, 2014, 03:51:22 PM
Change the anchor target to be "custom", and give it a relative value. 10% would be 0.1: http://www.tasharen.com/forum/index.php?topic=7013.0
Title: Re: UIWidget
Post by: VapapeurTeam on February 27, 2014, 05:46:39 AM
Wow, alright, I completely missed that Custom thingy. It's awesome, thank you :)
Title: Re: UIWidget
Post by: balzaque on March 10, 2014, 10:02:39 AM
Hi, I'm trying to make 4 widgets stay docked on the four corners of the screen.

My current settings:
Scene on 4:3

All widgets
size: 400x100, all anchors set to Advanced and all anchors not used set to None

Widget01:
Left, Targets Left, 20
Top, Targets Top, -20

Widget02:
Right, Targets Right, -20
Top, Targets Top, -20

Widget03:
Left, Targets Left, 20
Bottom, Targets Bottom, 20

Widget04:
Right, Targets Right, -20
Bottom, Targets Bottom, 20

When I try to resize the scene, like to 16:10, the widget sizes start to change for no reason and they don't stay where they are supposed to. Am I doing something wrong here? The target for the anchor is the "UI Root" and currently having only a UIPanel since I'm not using the UIRoot component. I also tried to use Custom on the anchors settings but it seems that as soon as I lose focus on the Widget the settings go back to the old value.

Thanks!

Edit: just figured out what I was doing wrong, the items inside the widget need to be anchored to the right part so when things stretch they follow staying in the right place. Fighting over this during the weekend but at least know I think I'm starting to understand how to do things right. xD
Title: Re: UIWidget
Post by: ArenMook on March 10, 2014, 09:30:27 PM
If you don't set anchors on some sides, it will behave as if anchored to the center (they will stay where you left them).

If you want something to remain anchored to the top-left, you need to set all 4 anchors. Left to left, right to left, top to top, bottom to top.
Title: Re: UIWidget
Post by: PoN on March 12, 2014, 03:36:32 AM
before i have animated scale of transform , but now i should animate Dimensions of UISprite, how can i do that?
thanks.
Title: Re: UIWidget
Post by: ArenMook on March 12, 2014, 06:11:06 PM
You can still animate the scale like before, or choose to animate the width and height. TweenWidth / TweenHeight can do that for example.
Title: Re: UIWidget
Post by: Anomalous Underdog on April 03, 2014, 05:31:48 AM
Let's say for example I anchor the left part of my widget, but I want the width to be locked to a constant value even if the widget's x position is changed. Is there a way to do that?

Currently my experience is that the right edge of the widget stays where it is on the screen, causing the widget's width to lengthen/shorten when its x position is changed.
Title: Re: UIWidget
Post by: Isamson on April 03, 2014, 03:33:03 PM
Within the Widget's Anchor setting, select advanced. This will allow you to snap your object sides to different objects. Since you want your right side to stay the same, drag the object(self) in the right anchor. Select the "Target's Left" and enter the size you want this object to be.
Title: Re: UIWidget
Post by: AbsurdInteractive on April 04, 2014, 05:30:22 PM
I had a question regarding Anchors on UIWidgets and UIPanels. The way my game structure is setup, I set all my cameras in the first scene, then I load the separate UI scenes in with LoadLevelAdditive.

I'd like to base all my NGUI Sprites and elements positioning anchors off of my Camera's 4 corners, but because the camera is set at runtime, and not in the UI scenes ahead of time. I was wondering what's the best way to setup the UI scenes so that they can be anchored correctly.
Title: Re: UIWidget
Post by: ArenMook on April 04, 2014, 10:54:15 PM
Easiest way would be to anchor everything to a panel, not the camera. The panel would automatically assume screen's dimensions if it's not clipped.
Title: Re: UIWidget
Post by: Aithoneku on April 09, 2014, 02:42:40 AM
I've got two problems with UIWidget so I would like to ask for help:

1.) As it was mentioned above, UIStretch is currently deprecated so I would like to ask how to achieve following functionality with anchoring system (I guess I'm missing something and cannot figure it out) - stretch a sprite so it fills whole screen but at the same time it's keeping aspect ratio AND it's visible completely regardless on whether screen aspect ratio is greater or less then aspect ratio of the sprite. (So it makes horizontal or vertical bars of space in order to keep the ratio). Similarly, how to achieve same thing, but this time the image should be cropped (horizontally or vertically depending on whether current aspect ratio of screen is greater or less then ratio of the sprite)? My current solution is my own custom Stretch script, but I would like to know the "correct" way how to achieve this with anchors if they should replace old anchors and stretch.

2.) Both width and height properties of UIWidget contains condition "keepAspectRatio != AspectRatioSource.BasedOnHeight"
  1. // width property, line 169
  2. if (mWidth != value && keepAspectRatio != AspectRatioSource.BasedOnHeight)
  3.  
  4. // height property, line 216
  5. if (mHeight != value && keepAspectRatio != AspectRatioSource.BasedOnHeight)
  6.  
Is there reason for that or is it a bug? I noticed following behavior with this when I set Aspect Ratio of a sprite to BasedOnHeight:
But when I change height property to
  1. if (mHeight != value && keepAspectRatio != AspectRatioSource.BasedOnWidth)
both works just fine.

Note: as this is my first post on this forum, I would like to thank you for your hard work with NGUI - it's really good GUI library, I guess best for Unity. I like it's both simplicity and ability to edit GUI in Unity Editor. It has it's bugs (for example when I use sprite with a lot of transparent space around and turn on "Trim Alpha" in atlas, the sprite is quite badly deformed in GUI screen when changing it's size), but still pretty much best solution I encountered.
Title: Re: UIWidget
Post by: ArenMook on April 09, 2014, 04:20:03 AM
#2 tells me that your version of NGUI is not up to date.

#1 -- Anchor sprite's top to screen's top. Anchor sprite's bottom to screen's bottom. Don't anchor left or right. Set the sprite to have an aspect ratio of your choice, based on height. If you want it to be based on width instead, set left and right anchors instead.
Title: Re: UIWidget
Post by: Aithoneku on April 09, 2014, 08:06:25 AM
#2 Ah, sorry, I thought it is. (It's company's and I thought we're keeping it updated.) Sorry about that.

#1 Sorry, but no, that won't work. This would work if I would define my problem as "I want to display whole image and keep it's aspect ratio AND I know that aspect ratio of screen will be ALWAYS greater then AR of the image" or as "I want to display image stretched vertically and crop it OR add spaces on sides according current screen AR keeping AR of the image", but I defined it as "stretch a sprite so it fills whole screen but at the same time it's keeping aspect ratio AND it's visible completely regardless on whether screen aspect ratio is greater or less then aspect ratio of the sprite". Your solution wouldn't work if the AR of screen would be less then AR of image. Example: image is 16:9, but screen is 4:3 - left and right sides of image would be cropped. Using horizontal (left and right) anchors instead of vertical anchors won't help either - what if image is 4:3 and screen is 16:9? Image would be cropped above and under the screen.

(Note: if you're going to say something like "then use image which is so wide that it's AR is greater then highest AR you're ever expecting - it's not up to me to decide that. Also, screens are getting wider and wider - 5 years ago, I would expect 1280x800 to be widest - that would be silly now, wouldn't be...)
Title: Re: UIWidget
Post by: ArenMook on April 10, 2014, 08:10:35 AM
Different aspect ratios mean something will be cropped, or padding will be visible, depending on how you do it. It's the only way to do it without skewing the image's aspect ratio. Either you anchor to top/bottom and get some padding on the sides, or you anchor left/right and get cropped top & bottom. If you want the image to always be 100% visible on the screen, implying that it gets smaller to always have all 4 sides visible, then you shouldn't be using anchors as it involves custom logic at this point. Write some code to reduce the size if it doesn't fit.
Title: Re: UIWidget
Post by: Aithoneku on April 10, 2014, 09:41:29 AM
I see, ok, so it's not possible, thanks for the info. I was just little confused, because I read somewhere that new anchor system is replacing functionality of UIStretch and UIAnchor - I wrongly thought it is meant that it replaces the functionality completely, not partially, sorry about that.

Just for the record, if you're interested, my solution is then using something similar to UIStretch. I'm aware, that it's deprecated, so I created my custom class which inspires by the UIStretch somehow.
Title: Re: UIWidget
Post by: artician on August 23, 2014, 07:34:20 PM
I'm using PlayMaker with NGUI, and I'm unable to figure out how to access the Anchor property on a UIWidget object.  PlayMaker has a Set Property function that exposes the properties in an object, but I can't find anything relating to UIAnchor anywhere.  Can anyone clear this up for me?
Title: Re: UIWidget
Post by: ArenMook on August 23, 2014, 08:16:54 PM
UIRect.leftAnchor, UIRect.rightAnchor, etc. You likely do need to write something for PlayMaker to understand them though. I'm not too familiar with it.
Title: Re: UIWidget
Post by: serioustommy on October 08, 2014, 12:19:22 PM
I'm trying to replicate what I used to do in UIAnchor in UIWidget but it doesn't seem possible (at least not without some custom scripts).

Basically I'm just trying to anchor relative to the screen size like setting the "relative offset" values in UIAnchor. If we want to be able to anchor to the screen is the best practice now to create a dummy panel/widget and attach some custom script to resize it to fit the screen size?
Title: Re: UIWidget
Post by: ArenMook on October 08, 2014, 01:38:11 PM
Instead of using fixed anchor points such as "Left", "Right", "Center" etc, use "Custom", then specify a relative value (generally in 0 to 1 range). Value of 0 means 'left' or 'bottom', depending on the axis. 0.5 is center, 1.0 is right/top. 0.25 means 25% from the left/bottom, etc.

It's all explained here: http://www.tasharen.com/forum/index.php?topic=7013.0
Title: Re: UIWidget
Post by: serioustommy on October 09, 2014, 06:27:03 AM
But a "target" is needed for that. What is the target when I want the target to be the whole screen? Do I need to create a dummy transparent panel that resizes to represent the whole screen?
Title: Re: UIWidget
Post by: ArenMook on October 10, 2014, 02:57:53 AM
Target the camera.
Title: UIWidget onChange
Post by: Maxii on October 13, 2014, 11:04:02 AM
My objective is to be notified when UIWidget's dimensions change. I've found UIWidget.onChange which is described as "Notification triggered when the widget's dimensions or position changes". In the code, onChange is raised in UpdateTransform() whose description is "Check to see if the widget has moved relative to the panel that manages it".

As I only want to know when the dimensions change, I'm not interested in being notified when the widget moves relative to the panel, so to eliminate those notifications, I've placed my 'faceCamera' script so that it rotates the panel rather than rotating the widget, thinking that this way, the widget won't move relative to the panel. Unfortunately, whether I rotate the widget underneath the panel, or rotate the panel directly, I still get all the widget onChange notifications of movement.

Am I misunderstanding something here? Shouldn't rotating the panel directly keep the widget from generating all these onChange (aka I moved relative to my panel) notifications? ... or is the "Check to see if the widget has moved relative to the panel that manages it" comment misleading, and any absolute widget movement raises onChange?
Title: Re: UIWidget
Post by: ArenMook on October 14, 2014, 03:50:22 PM
OnChange will be called if the widget gets moved or its size changes relative to the panel that manages it. Rotation changes may cause slight variation in the position changes, thus causing the inequality checks to go through. Not sure why you need to do that though. If you really only care about width and height changes, then why not just have a script that stores the previous width and height and compares them against the new ones?
Title: Re: UIWidget
Post by: Maxii on October 14, 2014, 05:32:16 PM
The check for a change in width/height is the current filter I use to ignore 99.9% of the onChange calls right now.

My reading of the comments on the event and methods led me to believe that onChange should only be called when the widget moves relative to its panel which I believe you are confirming. From my testing, when I rotate the panel that manages the widget (without moving the widget relative to the panel), I'm getting an onChange event every frame - aka hundreds per second until the rotation completes.

My filtering works fine. It just seems like a waste of effort when I have to filter it every frame to catch the .001% of the time when I change the dimensions. Thought you should know about the observation. Thanks for the support as always.
Title: Re: UIWidget
Post by: Maxii on October 17, 2014, 09:17:20 AM
Just to clarify - do you mean

1. OnChange will be called if the widget gets moved relative to the panel that manages it, or its size changes relative to the panel that manages it, or
2. OnChange will be called if the widget moves at all or its size changes relative to the panel that manages it.
Title: Re: UIWidget
Post by: ArenMook on October 18, 2014, 09:06:14 AM
Anything that involves visual movement relative to the panel that manages it. Scale, transform, width, height. Everything.
Title: Re: UIWidget
Post by: Maxii on October 18, 2014, 11:15:30 AM
Ahh! That did it. I was scaling my widget underneath the panel. Once I moved the scaler above the panel, onChange only fires now when I would expect it too. Thanks.