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

教程视频:脚本冒险 - YouTube

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

用C++进行UI绑定

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

SelectionBase类头文件

cpp 复制代码
#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类源文件

cpp 复制代码
#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进行结构体调用。

cpp 复制代码
#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产生报错,按钮按键的点击事件在蓝图函数中进行调用。

相关推荐
典孝赢麻崩乐急44 分钟前
数据库学习------数据库事务的特性
数据库·学习·oracle
●VON2 小时前
重生之我在暑假学习微服务第七天《微服务之服务治理篇》
java·学习·微服务·云原生·nacos·架构·springcloud
霖002 小时前
深入讲讲异步FIFO
笔记·vscode·单片机·嵌入式硬件·学习·fpga开发
全优统计3 小时前
伞状Meta分析重构癌症幸存者照护指南:从矛盾证据到精准决策
经验分享·学习
XMan_Liu3 小时前
SIP 呼叫中实现远端摄像头控制学习笔记
笔记·学习
三木今天学习了嘛3 小时前
【CVPR2025】FlowRAM:用区域感知与流匹配加速高精度机器人操作策略学习
学习·机器人
Asu52024 小时前
链表反转中最常用的方法————三指针法
java·数据结构·学习·链表
牛奶咖啡134 小时前
学习设计模式《二十》——解释器模式
学习·设计模式·解释器模式·认识解释器模式·解释器模式的优缺点·何时使用解释器模式·解释器模式的示例
dankokoko5 小时前
OPENGLPG第九版学习 - 纹理与帧缓存 part2
学习
枫景Maple5 小时前
Shader开发(六)什么是着色器
游戏引擎·着色器