UMG layout rules ?

Have been watching this series about UMG https://www.youtube.com/watch?v=8Osr1UsuEvA

It’s great and all, but I don’t quite get why build UMG the way he does. Why can’t it be Canvas and have button and text on that canvas without such deep hierarchy and several size boxes for slot widget?

HTML/CSS is much easier to understand how to design UI with than UMG :confused: Are there any good tutorials explaining general rules of building UI using UMG and what elements have to be parents in order to get proper layout ?

Thanks

Well, the part he’s showing is how to create the inventory slot, which goes inside the inventory, and that’s done by deleting the canvas.
Maybe you’re wondering, why not add buttons to the inventory and have them as slots? That would be a programming nightmare.
By making the inventory slot from a separate widget, you get a great deal of control of how it behaves and without this way of doing things you probably couldn’t do things like drag & drop operations.

So what’s with these deep hierarchies? And I agree, I find myself creating silly deep hierarchies when creating some widgets, but then again… there’s not much choice.
For example, the border can only have 1 child, so instead of directly filling the border with the stuff you want, you first have to add something that can hold more children.
Or, if you want two elements beside each other you have to use the horizontal box.
As for the size box, by default the widget components added tend to either try to take as little space as possible or as much as possible, if you want them to be a certain size, you got to use the size box. It’s a bit of a hassle.

I think I started by just reading the UE docs on umg while playing around with it in the engine. You will find yourself wanting to add something to something else, but you can’t since it can only have one child and it already has it, so you need to add something that can hold more children.
Want to create something with a header and a body which is divided into…? Okay start with the first part. Header and body are layout vertically, so you need a vertical box. Then look at the layout you want the body to be. It just kind of makes sense after a couple of days of messing around.

No, that’s not what I am wondering about.

I read docs, I watched WTF is? videos on youtube, so I got some ideas about UMG and widgets. However, none explain why use one over another widget and what’s the proper hierarchy. For example, WTF is? or HTF do I use ? videos imply that Canvas is the one that always has to be the parent. However in the video I linked he uses size box first, then canvas, then size box again.

Here is what I am after (that will be a 3D widget located in the lower left “corner” of the player’s view):

Basically a vertical box with semi-opaque background that houses several item widgets (initially there will be none, but as player picks up unique items, item widget with appropriate icon is added to the vertical box). On stacked items the amount (x999 text on the mockup) will change, on unique items it won’t even show.

I already have inventory system working. Now I just need to make UI for it :o

Yea, I’m not a big fan of the UMG system either. It seems overly complex for no good reason. As you say, HTML/CSS is more intuitive and can accomplish more than UMG can. I think you can use whatever you like as the parent object, but the canvas is the default which is probably why it’s used so often in videos as the parent.

I think your mockup there will work. A vertical box full of sub-widgets should work just fine. I typically use a canvas to achieve the semi-opaque background effect though. If that’s the case then I would start with a canvas for a parent and apply the background to this and then add the vertical box inside of this.

A comparison to HTML would be like:

<div style=“background-color:rgba(0,0,0,0.5)”> <- This is the canvas
<ul> <- This is the vertical box
<li></li>
<li></li> <- These are the sub widgets.
<li></li>
</ul>
</div>

While I have created quite a few widgets so far (inventory, equipment, skill window, and a few more niche things) I’m definitely no expert.
When it comes to the canvas panel, in a sense it has to be the top most parent, but not for each individual widget.
What I mean is, say you have an inventory and equipment window. They can either have a canvas panel each, and you add each of them to the viewport. Or you can have another “main widget” which you then add these inventory & equipment widgets to. What’s the best practice in that case, I really do not know.

But when it comes to inventory with inventory slots, definitely don’t use canvas panel for the slots.
You create the main inventory, which is a vertical box. Which would look something like
Canvas panel - border (visualizing the inventory) - vertical box (storing the slots).
Then, I suppose during the construction event of the inventory widget, you create the inventory slots you want and add them as children to the vertical box.

These inventory slots does not have a canvas panel, but instead (can) have a sizebox as the base so you can determine their size, a button (or something else) for the interaction and then maybe some image.
The button will stretch over the whole view, making it look a bit weird, but it will look good when added to the vertical box.

Of course, to have it look better, you might want to add a border inside a border so it’s not too sterile. Those black outlines though, I have no idea how to do.

