学习虚幻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产生报错,按钮按键的点击事件在蓝图函数中进行调用。

相关推荐
山河亦问安2 小时前
Spring原理编码学习
java·学习·spring
思成不止于此2 小时前
【C++ 数据结构】二叉搜索树:原理、实现与核心操作全解析
开发语言·数据结构·c++·笔记·学习·搜索二叉树·c++40周年
雨泽‎3 小时前
Unity在URP中开启后处理导致RenderTexture存在背景
unity·游戏引擎·图形渲染
钟屿4 小时前
Back to Basics: Let Denoising Generative Models Denoise 论文阅读学习
论文阅读·人工智能·笔记·学习·计算机视觉
d111111111d4 小时前
SPI通信协议--在STM32中介绍(学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习
断水客4 小时前
如何在手机上搭建Linux学习环境
linux·运维·学习
j***12155 小时前
网络爬虫学习:应用selenium获取Edge浏览器版本号,自动下载对应版本msedgedriver,确保Edge浏览器顺利打开。
爬虫·学习·selenium
✎ ﹏梦醒͜ღ҉繁华落℘7 小时前
freeRTOS学习笔记(十四)--内存
笔记·学习
又是忙碌的一天7 小时前
mysql 学习第二天 SQL语句
sql·学习·mysql
拼好饭和她皆失7 小时前
C#学习入门
开发语言·学习·c#