UMG Widget GetDesiredSize()

G’day,

I’ve been trying to use GetDesiredSize() in various Widget Blueprints without any luck.
It never seems to t return any useful values.

  1. Create new Widget Blueprint and make sure it is added to the scene somehow.
  2. Add an Image Widget, make it a variable.
  3. Set the Images horizontal and vertical align to fill.
  4. Set the Images Appearance → Brush → Image Size to some odd value.
  5. Use a Tick event to report the value of the images GetDesiredSize().

Does it need children or something to report a useful value, or is it simply a bug.

Just wondering.

Kris

EDIT: A more complete answer is below.

Ok, I think I see the source of confusion. I will help clarify things. However, I am curious why you would want to know the DesiredSize of a widget. Usually that’s not something you care about unless you are writing a layout panel.

##Slate/UMG Layout
Here’s a quick overview of how layout in Slate and UMG works. Slate layout is a two pass solution.

  1. First we compute the DesiredSize of each widget. For primitive widgets (e.g. Text, Images) the DesiredSize is computed based on their intrinsic properties. For example, the DesiredSize of a block of text depends on the font face, font size, and the actual text. For SImages, the desired size is determined by the size of the Brush being shown. Because Slate aims to support a variety of resolutions, the size of a Brush is specified explicitly by you in Slate Units. When you set a texture on a Brush we default it to the image’s size in pixels because that’s probably what a lot of folks want. However, you could use the same high-resolution image with varying brush sizes. By setting the size back to 32x32 you have effectively said that the image should be treated as though it is 32x32 Slate Units and that is the reported DesiredSize. For aggregate widgets (i.e. those that arrange other widgets together) the DesiredSize is computed based on the contained widgets and the arrangement rules. For example, if you have a panel that arranged two images size by side and the images are 32x32, then the DesiredSize of the panel will be 64x32.

  2. During the the second stage of Slate’s layout we arrange all the widgets so that we can call Event Tick() and ultimately Paint() the widgets to the screen. Arranging simply means that each widget is assigned an explicit position and size. The position and size are based on the available space, the desired size of widgets, and at the various layout setting that you specified (e.g. Padding, Alignment, Anchor points, etc.). The computed size and location of the widget are provides as Geometry in Tick(). Note that the DesiredSize() is used to compute the final Geometry, but it is not always going to be the same as the Geometry. If I set a widget to fill the whole screen, its DesiredSize() could be a small number, but its computed Geometry will be the size of the screen.

A word of caution: you should never attempt to set layout properties based on the results of layout. For example, it is a bad idea to grab the Geometry of a widget and then say “Let’s set the padding of something based on that Geometry”. This can lead to a cycle in the layout solution and your UI will wiggle like crazy. The bad thing about this is that it will be very difficult to debug such issues.


##Original Answer
Without knowing the exact details of your setup, I cannot tell. However, I did set up a trivial experiment and the desired size of my widget is reported correctly in Tick(). The desired sizes are computed and cached in a separate pass before Slate Ticks and Paints. By the time we Tick() and Paint() all the desired sizes are known.

A widget does not need children to have a desired size, but contained widgets will have a desired size of 0 when they don’t have any children.

Quesiton: What do you mean when you say the values aren’t useful?

2 Likes

I usually include screenshots, but it was late and I was tired.
Moving on.

The values returned are not the size of the widget but simply those set by Appearance → Brush → Image Size.

Here is a test setup I just created with UE4.6.1.
It becomes a child of an Overlay widget with its Overlay Slot set to fill both Horizontally & Vertically.

The Image being used is 2048x1024 in size.
Note that I reset Appearance → Brush → Image Size back to default 32x32.

Here is the graph setup to have Tick() & Paint() report desired size.

Here is the result in-game.

The image is clearly not 32x32 pixels in size.

This setup seems correct, hence my confusion about what values GetDesiredSize() is returning.

My current workaround is to use a custom UserWidget that uses the geomtry supplied in Tick() to figure out the size.

It works, but its a bit of a hack :slight_smile:

Thoughts?

I added some useful info to my original answer because this comment area could not fit all the text. Your solution is the correct one; a widget’s Geometry is computed by the layout system and provided in Tick. The DesiredSize() is merely an input into the layout system. Check out the more detailed answer above. Hope it helps.

Thank you for clearing things up for me.

However, I am curious why you would
want to know the DesiredSize of a
widget.

I wanted to know the size of the widget so that I could position other widgets on top of it. Without knowing its exact width and height the first widget, there was no way to accurately position these additional widgets accurately.

Here’s a rough example I did as a minimap with known sizes:


I feed the scenecomponent through a custom project function to get the X/Y coordinates.
I then scale those coordinates based on the size of the minimap render target texture to figure out where to render the dot.

I was hoping that I could do GetDesiredSize() instead having to access the geotmetry manually or do a Texture → GetSizeX/GetSizeY etc.