Auto Importing FBX via Commandlet

We are working on a commandlet that will check a folder for FBX and texture files and run an automated import on them.

When manually importing a file, the Editor appears to use the functionality in UFbxFactory. I’m wondering if this is what we will need to tap into for the automated import as well and how best to do that.

Before we spend a lot of time potentially heading in the wrong direction, I wanted to see if anyone could offer some guidance (examples would be amazing if you have them:)). Thanks for any help you can give!

You can do this in a commandlet to import assets:

FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked("AssetTools");
TArray<UObject*> ImportedObjects = AssetToolsModule.Get().ImportAssets(FileToImport, PackagePath, FactoryToUse);

FactoryToUse is optional. If you don’t specify one it will figure it out. However the major problem with FBX is that a dialog appears asking for FBX settings. FBX’s are complicated and we cant easily determine in all cases what is in the file and what the user wants without asking ( and there could be multiple things in the file). You are going to have to work around this. I suggest constructing your own UFbxFactory instance, passing it in to the method above and adding some method to the UFbxFactory to specify the settings up front and not show the dialog. There is some basic auto-detection of asset type in the FBX file so simply adding a flag to not show the dialog and use the defaults might work out OK for you.

I’m getting a compiler error, any ideas?

Error 1 error C2783: ‘TModuleInterface &FModuleManager::LoadModuleChecked(const FName)’ : could not deduce template argument for ‘TModuleInterface’ P:\Unreal Projects\SandboxrImport\Source\SandboxrImport\AutoImport.cpp 13 1 SandboxrImport

Think I got it…had to add a few things:

const FName moduleName = "AssetTools";

FModuleManager::LoadModuleChecked(moduleName);

FAssetToolsModule& AssetToolsModule = FModuleManager::GetModuleChecked(moduleName);

Currently getting an exception when trying to ImportAssets()

TArray ImportedObjects = AssetToolsModule.Get().ImportAssets(files, importPath);

Giving me this:

First-chance exception at 0x000007FEDBABD231 (UE4Editor-Documentation.dll) in UE4Editor.exe: 0xC0000005: Access violation reading location 0x0000000000000C68. Unhandled exception at 0x000007FEDBABD231 (UE4Editor-Documentation.dll) in UE4Editor.exe: 0xC0000005: Access violation reading location 0x0000000000000C68.

When I run the commandlet with this:

TArray files; files.Add(TEXT("P:/Unreal Projects/SandboxrImport/Content/NeedImport/T_Worker_D_adj02.tga"));

FString packagePath = TEXT(“/Game/Textures/blah”);

TArray ImportedObjects = AssetToolsModule.Get().ImportAssets(files, packagePath);

Which is throwing an exception:

[2014.09.08-00.49.57:846][ 0]LogWindows: Assertion failed: IsValid() [File:P:\Unreal Projects\UnrealEngine\Engine\Source\Runtime\Core\Public\Templates\SharedPointer.h] [Line: 647]

Changing the package path to “/Game/Textures” gives me this exception:

[2014.09.08-19.52.23:580][ 0]LogFactory: FactoryCreateBinary: Texture with TextureFactory (0 0 P:/Unreal Projects/SandboxrImport/Content/Textures/NeedImport/T_Worker_D_adj02.tga) [2014.09.08-19.52.23:649][ 0]LogTexture:Display: Building textures: T_Worker_D_adj02 (AutoDXT) 'UE4Editor.exe' (Win32): Loaded 'P:\UNREAL~1\UnrealEngine\Engine\Binaries\Win64\UE4Editor-AssetRegistry.dll'. Symbols loaded. [2014.09.08-19.52.27:465][ 0]LogAssetRegistry: FAssetRegistry took 0.0108 seconds to start up 'UE4Editor.exe' (Win32): Loaded 'P:\Unreal Projects\UnrealEngine\Engine\Binaries\Win64\UE4Editor-DirectoryWatcher.dll'. Symbols loaded. First-chance exception at 0x000007FEE1C7FE3F (UE4Editor-UnrealEd.dll) in UE4Editor.exe: 0xC0000005: Access violation writing location 0x0000000000000DB0. Unhandled exception at 0x000007FEE1C7FE3F (UE4Editor-UnrealEd.dll) in UE4Editor.exe: 0xC0000005: Access violation writing location 0x0000000000000DB0.

It looks like we can’t use ImportAssets from a commandline call to a commandlet. The Main() in the commandlet seems to fire before the Editor is fully loaded which is causing eexceptions from GEditor->Broadcast in AssetTools.cpp.

