Populate UMG Widget dynamically from C++

Ok, so I’m not actually sure which section to use, and as I’m a C++ guy I’m posting it here. So I’m driving my UI switching and display from my GameMode class in C++. I currently have 3 UIs set up, with plans to add more. Depending on context, I change the HUDState to switch the UI being shown.

One of these UIs is for inventory. At the moment it is bare, just a header and a scroll panel. The scroll panel is actually another widget I created for this. I also have a widget for items which is text wrapped in a button.

I need to know how to dynamically update the scroll box and populate it with item widgets as the player’s inventory changes. I’ve tried to do it from inside the widgets, I’ve got references to the widgets in my C++ and I’ve tried to do it there, and I just can’t seem to figure it out.

For specifics, as a player adds or removes from his inventory by whatever means, I would like an Item widget made and added to the scroll panel widget, which is displayed in the Inventory UI.

I would prefer C++, but if the only way to do this is the UMG visual editor that’s fine too.

Before it’s suggested, I have UMG added to Public and Slate and SlateCore added to my build.cs. I had to to be able to drive the states for the HUDs. I just can’t figure out how to dynamically construct item widgets and add them to the scroll panel.

You can just use NewObject to create the widget and then add it as a child to a panel widget, there are many types of panel widget (canvas panel, scroll box, vertical box, etc.) and most of them has their own specific way to add child, so you might want to look it up in the API document:

Now for you particular case, assuming that the scroll box that you have created is exposed as variable with the name “MyScrollBox” and that you are using a vertical box inside of it to arrange your item widgets then the code would be something like this (note that I write this code without trying it, it’s not even written in a proper c++ text editor, I only wanted to show you how it’s done in c++) :

UCLASS()
class UMyInventoryWidget : UUserWidget
{
	GENERATED_BODY()

	UPROPERTY()
	UVerticalBox* ItemWidgetsBox;

	virtual void NativeConstruct() override
	{
		Super::NativeConstruct();

		if ( UScrollBox* ScrollBox = Cast<UScrollBox>( GetWidgetFromName("MyScrollBox") ) )
		{
			ItemWidgetsBox = NewObject<UVerticalBox>();
			ScrollBox->AddChild( ItemWidgetsBox );
		}
		else
		{
			// Can't find the scroll widget, wrong name maybe, or a widget with that name is not a scrollwidget
			ItemWidgetsBox = nullptr;
		}		
	}

	UFUNCTION(BlueprintCallable)
	void SetItems( const TArray<UItem*>& Items )
	{
		static FMargin Padding( 5 );

		if ( !ItemWidgetsBox )
		{
			return;
		}

		ItemWidgetsBox->ClearChildren();
		
		for ( UItem* Item : Items )
		{
			UItemWidget* ItemWidget = NewObject<UItemWidget>();
			ItemWidget->SetItem( Item );

			UVerticalBoxSlot* Slot = ItemWidgetsBox->AddChildToVerticalBox( ItemWidget );
			Slot->SetPadding( Padding );
		}
	}

};

Thanks. That is exactly what I’ve been trying to figure out.

Hey there! I understand the code pretty well, but I am a little bit confused as to where I implement it. Do I create it as it is being called? In that case, each time I change the state of the item, I would have to reload the entire inventory widget, is that correct?

If it’s the state of an item (not the list of items) then I wouldn’t re-construct the inventory widget, I would make a multicast event in the item class and have the corresponding Item Widget to listen to that event and update the display accordingly.

Changing the list of items can also be optimized as to prevent the re-construction of the whole inventory widget, it all depending on the inventory system you use in your game, I didn’t do it the game that I am making simply because the one I had is quite simple and re-constructing the whole things takes a very short time, but I assume if the inventory contains 100 or more items and uses render texture for the icon then optimization might just worth it.