Download

UMG and C++

Hi,

Im diving a bit into UMG with C++. Until now I created all the widget logic with blueprints in the widget graph.
Now I want to do things more in C++.
I created a widget code class extending UUserWidget and added some variables (as UPROPERTYs) to it.
Then I created a widget to work with in the designer and reparented it to the code widget class.
So far, so good. I can see all the C++ variables and functions in the designer graph.

But how can I access the various components I set up in the designer?

For example:
In the designer I add a textbox.
In the code class I have a C++ function: SetValue(float Value);

In the implementation of the SetValue function, how do I access the textbox?
Since the BP widget class inherits from the code class, the code class cant know about the textbox, right?

Any help is appreciated :slight_smile:
Cheers,
Klaus

You have to declare your widget variable in c++ with the same name as the widget in the designer and use the following UPROPERTY



 UPROPERTY(BlueprintReadWrite, meta = (BindWidget)) 

More info here http://benhumphreys.ca/unreal/ui-bindwidget/

@JohnMakesGames
Awesome :slight_smile:
So for a UImage or UTextblock, I have to include the “UMG/Public/Components/xxxxx.h”
But what if I add a designer created widget. How would I reference that?

Say, I have created a “RadialBarWidget” in the designer and want to create an instance in my player controler…
For the designer created widgets, there is no .h file. How do I make C++ aware of that widget class?
(like step 2 in your link).
Is that possible without an underlying C++ class, or would i need to give my RadialBarWidget a C++ underbelly?

In C++ you can use StaticLoadObject with a path to get a hard reference. The only issue is that if you want to move the files around later, it will break and you have to fix the path.

If you make a derived blueprint class from your C++ class you can use

UPROPERTY(EditDefaultsOnly)
TSubClassOf<class UUserWidget> DesignerCreatedWidget = nullptr;

And you can then assign the references in the derived blueprint class.

Also if you use variables of type UUserWidget in C++, even if only internally within a class and not exposed outside, my recommendation is to still use UPROPERTY() on them. I have had some memory management issues if I don’t use them that are really hard to track down. I think it is because the UUserWidget class has “abstract” in the UCLASS macro.

@JoSf
So I have to use the generic ‘UUserWidget’. I cant state a more specific class?

What I have is:
-A base c++ widget class called ‘UBaseWidget’, extending ‘UUserWidget’.
-A ‘URadialBarWidget’ c++ class, now extending ‘UBaseWidget’.

  • A ‘RadialBarBP’ blueprint widget, reparented to URadialBarWidget.

The ‘RadialBarBP’ contains an image component. In the construction event, a dynamic material instance is created and assigned to the image brush (a reference to the DMI is stored in a variable). The material takes a scalar value as percentage.

Now I want to implement a C++ function to set/update the bar with a function like:


void UpdateValue(float NewValue)
{
     MatRef->SetScalarValue((FName("Percentage"), NewValue);
     return;
}

So in my c++ code I would have to access the DMI that I created in the BP widget.
Or should I add the material instance in the c++ code?

In the tutorial it works with a textblock:



UPROPERTY(BlueprintReadWrite, meta = (BindWidget))
UTextBlock* ItemTitle;


In this example I can access and set the text property of the ‘ItemTitle’.
But how do I do the binding to the DMI or any other user created widget (possibly embedded in another user widget)?

Isn’t ‘StaticLoadObject’ used at runtime?

Somehow I don’t get it :frowning:

Oh nevermind that, I was too deep in my own thoughts. Ignore all of that.

You can use a specific class.

C++ Widget.h



void UpdateValue(float NewValue);

public:
UPROPERTY(BlueprintReadWrite)
UMaterialInstanceDynamic* DMI;


.cpp



void URadialBarWidget::UpdateValue(float NewValue)
{
    // remember to protect pointer
    DMI->SetScalarParameterValue(FName("Percentage"), NewValue);
    return;
}


In Blueprint just set the DMI reference when you create the dynamic material instance.