.h
/*
* Made by Ovodus (Dmitry Petrushin). ovodus@yandex.ru
*/
#pragma once
#include "Components/Button.h"
#include "UMG.h"
#include "UMGStyle.h"
#include "OvodusButton.generated.h"
/**
* Classic Slate Button with Advanced Hit implementation.
* Use SetAdvancedHitTexture to set unique button's geometry, determined by it's alpha channel.
* Use SetAdvancedHitAlpha to set an integer in range 0-255. If pixel's alpha is lower than this value, it will be treated as an empty space.
*/
class DEMO_API SOvodusButton : public SButton {
public:
UTexture2D* AdvancedHitTexture;
int AdvancedHitAlpha;
SOvodusButton() : AdvancedHitTexture(NULL), AdvancedHitAlpha(0) {}
void SetAdvancedHitTexture(UTexture2D* InTexture) { AdvancedHitTexture = InTexture; }
void SetAdvancedHitAlpha(int InAlpha) { AdvancedHitAlpha = InAlpha; }
virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override {
if (!bIsHovered) return FReply::Unhandled();
return SButton::OnMouseButtonDown(MyGeometry, MouseEvent);
}
virtual FReply OnMouseButtonDoubleClick(const FGeometry& InMyGeometry, const FPointerEvent& InMouseEvent) override {
if (!bIsHovered) return FReply::Unhandled();
return SButton::OnMouseButtonDoubleClick(InMyGeometry, InMouseEvent);
}
virtual FReply OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override {
if (!bIsHovered) return FReply::Unhandled();
return SButton::OnMouseButtonUp(MyGeometry, MouseEvent);
}
virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual void OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override {
if (AdvancedHitTexture) return;
return SButton::OnMouseEnter(MyGeometry, MouseEvent);
}
virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override {
return SButton::OnMouseLeave(MouseEvent);
}
virtual FCursorReply OnCursorQuery(const FGeometry& MyGeometry, const FPointerEvent& CursorEvent) const override;
virtual TSharedPtr<IToolTip> GetToolTip() override { return (bIsHovered ? SWidget::GetToolTip() : NULL); }
};
/**
* Classic UMG Button with Advanced Hit implementation.
* Use SetAdvancedHitTexture to set unique button's geometry, determined by it's alpha channel.
* Use SetAdvancedHitAlpha to set an integer in range 0-255. If pixel's alpha is lower than this value, it will be treated as an empty space.
*/
UCLASS()
class DEMO_API UOvodusButton : public UButton
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "AdvancedHitTest") UTexture2D* AdvancedHitTexture;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "AdvancedHitTest", meta = (ClampMin = "0.0", ClampMax = "255.0", UIMin = "0.0", UIMax = "255.0"))
int AdvancedHitAlpha = NULL;
UFUNCTION(BlueprintCallable, Category = "AdvancedHitTest") void SetAdvancedHitTexture(UTexture2D* InTexture) {
AdvancedHitTexture = InTexture;
if (MyButton.IsValid()) (static_cast<SOvodusButton*>(MyButton.Get()))->SetAdvancedHitTexture(AdvancedHitTexture);
}
UFUNCTION(BlueprintCallable, Category = "AdvancedHitTest") void SetAdvancedHitAlpha(int InAlpha) {
AdvancedHitAlpha = InAlpha;
if (MyButton.IsValid()) (static_cast<SOvodusButton*>(MyButton.Get()))->SetAdvancedHitAlpha(AdvancedHitAlpha);
}
UOvodusButton(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer), AdvancedHitTexture(NULL), AdvancedHitAlpha(NULL){}
virtual void SynchronizeProperties() override;
virtual TSharedRef<SWidget> RebuildWidget() override;
};
.cpp
/*
* Made by Ovodus (Dmitry Petrushin). ovodus@yandex.ru
*/
#include "OvodusButton.h"
#include "ButtonSlot.h"
#include "SButton.h"
#pragma region >>> SOvodusButton <<<
FReply SOvodusButton::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) {
if (!AdvancedHitTexture) return SButton::OnMouseMove(MyGeometry, MouseEvent);
bool WhatToReturn = true;
FVector2D LocalPosition = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition());
LocalPosition.X = floor(LocalPosition.X);
LocalPosition.Y = floor(LocalPosition.Y);
LocalPosition /= MyGeometry.GetLocalSize();
int ImageWidth = AdvancedHitTexture->PlatformData->SizeX;
LocalPosition.X *= ImageWidth;
LocalPosition.Y *= AdvancedHitTexture->PlatformData->SizeY;
int BufferPosition = (LocalPosition.Y * ImageWidth) + LocalPosition.X;
FColor* ImageData = static_cast<FColor*>((AdvancedHitTexture->PlatformData->Mips[0]).BulkData.Lock(LOCK_READ_ONLY));
if (!ImageData) { WhatToReturn = false; }
else { if (ImageData[BufferPosition].A <= AdvancedHitAlpha) WhatToReturn = false; }
AdvancedHitTexture->PlatformData->Mips[0].BulkData.Unlock();
if (WhatToReturn != bIsHovered) {
bIsHovered = WhatToReturn;
if (bIsHovered) SButton::OnMouseEnter(MyGeometry, MouseEvent);
else SButton::OnMouseLeave(MouseEvent);
}
return SButton::OnMouseMove(MyGeometry, MouseEvent);
}
FCursorReply SOvodusButton::OnCursorQuery(const FGeometry& MyGeometry, const FPointerEvent& CursorEvent) const {
if (!bIsHovered) return FCursorReply::Unhandled();
TOptional<EMouseCursor::Type> TheCursor = Cursor.Get();
return (TheCursor.IsSet()) ? FCursorReply::Cursor(TheCursor.GetValue()) : FCursorReply::Unhandled();
}
#pragma endregion
#pragma region >>> UOvodusButton <<<
void UOvodusButton::SynchronizeProperties() {
Super::SynchronizeProperties();
(static_cast<SOvodusButton*>(MyButton.Get()))->SetAdvancedHitTexture(AdvancedHitTexture);
(static_cast<SOvodusButton*>(MyButton.Get()))->SetAdvancedHitAlpha(AdvancedHitAlpha);
}
TSharedRef<SWidget> UOvodusButton::RebuildWidget() {
TSharedPtr<SOvodusButton> OvodusButton = SNew(SOvodusButton)
.OnClicked(BIND_UOBJECT_DELEGATE(FOnClicked, SlateHandleClicked))
.OnPressed(BIND_UOBJECT_DELEGATE(FSimpleDelegate, SlateHandlePressed))
.OnReleased(BIND_UOBJECT_DELEGATE(FSimpleDelegate, SlateHandleReleased))
.OnHovered_UObject(this, &ThisClass::SlateHandleHovered)
.OnUnhovered_UObject(this, &ThisClass::SlateHandleUnhovered)
.ButtonStyle(&WidgetStyle)
.ClickMethod(ClickMethod)
.TouchMethod(TouchMethod)
.IsFocusable(IsFocusable)
;
OvodusButton->SetAdvancedHitTexture(AdvancedHitTexture);
OvodusButton->SetAdvancedHitAlpha(AdvancedHitAlpha);
MyButton = OvodusButton;
if (GetChildrenCount() > 0) Cast<UButtonSlot>(GetContentSlot())->BuildSlot(MyButton.ToSharedRef());
return MyButton.ToSharedRef();
}
#pragma endregion
加入UMG模块
如何使用呢?首先先导入一张PNG图片,然后打开图片设置
最后在UMG里面找到 右边
设置好就可以了,下面的style别忘记了