【UE4】編輯器開發(三)資源類型拓展

一、創建一個自定義新資源

首先創建兩個模塊:NewAssets和AssetEditor,分別用於保存資源類和編輯器模塊相關的類。
因爲NewAssets模塊在項目打包時需要打包進項目程序,而AssetEditor則不需要,所以AssetEditor的模塊類型是Editor。因爲我們需要用到UE4編輯器模塊,所以需要包含UnrealEd模塊。

在NewAssets模塊中創建一個繼承UObject的類,類名爲UCustAsset。這個類就是我們定義的新資源類型。

UCLASS(Blueprintable, BlueprintType)
class NEWASSETS_API UCustAsset : public UObject
{
	GENERATED_BODY()
	
};

在AssetEditor創建一個繼承UFactory的類,類名爲UCustAssetFactory。這個類就是允許在UE4中創建自定義資源編輯器的工廠類,可以理解爲這個類定義了資源創建的方式。首先,必須實現FactoryCreateNew這個父類抽象方法,否則資源會創建失敗!

UNewAssetFactory::UNewAssetFactory()
{
	bCreateNew = true;				//當bCreateNew或者ShouldShowInNewMenu方法返回true時,該資源可以通過資源菜單創建
	bEditAfterNew = true;			//源碼註解是創建資源後,打開關聯編輯器,但沒有發現有什麼實際作用,後期發現作用後再補充	
	SupportedClass = UNewAsset::StaticClass();		//該資源對應或支持的對象類
	//這裏注意一下,就是UE4自己實現的一些工廠類中,SupportedClass的類是資源藍圖類,而ParentClass(的子類)纔是資源實例類。一個是資源藍圖類,一個是真正遊戲中實例化的類。注意區分。
}

//當返回true時,該資源可以通過資源菜單創建。如果沒有實現此方法,則會調用CanCreateNew方法來判斷是否可以通過菜單創建,CanCreateNew是返回bCreateNew的值。
bool UCustAssetFactory::ShouldShowInNewMenu() const { return true; }	

//返回對象,這裏一般返回SupportedClass的實例對象。當創建完資源並確認命名後,該方法將會被執行。
UObject* UNewAssetFactory::FactoryCreateNew(
	UClass* InClass,
	UObject* InParent;
	FName InName,
	EObjectFlags Flags,
	UObject* Context,
	FFeedbackContext* Warn,
	FName CallingContext
)
{
	return NewObject<UNewAsset>(InParent, InClass, InName, Flags | RF_Transactional);
}

創建資源菜單中會出現我們新定義的資源類型:
創建新資源
打開資源後,將會出現一個空(最基本)的資源編輯器窗口:
創建新資源
資源除了通過資源菜單創建,還可以從文件導入,下邊幾個是對文件導入支持的參數:

參數 說明
bEditorImport 是否支持通過文件導入資源
Formats 支持導入的文件格式,格式爲“ext;Description”,ext是擴展名
bText 資源將從文本格式的文件導入的還是二進制文件導入的

二、設置新資源在ContentBrowser中的顯示

創建兩個類,分別繼承FAssetTypeActions_Base和FAssetEditorToolkit。

1. 資源縮略圖操作

繼承FAssetTypeActions_Base的類,名爲FCustAssetActions。它主要負責資源圖標相關內容,包括顯示樣式和打開資源編輯器窗口等。下面我們實現一個必要方法,當雙擊打開資源(編輯器)時,將會執行此方法,並調出資源編輯器窗口。
FCustAssetActions.cpp:

void FCustAssetTypeActions::OpenAssetEditor(const TArray<UObject*>& InObjects, TSharedPtr<IToolkitHost> EditWithinLevelEditor)
{
	//這個ToolkitMode的作用待確認,一般情況都是無效,返回Standalone。
	EToolkitMode::Type Mode = EditWithinLevelEditor.IsValid() ? EToolkitMode::WorldCentric : EToolkitMode::Standalone;
	//變量對象數組,如果拿到我們的資源對象,就執行Toolkit初始化
	for (auto ObjIt = InObjects.CreateConstIterator(); ObjIt; ++ObjIt)
	{
		auto CustAsset = Cast<UCustAsset>(*ObjIt);

		if (CustAsset != nullptr)
		{
			TSharedRef<FCustAssetEditorToolkit> EditorToolkit = MakeShareable(new FCustAssetEditorToolkit());
			EditorToolkit->Initialize(CustAsset, Mode, EditWithinLevelEditor);
		}
	}
}

