教程视频:脚本冒险 - 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产生报错,按钮按键的点击事件在蓝图函数中进行调用。