Page History
...
When omitting include files and forward declarations, a minimal implementation of an asset importer looks as follows.
class CMyMeshImporter : public CAssetImporter { DECLARE_ASSET_IMPORTER_DESC(CMyMeshImporter) // (1) public : virtual std::vector<string> GetFileExtensions() const override; // (2) virtual std::vector<string> GetAssetTypes() const override; // (3) |
private : virtual std::vector<string> GetAssetNames( const std::vector<string>& assetTypes, CAssetImportContext& ctx) override; // (4) virtual std::vector<CAsset*> ImportAssets( const std::vector<string>& assetNames, CAssetImportContext& ctx) override; // (5) }; |
...
Every asset importer is a sub-class of CAssetImporter.
The macro (1) handles details of the IClassDesc system, and essentially makes the importer visible to the Sandbox. There are four methods that every importer needs to implement.
(1) and (2) are called by Sandbox to query what source file type and what asset types the importer supports, respectively. In this example, we only create Mesh assets from the fictional mymesh format, so the implementation looks like this:
...
std::vector<string> CMyMeshImporter::GetFileExtensions() const { return { "mymesh" }; // File extensions are lower-case and without leading dot. } |
std::vector<string> CMyMeshImporter::GetAssetTypes() const { return { "Mesh" }; } |
Note that the other two methods, (4) and (5) are private. They are not part of the public interface, but implementation details of the asset importer. The CAssetImporter
class has a single method for importing, CAssetImporter::Import(),
that implements the governing logic of importing assets in a two-phase process. First, it gets a list of potentially imported asset names and processes it. Then, a subset of that list is actually imported.
...
GetAssetNames
is passed a list of requested asset types and returns a list of asset names that might be written. However, it must neither modify existing assets nor create new ones, because some additional steps might be necessary before touching files on disk. For example, the files need to be checked out for version control. The list of asset names, or, more generally, a subset of it, is then passed, ImportAssets
which then actually writes the files.
...
std::vector<string> CMeshImporter::GetAssetNames( const std::vector<string>& assetTypes, CAssetImportContext& ctx) { const string basename = PathUtil::GetFileName(ctx.GetInputFilePath()); // (6) std::vector<string> assetNames; for ( const string& type : assetTypes) { if (type == "Mesh" ) { assetNames.push_back(basename + ".cgf.cryasset" ); } } return assetNames; } |
std::string<CAsset*> CMeshImporter::ImportAssets( const std::vector<string>& assetNames, CAssetImportContext& ctx) { std::vector<CAsset*> importedAssets; for ( const string& name : assetNames) { importedAssets.push_back(ImportInternal(name)); } return importedAssets; } |
Each of these methods is passed an import context that holds data of for importing process of a single source file. The path to the source file, and the path to the output directory, for example, can be queried from the context (6).
...
As the RC does most of the work, the importing of most asset types looks similar to this:
...
void CAssetImporterFBX::ImportMesh(CAssetImportContext& ctx) { InitMetaData(); // Basically arguments passed to RC. CallRC(assetPath); // Calls RC to create asset in temporary directory. } |
Then, all cryasset files in the temporary directory are listed. The actual assets of type CAsset*
are created by loading these cryassets from disk. The places you can do this are limited by design, but one possibility is to use CAssetImportContext::LoadAssset
.
...