I created a Blueprint, as shown in Capture 1 below, with CommonButtonBase containing one Icon.
To allow for various replacements of the Icon in the external Widget using the binding UImage* ImgIcon, I defined a Property as UObject*, referencing the FSlateBrush of UImage. Icon can be applied not only with Texture but also with MaterialInterface and AtlasInterface.(AllowedClasses=“/Script/Engine.Texture,/Script/Engine.MaterialInterface,/Script/Engine.SlateTextureAtlasInterface”, refer to the code for details.)
This way, as illustrated in Capture 2 below, you can change the Icon for each Widget placed.
If you look at the code below, you can identify the issue. The UObject* Icon used for this functionality is only utilized as a Property for UI operators, resulting in wastage. Is it acceptable to use it in this manner?
- Header
#pragma once
#include "CoreMinimal.h"
#include "CommonButtonBase.h"
#include "SimpleIconButton.generated.h"
class UImage;
UCLASS(Abstract, Blueprintable, BlueprintType)
class SOL_API USimpleIconButton : public UCommonButtonBase
{
GENERATED_BODY()
protected:
virtual void NativePreConstruct() override;
public:
UFUNCTION(BlueprintCallable)
void SetIconFromTexture(UTexture2D* Texture2D);
UFUNCTION(BlueprintCallable)
void SetIconFromResourceObject(TSoftObjectPtr<UTexture2D> SoftTexture);
protected:
UPROPERTY(meta=(BindWidgetOptional), BlueprintReadOnly)
TObjectPtr<UImage> ImgIcon;
// Copied from FSlateBrush::ResourceObject property
UPROPERTY(EditAnywhere, meta=(DisplayThumbnail="true", DisplayName="Icon", AllowedClasses="/Script/Engine.Texture,/Script/Engine.MaterialInterface,/Script/Engine.SlateTextureAtlasInterface", DisallowedClasses = "/Script/MediaAssets.MediaTexture"))
TObjectPtr<UObject> Icon;
};
- Source
#include "SimpleIconButton.h"
#include "Components/Image.h"
void USimpleIconButton::NativePreConstruct()
{
Super::NativePreConstruct();
ImgIcon->SetBrushResourceObject(Icon);
// This icon will not be used after this function is called.
}
void USimpleIconButton::SetIconFromTexture(UTexture2D* Texture2D)
{
ImgIcon->SetBrushResourceObject(Texture2D);
}
void USimpleIconButton::SetIconFromResourceObject(TSoftObjectPtr<UTexture2D> SoftTexture)
{
ImgIcon->SetBrushFromSoftTexture(SoftTexture);
}
The version that did not waste the previously written Icon was implemented as shown below, but it was abandoned as it could not handle TSoftObjectPtr.
void USimpleIconButton::NativePreConstruct()
{
Super::NativePreConstruct();
UpdateIcon();
}
void USimpleIconButton::SetIconFromTexture(UTexture2D* Texture2D)
{
Icon = Texture2D;
UpdateIcon();
}
void USimpleIconButton::SetIconFromResourceObject(TSoftObjectPtr<UTexture2D> SoftTexture)
{
Icon = SoftTexture; // error! cannot store TSoftObjectPtr in Icon.
UpdateIcon();
}
void USimpleIconButton::UpdateIcon()
{
if (ImgIcon)
{
ImgIcon->SetBrushResourceObject(Icon);
}
}
Thank you in advance for your response.