其它方法:

資源名

virtual FText GetName() const override;
資源名
資源名

資源描述

virtual FText GetAssetDescription(const struct FAssetData& AssetData) const override;
資源描述

資源類型顏色

virtual FColor GetTypeColor() const override;

資源類型顏色和縮略圖背景色
資源類型顏色

篩選

virtual bool CanFilter() override;
篩選

資源縮略圖圖標

virtual TSharedPtr GetThumbnailOverlay(const struct FAssetData& AssetData) const override;
資源縮略圖

2. 編輯器佈局與設置

另外一個類繼承FAssetEditorToolkit,是編輯器的工具集類,負責編輯器的樣式、佈局等功能。
需要實現的功能有兩個RegisterTabSpawners和UnregisterTabSpawners,用於註冊和卸載Tab。當然還有幾個方法需要覆蓋父類抽象方法,可以在父類中找到。

void FCustAssetEditorToolkit::RegisterTabSpawners(const TSharedRef<FTabManager>& InTabManager)
{
	Super::RegisterTabSpawners(InTabManager);

	InTabManager->RegisterTabSpawner(FName("TestTab"), FOnSpawnTab::CreateLambda(
		[&](const FSpawnTabArgs& Args)
	{
		return SNew(SDockTab)
			[
				SNew(STextBlock).Text(LOCTEXT("TestTab", "TestTab"))
			];
	}
	));
	InTabManager->RegisterTabSpawner(FName("CustTab"), FOnSpawnTab::CreateLambda(
	[&](const FSpawnTabArgs& Args)
	{
		return SNew(SDockTab)
			[
				SNew(SImage)
			];
	}
	));
}

void FCustAssetEditorToolkit::UnregisterTabSpawners(const TSharedRef<FTabManager>& InTabManager)
{
	Super::UnregisterTabSpawners(InTabManager);

	InTabManager->UnregisterTabSpawner(FName("CustTab"));
	InTabManager->UnregisterTabSpawner(FName("TestTab"));
}

註冊的Tab會出現在菜單欄中,點擊就可以打開。
Tab
當我們註冊了Tab,還有一件事要做,就是設置我們的編輯器佈局。這一方法在打開編輯器時可以調用。

void FCustAssetEditorToolkit::Initialize(UCustAsset* InAsset, const EToolkitMode::Type InMode, const TSharedPtr<IToolkitHost>& InToolkitHost)
{
	CustAsset = InAsset;

	const TSharedRef<FTabManager::FLayout> StandaloneCustLayout = FTabManager::NewLayout("StandaloneCustLayout_Layout")
			->AddArea
			(
				FTabManager::NewPrimaryArea()
				->Split(FTabManager::NewStack()->AddTab(FName("TestTab"), ETabState::OpenedTab))
			)
		);

	InitAssetEditor(InMode, InToolkitHost, CustAssetEditorToolkit::AppID, StandaloneCustLayout, true, true, InAsset);
	RegenerateMenusAndToolbars();
}

3. 註冊Action

最後,還要把Action類註冊一下。

void FAssetEditorModule::StartupModule()
{
	IAssetTools& AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();
	TSharedRef<IAssetTypeActions> CustAssetAction = MakeShareable(new FCustAssetTypeActions());
	RegisteredAssetTypeActions.Add(CustAssetAction);
	AssetTools.RegisterAssetTypeActions(CustAssetAction);
}

void FAssetEditorModule::ShutdownModule()
{
	FAssetToolsModule* AssetToolsModule = FModuleManager::GetModulePtr<FAssetToolsModule>("AssetTools");
	if (AssetToolsModule != nullptr)
	{
		IAssetTools& AssetTools = AssetToolsModule->Get();
		
		for (auto Action : RegisteredAssetTypeActions)
		{
			AssetTools.UnregisterAssetTypeActions(Action);
		}
	}
}

下邊是初步設置的編輯器窗口樣式。更多設置和說明在後續的文章中再詳細解釋,先初步瞭解大概流程。
編輯器窗口

參考文章:

UE4 創建自定義資源,導入與重新導入自定義資源
UE4項目記錄(十一)自定義資源

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章