Slate是使用C++代码来实现Widget功能的框架。Slate中已经有定义好的Widget元素可以使用,也可以使用这些Widget元素创建新的Widget。
一、引入对Slate库的依赖
在项目中要使用Slate框架,首先需要引入对Slate库的依赖。可以在*.Build.cs中添加对InputCore、Slate、SlateCore的依赖:
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
二、将Widget添加到Viewport或从Viewport中删除
使用GameViewportClient::AddViewportWidgetContent()将Widget添加到
Viewport中,主要有以下三种方式:
TSharedPtr<MyWidget> MyWidgetPtr;
//--1
GEngine->GameViewport->AddViewportWidgetContent(
SNew(MyWidgetPtr.ToSharedRef())
);
//--2
GEngine->GameViewport->AddViewportWidgetContent(
SNew(SWeakWidget)
.PossiblyNullContent(MyWidgetClass)
);
//--3
GEngine->GameViewport->AddViewportWidgetContent(
SAssignNew(MyWidgetPtr, SWeakWidget)
.PossiblyNullContent(MyWidgetClass)
);
使用GameViewportClient::RemoveViewportWidgetContent()将Widget删除
GEngine->GameViewport->RemoveViewportWidgetContent(
SNew(MyWidgetPtr.ToSharedRef())
);
使用GameViewportClient::RemoveAllViewportWidgets()将Widget全部删除
GEngine->GameViewport->RemoveAllViewportWidgets();
三、Widget类型
Leaf Widgets - 没有子slot。比如STextBlock
Panels - 可有多个子slot。比如SOverlay、SHorizontalBox。使用SOverlay::Slot()、SHorizontalBox::Slot()添加子slot
Compound Widgets - 只有一个子slot。比如SEditableTextBox。使用SEditableTextBox.ChildSlot添加子slot
四、创建Widget的方式
TSharedRef<SButton> MyButton = SNew(SButton);
or
TSharedPtr<SButton> MyButton;
SAssignNew( MyButton, SButton );
五、一个简单的例子
创建一个Widget,包含一个Button和一个TextBox,代码如下:
// StandardSlateWidget.h
#pragma once
#include "CoreMinimal.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/Input/SEditableTextBox.h"
#include "Templates/SharedPointer.h"
class ANDROIDPROJECT1_API SStandardSlateWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SStandardSlateWidget)
{}
SLATE_ARGUMENT(TWeakObjectPtr<class AStandardHUD>, OwnerHUDArg);
SLATE_END_ARGS()
void Construct(const FArguments& InArgs);
private:
TWeakObjectPtr<class AStandardHUD> OwnerHUD;
FReply Btn_OnClicked();
FText MyText;
FText GetText() const;
void OnTextChanged(const FText& Text);
};
// StandardSlateWidget.cpp
#include "StandardSlateWidget.h"
#include "SlateOptMacros.h"
#include "Widgets/SBoxPanel.h"
#include "Widgets/SOverlay.h"
#include "Widgets/Input/SEditableTextBox.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/Text/STextBlock.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Engine/Engine.h"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
// ++ This is needed in order to use the localization macro LOCTEXT
#define LOCTEXT_NAMESPACE "SStandardSlateWidget"
FReply SStandardSlateWidget::Btn_OnClicked()
{
FString MsgText = FString(TEXT("click me"));
//GEngine->AddOnScreenDebugMessage(-1, 50.f, FColor::Blue, MsgText);
//UE_LOG(LogTemp, Log, TEXT("MsgText=%s"), *MsgText);
MsgText = GetText().ToString() + FString(TEXT("-")) + MsgText;
MyText = FText::FromString(MsgText);
return FReply::Handled();
};
FText SStandardSlateWidget::GetText() const
{
return MyText;
}
void SStandardSlateWidget::OnTextChanged(const FText& InText)
{
MyText = InText;
GEngine->AddOnScreenDebugMessage(-1, 50.f, FColor::Blue, InText.ToString());
};
void SStandardSlateWidget::Construct(const FArguments& InArgs)
{
OwnerHUD = InArgs._OwnerHUDArg;
ChildSlot
.VAlign(VAlign_Fill)
.HAlign(HAlign_Fill)
[
SNew(SOverlay)
+ SOverlay::Slot()
.VAlign(VAlign_Top)
.HAlign(HAlign_Fill)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.Padding(1.0f)
.HAlign(HAlign_Fill)
[
SNew(SButton)
.OnClicked(this, &SStandardSlateWidget::Btn_OnClicked)
.Content()
[
SNew(STextBlock)
.Text(LOCTEXT("ClickButton", "click me"))
.ToolTipText(LOCTEXT("ClickButton_Tooltip", "clickButton tooltip"))
]
]
+ SHorizontalBox::Slot()
.Padding(1.0f)
.HAlign(HAlign_Fill)
[
SNew(SEditableTextBox)
.Text(this, &SStandardSlateWidget::GetText)
.OnTextChanged(this, &SStandardSlateWidget::OnTextChanged)
]
]
];
}
#undef LOCTEXT_NAMESPACE
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
// StandardHUD.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "StandardSlateWidget.h"
#include "StandardHUD.generated.h"
UCLASS()
class ANDROIDPROJECT1_API AStandardHUD : public AHUD
{
GENERATED_BODY()
public:
TSharedPtr<SStandardSlateWidget> MyUIWidget;
void BeginPlay();
};
// StandardHUD.cpp
#include "StandardHUD.h"
#include "StandardSlateWidget.h"
#include "Widgets/SWeakWidget.h"
#include "Runtime/Engine/Classes/Engine/Engine.h"
void AStandardHUD::BeginPlay()
{
MyUIWidget = SNew(SStandardSlateWidget);
GEngine->GameViewport->AddViewportWidgetContent(
SNew(SWeakWidget)
.PossiblyNullContent(MyUIWidget.ToSharedRef())
);
MyUIWidget->SetVisibility(EVisibility::Visible);
}
其中SLATE_BEGIN_ARGS、SLATE_ARGUMENT、SLATE_END_ARGS等,是在“Epic Games\UE_4.18\Engine\Source\Runtime\SlateCore\Public\Widgets\DeclarativeSyntaxSupport.h”中定义的:
#define SLATE_BEGIN_ARGS( WidgetType ) \
public: \
struct FArguments : public TSlateBaseNamedArgs<WidgetType> \
{ \
typedef FArguments WidgetArgsType; \
FORCENOINLINE FArguments()
#define SLATE_ARGUMENT( ArgType, ArgName ) \
ArgType _##ArgName; \
WidgetArgsType& ArgName( ArgType InArg ) \
{ \
_##ArgName = InArg; \
return this->Me(); \
}
#define SLATE_END_ARGS() \
};
参考文档
Slate UI Framework
Slate Architecture
Details Panel Customization
Using Slate In-Game
Slate Overview
Using Slate in a Project
Slate Widget Examples
Slate, Hello
Slate, Loading Styles & Resources
Template:Slate Style Sets Part 2
Template:Slate Data Binding Part 3