【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项目记录(十一)自定义资源

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