Posted October 19, 2024 by AbyssEclipse
#Unreal Engine 5 #C++ #Puzzle #Jigsaw Puzzle
Anyhow, in a past devlog, I talked about adding widgets through C++ using BindWidget. However, this time, I wanted to not only create widget components, but also to add them to my class in a hierarchy (ie; having a UImage be a child of a USizebox). I found useful information on this forum post:
void UJigsawSlot::NativeConstruct() { SizeBox = WidgetTree->ConstructWidget<USizeBox>(USizeBox::StaticClass(), TEXT("RootWidget")); WidgetTree->RootWidget = SizeBox; SizeBox->AddChild(Image); }
And this method did indeed work; when I created the appropriate widgets in the editor, it wouldn't let me add an Image widget component that is a child of the root, it only let me add an image component that is a child of the sizebox:
Afterwards, I needed to add event dispatchers through C++ in a way that they could be run by blueprints. I've done event dispatchers before, but it's been a while so I needed a refresher.
I used the instructions from this forum post:
C++ Event dispatchers: How do we implement them?
And this here is the code I wrote:
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Blueprint/UserWidget.h" #include "JigsawSlot.generated.h" //delegates must be created outside fo the class declaration //delegate type declarations must start with F DECLARE_DYNAMIC_MULTICAST_DELEGATE(FPieceCorrectlyPlacedDelegate); // We make the class abstract, as we don't want to create // instances of this, instead we want to create instances // of our UMG Blueprint subclass. UCLASS(Abstract) class PUZZLEGAME_API UJigsawSlot : public UUserWidget { GENERATED_BODY() public: /* Widgets*/ UPROPERTY(BlueprintReadWrite, Category = "Puzzle", meta = (BindWidget)) class USizeBox* SizeBox; UPROPERTY(BlueprintReadWrite, Category = "Puzzle", meta = (BindWidget)) class UImage* Image; /* Variables*/ UPROPERTY(BlueprintReadWrite, Category = "Puzzle", meta = (ExposeOnSpawn = "true")) FVector2D SlotCoordinate = FVector2D(0, 0); UPROPERTY(BlueprintReadWrite, Category = "Puzzle", meta = (ExposeOnSpawn = "true")) UTexture* JigsawImage; UPROPERTY(BlueprintReadWrite, Category = "Puzzle", meta = (ExposeOnSpawn = "true")) int NumberOfPieces; /* Delegates/ Event Dispatchers*/ UPROPERTY(BlueprintAssignable, Category = "Delegate") FPieceCorrectlyPlacedDelegate OnPieceCorrectlyPlaced; protected: // Doing setup in the C++ constructor is not as useful as using NativeConstruct. virtual void NativeConstruct() override; };
// Fill out your copyright notice in the Description page of Project Settings. #include "JigsawSlot.h" #include "Components/Image.h" #include "Components/SizeBox.h" #include "Blueprint/WidgetTree.h" void UJigsawSlot::NativeConstruct() { SizeBox = WidgetTree->ConstructWidget<USizeBox>(USizeBox::StaticClass(), TEXT("RootWidget")); WidgetTree->RootWidget = SizeBox; SizeBox->AddChild(Image); }
And this code worked great! I was able to implement the Event Dispatcher in blueprints: