Merge branch 'master' into master

pull/1841/head
Kim Kulling 2018-03-20 20:33:17 +01:00 committed by GitHub
commit f898f40486
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 280 additions and 90 deletions

View File

@ -117,6 +117,7 @@ bool D3MFExporter::exportArchive( const char *file ) {
if ( nullptr == m_zipArchive ) { if ( nullptr == m_zipArchive ) {
return false; return false;
} }
ok |= exportContentTypes(); ok |= exportContentTypes();
ok |= export3DModel(); ok |= export3DModel();
ok |= exportRelations(); ok |= exportRelations();
@ -181,6 +182,8 @@ bool D3MFExporter::export3DModel() {
mModelOutput << "<" << XmlTag::resources << ">"; mModelOutput << "<" << XmlTag::resources << ">";
mModelOutput << std::endl; mModelOutput << std::endl;
writeMetaData();
writeBaseMaterials(); writeBaseMaterials();
writeObjects(); writeObjects();
@ -209,6 +212,29 @@ void D3MFExporter::writeHeader() {
mModelOutput << std::endl; mModelOutput << std::endl;
} }
void D3MFExporter::writeMetaData() {
if ( nullptr == mScene->mMetaData ) {
return;
}
const unsigned int numMetaEntries( mScene->mMetaData->mNumProperties );
if ( 0 == numMetaEntries ) {
return;
}
const aiString *key;
const aiMetadataEntry *entry(nullptr);
for ( size_t i = 0; i < numMetaEntries; ++i ) {
mScene->mMetaData->Get( i, key, entry );
std::string k( key->C_Str() );
aiString value;
mScene->mMetaData->Get( k, value );
mModelOutput << "<" << XmlTag::meta << " " << XmlTag::meta_name << "=\"" << key->C_Str() << "\">";
mModelOutput << value.C_Str();
mModelOutput << "</" << XmlTag::meta << ">" << std::endl;
}
}
void D3MFExporter::writeBaseMaterials() { void D3MFExporter::writeBaseMaterials() {
mModelOutput << "<basematerials id=\"1\">\n"; mModelOutput << "<basematerials id=\"1\">\n";
for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) { for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) {

View File

@ -76,6 +76,7 @@ public:
protected: protected:
void writeHeader(); void writeHeader();
void writeMetaData();
void writeBaseMaterials(); void writeBaseMaterials();
void writeObjects(); void writeObjects();
void writeMesh( aiMesh *mesh ); void writeMesh( aiMesh *mesh );

View File

@ -102,6 +102,8 @@ public:
// //
} else if ( nodeName == D3MF::XmlTag::basematerials ) { } else if ( nodeName == D3MF::XmlTag::basematerials ) {
ReadBaseMaterials(); ReadBaseMaterials();
} else if ( nodeName == D3MF::XmlTag::meta ) {
ReadMetadata();
} }
} }
@ -109,19 +111,31 @@ public:
scene->mRootNode->mName.Set( "3MF" ); scene->mRootNode->mName.Set( "3MF" );
} }
// import the metadata
if ( !mMetaData.empty() ) {
const size_t numMeta( mMetaData.size() );
scene->mMetaData = aiMetadata::Alloc( numMeta );
for ( size_t i = 0; i < numMeta; ++i ) {
aiString val( mMetaData[ i ].value );
scene->mMetaData->Set( i, mMetaData[ i ].name, val );
}
}
// import the meshes
scene->mNumMeshes = static_cast<unsigned int>( mMeshes.size()); scene->mNumMeshes = static_cast<unsigned int>( mMeshes.size());
scene->mMeshes = new aiMesh*[scene->mNumMeshes](); scene->mMeshes = new aiMesh*[scene->mNumMeshes]();
std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes);
// import the materials
scene->mNumMaterials = static_cast<unsigned int>( mMatArray.size() ); scene->mNumMaterials = static_cast<unsigned int>( mMatArray.size() );
if ( 0 != scene->mNumMaterials ) { if ( 0 != scene->mNumMaterials ) {
scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ]; scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ];
std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials ); std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials );
} }
// create the scenegraph
scene->mRootNode->mNumChildren = static_cast<unsigned int>(children.size()); scene->mRootNode->mNumChildren = static_cast<unsigned int>(children.size());
scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren](); scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren]();
std::copy(children.begin(), children.end(), scene->mRootNode->mChildren); std::copy(children.begin(), children.end(), scene->mRootNode->mChildren);
} }
@ -180,6 +194,21 @@ private:
return mesh; return mesh;
} }
void ReadMetadata() {
const std::string name = xmlReader->getAttributeValue( D3MF::XmlTag::meta_name.c_str() );
xmlReader->read();
const std::string value = xmlReader->getNodeData();
if ( name.empty() ) {
return;
}
MetaEntry entry;
entry.name = name;
entry.value = value;
mMetaData.push_back( entry );
}
void ImportVertices(aiMesh* mesh) { void ImportVertices(aiMesh* mesh) {
std::vector<aiVector3D> vertices; std::vector<aiVector3D> vertices;
while(ReadToEndElement(D3MF::XmlTag::vertices)) { while(ReadToEndElement(D3MF::XmlTag::vertices)) {
@ -371,8 +400,12 @@ private:
return false; return false;
} }
private: private:
struct MetaEntry {
std::string name;
std::string value;
};
std::vector<MetaEntry> mMetaData;
std::vector<aiMesh*> mMeshes; std::vector<aiMesh*> mMeshes;
MatArray mMatArray; MatArray mMatArray;
unsigned int mActiveMatGroup; unsigned int mActiveMatGroup;

View File

@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of DefaultLogger (and Logger) * @brief Implementation of DefaultLogger (and Logger)
*/ */
// Default log streams // Default log streams
#include "Win32DebugLogStream.h" #include "Win32DebugLogStream.h"
#include "StdOStreamLogStream.h" #include "StdOStreamLogStream.h"
@ -62,7 +61,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
# include <thread> # include <thread>
# include <mutex> # include <mutex>
std::mutex loggerMutex; std::mutex loggerMutex;
#endif #endif
@ -76,22 +74,19 @@ static const unsigned int SeverityAll = Logger::Info | Logger::Err | Logger::War
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Represents a log-stream + its error severity // Represents a log-stream + its error severity
struct LogStreamInfo struct LogStreamInfo {
{
unsigned int m_uiErrorSeverity; unsigned int m_uiErrorSeverity;
LogStream *m_pStream; LogStream *m_pStream;
// Constructor // Constructor
LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) : LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) :
m_uiErrorSeverity( uiErrorSev ), m_uiErrorSeverity( uiErrorSev ),
m_pStream( pStream ) m_pStream( pStream ) {
{
// empty // empty
} }
// Destructor // Destructor
~LogStreamInfo() ~LogStreamInfo() {
{
delete m_pStream; delete m_pStream;
} }
}; };
@ -109,7 +104,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
#ifdef WIN32 #ifdef WIN32
return new Win32DebugLogStream(); return new Win32DebugLogStream();
#else #else
return NULL; return nullptr;
#endif #endif
// Platform-independent default streams // Platform-independent default streams
@ -118,7 +113,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
case aiDefaultLogStream_STDOUT: case aiDefaultLogStream_STDOUT:
return new StdOStreamLogStream(std::cout); return new StdOStreamLogStream(std::cout);
case aiDefaultLogStream_FILE: case aiDefaultLogStream_FILE:
return (name && *name ? new FileLogStream(name,io) : NULL); return (name && *name ? new FileLogStream(name,io) : nullptr );
default: default:
// We don't know this default log stream, so raise an assertion // We don't know this default log stream, so raise an assertion
ai_assert(false); ai_assert(false);
@ -134,34 +129,38 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/, Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/,
LogSeverity severity /*= NORMAL*/, LogSeverity severity /*= NORMAL*/,
unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/, unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/,
IOSystem* io /*= NULL*/) IOSystem* io /*= NULL*/) {
{
// enter the mutex here to avoid concurrency problems // enter the mutex here to avoid concurrency problems
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
std::lock_guard<std::mutex> lock(loggerMutex); std::lock_guard<std::mutex> lock(loggerMutex);
#endif #endif
if (m_pLogger && !isNullLogger() ) if ( m_pLogger && !isNullLogger() ) {
delete m_pLogger; delete m_pLogger;
}
m_pLogger = new DefaultLogger( severity ); m_pLogger = new DefaultLogger( severity );
// Attach default log streams // Attach default log streams
// Stream the log to the MSVC debugger? // Stream the log to the MSVC debugger?
if (defStreams & aiDefaultLogStream_DEBUGGER) if ( defStreams & aiDefaultLogStream_DEBUGGER ) {
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_DEBUGGER ) ); m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_DEBUGGER ) );
}
// Stream the log to COUT? // Stream the log to COUT?
if (defStreams & aiDefaultLogStream_STDOUT) if ( defStreams & aiDefaultLogStream_STDOUT ) {
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDOUT ) ); m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDOUT ) );
}
// Stream the log to CERR? // Stream the log to CERR?
if (defStreams & aiDefaultLogStream_STDERR) if ( defStreams & aiDefaultLogStream_STDERR ) {
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDERR ) ); m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDERR ) );
}
// Stream the log to a file // Stream the log to a file
if (defStreams & aiDefaultLogStream_FILE && name && *name) if ( defStreams & aiDefaultLogStream_FILE && name && *name ) {
m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_FILE, name, io ) ); m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_FILE, name, io ) );
}
return m_pLogger; return m_pLogger;
} }
@ -200,7 +199,6 @@ void Logger::warn(const char* message) {
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
void Logger::error(const char* message) { void Logger::error(const char* message) {
// SECURITY FIX: see above // SECURITY FIX: see above
if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
return; return;
@ -209,23 +207,24 @@ void Logger::error(const char* message) {
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
void DefaultLogger::set( Logger *logger ) void DefaultLogger::set( Logger *logger ) {
{
// enter the mutex here to avoid concurrency problems // enter the mutex here to avoid concurrency problems
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
std::lock_guard<std::mutex> lock(loggerMutex); std::lock_guard<std::mutex> lock(loggerMutex);
#endif #endif
if (!logger)logger = &s_pNullLogger; if ( nullptr == logger ) {
if (m_pLogger && !isNullLogger() ) logger = &s_pNullLogger;
}
if ( nullptr != m_pLogger && !isNullLogger() ) {
delete m_pLogger; delete m_pLogger;
}
DefaultLogger::m_pLogger = logger; DefaultLogger::m_pLogger = logger;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
bool DefaultLogger::isNullLogger() bool DefaultLogger::isNullLogger() {
{
return m_pLogger == &s_pNullLogger; return m_pLogger == &s_pNullLogger;
} }
@ -236,8 +235,7 @@ Logger *DefaultLogger::get() {
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Kills the only instance // Kills the only instance
void DefaultLogger::kill() void DefaultLogger::kill() {
{
// enter the mutex here to avoid concurrency problems // enter the mutex here to avoid concurrency problems
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
std::lock_guard<std::mutex> lock(loggerMutex); std::lock_guard<std::mutex> lock(loggerMutex);
@ -252,10 +250,10 @@ void DefaultLogger::kill()
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Debug message // Debug message
void DefaultLogger::OnDebug( const char* message ) void DefaultLogger::OnDebug( const char* message ) {
{ if ( m_Severity == Logger::NORMAL ) {
if ( m_Severity == Logger::NORMAL )
return; return;
}
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
char msg[Size]; char msg[Size];
@ -266,8 +264,7 @@ void DefaultLogger::OnDebug( const char* message )
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Logs an info // Logs an info
void DefaultLogger::OnInfo( const char* message ) void DefaultLogger::OnInfo( const char* message ){
{
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
char msg[Size]; char msg[Size];
ai_snprintf(msg, Size, "Info, T%u: %s", GetThreadID(), message ); ai_snprintf(msg, Size, "Info, T%u: %s", GetThreadID(), message );
@ -277,8 +274,7 @@ void DefaultLogger::OnInfo( const char* message )
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Logs a warning // Logs a warning
void DefaultLogger::OnWarn( const char* message ) void DefaultLogger::OnWarn( const char* message ) {
{
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
char msg[Size]; char msg[Size];
ai_snprintf(msg, Size, "Warn, T%u: %s", GetThreadID(), message ); ai_snprintf(msg, Size, "Warn, T%u: %s", GetThreadID(), message );
@ -288,8 +284,7 @@ void DefaultLogger::OnWarn( const char* message )
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Logs an error // Logs an error
void DefaultLogger::OnError( const char* message ) void DefaultLogger::OnError( const char* message ) {
{
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
char msg[ Size ]; char msg[ Size ];
ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message ); ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message );
@ -299,10 +294,10 @@ void DefaultLogger::OnError( const char* message )
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Will attach a new stream // Will attach a new stream
bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) {
{ if ( nullptr == pStream ) {
if (!pStream)
return false; return false;
}
if (0 == severity) { if (0 == severity) {
severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging; severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging;
@ -312,8 +307,7 @@ bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
it != m_StreamArray.end(); it != m_StreamArray.end();
++it ) ++it )
{ {
if ( (*it)->m_pStream == pStream ) if ( (*it)->m_pStream == pStream ) {
{
(*it)->m_uiErrorSeverity |= severity; (*it)->m_uiErrorSeverity |= severity;
return true; return true;
} }
@ -326,34 +320,31 @@ bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Detach a stream // Detach a stream
bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) {
{ if ( nullptr == pStream ) {
if (!pStream)
return false; return false;
}
if (0 == severity) { if (0 == severity) {
severity = SeverityAll; severity = SeverityAll;
} }
for ( StreamIt it = m_StreamArray.begin(); bool res( false );
it != m_StreamArray.end(); for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
++it ) if ( (*it)->m_pStream == pStream ) {
{
if ( (*it)->m_pStream == pStream )
{
(*it)->m_uiErrorSeverity &= ~severity; (*it)->m_uiErrorSeverity &= ~severity;
if ( (*it)->m_uiErrorSeverity == 0 ) if ( (*it)->m_uiErrorSeverity == 0 ) {
{
// don't delete the underlying stream 'cause the caller gains ownership again // don't delete the underlying stream 'cause the caller gains ownership again
(**it).m_pStream = NULL; (**it).m_pStream = nullptr;
delete *it; delete *it;
m_StreamArray.erase( it ); m_StreamArray.erase( it );
res = true;
break; break;
} }
return true; return true;
} }
} }
return false; return res;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
@ -361,15 +352,13 @@ bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity )
DefaultLogger::DefaultLogger(LogSeverity severity) DefaultLogger::DefaultLogger(LogSeverity severity)
: Logger ( severity ) : Logger ( severity )
, noRepeatMsg (false) , noRepeatMsg (false)
, lastLen( 0 ) , lastLen( 0 ) {
{
lastMsg[0] = '\0'; lastMsg[0] = '\0';
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Destructor // Destructor
DefaultLogger::~DefaultLogger() DefaultLogger::~DefaultLogger() {
{
for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) { for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
// also frees the underlying stream, we are its owner. // also frees the underlying stream, we are its owner.
delete *it; delete *it;
@ -378,9 +367,8 @@ DefaultLogger::~DefaultLogger()
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Writes message to stream // Writes message to stream
void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) {
{ ai_assert(nullptr != message);
ai_assert(NULL != message);
// Check whether this is a repeated message // Check whether this is a repeated message
if (! ::strncmp( message,lastMsg, lastLen-1)) if (! ::strncmp( message,lastMsg, lastLen-1))

View File

@ -308,7 +308,8 @@ bool IsVerboseFormat(const aiScene* pScene) {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties) { aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath,
unsigned int pPreprocessing, const ExportProperties* pProperties) {
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
// when they create scenes from scratch, users will likely create them not in verbose // when they create scenes from scratch, users will likely create them not in verbose

View File

@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/SceneCombiner.h> #include <assimp/SceneCombiner.h>
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <assimp/metadata.h>
#include <assimp/Hash.h> #include <assimp/Hash.h>
#include "time.h" #include "time.h"
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
@ -1001,7 +1002,12 @@ void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate)
*_dest = new aiScene(); *_dest = new aiScene();
} }
aiScene* dest = *_dest; aiScene* dest = *_dest;
ai_assert(dest); ai_assert(nullptr != dest);
// copy metadata
if ( nullptr != src->mMetaData ) {
dest->mMetaData = new aiMetadata( *src->mMetaData );
}
// copy animations // copy animations
dest->mNumAnimations = src->mNumAnimations; dest->mNumAnimations = src->mNumAnimations;

View File

@ -67,6 +67,7 @@ typedef enum aiMetadataType {
AI_DOUBLE = 4, AI_DOUBLE = 4,
AI_AISTRING = 5, AI_AISTRING = 5,
AI_AIVECTOR3D = 6, AI_AIVECTOR3D = 6,
AI_META_MAX = 7,
#ifndef SWIG #ifndef SWIG
FORCE_32BIT = INT_MAX FORCE_32BIT = INT_MAX
@ -130,17 +131,78 @@ struct aiMetadata {
*/ */
aiMetadata() aiMetadata()
: mNumProperties(0) : mNumProperties(0)
, mKeys(NULL) , mKeys(nullptr)
, mValues(NULL) { , mValues(nullptr) {
// empty // empty
} }
aiMetadata( const aiMetadata &rhs )
: mNumProperties( rhs.mNumProperties )
, mKeys( nullptr )
, mValues( nullptr ) {
mKeys = new aiString[ mNumProperties ];
for ( unsigned int i = 0; i < mNumProperties; ++i ) {
mKeys[ i ] = rhs.mKeys[ i ];
}
mValues = new aiMetadataEntry[ mNumProperties ];
for ( unsigned int i = 0; i < mNumProperties; ++i ) {
mValues[ i ].mType = rhs.mValues[ i ].mType;
switch ( rhs.mValues[ i ].mType ) {
case AI_BOOL:
mValues[ i ].mData = new bool( rhs.mValues[i].mData );
break;
case AI_INT32: {
int32_t v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( int32_t ) );
mValues[ i ].mData = new int32_t( v );
}
break;
case AI_UINT64: {
uint64_t v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( uint64_t ) );
mValues[ i ].mData = new uint64_t( v );
}
break;
case AI_FLOAT: {
float v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( float ) );
mValues[ i ].mData = new float( v );
}
break;
case AI_DOUBLE: {
double v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( double ) );
mValues[ i ].mData = new double( v );
}
break;
case AI_AISTRING: {
aiString v;
rhs.Get<aiString>( mKeys[ i ], v );
mValues[ i ].mData = new aiString( v );
}
break;
case AI_AIVECTOR3D: {
aiVector3D v;
rhs.Get<aiVector3D>( mKeys[ i ], v );
mValues[ i ].mData = new aiVector3D( v );
}
break;
#ifndef SWIG
case FORCE_32BIT:
#endif
default:
break;
}
}
}
/** /**
* @brief The destructor. * @brief The destructor.
*/ */
~aiMetadata() { ~aiMetadata() {
delete [] mKeys; delete [] mKeys;
mKeys = NULL; mKeys = nullptr;
if (mValues) { if (mValues) {
// Delete each metadata entry // Delete each metadata entry
for (unsigned i=0; i<mNumProperties; ++i) { for (unsigned i=0; i<mNumProperties; ++i) {
@ -177,7 +239,7 @@ struct aiMetadata {
// Delete the metadata array // Delete the metadata array
delete [] mValues; delete [] mValues;
mValues = NULL; mValues = nullptr;
} }
} }
@ -208,8 +270,8 @@ struct aiMetadata {
} }
template<typename T> template<typename T>
inline void Add(const std::string& key, const T& value) inline
{ void Add(const std::string& key, const T& value) {
aiString* new_keys = new aiString[mNumProperties + 1]; aiString* new_keys = new aiString[mNumProperties + 1];
aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1]; aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1];
@ -256,7 +318,7 @@ struct aiMetadata {
template<typename T> template<typename T>
inline inline
bool Get( unsigned index, T& value ) { bool Get( unsigned index, T& value ) const {
// In range assertion // In range assertion
if ( index >= mNumProperties ) { if ( index >= mNumProperties ) {
return false; return false;
@ -277,7 +339,7 @@ struct aiMetadata {
template<typename T> template<typename T>
inline inline
bool Get( const aiString& key, T& value ) { bool Get( const aiString& key, T& value ) const {
// Search for the given key // Search for the given key
for ( unsigned int i = 0; i < mNumProperties; ++i ) { for ( unsigned int i = 0; i < mNumProperties; ++i ) {
if ( mKeys[ i ] == key ) { if ( mKeys[ i ] == key ) {
@ -288,7 +350,8 @@ struct aiMetadata {
} }
template<typename T> template<typename T>
inline bool Get( const std::string& key, T& value ) { inline
bool Get( const std::string& key, T& value ) const {
return Get(aiString(key), value); return Get(aiString(key), value);
} }
@ -297,7 +360,8 @@ struct aiMetadata {
/// \param [out] pKey - pointer to the key value. /// \param [out] pKey - pointer to the key value.
/// \param [out] pEntry - pointer to the entry: type and value. /// \param [out] pEntry - pointer to the entry: type and value.
/// \return false - if pIndex is out of range, else - true. /// \return false - if pIndex is out of range, else - true.
inline bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) { inline
bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) const {
if ( index >= mNumProperties ) { if ( index >= mNumProperties ) {
return false; return false;
} }

View File

@ -181,3 +181,74 @@ TEST_F( utMetadata, get_set_aiVector3D_Test ) {
EXPECT_TRUE( success ); EXPECT_TRUE( success );
} }
TEST_F( utMetadata, copy_test ) {
m_data = aiMetadata::Alloc( AI_META_MAX );
bool bv = true;
m_data->Set( 0, "bool", bv );
int32_t i32v = -10;
m_data->Set( 1, "int32", i32v );
uint64_t ui64v = static_cast<uint64_t>( 10 );
m_data->Set( 2, "uint64", ui64v );
float fv = 1.0f;
m_data->Set( 3, "float", fv );
double dv = 2.0;
m_data->Set( 4, "double", dv );
const aiString strVal( std::string( "test" ) );
m_data->Set( 5, "aiString", strVal );
aiVector3D vecVal( 1, 2, 3 );
m_data->Set( 6, "aiVector3D", vecVal );
aiMetadata copy( *m_data );
EXPECT_EQ( 7, copy.mNumProperties );
// bool test
{
bool v;
EXPECT_TRUE( copy.Get( "bool", v ) );
EXPECT_EQ( bv, v );
}
// int32_t test
{
int32_t v;
bool ok = copy.Get( "int32", v );
EXPECT_TRUE( ok );
EXPECT_EQ( i32v, v );
}
// uint64_t test
{
uint64_t v;
bool ok = copy.Get( "uint64", v );
EXPECT_TRUE( ok );
EXPECT_EQ( ui64v, v );
}
// float test
{
float v;
EXPECT_TRUE( copy.Get( "float", v ) );
EXPECT_EQ( fv, v );
}
// double test
{
double v;
EXPECT_TRUE( copy.Get( "double", v ) );
EXPECT_EQ( dv, v );
}
// bool test
{
aiString v;
EXPECT_TRUE( copy.Get( "aiString", v ) );
EXPECT_EQ( strVal, v );
}
// bool test
{
aiVector3D v;
EXPECT_TRUE( copy.Get( "aiVector3D", v ) );
EXPECT_EQ( vecVal, v );
}
}