The vertical box should be expanding automatically as you add new slots.
The size box is a bit tricky to use. Sometimes the buttons (let’s say you’re using buttons) will fill as much as they can, as long as they keep square. Other times, they will stretch into rectangles. It’s a fiddly business. I’d say try without it first and see how it works.

Example: inventory widget and slot widget. And also a debug window…

Invex.png

Oh yeah, I forgot;
If you add 2 elements to say a vertical box, you can choose if they should fill or have some other alignment. But in the case of a header and body situation, you probably don’t want them to divide the space in half. The header should only be at the top. That’s a good situation for the size box, if the “align to top” doesn’t do its job properly.

Canvas is useful if you want to shift widgets around, casting a widget as a canvas slot gives you access to the canvas’ child’s screen location. Canvas is also useful if you want to control Z order of canvas’ children. A canvas nested in another canvas can be useful if you want to have a draggable window.

Since your 3d widget component will be pretty much immobile and house just a vertical box populated during run-time with custom Item widgets, no canvas is really needed.
Neither would I bother with canvas for the Item itself.

For the vertical box, I’d try:
[Border](to control colour and opacity of the background, or even assign material)
[VerticalBox](or scrollbox if you worry about overfill)

For the item:
[Border]
[Overlay]
[INDENT][Image](H/V fill)
[TextBlock](align bottom right)[/INDENT]

Thanks folks, I’ll experiment. It just seems to be overly complex and poorly documented :confused:

Well, true, but I need to vertical box to expand upward, not downward. Does [border] provide anchors for [vertical box] ?

Also, vertical box will be dynamically filled. Would I be able to access it without having canvas ?

It’s the canvas that provides anchors, true. But, in this case you are using a 3d widget - that quad *is *your canvas. Every time you add an Item, you can increase the DrawSize of the widget component by the size of the added Item (and/or simply push the component up thus creating more space below - creating the illusion of the box expanding upwards. Untested, but that should work.

You could also vertically align the vertical box to the bottom of its border - this should work automagically, actually.

Yet another solution here would be to use a vertical scrollbox and set the scroll value to max as soon as you push the item in. This way you do not need to worry about adjusting the size of the 3d widget, set it to it’s max and let the scrollbox accumulate Items (and you can still scroll to them should you run out of vertical space).

Yes, Widget Component reference –> GetUserWidgetObject –> Cast to YourWidget –> exposed VerticalBox –> Add Child

Again, me saying that this should work does not mean it will. But do let us know if something is not adding up.

I got basic layout done (will have to probably tweak it as I move along).

Now I am thinking of how to pass item data from my inventory to the widget. As I add item into the inventory (2 arrays of structs - one for unique items, one for stackable/“currency” items), I can just pass reference to the widget. I am not quite sure yet how to update text on widgets for stackable items (like, instead of adding yet another widget to my vertical box as I add another item into inventory, I’d only update text on the widget for specific item if it already exists in my inventory).

I already have code that lists inventory (I needed to check if it’s really working, so when I press “I”, Print String prints items and their respective amount on the screen). I am just not sure how to relate that to UMG :confused:

I’d appreciate your advice.

Thanks

P.S. Thinking more about this and maybe I should just pass entire inventory array into UMG and re-fill vertical box every time item is added to/taken from the inventory ?

What I ended up doing at some point, through trial and error (mostly error), was to make the inventory a separate actor altogether. That actor would be then responsible for handling the inventory content and widgets, and it would have its own setters and getters. The actor would hold an array of Item structs and populate/update the inventory widget with the content of this array. The reason behind this is that it’s much easier to manipulate an array than fiddle with a widget’s list of children.

This is a solid idea.

You generally do not need to redraw the *entire *inventory. When inserting in the middle or removing, you can repopulate from the index of insertion only. Indexing can get a bit more complicated when you need to handle something like in ste1nar’s example.

Another thing you could consider, is to pre-spawn all the Item widget that a menu can hold - this can be useful for an inventory of fixed size - the widgets either display the item or an empty slot.

I apologize for necroing this, but…

How exactly would you go about “pre-spawning” widgets for a panel?

You can manually populate the panel by drag-dropping user widgets there. Or you can use Event Pre Contruct (for visualising in the Designer) / Event Construct and create children widgets in a loop.

Example here, using just the loop (ignore all nodes before it) and adding the script to a Pre Construct event should give you a grid layout in the designer. Handy if you do not want to drag and set up 100 user widgets manually.