How do I create a new asset type?

I have a data file type, and a C++ library to read/write this data file type.
The file type describes a procedural layout of objects – a little like a lightweight scene, except much more specialized.
I want these files to be included in cooked game data as uassets.

I’d like to create an actor type that can be configured with one of these assets, and inflates it into geometry, both in editor, and in game.

My guess is that an appropriate way to go about this is:

  1. Derive my actor type from instanced-static-mesh-actor
  2. Define a new asset type that I can “import” from my data type, and which generates .uasset files.
  3. Inside the construct script, and each time the configured asset changes, my actor will remove any previously-created static mesh instances, and then re-create new instances based on the loaded data.

What I’m looking for is a map or description about how to go about #2.
How do I create a new asset type that I can “import” in the content browser, and that I can generate references to as properties for my new actor?
What are all the bits I need to implement to make:

  • file import dialog select right file type
  • content browser type filter recognize this asset type
  • actor property asset picker (like “texture picker” or “mesh picker”)
  • thumbnails for imported assets
  • actually creating the .uasset file from the selected raw import data

What are the base classes, how do they fit together, and how are they called/managed by the engine?

Have a look at the UFactory and FReimportHandler implementations. The CSV importer is an easy way to get into it, because it is very simple.

Here is a copy of a part of the UFactory interface:



    virtual FText GetDisplayName() const override;
    virtual UObject* FactoryCreateText(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, const TCHAR* Type, const TCHAR*& Buffer, const TCHAR* BufferEnd, FFeedbackContext* Warn) override;
    virtual bool DoesSupportClass(UClass * Class) override;
    virtual bool FactoryCanImport(const FString& Filename) override;

As you can see with FactoryCreateText, you can return any UObject as asset.
So as long as your asset class is a UObject with serializable UProperties it should just magically work.
This should take of everything except the thumbnail - I have no idea how that works, maybe have a look at the content browser code.

For the thumbnails, he have to create a new Slate Style class and tell Style to register the thumbnail brush as his class icon to be used in the Editor.
Up to 4.12 you have to call FIconFinder::RegisterIconSource(…) and grab the icon from your new Style class; on 4.13 and above, Editor will do this automatically for you; example:



#define PLUGIN_BRUSH(RelativePath,...) FSlateImageBrush(FMyStyle::InContent(RelativePath,TEXT(".png")),__VA_ARGS__)

class FMyStyle {
private:
	static TSharedPtr<FSlateStyleSet> StyleSet;
	static FString InContent(const FString &RelativePath, const TCHAR* Extension);
public:
	static void Initialize();
}


void FMyStyle::Initialize() {
	if (StyleSet.IsValid()) {return;}
	//
	const FVector2D Icon16x16(16.0f,16.0f);
	const FVector2D Icon128x128(128.0f,128.0f);
	//
	StyleSet = MakeShareable(new FSlateStyleSet(TEXT("FMyStyle")));
	StyleSet->SetContentRoot(IPluginManager::Get().FindPlugin(TEXT("MyPluginName"))->GetContentDir());
	//
	StyleSet->Set("ClassIcon.MyObjectClass", new PLUGIN_BRUSH(TEXT("Icons/Fsm_16x"),Icon16x16));                // Registers icon for  my  "UMyObjectClass"
	StyleSet->Set("ClassThumbnail.MyObjectClass", new PLUGIN_BRUSH(TEXT("Icons/Fsm_128x"),Icon128x128));  // Note how it ignores class prefixes. Don't use here 'A', 'E', 'F', 'U', etc; 
	//
	FSlateStyleRegistry::RegisterSlateStyle(*StyleSet.Get());
	//FClassIconFinder::RegisterIconSource(StyleSet.Get()); /// Depricated 4.13! Call this if you are on 4.12 or bellow...
};


After you do that, simply call Initialize() somewhere; usually inside a plugin’s startup function:



void FSMSettings::StartupModule() {
    FMyStyle::Initialize();
}


Whenever you create a new asset based on *MyObjectClass *it displays on Content Browser your custom *ClassThumbnail * you’ve made for it from now on :slight_smile:

Thanks for the answers! This gives me a fair bit to go on.