文章目錄
一、創建一個自定義新資源
首先創建兩個模塊: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,還有一件事要做,就是設置我們的編輯器佈局。這一方法在打開編輯器時可以調用。
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);
}
}
}
下邊是初步設置的編輯器窗口樣式。更多設置和說明在後續的文章中再詳細解釋,先初步瞭解大概流程。