using an editor source function in a custom class?

I am trying to write a new class that uses the import function from FBXMainImport.cpp.

The function is:



namespace UnFbx
{
bool FFbxImporter::ImportFile(FString Filename)
{
	bool Result = true;
	
	bool bStatus;
	
	FileBasePath = FPaths::GetPath(Filename);

	// Create the Scene
	Scene = FbxScene::Create(SdkManager,"");
	UE_LOG(LogFbx, Log, TEXT("Loading FBX Scene from %s"), *Filename);

	int32 FileMajor, FileMinor, FileRevision;

	IOS_REF.SetBoolProp(IMP_FBX_MATERIAL,		true);
	IOS_REF.SetBoolProp(IMP_FBX_TEXTURE,		 true);
	IOS_REF.SetBoolProp(IMP_FBX_LINK,			true);
	IOS_REF.SetBoolProp(IMP_FBX_SHAPE,		   true);
	IOS_REF.SetBoolProp(IMP_FBX_GOBO,			true);
	IOS_REF.SetBoolProp(IMP_FBX_ANIMATION,	   true);
	IOS_REF.SetBoolProp(IMP_SKINS,			   true);
	IOS_REF.SetBoolProp(IMP_DEFORMATION,		 true);
	IOS_REF.SetBoolProp(IMP_FBX_GLOBAL_SETTINGS, true);
	IOS_REF.SetBoolProp(IMP_TAKE,				true);

	// Import the scene.
	bStatus = Importer->Import(Scene);

	// Get the version number of the FBX file format.
	Importer->GetFileVersion(FileMajor, FileMinor, FileRevision);

	// output result
	if(bStatus)
	{
		UE_LOG(LogFbx, Log, TEXT("FBX Scene Loaded Succesfully"));
		CurPhase = IMPORTED;
		
		// Release importer now as it is unneeded and in the failure case is part of CleanUp()
		Importer->Destroy();
		Importer = NULL;
	}
	else
	{
		ErrorMessage = ANSI_TO_TCHAR(Importer->GetStatus().GetErrorString());
		AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Warning, FText::Format(LOCTEXT("FbxSkeletaLMeshimport_FileLoadingFailed", "FBX Scene Loading Failed : '{0}'"), FText::FromString(ErrorMessage))), FFbxErrors::Generic_LoadingSceneFailed);
		CleanUp();
		Result = false;
		CurPhase = NOTSTARTED;
	}
	
	return Result;
}
}



Inside a new function in my class, I have:



UnFbx::FFbxImporter fbxFunc;
	fbxFunc.ImportFile(".../file.fbx");

which should work, shouldn’t it?

But I get an error:

Error 2 error C2248: ‘UnFbx::FFbxImporter::FFbxImporter’ : cannot access protected member declared in class ‘UnFbx::FFbxImporter’

Is this because it is ‘Private’? Can I get around this?

The constructor is protected as it is intended to be used as a singleton. You need to do:


FFbxImporter* Importer = FFbxImporter::GetInstance();
Importer->DoSomething();

I think you may still have problems though. Only methods prefixed with UNREALED_API are exported from the module for external use. So try ImportFromFile instead of ImportFile. I guess this might work, though I’m kind of confused as to why the header file is in the private source subdirectory if it is exporting symbols. I had assumed being in private meant nothing was exported for use by other modules.

Thank you! that looks better, I have the code looking ok, but it gives me unresolved externals on building…

my function:



