+ 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-9d2fd5bffc1f
pull/2/head
aramis_acg 2011-10-15 13:37:59 +00:00
parent c807fd65f3
commit 255ed412d5
2 changed files with 102 additions and 40 deletions

View File

@ -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

View File

@ -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.