I am trying to create a super basic widget in C++
I want a canvas that holds just a black image that covers all the screen.
I dont know what is missing but I create an instance and add to viewport and nothing
is there. Also I create a blueprint user widget derived from my C++ widget
and the WBP is empty too.
What I am doing wrong?
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Components/Image.h"
#include "Components/CanvasPanel.h"
#include "fadeWid.generated.h"
UCLASS()
class MYPROJECT18_API UfadeWid : public UUserWidget
{
GENERATED_BODY()
protected:
virtual void NativeConstruct() override;
private:
UPROPERTY()
UCanvasPanel* RootCanvas;
UPROPERTY()
UImage* BlackImage;
};
#include "fadeWid.h"
#include "Components/Image.h"
#include "Components/CanvasPanel.h"
#include "Components/CanvasPanelSlot.h"
#include "Blueprint/WidgetTree.h"
void UfadeWid::NativeConstruct()
{
Super::NativeConstruct();
RootCanvas = WidgetTree->ConstructWidget<UCanvasPanel>(UCanvasPanel::StaticClass(), TEXT("RootCanvas"));
WidgetTree->RootWidget = RootCanvas;
BlackImage = WidgetTree->ConstructWidget<UImage>(UImage::StaticClass(), TEXT("BlackImage"));
FSlateBrush Brush;
Brush.TintColor = FSlateColor(FLinearColor::Black);
BlackImage->SetBrush(Brush);
UCanvasPanelSlot* CanvasSlot = RootCanvas->AddChildToCanvas(BlackImage);
CanvasSlot->SetAnchors(FAnchors(0.0f, 0.0f, 1.0f, 1.0f));
CanvasSlot->SetOffsets(FMargin(0.0f, 0.0f, 0.0f, 0.0f));
}
I know I can create a child BP widget and bind components to access from code but as the widget is so simple I just want to avoid the BP side for this.
Try to add these (you may have to put it in a constructor)
this->Space = EWidgetSpace::Screen;
PrimaryComponentTick.bCanEverTick = true;
bTickInEditor = false;
cant resolve those symbols 
.h:
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "fadeWid.generated.h"
UCLASS()
class ALS_API UfadeWid : public UUserWidget
{
GENERATED_BODY()
public:
UfadeWid(const FObjectInitializer& ObjectInitializer);
virtual void NativeConstruct() override;
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable)
void FadeIn(float time);
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable)
void FadeOut(float time);
UPROPERTY()
UCanvasPanel* RootCanvas;
UPROPERTY()
UImage* BlackImage;
};
.cpp:
#include "fadeWid.h"
#include "Components/Image.h"
#include "Components/CanvasPanel.h"
#include "Components/CanvasPanelSlot.h"
#include "Blueprint/WidgetTree.h"
#include "Components/WidgetComponent.h"
UfadeWid::UfadeWid(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
}
void UfadeWid::NativeConstruct()
{
Super::NativeConstruct();
RootCanvas = WidgetTree->ConstructWidget<UCanvasPanel>(UCanvasPanel::StaticClass(), TEXT("RootCanvas"));
WidgetTree->RootWidget = RootCanvas;
BlackImage = WidgetTree->ConstructWidget<UImage>(UImage::StaticClass(), TEXT("BlackImage"));
FSlateBrush Brush;
Brush.TintColor = FSlateColor(FLinearColor::Black);
BlackImage->SetBrush(Brush);
UCanvasPanelSlot* CanvasSlot = RootCanvas->AddChildToCanvas(BlackImage);
CanvasSlot->SetAnchors(FAnchors(0.0f, 0.0f, 1.0f, 1.0f));
CanvasSlot->SetOffsets(FMargin(0.0f, 0.0f, 0.0f, 0.0f));
}
W0ps i misled you there, comment out the 3 lines i mentioned
//this->Space = EWidgetSpace::Screen;
//PrimaryComponentTick.bCanEverTick = true;
//bTickInEditor = false;
In NativeConstruct() add WidgetTree = NewObject<UWidgetTree>(); at the very top, this is becuase in some UE version widget tree might be null, this is not the case here because if so the engine would crash but anyway…
I think you have to wrap your (UUserWidget) with UWidgetComponent so the widget would get processing power, not really need to create new files but in the .h add
class YOUR_API USomeWidgetComponent : public UWidgetComponent
{
GENERATED_BODY()
public:
USomeWidgetComponent(const FObjectInitializer& ObjectInitializer);
virtual void BeginPlay() override;
};
at the very top, now add to your .cpp file
add these lines from before
this->Space = EWidgetSpace::Screen;
PrimaryComponentTick.bCanEverTick = true;
bTickInEditor = false;
to
USomeWidgetComponent::USomeWidgetComponent(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
this->Space = EWidgetSpace::Screen;
PrimaryComponentTick.bCanEverTick = true;
bTickInEditor = false;
}
void USomeWidgetComponent::BeginPlay()
{
this->SetWidget(CreateWidget<UfadeWid>(GetWorld()));
this->GetUserWidgetObject()->AddToViewport();
}
Now create an actor with this component attached and run the game, is it working ?
if Yes, than your widget is OK, its just you can’t add it to viewport by itself - it should be wrapped with widget component (this is the only way i managed to create pure cpp widget).
If it’s not working i suspect that the problem is with the UCanvasPanel, try to make the root UOverlay, may that will do the trick.