UStaticMesh* Avp_import::importFbxFile(FString filename)
{

	UStaticMesh* NewStaticMesh = NULL;

	UnFbx::FFbxImporter* Importer = UnFbx::FFbxImporter::GetInstance();

	if (!Importer->ImportFromFile("D:/assets/test/tags5.fbx", ".fbx"))
	{
		// Log the error message and fail the import.
		//Warn->Log(ELogVerbosity::Error, Importer->GetErrorMessage());
	}
	else
	{
		// Log the import message and import the mesh.
		const TCHAR* errorMessage = Importer->GetErrorMessage();
		if (errorMessage[0] != '\0')
		{
			//	Warn->Log(errorMessage);
		}

		FbxNode* RootNodeToImport = NULL;
		RootNodeToImport = Importer->Scene->GetRootNode();
		bool bCountLODGroupMeshes = 0;
		int32 NumLODGroups = 0;
		int32 InterestingNodeCount = Importer->GetFbxMeshCount(RootNodeToImport, bCountLODGroupMeshes, NumLODGroups);

		if (RootNodeToImport && InterestingNodeCount > 0)
		{
			int32 NodeIndex = 0;

			int32 ImportedMeshCount = 0;
			
			// CAST TO STATIC MESH HERE			
		}

	}

	return NewStaticMesh;

	Importer->ReleaseScene();
}

Do i need to link some dependencies somewhere?

Error 9 error LNK2019: unresolved external symbol “__declspec(dllimport) public: bool __cdecl UnFbx::FFbxImporter::ImportFromFile(class FString const &,class FString const &)” (_imp?ImportFromFile@FFbxImporter@UnFbx@@QEAA_NAEBVFString@@0@Z) referenced in function “public: static class UStaticMesh * __cdecl Avp_import::importFbxFile(class FString)” (?importFbxFile@Avp_import@@SAPEAVUStaticMesh@@VFString@@@Z)

Where have you put your code? This class is defined in the UnrealEd module, so if it even is possible to import it, you could only do so from inside an Editor module in your project (as opposed to the main game module), which referenced “UnrealEd” in its dependencies within its .build.cs file.

Even then you’re going to have issues, since you won’t be able to access the Scene member as you’ve tried, as it’s not exported. Looking through the list of methods that are exported, there is ImportStaticMesh, but it requires an FbxNode as input, and I don’t see any way to get one from the accessible methods. It looks to me like if this class was intended to be exposed to other modules, that functionality wasn’t completed. So your only options may be to either modify the engine code, or just copy and paste what you need into your project.

Ah. ****, I was starting to suspect this might be the case.

I have it in a game class.

So extending the editor might be an option?

Would a commandlet work differently? Or would I have the same issues?

When you say copy and paste, you mean copy everything from the UnrealEd module into new classes in the game code?

Well, if you are willing to modify the engine source, you can move it to the public folder and also add export tags (UNREALED_API) to the FFbxImporter class itself and/or specific methods you need to access. You’d still have to move your code that uses it to an editor module, but unless you need to import meshes at runtime in your packaged game, it would make sense to do that anyway. Regardless it’s a bit of work…

The copy and paste alternative means copying the FFbxImporter class implementation and anything it relies on into your own module, yes. This may also be problematic as I suspect it may be using a third party library.

Although I’ve heard the term before, I’m afraid I have no idea what a commandlet is.

I don’t either, to be honest! but I will look into them also. So it seems there is no easy way to do this. It should be such a simple thing!

It’s probably worth posting in the feedback forum as a request. I get the feeling there’s a bunch of stuff in the engine source that would be useful to have exported for use in external modules, but just hasn’t been because internally to Epic it hasn’t been needed and noone else has asked. I’ve had to copy and paste engine code on a couple of occasions myself for the same reasons.

For anyone who still has issues with this, I had a “cannot resolve externals” error when using FFbxImporter and it was because of what is mentioned above but if you look at the FbxImporter.h file any function that has UNREALED_API in the declaration can be used externally. Below are two examples. The first works and the second does not however, both are functions defined in the FFbxImporter class.



//Working import function
using namespace UnFbx; 

FString FbxPath = absoluteFilePath;
FFbxImporter* = FFbxImporter::GetInstance(); 

if (FBXImporter->ImportFromFile(FbxPath, "Mesh"))
{
   UE_LOG(LogTemp, Warning, TEXT("FBX Importer Imported from file"));
}


// Nonworking import function 
FString FbxPath = absoluteFilePath;
FFbxImporter* = FFbxImporter::GetInstance();

if (FBXImporter->ImportFile(FbxPath, "Mesh"))
{
    UE_LOG(LogTemp, Warning, TEXT("FBX Importer Imported from file"));
}