2 min read

[14/50] A reusable Icon Button in C++ for Unreal UMG

Stable diffusion returns this for the prompt: "An artwork about icons and buttons."
Stable diffusion returns this for the prompt: "An artwork about icons and buttons."

Buttons are usually the primary way a user interacts with the User Interface (UI) and associating meaningful icons with them provides important visual cues and enhances the cognitive processing of the action implied by the button.

In this post we share a simple C++ class to create re-usable icon buttons. We instantiate this class via Blueprint within the editor to create our icon-button set to align with the design standards.

💡
While this post discusses an implementation using raw UMG, we have since moved to the Common UI framework for managing our interface.
#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Components/Image.h"
#include "Components/Button.h"
#include "Animation/WidgetAnimation.h"
#include "IconButton.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnIconButtonClicked);

UCLASS()
class PROJECT_API UIconButton : public UUserWidget
{
	GENERATED_BODY()

public:
	UPROPERTY(meta = (BindWidget))
	UImage* Icon;

	UPROPERTY(meta = (BindWidget))
	UButton* LocalButton;

	UPROPERTY(VisibleAnywhere, BlueprintCallable)
	FOnIconButtonClicked OnClicked;

	UPROPERTY(Transient, meta = (BindWidgetAnim))
	UWidgetAnimation* MouseHoverAnimation;

	virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
	
	virtual void NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
	
	virtual void NativeOnMouseLeave(const FPointerEvent& InMouseEvent) override;

};

We have two primary components - UImage for the icon and a UButton The wraper component is left to the designer when creating the Blueprints from this base class.

Besides the overriden user interation functions like mouse-enter, mouse-leave etc. We also have the FOnIconButtonClicked delegate to notify click events from the inner button: LocalButton.

// Fill out your copyright notice in the Description page of Project Settings.


#include "PaperplanesWidgets/IconButton.h"


FReply UIconButton::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
	FReply EventReply = Super::NativeOnMouseButtonDown(InGeometry, InMouseEvent);
	OnClicked.Broadcast();
	return EventReply;
}

void UIconButton::NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
	UUserWidget::PlayAnimation(this->MouseHoverAnimation, 0.f, 1, EUMGSequencePlayMode::Forward, 1, false);
}

void UIconButton::NativeOnMouseLeave(const FPointerEvent& InMouseEvent)
{
	UUserWidget::PlayAnimation(this->MouseHoverAnimation, 0.f, 1, EUMGSequencePlayMode::Reverse, 1, false);
}

In the implementation of the header, we just bind the delegate and add triggers for mouse enter and exit animations.

Creating base classes for UMG widget in C++ and instantiating the widgets in the editor provides a very clean workflow for handling business-logic associated with the widgets. In future posts, we look more into this.