看完能得到什么?
对自定义的资源进行导出、导入、覆盖
展示效果如下
导出,可以看到桌面上多了一个以simpAnim为后缀的文件
导入,导入我们上面导出的文件,可以看到导入后里面的数值还是18
覆盖,我们将原来的文件里面的Value修改,并将第一个gif导出的文件拖进来,可以看到文件的Value又变成18了
1、导出
#pragma once
#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "Exporters/Exporter.h"
#include "SimpleAnimationAssetExporter.generated.h"
UCLASS()
class USimpleAnimationAssetExporter : public UExporter
{
GENERATED_UCLASS_BODY()
virtual bool SupportsObject(UObject* Object) const override;
virtual bool ExportBinary(UObject* Object, const TCHAR* Type, FArchive& Ar, FFeedbackContext* Warn, int32 FileIndex = 0, uint32 PortFlags = 0) override;
};
我们需要继承 UExporter,并且重写上述两个方法,上述两个方法分别代表:
SupportsObject: 支持导出的对象
ExportBinary: 导出对象保存的数据形式(或者说把数据保存成什么样)
#include "SimpleAnimationAssetExporter.h"
#include "SimpleAnimationAsset.h"
USimpleAnimationAssetExporter::USimpleAnimationAssetExporter(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
SupportedClass = USimpleAnimationAsset::StaticClass();
PreferredFormatIndex = 0;
FormatExtension.Add(TEXT("simpAnim"));
FormatDescription.Add(TEXT("Simple Animation Asset"));
}
bool USimpleAnimationAssetExporter::SupportsObject(UObject* Object) const
{
bool bSupportsObject = false;
if (Super::SupportsObject(Object))
{
bSupportsObject = IsValid(Cast<USimpleAnimationAsset>(Object));
}
return bSupportsObject;
}
bool USimpleAnimationAssetExporter::ExportBinary(UObject* Object, const TCHAR* Type, FArchive& Ar, FFeedbackContext* Warn, int32 FileIndex, uint32 PortFlags)
{
USimpleAnimationAsset* Asset = CastChecked<USimpleAnimationAsset>(Object);
if (!IsValid(Asset))
{
return false;
}
Ar << Asset->IntValue;
return true;
}
需要注意的是,在构造函数中,我们要定义 “导出所支持的资源类型”,也就是SupportedClass ,后面几个参数分别代表:
1、使用下面定义的后缀、文件说明的优先级索引
2、文件后缀
3、文件说明
后缀和说明如下面“保存类型里”所示,
在ExportBinary函数中,简单的将IntValue的值以字节的形式保存到文件中,所以你会看到 str其实是不会保存的也就无法加载 哈哈哈哈
2、导入
#include "CoreMinimal.h"
#include "Factories/Factory.h"
#include "SimpleAnimationAssetFactoryImport.generated.h"
UCLASS()
class USimpleAnimationAssetFactoryImport : public UFactory
{
GENERATED_UCLASS_BODY()
public:
virtual UObject* FactoryCreateFile(UClass* InClass, UObject* InParent,
FName InName, EObjectFlags Flags, const FString& Filename, const TCHAR* Parms,
FFeedbackContext* Warn, bool& bOutOperationCanceled) override;
};
导入相当于利用重新创建一个新的资源,因此和我们最开始定义的创建新资源一样继承自 “UFactory”,我们需要重写其FactoryCreateFile,用于导入的时候创建对应的UE内资源
#pragma once
#include "SimpleAnimationAssetFactoryImport.h"
#include "SimpleAnimationAsset.h"
#include "Containers/UnrealString.h"
#include "Misc/FileHelper.h"
USimpleAnimationAssetFactoryImport::USimpleAnimationAssetFactoryImport(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
Formats.Add(FString(TEXT("simpAnim;")));
SupportedClass = USimpleAnimationAsset::StaticClass();
bCreateNew = false;
bEditorImport = true;
}
UObject* USimpleAnimationAssetFactoryImport::FactoryCreateFile(UClass* InClass, UObject* InParent,
FName InName, EObjectFlags Flags, const FString& Filename, const TCHAR* Parms,
FFeedbackContext* Warn, bool& bOutOperationCanceled)
{
USimpleAnimationAsset* SimpleAnimationAsset = nullptr;
TArray<uint8> Bytes;
if (FFileHelper::LoadFileToArray(Bytes, *Filename) && Bytes.Num() >= sizeof(int32))
{
SimpleAnimationAsset = NewObject<USimpleAnimationAsset>(InParent, InClass, InName, Flags);
for (uint32 i = 0; i < sizeof(int32); ++i) {
SimpleAnimationAsset->IntValue |= Bytes[i] << (i * 8);
}
}
bOutOperationCanceled = false;
return SimpleAnimationAsset;
}
需要注意的是,在构造函数中,我们要定义 “导入所支持的资源类型”,也就是SupportedClass ,其他几个参数分别代表:
1、支持的文件后缀(工厂支持的格式列表)
2、导入的时候是否从CanCreateNew()返回的默认值
3、是否允许工厂从文件导入对象
在FactoryCreateFile方法中,简单的将IntValue的值以字节的形式读取到UE中,并将其赋值给IntValue
3、覆盖
#pragma once
#include "CoreMinimal.h"
#include "Factories/Factory.h"
#include "EditorReimportHandler.h"
#include "SimpleAnimationAssetFactoryImport.generated.h"
UCLASS()
class USimpleAnimationAssetFactoryImport : public UFactory
, public FReimportHandler
{
GENERATED_UCLASS_BODY()
public:
virtual UObject* FactoryCreateFile(UClass* InClass, UObject* InParent,
FName InName, EObjectFlags Flags, const FString& Filename, const TCHAR* Parms,
FFeedbackContext* Warn, bool& bOutOperationCanceled) override;
virtual bool CanReimport(UObject* Obj, TArray<FString>& OutFilenames) override;
virtual EReimportResult::Type Reimport(UObject* Obj) override;
};
我们需要在import中多继承一个基类 FReimportHandler,该类用于重新导入,也就是覆盖
新增几个导入相关的函数:
CanReimport: 是否可以进行重新导入操作
Reimport: 导入的实际数据操作
bool USimpleAnimationAssetFactoryImport::CanReimport(UObject* Obj, TArray<FString>& OutFilenames)
{
return true;
}
EReimportResult::Type USimpleAnimationAssetFactoryImport::Reimport(UObject* Obj)
{
if (IsValid(Obj)) {
bool OutCancel = false;
UObject* NewObj = ImportObject(Obj->GetClass(), Obj->GetOuter(),
Obj->GetFName(), Obj->GetFlags(), PreferredReimportPath,
nullptr, OutCancel);
if (!OutCancel) {
USimpleAnimationAsset* SimpleAnimationAsset = Cast<USimpleAnimationAsset>(NewObj);
return EReimportResult::Succeeded;
}
}
return EReimportResult::Failed;
}
是否可以重新导入,我们直接定义为True,这里可以根据需求增加导入的限制
Reimport 中 我们将导入的对象转为我们定义的资源类型 USimpleAnimationAsset