+ add Exporter::RegisterExporter and Exporter::UnregisterExporter pair of methods. Make parts of the internal export interface public to allow custom exporters to be added on the fly. This is a non-breaking API change.
git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1084 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/2/head
parent
c807fd65f3
commit
255ed412d5
|
@ -75,47 +75,20 @@ void ExportSceneObj(const char*,IOSystem*, const aiScene*);
|
|||
void ExportSceneSTL(const char*,IOSystem*, const aiScene*);
|
||||
void ExportScene3DS(const char*, IOSystem*, const aiScene*) {}
|
||||
|
||||
/// Function pointer type of a Export worker function
|
||||
typedef void (*fpExportFunc)(const char*,IOSystem*,const aiScene*);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/// Internal description of an Assimp export format option
|
||||
struct ExportFormatEntry
|
||||
{
|
||||
/// Public description structure to be returned by aiGetExportFormatDescription()
|
||||
aiExportFormatDesc mDescription;
|
||||
|
||||
// Worker function to do the actual exporting
|
||||
fpExportFunc mExportFunction;
|
||||
|
||||
// Postprocessing steps to be executed PRIOR to calling mExportFunction
|
||||
unsigned int mEnforcePP;
|
||||
|
||||
// Constructor to fill all entries
|
||||
ExportFormatEntry( const char* pId, const char* pDesc, const char* pExtension, fpExportFunc pFunction, unsigned int pEnforcePP = 0u)
|
||||
{
|
||||
mDescription.id = pId;
|
||||
mDescription.description = pDesc;
|
||||
mDescription.fileExtension = pExtension;
|
||||
mExportFunction = pFunction;
|
||||
mEnforcePP = pEnforcePP;
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// global array of all export formats which Assimp supports in its current build
|
||||
ExportFormatEntry gExporters[] =
|
||||
Exporter::ExportFormatEntry gExporters[] =
|
||||
{
|
||||
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
|
||||
ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
|
||||
Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
|
||||
#endif
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
|
||||
ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj),
|
||||
Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj),
|
||||
#endif
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_STL_EXPORTER
|
||||
ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL,
|
||||
Exporter::ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL,
|
||||
aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
|
||||
),
|
||||
#endif
|
||||
|
@ -125,6 +98,8 @@ ExportFormatEntry gExporters[] =
|
|||
//#endif
|
||||
};
|
||||
|
||||
#define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))
|
||||
|
||||
|
||||
class ExporterPimpl {
|
||||
public:
|
||||
|
@ -135,6 +110,10 @@ public:
|
|||
, mIsDefaultIOHandler(true)
|
||||
{
|
||||
GetPostProcessingStepInstanceList(mPostProcessingSteps);
|
||||
|
||||
// grab all builtin exporters
|
||||
mExporters.resize(ASSIMP_NUM_EXPORTERS);
|
||||
std::copy(gExporters,gExporters+ASSIMP_NUM_EXPORTERS,mExporters.begin());
|
||||
}
|
||||
|
||||
~ExporterPimpl()
|
||||
|
@ -158,9 +137,11 @@ public:
|
|||
|
||||
/** Last fatal export error */
|
||||
std::string mError;
|
||||
|
||||
/** Exporters, this includes those registered using #Assimp::Exporter::RegisterExporter */
|
||||
std::vector<Exporter::ExportFormatEntry> mExporters;
|
||||
};
|
||||
|
||||
#define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
||||
|
@ -239,8 +220,9 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
|
|||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
pimpl->mError = "";
|
||||
for (size_t i = 0; i < ASSIMP_NUM_EXPORTERS; ++i) {
|
||||
if (!strcmp(gExporters[i].mDescription.id,pFormatId)) {
|
||||
for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
|
||||
const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i];
|
||||
if (!strcmp(exp.mDescription.id,pFormatId)) {
|
||||
|
||||
try {
|
||||
|
||||
|
@ -258,7 +240,7 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
|
|||
const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded;
|
||||
|
||||
// Erase all pp steps that were already applied to this scene
|
||||
unsigned int pp = (gExporters[i].mEnforcePP | pPreprocessing) & ~(priv
|
||||
unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv
|
||||
? (priv->mPPStepsApplied & ~nonIdempotentSteps)
|
||||
: 0u);
|
||||
|
||||
|
@ -282,7 +264,7 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
|
|||
}
|
||||
}
|
||||
|
||||
if (verbosify || (gExporters[i].mEnforcePP & aiProcess_JoinIdenticalVertices)) {
|
||||
if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
|
||||
DefaultLogger::get()->debug("export: Scene data not in verbose format, applying MakeVerboseFormat step first");
|
||||
|
||||
MakeVerboseFormatProcess proc;
|
||||
|
@ -331,7 +313,7 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
|
|||
privOut->mPPStepsApplied |= pp;
|
||||
}
|
||||
|
||||
gExporters[i].mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get());
|
||||
exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get());
|
||||
}
|
||||
catch (DeadlyExportError& err) {
|
||||
pimpl->mError = err.what();
|
||||
|
@ -383,18 +365,42 @@ const aiExportDataBlob* Exporter :: GetOrphanedBlob() const
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
size_t Exporter :: GetExportFormatCount() const
|
||||
{
|
||||
return ASSIMP_NUM_EXPORTERS;
|
||||
return pimpl->mExporters.size();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex ) const
|
||||
{
|
||||
if (pIndex >= ASSIMP_NUM_EXPORTERS) {
|
||||
if (pIndex >= GetExportFormatCount()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &gExporters[pIndex].mDescription;
|
||||
return &pimpl->mExporters[pIndex].mDescription;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiReturn Exporter :: RegisterExporter(const ExportFormatEntry& desc)
|
||||
{
|
||||
BOOST_FOREACH(const ExportFormatEntry& e, pimpl->mExporters) {
|
||||
if (!strcmp(e.mDescription.id,desc.mDescription.id)) {
|
||||
return aiReturn_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
pimpl->mExporters.push_back(desc);
|
||||
return aiReturn_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Exporter :: UnregisterExporter(const char* id)
|
||||
{
|
||||
for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin(); it != pimpl->mExporters.end(); ++it) {
|
||||
if (!strcmp((*it).mDescription.id,id)) {
|
||||
pimpl->mExporters.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_EXPORT
|
||||
|
|
|
@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace Assimp {
|
||||
class ExporterPimpl;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
/** CPP-API: The Exporter class forms an C++ interface to the export functionality
|
||||
* of the Open Asset Import Library. Note that the export interface is available
|
||||
|
@ -76,6 +77,37 @@ class ASSIMP_API Exporter
|
|||
// : public boost::noncopyable
|
||||
//#endif // __cplusplus
|
||||
{
|
||||
public:
|
||||
|
||||
/** Function pointer type of a Export worker function */
|
||||
typedef void (*fpExportFunc)(const char*,IOSystem*,const aiScene*);
|
||||
|
||||
/** Internal description of an Assimp export format option */
|
||||
struct ExportFormatEntry
|
||||
{
|
||||
/// Public description structure to be returned by aiGetExportFormatDescription()
|
||||
aiExportFormatDesc mDescription;
|
||||
|
||||
// Worker function to do the actual exporting
|
||||
fpExportFunc mExportFunction;
|
||||
|
||||
// Postprocessing steps to be executed PRIOR to invoking mExportFunction
|
||||
unsigned int mEnforcePP;
|
||||
|
||||
// Constructor to fill all entries
|
||||
ExportFormatEntry( const char* pId, const char* pDesc, const char* pExtension, fpExportFunc pFunction, unsigned int pEnforcePP = 0u)
|
||||
{
|
||||
mDescription.id = pId;
|
||||
mDescription.description = pDesc;
|
||||
mDescription.fileExtension = pExtension;
|
||||
mExportFunction = pFunction;
|
||||
mEnforcePP = pEnforcePP;
|
||||
}
|
||||
|
||||
ExportFormatEntry() : mExportFunction(), mEnforcePP() {}
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
|
@ -223,6 +255,30 @@ public:
|
|||
const aiExportFormatDesc* GetExportFormatDescription( size_t pIndex ) const;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Register a custom exporter. Custom export formats are limited to
|
||||
* to the current #Exporter instance and do not affect the
|
||||
* library globally.
|
||||
* @param desc Exporter description.
|
||||
* @return aiReturn_SUCCESS if the export format was successfully
|
||||
* registered. A common cause that would prevent an exporter
|
||||
* from being registered is that its format id is already
|
||||
* occupied by another format. */
|
||||
aiReturn RegisterExporter(const ExportFormatEntry& desc);
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Remove an export format previously registered with #RegisterExporter
|
||||
* from the #Exporter instance (this can also be used to drop
|
||||
* builtin exporters because those are implicitly registered
|
||||
* using #RegisterExporter).
|
||||
* @param id Format id to be unregistered, this refers to the
|
||||
* 'id' field of #aiExportFormatDesc.
|
||||
* @note Calling this method on a format description not yet registered
|
||||
* has no effect.*/
|
||||
void UnregisterExporter(const char* id);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Just because we don't want you to know how we're hacking around.
|
||||
|
|
Loading…
Reference in New Issue