UE4 UMG自定义可点击区域Button

.h

/* 
* Made by Ovodus (Dmitry Petrushin). [email protected] 
*/
#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 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(MyButton.Get()))->SetAdvancedHitTexture(AdvancedHitTexture);
	}
	UFUNCTION(BlueprintCallable, Category = "AdvancedHitTest") void SetAdvancedHitAlpha(int InAlpha) {
		AdvancedHitAlpha = InAlpha;
		if (MyButton.IsValid()) (static_cast(MyButton.Get()))->SetAdvancedHitAlpha(AdvancedHitAlpha);
	}

	UOvodusButton(const FObjectInitializer& ObjectInitializer) :  Super(ObjectInitializer), AdvancedHitTexture(NULL), AdvancedHitAlpha(NULL){}

	virtual void SynchronizeProperties() override;
	virtual TSharedRef RebuildWidget() override;
};

.cpp

 

 

/*
* Made by Ovodus (Dmitry Petrushin). [email protected]
*/

#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((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 TheCursor = Cursor.Get();
	return (TheCursor.IsSet()) ? FCursorReply::Cursor(TheCursor.GetValue()) : FCursorReply::Unhandled();
}
#pragma endregion

#pragma region >>> UOvodusButton <<<
void UOvodusButton::SynchronizeProperties() {
	Super::SynchronizeProperties();
	(static_cast(MyButton.Get()))->SetAdvancedHitTexture(AdvancedHitTexture);
	(static_cast(MyButton.Get()))->SetAdvancedHitAlpha(AdvancedHitAlpha);
}
TSharedRef UOvodusButton::RebuildWidget() {
	TSharedPtr 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(GetContentSlot())->BuildSlot(MyButton.ToSharedRef());

	return MyButton.ToSharedRef();
}
#pragma endregion

加入UMG模块

如何使用呢?首先先导入一张PNG图片,然后打开图片设置

UE4 UMG自定义可点击区域Button_第1张图片UE4 UMG自定义可点击区域Button_第2张图片

最后在UMG里面找到UE4 UMG自定义可点击区域Button_第3张图片 右边UE4 UMG自定义可点击区域Button_第4张图片设置好就可以了,下面的style别忘记了

你可能感兴趣的:(UE4)