UE4 UMG自定义可点击区域Button

.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别忘记了

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值