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

相关推荐
艾莉丝努力练剑1 小时前
【C语言】学习过程教训与经验杂谈:思想准备、知识回顾(三)
c语言·开发语言·数据结构·学习·算法
ZZZS05161 小时前
stack栈练习
c++·笔记·学习·算法·动态规划
位东风1 小时前
【c++学习记录】状态模式,实现一个登陆功能
c++·学习·状态模式
Star Curry2 小时前
【新手小白的嵌入式学习之路】-STM32的学习_GPIO 8种模式学习心得
stm32·嵌入式硬件·学习
AI视觉网奇3 小时前
rag学习笔记
笔记·学习
枯萎穿心攻击3 小时前
ECS由浅入深第三节:进阶?System 的行为与复杂交互模式
开发语言·unity·c#·游戏引擎
不绝1914 小时前
怪物机制分析(有限状态机、编辑器可视化、巡逻机制)
网络·游戏·unity·游戏引擎
Feliz Da Vida4 小时前
[代码学习] c++ 通过H矩阵快速生成图像对应的mask
c++·学习
wuxuanok5 小时前
Web后端开发-Mybatis
java·开发语言·笔记·学习·mybatis
一切顺势而行6 小时前
vue总结2
学习