PART 5 · 강의 2/3

커스텀 에셋 에디터

FAssetEditorToolkit으로 커스텀 에셋 전용 에디터 UI를 구축합니다

01

FAssetEditorToolkit 개요

에셋 에디터의 프레임워크 이해하기

블루프린트 에디터, 머티리얼 에디터 같은 전용 에디터는 모두 FAssetEditorToolkit을 기반으로 합니다. 탭 매니저로 레이아웃을 구성하고, 툴바와 메뉴를 커스터마이징합니다.

구성 요소역할
FAssetEditorToolkit에셋 에디터의 기본 프레임워크
FTabManager탭 레이아웃 관리 (도킹, 분할)
FToolBarBuilder에디터 전용 툴바
IDetailsView프로퍼티 편집 패널
02

에셋 에디터 구현

Dialogue Tree 전용 에디터 만들기

FDialogueTreeEditor.h #pragma once #include "Toolkits/AssetEditorToolkit.h" class FDialogueTreeEditor : public FAssetEditorToolkit { public: void InitEditor( const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& Host, UDialogueTree* InTree); // FAssetEditorToolkit virtual FName GetToolkitFName() const override { return "DialogueTreeEditor"; } virtual FText GetBaseToolkitName() const override { return LOCTEXT("Name", "Dialogue Tree Editor"); } virtual FString GetWorldCentricTabPrefix() const override { return "DialogueTree"; } virtual FLinearColor GetWorldCentricTabColorScale() const override { return FLinearColor(0.0f, 0.8f, 1.0f); } // 탭 레이아웃 정의 virtual void RegisterTabSpawners( const TSharedRef<FTabManager>& TabManager) override; virtual void UnregisterTabSpawners( const TSharedRef<FTabManager>& TabManager) override; private: TSharedRef<SDockTab> SpawnDetailsTab( const FSpawnTabArgs& Args); TSharedRef<SDockTab> SpawnNodeListTab( const FSpawnTabArgs& Args); TSharedRef<SDockTab> SpawnPreviewTab( const FSpawnTabArgs& Args); UDialogueTree* EditingTree = nullptr; TSharedPtr<IDetailsView> DetailsView; static const FName DetailsTabId; static const FName NodeListTabId; static const FName PreviewTabId; };
FDialogueTreeEditor.cpp (핵심 부분) const FName FDialogueTreeEditor::DetailsTabId("Details"); const FName FDialogueTreeEditor::NodeListTabId("NodeList"); const FName FDialogueTreeEditor::PreviewTabId("Preview"); void FDialogueTreeEditor::InitEditor( const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& Host, UDialogueTree* InTree) { EditingTree = InTree; // 기본 탭 레이아웃 정의 const TSharedRef<FTabManager::FLayout> Layout = FTabManager::NewLayout("DialogueTreeEditorLayout_v1") ->AddArea( FTabManager::NewPrimaryArea() ->SetOrientation(Orient_Horizontal) ->Split( FTabManager::NewStack() ->SetSizeCoefficient(0.3f) ->AddTab(NodeListTabId, ETabState::OpenedTab)) ->Split( FTabManager::NewStack() ->SetSizeCoefficient(0.4f) ->AddTab(PreviewTabId, ETabState::OpenedTab)) ->Split( FTabManager::NewStack() ->SetSizeCoefficient(0.3f) ->AddTab(DetailsTabId, ETabState::OpenedTab)) ); // 에디터 초기화 InitAssetEditor(Mode, Host, FName("DialogueTreeEditorApp"), Layout, true, // bCreateDefaultStandaloneMenu true, // bCreateDefaultToolbar InTree); } void FDialogueTreeEditor::RegisterTabSpawners( const TSharedRef<FTabManager>& InTabManager) { FAssetEditorToolkit::RegisterTabSpawners(InTabManager); InTabManager->RegisterTabSpawner( DetailsTabId, FOnSpawnTab::CreateSP( this, &FDialogueTreeEditor::SpawnDetailsTab)) .SetDisplayName(LOCTEXT("Details", "Details")) .SetIcon(FSlateIcon( FAppStyle::GetAppStyleSetName(), "LevelEditor.Tabs.Details")); InTabManager->RegisterTabSpawner( NodeListTabId, FOnSpawnTab::CreateSP( this, &FDialogueTreeEditor::SpawnNodeListTab)) .SetDisplayName(LOCTEXT("Nodes", "Node List")); InTabManager->RegisterTabSpawner( PreviewTabId, FOnSpawnTab::CreateSP( this, &FDialogueTreeEditor::SpawnPreviewTab)) .SetDisplayName(LOCTEXT("Preview", "Preview")); } TSharedRef<SDockTab> FDialogueTreeEditor::SpawnDetailsTab( const FSpawnTabArgs& Args) { // 디테일 뷰 생성 FPropertyEditorModule& PropModule = FModuleManager::GetModuleChecked<FPropertyEditorModule>( "PropertyEditor"); FDetailsViewArgs ViewArgs; ViewArgs.bAllowSearch = true; ViewArgs.bHideSelectionTip = true; DetailsView = PropModule.CreateDetailView(ViewArgs); DetailsView->SetObject(EditingTree); return SNew(SDockTab) .Label(LOCTEXT("Details", "Details")) [ DetailsView.ToSharedRef() ]; }
03

AssetTypeActions에서 에디터 열기

더블클릭으로 커스텀 에디터 실행하기

C++ - OpenAssetEditor 구현 void FDialogueTreeTypeActions::OpenAssetEditor( const TArray<UObject*>& InObjects, TSharedPtr<IToolkitHost> EditWithinLevelEditor) { EToolkitMode::Type Mode = EditWithinLevelEditor.IsValid() ? EToolkitMode::WorldCentric : EToolkitMode::Standalone; for (UObject* Obj : InObjects) { UDialogueTree* Tree = Cast<UDialogueTree>(Obj); if (Tree) { TSharedRef<FDialogueTreeEditor> Editor( new FDialogueTreeEditor()); Editor->InitEditor( Mode, EditWithinLevelEditor, Tree); } } }
04

에디터 툴바 커스터마이징

에셋 에디터 전용 툴바 버튼 추가

C++ - 에디터 툴바 // InitEditor에서 툴바 확장 등록 void FDialogueTreeEditor::InitEditor(...) { // ... InitAssetEditor 호출 후 ... // 에디터 전용 툴바 확장 TSharedPtr<FExtender> ToolbarExtender = MakeShareable(new FExtender); ToolbarExtender->AddToolBarExtension( "Asset", EExtensionHook::After, GetToolkitCommands(), FToolBarExtensionDelegate::CreateSP( this, &FDialogueTreeEditor::BuildToolbar)); AddToolbarExtender(ToolbarExtender); RegenerateMenusAndToolbars(); } void FDialogueTreeEditor::BuildToolbar( FToolBarBuilder& Builder) { Builder.AddSeparator(); Builder.AddToolBarButton( FUIAction(FExecuteAction::CreateSP( this, &FDialogueTreeEditor::OnValidateTree)), NAME_None, LOCTEXT("Validate", "Validate"), LOCTEXT("ValidateTip", "Validate dialogue tree"), FSlateIcon(FAppStyle::GetAppStyleSetName(), "Icons.Check")); Builder.AddToolBarButton( FUIAction(FExecuteAction::CreateSP( this, &FDialogueTreeEditor::OnExportJSON)), NAME_None, LOCTEXT("Export", "Export JSON"), LOCTEXT("ExportTip", "Export as JSON file"), FSlateIcon(FAppStyle::GetAppStyleSetName(), "Icons.Save")); }
레이아웃 저장/복원

FTabManager::NewLayout에 전달하는 레이아웃 이름에 버전 접미사(예: _v1)를 붙이면 레이아웃이 변경될 때 사용자의 저장된 레이아웃을 리셋할 수 있습니다. 버전을 올리면 새 기본 레이아웃이 적용됩니다.

SUMMARY

핵심 요약

  • FAssetEditorToolkit은 커스텀 에셋 전용 에디터의 프레임워크이며, 탭 레이아웃, 툴바, 메뉴를 제공합니다
  • FTabManager::NewLayout으로 탭의 분할 구조(Details, Node List, Preview 등)를 정의합니다
  • IDetailsView로 UObject의 프로퍼티를 자동으로 편집 가능한 패널을 생성합니다
  • FAssetTypeActions::OpenAssetEditor에서 커스텀 에디터를 생성하여 더블클릭으로 열 수 있게 합니다
  • 에디터 전용 툴바 버튼으로 Validate, Export 같은 에셋별 작업을 제공합니다
PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: FAssetEditorToolkit으로 에셋 에디터 생성

FAssetEditorToolkit을 상속받아 커스텀 에셋(UMyQuestData)을 더블클릭하면 열리는 전용 에디터를 만드세요. 기본 레이아웃에 프로퍼티 에디터(FPropertyEditorModule)와 프리뷰 패널을 배치하세요.

실습 2: 에셋 에디터 툴바와 메뉴

커스텀 에셋 에디터에 Save, Validate, Export 버튼이 포함된 툴바를 추가하세요. Save 시 에셋을 저장하고, Validate 시 데이터 무결성을 검사하며, Export 시 JSON으로 내보내는 기능을 구현하세요.

심화 과제: 노드 그래프 에셋 에디터

SGraphEditor를 활용하여 노드 기반 비주얼 에디터를 구현하세요. 대화 시스템이나 AI 행동 트리처럼 노드를 연결하여 흐름을 편집할 수 있는 에셋 에디터를 만드세요.