BP Widget Component - C++ class & interface casting

Hello everyone !

I have a tricky question for you guys.

So this is basically one part of the architecture of my RTS C++ game. Each main class (Building, Infantry, Vehicle… all C++) NEEDS to implement the SelectableA interface. The reason is that to select a unit with my selection box, I cast to the interface, so that any object having the interface is obviously an object to interract with. This is working really fine.

Now, I used a Blueprint to create a Widget (Because there is no viewport in C++, so it’s hard to see what you do…) and I instantiated it in my main classes (Infantries and Buildings) as a Widget Component using the following code :

static ConstructorHelpers::FClassFinder<UUserWidget> hudWidgetObj(TEXT("/Game/HUD/SelectableActorHUD_Widget"));
UClass * hudWidgetClass;
if (hudWidgetObj.Succeeded()) {
	hudWidgetClass = hudWidgetObj.Class;
}
hudWidget = CreateDefaultSubobject<UWidgetComponent>("Widget");
hudWidget->SetWidgetClass(hudWidgetClass);

Where hudWidget is a UWidgetComponent*. Everything is working great, I have a health bar (progress bar) above my buildings/infantries.

BUT here comes the tricky part. I need a way to bind my Widget to the unit’s health, no matter its kind. That means, I would need to have a reference of my C++ Building/Infantry Pawn inside the Blueprint, and be able to cast it to the interface so I can use the “GetHealth” from the C++ interface.

So my questions is(are) :

  • How to give my Blueprint Widget a reference to the Pawn ?
  • How to cast this Pawn to the C++ interface inside the blueprint (more specifically in the bind function of the progres bar).

If you have other ways to do it, I can change the way I add my Widget to the classes. I heard about doing a C++ class and doing a child of it as a BP (here, for the widget), but I don’t know if it’s gonna help me, I’m really not good with Blueprint.

Thanks !

Well If I understand you correctly what you want to do Is create a new custom C++ class that derives from UUserWidget then add all the values you need then create a blueprint from it for your design work, Add the new widget to the UWidgetComponent.
When ever you need to display changes in state you can set it through the actor by getting its display widget and settings its health all through C++.

try these for Custom UMG
A new, community-hosted Unreal Engine Wiki - Announcements - Unreal Engine Forums.
[Tutorial] Extend UUserWidget for UMG - Community Content, Tools and Tutorials - Unreal Engine Forums

Hope this helps

This is even trickier than I think it would be, and I already concidered this solution. Now that you post it again, I gave it another look and I think this is the way to go. This is exactly what I’m gonna try :

  • Do a C++ class “hud_parent” inheriting from C++ UUserWidget.
  • Put a variable to reference the pawn, setter/getter and a function “func” for the binding.
  • Do a BP class “hud_child” inheriting from “hud_parent”.
  • Configure the bind function to use the “func” function from the parent class.

Now, with that set, I can go back to my Building C++ class, and create a “hud_child” just like I was doing before. After that, I can do hudWidget->GetUserWidgetObject() and cast it to a “hud_parent”. From there, I can set the Pawn.

So I would have my pawn set in the BP, and a binding function all set. If I can call a C++ function from BP, then it should work. I’ll be back to report how it worked.

EDIT : FINAL RESULTS

So i’ve tried what I said and it worked perfectly.

From my main classes, after the creation of my Widget Component, I do that :

UUserWidget* widget = hudWidget->GetUserWidgetObject();
if (widget) {
	Cast<USelectableActor_HUD>(widget)->SetActorOwner((Cast<APawn>(this)));
}

From there, my widget know whose his owner, and can start to cast & retrieve variables from the Building/Infantry class !
Thanks !

Hey, glad you got it working I could not reply yesterday as was having trouble getting onto answerhub for some reason.

It seems a little strange that you are using the widget to get the value from the actor it is attached to, could you not set the widget from the actor itself as it already has a reference to the widget.

You mean like creating the UUserWidget, setting it’s owner and then use hudWidget->setWidget(theUserWidget) ? Yeah I wanted to do that but I don’t know how to create an instance of my custom UUserWidget, while “SetWidgetClass” from WidgetComponent seems to handle the creation of one. If you know how I could change my code to use your technique, I’m willing to hear it ! :smiley:

Yes exactly, I’m not at my pc now but I think it’s something like
CreateWidget(this, UCustomUserWidgetClass);

UCustomUserWidgetClass Being the reference to the blueprint then adding the widget to the widgetcomponent or maybe you get the widget from the widgetcomponent after it has created it when you need it… yes I think that’s it, I will be able to take a look later tonight.

No I was right the first time you just create the widget i.e CreateWidget(this, UCustomUserWidgetClass); and store it as ref variable then attach it to the WdgetComponent

MyWidgetComponent->SetWidget(MyUUserWidget);

Hop that helps.

I can’t make it to work but I think I’m doing it wrong…

USelectableActor_HUD *widget2 = CreateWidget(this, hudWidgetClass);

USelectableActor_HUD = My C++ widget class.
hudWigetClass = the class of the BP widget derivated from USelectabeActor_HUD, obtained by a ConstructorHelpers.
I also tried with this->GetGameInstance() since the first parameter ask to be a GameInstance, but that doesn’t work anyway…

ok you are missing the type selector and the gameinstance it wants is the PlayerController as I think I had set it up in my PlayerController so this was sufficient.
try this:

USelectableActor_HUD * widget =
     CreateWidget<USelectableActor_HUD>(GetWorld()->GetFirstPlayerController(),
     hudWidgetClass);

EDIT keeps changing my code on submit grrr

it compiles, but crash UE4… wtf.

Are you setting all that up in the constructor? I think the creation of the widget has to be done after construction so say in beginplay create the widget and add it to the widget component.

Slow clap GGWP, that was the problem. Thanks !
Lesson of the day : Never manipulate Widget in the constructor.