As an alternative, I was able to use FEditorDelegates::OnMapOpened in order to fire my import function automatically, which works since the map is not loaded until the Editor is fully loaded. This seems a bit hacky, but does the job.

I could not find a way to wait for the Editor to fully load with the commandlet. I don’t think this is intentional, so it might be a bug with commandlets running editor functions.

Hi,blurdot :

I am trying to import FBX file to my project but I got some problem,it bother me for a long time.

TArray<UObject*> FileToImport; 
FileToImport.Add(TEXT("P:/UnrealProjects/SandboxrImport/Content/NeedImport/T_Worker_D_adj02.tga"));
TArray<UObject*> ImportedObjects = AssetToolsModule.Get().ImportAssets(FileToImport, PackagePath, FactoryToUse);

but it did not work,

Would you mind show me your .cpp file,this is my e-mail:iceprincefounder@qq.com.

Very appreciate your help!

@blurdot, Were you able to use Commandlet for it?
Or any other solution?

It’s in the 4.14 prerelease and sorta buggy at the moment, but there is a new Commandlet coming to do this! It’s called ImportAssetCommandlet (see commit) and can be invoked as UE4Editor.exe filepath.uproject -run=ImportAssets -source=filepath.fbx -dest=assetpath -importsettings="".

Yeah its pretty new and has no documentation at all yet. If you find bugs with it please point them out.

Well, it crashes if you don’t have source control enabled, since PackageStates is always empty:

[2016.11.14-19.33.56:799][  0]LogWindows:Error: Assertion failed: (Index >= 0) & (Index < ArrayNum) [File:d:\build\++ue4+release-4.14+compile\sync\engine\source\runtime\core\public\Containers/Array.h] [Line: 634] 
[2016.11.14-19.33.56:799][  0]LogWindows:Error: Array index out of bounds: 0 from an array of size 0
...
[2016.11.14-19.33.56:799][  0]LogWindows:Error: UE4Editor-UnrealEd.dll!UImportAssetsCommandlet::ImportAndSave() [d:\build\++ue4+release-4.14+compile\sync\engine\source\editor\unrealed\private\commandlets\importassetscommandlet.cpp:195]

That was fixed but it may not make it into a public release until 4.14.1

Thanks. It looks like it did indeed miss the cut :frowning:

Another bug with ImportAssetsCommandlet.
This commandlet can easily crash when trying to save engine and plugin content.
For example, if somewhere in my UFactory, I call LoadObject, in the process of loading the Material, it calls UObjectBaseUtility::MarkPackageDirty. there is a safeguard in there to not set the dirty flag when loading objects BUT the flag does get set in Commandlets.

This manifests as a crash when it tries to save the dirty assets:

[2016.11.19-00.13.11:170][  0]LogInit:Display: SourceControl:Error: Error fatal: C:/Program Files (x86)/Epic Games/4.14/Engine/Content/EngineSky/M_Sky_Panning_Clouds2.uasset: 'C:/Program Files (x86)/Epic Games/4.14/Engine/Content/EngineSky/M_Sky_Panning_Clouds2.uasset' is outside repository

The commandlet has a argument called “importsettings”. Does anyone know how this JSON file should look like? I couldn’t find any information.

{
“ImportGroups”: [
{
“FileNames”: [
“path/to/fbx/file/test.fbx”
],
“bReplaceExisting”: “true”,
“DestinationPath”: “/Game/Geometry/Test/”,
“FactoryName”: “FbxFactory”,
“ImportSettings”: {
“bImportMesh”: 1,
“bConvertSceneUnit”: 1,
“bConvertScene”: 1,
“bCombineMeshes”: 0,
“bImportTextures”: 0,
“bImportMaterials”: 0,
“AnimSequenceImportData”: {
“bImportMeshesInBoneHierarchy”: 1,
“bDeleteExistingMorphTargetCurves”: 1
},
“SkeletalMeshImportData”: {},
“TextureImportData”: {},
“StaticMeshImportData”: {
“bRemoveDegenerates”: 1,
“bAutoGenerateCollision”: 1
}
}
}
]
}

Hard to find, since there are no docs about this.
http://api.unrealengine.com/INT/API/Editor/UnrealEd/Factories/

Matt, I want konw how to suppress import dialogs when import fbx scene?I will be very grateful for your answer.

I’ve tried a lot of different ways to get this to work and still nothing is perfect. I’ve got the commandlet solved but I’d like to make it a new “scene import”. Here’s a post with all of my code and maybe something will help you.
fbx-automated-command-line-import