文章目录
一、创建一个自定义新资源
首先创建两个模块: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);
}
}
}
下边是初步设置的编辑器窗口样式。更多设置和说明在后续的文章中再详细解释,先初步了解大概流程。