Slate
HUD
UMG (Unreal Motion Graphics)
逻辑层部分 Slate、SlateCore
渲染部分 SlateRHIRenderer
基类为 SWidget
Slot 为槽,代表可以放置 子 Widget
声明性语法——宏
SLATE_BEGIN_ARGS( SSubMenuButton )
: _ShouldAppearHovered( false )
{}
/** 将显示在按钮上的标签 */
SLATE_ATTRIBUTE( FString, Label )
/** 单击按钮时调用 */
SLATE_EVENT( FOnClicked, OnClicked )
/** 将放置在按钮上的内容 */
SLATE_NAMED_SLOT( FArguments, FSimpleSlot, Content )
/** 在悬停状态下是否应显示按钮 */
SLATE_ATTRIBUTE( bool, ShouldAppearHovered )
SLATE_END_ARGS()
SNew
SAssignNew
创建插件
点击事件代码对比
\Engine\Source\Runtime\AppFramework\Private\Framework\Testing
路径下的文件,拷贝至 插件 Plugins\MyEditorMode\Source\MyEditorMode\Private
vs 添加文件,或者右键工程 Generate Visual Stuido project files
编译不通过
头文件问题,将头文件改成当前目录下的头文件
变量重名问题,注释掉相应的变量声明
LNK2019: 无法解析的外部符号 GetTestRenderTransform(void) 和 GetTestRenderTransformPivot(void),SWidgetGallery.cpp 中 MakeWidgetGallery 函数注释掉相关语句,如下所示。
TSharedRef<SWidget> MakeWidgetGallery()
{
//extern TOptional<FSlateRenderTransform> GetTestRenderTransform();
//extern FVector2D GetTestRenderTransformPivot();
return
SNew(SWidgetGallery);
//.RenderTransform_Static(&GetTestRenderTransform)
//.RenderTransformPivot_Static(&GetTestRenderTransformPivot);
}
修改 MyEditorMode .cpp 种的 OnSpawnPluginTab 函数
TSharedRef<SDockTab> FMyEditorModeModule::OnSpawnPluginTab(const FSpawnTabArgs& SpawnTabArgs)
{
FTestStyle::ResetToDefault();
TSharedPtr<SWidget> ToolkitWidget;return SNew(SDockTab)
.TabRole(ETabRole::NomadTab)
[
// Put your tab content here!
SAssignNew(ToolkitWidget, SBorder)
[
MakeWidgetGallery()
]
];
}
.build.cs 添加依赖模块(如果自带,可以取消注释)
PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
图示
创建 HUD派生类:AMyHUD
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "MyHUD.generated.h"
UCLASS()
class DESIGNPATTERNS_API AMyHUD : public AHUD
{
GENERATED_BODY()
public:
virtual void BeginPlay() override;void ShowMySlate();
void RemoveMySlate();
// 没有 include "MyCompoundWidget",而使用 class ,避免头文件相互引用而编译错误
TSharedPtr<class SMyCompoundWidget> MyCompoundWidget;
// 添加视口方法三
TSharedPtr<SWidget> WidgetContainer;
};
#pragma once
#include "MyHUD.h"
#include "Kismet/GameplayStatics.h"
#include "SMyCompoundWidget.h"
#include "Widgets/SWeakWidget.h"
void AMyHUD::BeginPlay()
{
Super::BeginPlay();
ShowMySlate();
}
void AMyHUD::ShowMySlate()
{
if (GEngine && GEngine->GameViewport)
{
// 第二个参数为 ZOrder,默认为 0
//GEngine->GameViewport->AddViewportWidgetContent(SNew(SMyCompoundWidget), 0);
//GEngine->GameViewport->AddViewportWidgetContent(SAssignNew(MyCompoundWidget, SMyCompoundWidget)); //
MyCompoundWidget = SNew(SMyCompoundWidget).OwnerHUDArg(this);
//SAssignNew(MyCompoundWidget, SMyCompoundWidget);
// 添加视口方法一,可被移除
//GEngine->GameViewport->AddViewportWidgetContent(MyCompoundWidget.ToSharedRef());
// 添加视口方法二,此处无法移除,因为 weak widget
//GEngine->GameViewport->AddViewportWidgetContent(
//SNew(SWeakWidget).PossiblyNullContent(MyCompoundWidget.ToSharedRef()), 0);
// 添加视口方法三,可被移除
GEngine->GameViewport->AddViewportWidgetContent(
SAssignNew(WidgetContainer,SWeakWidget).PossiblyNullContent(MyCompoundWidget.ToSharedRef()), 0);
// 显示鼠标及设置输入模式
APlayerController* PC = UGameplayStatics::GetPlayerController(GetWorld(), 0);
if (PC)
{
PC->bShowMouseCursor = true;
PC->SetInputMode(FInputModeUIOnly());
}
}
}
void AMyHUD::RemoveMySlate()
{
if (GEngine && GEngine->GameViewport && WidgetContainer.IsValid())
{
// 移除添加视口方法一
GEngine->GameViewport->RemoveViewportWidgetContent(MyCompoundWidget.ToSharedRef()); // 移除添加视口方法三
GEngine->GameViewport->RemoveViewportWidgetContent(WidgetContainer.ToSharedRef());
// 移除所有
//GEngine->GameViewport->RemoveAllViewportWidgets();
// 显示鼠标及设置输入模式
APlayerController* PC = UGameplayStatics::GetPlayerController(GetWorld(), 0);
if (PC)
{
PC->bShowMouseCursor = false;
PC->SetInputMode(FInputModeGameOnly());
}
}
}
创建SCompoundWidget 派生类:SMyCompoundWidget
#include "CoreMinimal.h"
#include "Widgets/SCompoundWidget.h"
#include "MyHUD.h"
/**
*
*/
class DESIGNPATTERNS_API SMyCompoundWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMyCompoundWidget)
{}
// 添加参数
SLATE_ARGUMENT(TWeakObjectPtr<AMyHUD>, OwnerHUDArg);
SLATE_END_ARGS()/** Constructs this widget with InArgs */
void Construct(const FArguments& InArgs);
FReply OnPlayClicked() const;
FReply OnQuitClicked() const;
private:
TWeakObjectPtr<AMyHUD> OwnerHUD;
};
#include "SMyCompoundWidget.h"
#include "SlateOptMacros.h"
#include "Widgets/Images/SImage.h"
#include "MyHUD.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Kismet/GameplayStatics.h"
#include "Widgets/Layout/SBackgroundBlur.h"
#define LOCTEXT_NAMESPACE "MyNamespace"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SMyCompoundWidget::Construct(const FArguments& InArgs)
{
// 注意此处带下划线
OwnerHUD = InArgs._OwnerHUDArg;
// 文本和按钮间距设置
const FMargin ContentPadding = FMargin(500.0f, 300.0f);
const FMargin ButtonPadding = FMargin(10.f);
// 按钮和标题文本
const FText TitleText = LOCTEXT("SlateTest", "Just a Slate Test");
const FText PlayText = LOCTEXT("PlayGame", "Play");
const FText QuitText = LOCTEXT("QuitGame", "Quit Game");
//按钮字体及大小设置
FSlateFontInfo ButtonTextStyle = FCoreStyle::Get().GetFontStyle("EmbossedText");
ButtonTextStyle.Size = 40.f;
//标题字体及大小设置
FSlateFontInfo TitleTextStyle = ButtonTextStyle;
TitleTextStyle.Size = 60.f;//所有UI控件都写在这里
ChildSlot
[
SNew(SOverlay)
+ SOverlay::Slot()
.HAlign(HAlign_Fill).VAlign(VAlign_Fill)
[
SNew(SImage) // 背景(半透明黑)
.ColorAndOpacity(FColor(0,0,0,127))
]
+ SOverlay::Slot()
.HAlign(HAlign_Fill).VAlign(VAlign_Fill)
[
SNew(SBackgroundBlur) // 高斯模糊
.BlurStrength(10.0f)
]
+ SOverlay::Slot()
.HAlign(HAlign_Fill).VAlign(VAlign_Fill)
.Padding(ContentPadding)
[
SNew(SVerticalBox)
// Title Text
+ SVerticalBox::Slot()
[
SNew(STextBlock)
.Font(TitleTextStyle)
.Text(TitleText)
.Justification(ETextJustify::Center)
]
// Play Button
+ SVerticalBox::Slot()
.Padding(ButtonPadding)
[
SNew(SButton)
.OnClicked(this, &SMyCompoundWidget::OnPlayClicked)
[
SNew(STextBlock)
.Font(ButtonTextStyle)
.Text(PlayText)
.Justification(ETextJustify::Center)
]
]
// Quit Button
+ SVerticalBox::Slot()
.Padding(ButtonPadding)
[
SNew(SButton)
.OnClicked(this, &SMyCompoundWidget::OnQuitClicked)
[
SNew(STextBlock)
.Font(ButtonTextStyle)
.Text(QuitText)
.Justification(ETextJustify::Center)
]
]
]
];
}
FReply SMyCompoundWidget::OnPlayClicked() const
{
if (OwnerHUD.IsValid())
{
OwnerHUD->RemoveMySlate();
}
return FReply::Handled();
}
FReply SMyCompoundWidget::OnQuitClicked() const
{
if (OwnerHUD.IsValid())
{
OwnerHUD->PlayerOwner->ConsoleCommand("quit");
}
return FReply::Handled();
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
#undef LOCTEXT_NAMESPACE
创建 GameModeBase派生类:AMyPlayerController ,PlayerController派生类:AMyPlayerController
设定 PlayerControllerClass 为 AMyPlayerController
设定 HUDClass 为AMyHUD
关卡 World Setting->GameMode Override 设置为 MyGameMode
UCLASS()
class DESIGNPATTERNS_API AMyPlayerController : public APlayerController
{
GENERATED_BODY()
};
UCLASS()
class DESIGNPATTERNS_API AMyGameMode : public AGameModeBase
{
GENERATED_BODY()
public:
AMyGameMode() {
PlayerControllerClass = AMyPlayerController::StaticClass();
HUDClass = AMyHUD::StaticClass();
}
};
实际写 Slate 的时候,可以多参考下源码 Engine\Source\Runtime\Slate\Public\Widgets\
显示扩展点
Widget Reflector
手机扫一扫
移动阅读更方便
你可能感兴趣的文章