学习虚幻C++开发日志——创建Selection Widget及其应用

教程视频:脚本冒险 - YouTube

前提:此代码运用到Common UI插件,需将其开启,以免后序编写产生未定义结构体的报错信息!

用C++进行UI绑定

创建继承于CommonUserWidget的类,此处命名为SelectionBase 

SelectionBase类头文件

#pragma once

#include "CoreMinimal.h"
#include"UObject/Object.h"
#include"CommonButtonBase.h"
#include"SelectionOption.h"

#include "SelectionBase.generated.h"

// 声明一个委托类型,该委托接受一个整数参数
DECLARE_DELEGATE_OneParam(FOnSelectionChange, int);

class UCommonTextBlock;
     
UCLASS()
class MYPROJECT_API USelectionBase :public UCommonUserWidget
{
	GENERATED_BODY()
public:
	USelectionBase();
	virtual void NativeConstruct()override;

	void Clear();
	void AddOption(const FSelectionOption& InOption);
	void SetCurrentSelection(int InIndex);


	UFUNCTION(BlueprintCallable)
	void SelectionPrevious();

	UFUNCTION(BlueprintCallable)
	void SelectNext();

	
	FOnSelectionChange OnSelectionChange;
protected:
	UFUNCTION()
	UWidget* OnNavigation(EUINavigation InNavigation);

	void UpdateCurrentSelection();

	UPROPERTY(EditAnywhere,BlueprintReadOnly)
	TArray<FSelectionOption>Options;

	UPROPERTY(BlueprintReadOnly,meta=(BindWidget))
	TObjectPtr<UCommonTextBlock>Label;

	int CurrentSelection;
};

SelectionBase类源文件

#include"SelectionBase.h"
#include"CommonTextBlock.h"
#include"Logging/StructuredLog.h"

USelectionBase::USelectionBase()
{
	//设置当前选择为0
	CurrentSelection = 0;

	//开启可以聚焦(CommonUI特性)
	SetIsFocusable(true);

	//设置对象可见性为可见
	SetVisibilityInternal(ESlateVisibility::Visible);
}

void USelectionBase::NativeConstruct()
{
	Super::NativeConstruct();
	if (Options.Num() == 0)
	{
		//UE_LOGFMT(LogTemp, Log, "USelectionBase:No options where provied.");
		return;
	}
	UpdateCurrentSelection();

	FCustomWidgetNavigationDelegate NavigationDelegate;
	NavigationDelegate.BindDynamic(this, &USelectionBase::OnNavigation);

    //设置自定义的导航规则,当使用左或右箭头导航时,调用 OnNavigation 方法。
	SetNavigationRuleCustom(EUINavigation::Left, NavigationDelegate);
	SetNavigationRuleCustom(EUINavigation::Right, NavigationDelegate);
}

void USelectionBase::Clear()
{
	//重置 Options 数组,移除所有选项。
	Options.Reset();
}

void USelectionBase::AddOption(const FSelectionOption& InOption)
{
	//向 Options 数组中添加一个新的选项。
	Options.Add(InOption);
	//调用 UpdateCurrentSelection 方法来更新当前选择
	UpdateCurrentSelection();
}

void USelectionBase::SetCurrentSelection(int InIndex)
{
	check(InIndex >= 0 && InIndex <Options.Num());
	//设置当前选择到指定的索引。
	CurrentSelection = InIndex;
	UpdateCurrentSelection();
}

void USelectionBase::SelectionPrevious()
{
	OnNavigation(EUINavigation::Left);
}

void USelectionBase::SelectNext()
{
	OnNavigation(EUINavigation::Right);
}


UWidget* USelectionBase::OnNavigation(EUINavigation InNavigation)
{
	check(InNavigation == EUINavigation::Left || InNavigation == EUINavigation::Right);
	const auto Direction = InNavigation == EUINavigation::Left ? -1 : 1;

	CurrentSelection += Direction;

	//处理循环选择(当选择超出范围时回到另一端)。
	if (CurrentSelection < 0)
	{
		CurrentSelection = Options.Num() - 1;
	}
	else if (CurrentSelection >= Options.Num())
	{
		CurrentSelection = 0;
	}

	UpdateCurrentSelection();

	OnSelectionChange.ExecuteIfBound(CurrentSelection);
	return this;
}

void USelectionBase::UpdateCurrentSelection()
{
	//检查当前选择是否有效。
	if (CurrentSelection < 0 || CurrentSelection >= Options.Num())
	{
		// Handle the error, e.g., log an error message and return
		//UE_LOG(LogTemp, Error, TEXT("UpdateCurrentSelection Widget: Invalid array index: %d"), CurrentSelection);
		return;
	}
	//更新显示的标签为当前选择项的标签
	Label->SetText(Options[CurrentSelection].Label);
}

此处创建了SelectionOption.cpp文件进行定义Option结构体,使其在SelectionBase进行结构体调用。 

#pragma once

#include"SelectionOption.generated.h"
USTRUCT(BlueprintType)
struct FSelectionOption
{
	GENERATED_BODY()

	UPROPERTY(EditAnywhere,BlueprintReadOnly,Category="Option")
	FText Label;
};

最后在虚幻编辑器进行蓝图调用绑定

创建一个蓝图UI组件继承于SelectionBase,

需要创建一个CommonText并且命名为Label的变量进行Bind Widgets,否则会编译UMG产生报错,按钮按键的点击事件在蓝图函数中进行调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值