Hey, has anyone been able to create a layout for a UMG Widget in C++?
Right now iam designing the widget in the UMG Designer and then access the object from code but i want to avoid that for several reasons. So has anyone some infos on that?
this is what i have so far the problem is the thing doesnt show up in the widget Hierachy nor in the Designer itself
Header:
UImage* ButtonImageControl;
Source:
//part of the construction script
ButtonImageControl = PCIP.CreateDefaultSubobject<UImage>(this, FName(TEXT("Button Image Control")));
ButtonImageControl->AddToRoot();
Have you looked at what this function does? I do not think it means what you think it means.
//
// Add an object to the root set. This prevents the object and all
// its descendants from being deleted during garbage collection.
//
FORCEINLINE void AddToRoot()
{
SetFlags( RF_RootSet );
}
As a reminder, all the constructor does is initialize the values of the class default object. While constructing a UWidget as a default subobject is possible, adding logic to display it on screen is not. The two functions used by UMG to construct widgets are UWidgetTree::ConstructWidget (UWidget + UUserWidget) and CreateWidget (UUserWidget only). The function used to display UUserWidgets is AddToViewport. Have a look at what they do, and you should have a fair indication of what you need to do:
ConstructObject is already covered by your CreateDefaultSubobject. Initialize is only necessary for UserWidgets (it uses the Blueprint generated widget class and creates the widget tree done in the designer).
if ( !FullScreenWidget.IsValid() )
{
TSharedPtr<SWidget> OutUserSlateWidget;
TSharedRef<SWidget> RootWidget = MakeViewportWidget(OutUserSlateWidget);
FullScreenWidget = RootWidget;
// If this is a game world add the widget to the current worlds viewport.
UWorld* World = GetWorld();
if ( World && World->IsGameWorld() )
{
if ( UGameViewportClient* ViewportClient = World->GetGameViewport() )
{
ViewportClient->AddViewportWidgetContent(RootWidget, 10 + ZOrder);
}
}
}
All this does is store a weak pointer to the underlying Slate widget so that UUserWidget can remove it as needed, then it adds said widget to the viewport overlay. Basically, all you need to do is get the game viewport and add the widget to it. As mentioned, this won’t work in the constructor. The earliest you can do this is PostInitializeComponents (maybe PreInitializeComponents, but don’t bother unless you have components depending on this widget for initialization).
Note that I’ve never tried creating a UWidget as a default subobject. It may be that you also have to construct it in PostInitializeComponents.