본문으로 건너뛰기
Unreal Engine 모듈 · 플러그인 개발LESSON 23

Slate 기초와 Dockable Editor Tab 만들기

난이도심화
예상 시간140분
선수지식22강의 ToolMenus 명령

23강. Slate 기초와 Dockable Editor Tab 만들기

1. 이번 강의에서 해결할 문제​

검사 결과가 로그에만 있으면 에셋 선택, 재검사, 오류 이동을 한 흐름으로 처리하기 어렵습니다. 임시 SWindow를 매번 만들면 Editor 레이아웃에 저장되지 않고 중복 창 관리도 필요합니다. Editor 작업 도구는 Docking과 재호출이 가능한 Tab으로 제공하는 편이 자연스럽습니다.

2. 학습 목표​

3. 핵심 개념​

Slate는 Unreal Editor UI의 C++ 기반 선언형 프레임워크입니다. TSharedRef·TSharedPtr로 Widget 수명을 관리하며, UObject Garbage Collection과 다른 소유권 모델을 사용합니다. Dockable Tool은 FGlobalTabmanager에 Tab Spawner를 등록하고 SDockTab 안에 전용 Widget을 배치합니다.

이 강의는 검사 실행 버튼과 상태 문구만 만들고, Asset Registry 결과 목록은 27강에서 연결합니다.

4. 단계별 실습​

Private/Widgets/SDataGuardPanel.h
#pragma once

#include "Widgets/SCompoundWidget.h"

class SDataGuardPanel final : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SDataGuardPanel) {}
SLATE_END_ARGS()

void Construct(const FArguments& InArgs);

private:
FReply HandleRunValidation();
FText GetStatusText() const;

int32 LastIssueCount = 0;
};
Private/Widgets/SDataGuardPanel.cpp
#include "Widgets/SDataGuardPanel.h"

#include "Widgets/Input/SButton.h"
#include "Widgets/Layout/SBorder.h"
#include "Widgets/Layout/SBox.h"
#include "Widgets/Text/STextBlock.h"

#define LOCTEXT_NAMESPACE "SDataGuardPanel"

void SDataGuardPanel::Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(SBorder)
.Padding(16.0f)
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(LOCTEXT("Title", "Data Guard"))
]
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(0.0f, 12.0f)
[
SNew(SButton)
.Text(LOCTEXT("Run", "Run Project Validation"))
.ToolTipText(LOCTEXT("RunTip", "Scan configured project assets."))
.OnClicked(this, &SDataGuardPanel::HandleRunValidation)
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(this, &SDataGuardPanel::GetStatusText)
]
]
];
}

FReply SDataGuardPanel::HandleRunValidation()
{
LastIssueCount = 0;
return FReply::Handled();
}

FText SDataGuardPanel::GetStatusText() const
{
return FText::Format(
LOCTEXT("Status", "Last scan: {0} issues"),
FText::AsNumber(LastIssueCount));
}

#undef LOCTEXT_NAMESPACE

Module에 Tab을 등록합니다.

DataGuardEditorModule.cpp의 Tab 부분
#include "Widgets/Docking/SDockTab.h"
#include "Widgets/SDataGuardPanel.h"

namespace DataGuardTabs
{
static const FName MainTab(TEXT("DataGuard.Main"));
}

void FDataGuardEditorModule::StartupModule()
{
FGlobalTabmanager::Get()->RegisterNomadTabSpawner(
DataGuardTabs::MainTab,
FOnSpawnTab::CreateRaw(this, &FDataGuardEditorModule::SpawnMainTab))
.SetDisplayName(LOCTEXT("DataGuardTab", "Data Guard"))
.SetMenuType(ETabSpawnerMenuType::Hidden);

UToolMenus::RegisterStartupCallback(/* 22강과 동일 */);
}

TSharedRef<SDockTab> FDataGuardEditorModule::SpawnMainTab(
const FSpawnTabArgs& Args)
{
return SNew(SDockTab)
.TabRole(ETabRole::NomadTab)
[
SNew(SDataGuardPanel)
];
}

void FDataGuardEditorModule::OpenDataGuard()
{
FGlobalTabmanager::Get()->TryInvokeTab(DataGuardTabs::MainTab);
}

void FDataGuardEditorModule::ShutdownModule()
{
FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(
DataGuardTabs::MainTab);
// 22강의 ToolMenus 해제도 그대로 수행합니다.
}

Build.cs의 Slate와 SlateCore는 Private Dependency로 유지합니다. Public API가 Slate Widget을 노출하지 않기 때문입니다.

5. 코드가 동작하는 이유​

Tab Manager가 ID와 생성 Delegate를 보관하고, 사용자가 메뉴를 실행할 때 TryInvokeTab이 이미 열린 탭을 활성화하거나 새 탭을 생성합니다. Panel은 Slate 공유 포인터 수명 안에서만 존재하고 Module은 Spawner 등록 수명을 책임집니다.

6. 자주 하는 실수와 해결법​

7. 직접 실습​

8. 이해 점검 질문 3개​

9. 핵심 요약​

MINI QUIZ

Slate 기초와 Dockable Editor Tab 만들기 미니 퀴즈

선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.

0 / 2
  1. 문제 1“Slate 기초와 Dockable Editor Tab 만들기”에서 다음 단계로 넘어가기 전에 확인할 핵심은 무엇인가요?
  2. 문제 2‘UObject 포인터를 Slate에 Raw로 장기 보관’ 실수를 판단할 때 “Slate 기초와 Dockable Editor Tab 만들기” 강의가 제시한 기준은 무엇인가요?
LESSON STATUS

학습을 마쳤나요?

직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.

23강. Slate 기초와 Dockable Editor Tab 만들기 미완료 상태