closes https://github.com/assimp/assimp/issues/2166: add missing setter for metadata.

pull/3137/head
Kim Kulling 2020-04-06 11:16:16 +02:00
parent 085212e58a
commit 131aed73b0
4 changed files with 487 additions and 511 deletions

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2020, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2020, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -49,29 +47,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_METADATA_H_INC #define AI_METADATA_H_INC
#ifdef __GNUC__ #ifdef __GNUC__
# pragma GCC system_header #pragma GCC system_header
#endif #endif
#if defined(_MSC_VER) && (_MSC_VER <= 1500) #if defined(_MSC_VER) && (_MSC_VER <= 1500)
# include "Compiler/pstdint.h" #include "Compiler/pstdint.h"
#else #else
# include <stdint.h> #include <stdint.h>
#endif #endif
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** /**
* Enum used to distinguish data types * Enum used to distinguish data types
*/ */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
typedef enum aiMetadataType { typedef enum aiMetadataType {
AI_BOOL = 0, AI_BOOL = 0,
AI_INT32 = 1, AI_INT32 = 1,
AI_UINT64 = 2, AI_UINT64 = 2,
AI_FLOAT = 3, AI_FLOAT = 3,
AI_DOUBLE = 4, AI_DOUBLE = 4,
AI_AISTRING = 5, AI_AISTRING = 5,
AI_AIVECTOR3D = 6, AI_AIVECTOR3D = 6,
AI_META_MAX = 7, AI_META_MAX = 7,
#ifndef SWIG #ifndef SWIG
FORCE_32BIT = INT_MAX FORCE_32BIT = INT_MAX
@ -84,10 +82,10 @@ typedef enum aiMetadataType {
* *
* The type field uniquely identifies the underlying type of the data field * The type field uniquely identifies the underlying type of the data field
*/ */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct aiMetadataEntry { struct aiMetadataEntry {
aiMetadataType mType; aiMetadataType mType;
void* mData; void *mData;
}; };
#ifdef __cplusplus #ifdef __cplusplus
@ -98,15 +96,29 @@ struct aiMetadataEntry {
/** /**
* Helper functions to get the aiType enum entry for a type * Helper functions to get the aiType enum entry for a type
*/ */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
inline aiMetadataType GetAiType( bool ) { return AI_BOOL; } inline aiMetadataType GetAiType(bool) {
inline aiMetadataType GetAiType( int32_t ) { return AI_INT32; } return AI_BOOL;
inline aiMetadataType GetAiType( uint64_t ) { return AI_UINT64; } }
inline aiMetadataType GetAiType( float ) { return AI_FLOAT; } inline aiMetadataType GetAiType(int32_t) {
inline aiMetadataType GetAiType( double ) { return AI_DOUBLE; } return AI_INT32;
inline aiMetadataType GetAiType( const aiString & ) { return AI_AISTRING; } }
inline aiMetadataType GetAiType( const aiVector3D & ) { return AI_AIVECTOR3D; } inline aiMetadataType GetAiType(uint64_t) {
return AI_UINT64;
}
inline aiMetadataType GetAiType(float) {
return AI_FLOAT;
}
inline aiMetadataType GetAiType(double) {
return AI_DOUBLE;
}
inline aiMetadataType GetAiType(const aiString &) {
return AI_AISTRING;
}
inline aiMetadataType GetAiType(const aiVector3D &) {
return AI_AIVECTOR3D;
}
#endif // __cplusplus #endif // __cplusplus
@ -116,17 +128,17 @@ inline aiMetadataType GetAiType( const aiVector3D & ) { return AI_AIVECTOR3D; }
* *
* Metadata is a key-value store using string keys and values. * Metadata is a key-value store using string keys and values.
*/ */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct aiMetadata { struct aiMetadata {
/** Length of the mKeys and mValues arrays, respectively */ /** Length of the mKeys and mValues arrays, respectively */
unsigned int mNumProperties; unsigned int mNumProperties;
/** Arrays of keys, may not be NULL. Entries in this array may not be NULL as well. */ /** Arrays of keys, may not be NULL. Entries in this array may not be NULL as well. */
C_STRUCT aiString* mKeys; C_STRUCT aiString *mKeys;
/** Arrays of values, may not be NULL. Entries in this array may be NULL if the /** Arrays of values, may not be NULL. Entries in this array may be NULL if the
* corresponding property key has no assigned value. */ * corresponding property key has no assigned value. */
C_STRUCT aiMetadataEntry* mValues; C_STRUCT aiMetadataEntry *mValues;
#ifdef __cplusplus #ifdef __cplusplus
@ -134,71 +146,62 @@ struct aiMetadata {
* @brief The default constructor, set all members to zero by default. * @brief The default constructor, set all members to zero by default.
*/ */
aiMetadata() AI_NO_EXCEPT aiMetadata() AI_NO_EXCEPT
: mNumProperties(0) : mNumProperties(0),
, mKeys(nullptr) mKeys(nullptr),
, mValues(nullptr) { mValues(nullptr) {
// empty // empty
} }
aiMetadata( const aiMetadata &rhs ) aiMetadata(const aiMetadata &rhs) :
: mNumProperties( rhs.mNumProperties ) mNumProperties(rhs.mNumProperties), mKeys(nullptr), mValues(nullptr) {
, mKeys( nullptr ) mKeys = new aiString[mNumProperties];
, mValues( nullptr ) { for (size_t i = 0; i < static_cast<size_t>(mNumProperties); ++i) {
mKeys = new aiString[ mNumProperties ]; mKeys[i] = rhs.mKeys[i];
for ( size_t i = 0; i < static_cast<size_t>( mNumProperties ); ++i ) {
mKeys[ i ] = rhs.mKeys[ i ];
} }
mValues = new aiMetadataEntry[ mNumProperties ]; mValues = new aiMetadataEntry[mNumProperties];
for ( size_t i = 0; i < static_cast<size_t>(mNumProperties); ++i ) { for (size_t i = 0; i < static_cast<size_t>(mNumProperties); ++i) {
mValues[ i ].mType = rhs.mValues[ i ].mType; mValues[i].mType = rhs.mValues[i].mType;
switch ( rhs.mValues[ i ].mType ) { switch (rhs.mValues[i].mType) {
case AI_BOOL: case AI_BOOL:
mValues[ i ].mData = new bool; mValues[i].mData = new bool;
::memcpy( mValues[ i ].mData, rhs.mValues[ i ].mData, sizeof(bool) ); ::memcpy(mValues[i].mData, rhs.mValues[i].mData, sizeof(bool));
break; break;
case AI_INT32: { case AI_INT32: {
int32_t v; int32_t v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( int32_t ) ); ::memcpy(&v, rhs.mValues[i].mData, sizeof(int32_t));
mValues[ i ].mData = new int32_t( v ); mValues[i].mData = new int32_t(v);
} } break;
break;
case AI_UINT64: { case AI_UINT64: {
uint64_t v; uint64_t v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( uint64_t ) ); ::memcpy(&v, rhs.mValues[i].mData, sizeof(uint64_t));
mValues[ i ].mData = new uint64_t( v ); mValues[i].mData = new uint64_t(v);
} } break;
break;
case AI_FLOAT: { case AI_FLOAT: {
float v; float v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( float ) ); ::memcpy(&v, rhs.mValues[i].mData, sizeof(float));
mValues[ i ].mData = new float( v ); mValues[i].mData = new float(v);
} } break;
break;
case AI_DOUBLE: { case AI_DOUBLE: {
double v; double v;
::memcpy( &v, rhs.mValues[ i ].mData, sizeof( double ) ); ::memcpy(&v, rhs.mValues[i].mData, sizeof(double));
mValues[ i ].mData = new double( v ); mValues[i].mData = new double(v);
} } break;
break;
case AI_AISTRING: { case AI_AISTRING: {
aiString v; aiString v;
rhs.Get<aiString>( mKeys[ i ], v ); rhs.Get<aiString>(mKeys[i], v);
mValues[ i ].mData = new aiString( v ); mValues[i].mData = new aiString(v);
} } break;
break;
case AI_AIVECTOR3D: { case AI_AIVECTOR3D: {
aiVector3D v; aiVector3D v;
rhs.Get<aiVector3D>( mKeys[ i ], v ); rhs.Get<aiVector3D>(mKeys[i], v);
mValues[ i ].mData = new aiVector3D( v ); mValues[i].mData = new aiVector3D(v);
} } break;
break;
#ifndef SWIG #ifndef SWIG
case FORCE_32BIT: case FORCE_32BIT:
#endif #endif
default: default:
break; break;
} }
} }
} }
@ -206,33 +209,33 @@ struct aiMetadata {
* @brief The destructor. * @brief The destructor.
*/ */
~aiMetadata() { ~aiMetadata() {
delete [] mKeys; delete[] mKeys;
mKeys = nullptr; 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) {
void* data = mValues[i].mData; void *data = mValues[i].mData;
switch (mValues[i].mType) { switch (mValues[i].mType) {
case AI_BOOL: case AI_BOOL:
delete static_cast< bool* >( data ); delete static_cast<bool *>(data);
break; break;
case AI_INT32: case AI_INT32:
delete static_cast< int32_t* >( data ); delete static_cast<int32_t *>(data);
break; break;
case AI_UINT64: case AI_UINT64:
delete static_cast< uint64_t* >( data ); delete static_cast<uint64_t *>(data);
break; break;
case AI_FLOAT: case AI_FLOAT:
delete static_cast< float* >( data ); delete static_cast<float *>(data);
break; break;
case AI_DOUBLE: case AI_DOUBLE:
delete static_cast< double* >( data ); delete static_cast<double *>(data);
break; break;
case AI_AISTRING: case AI_AISTRING:
delete static_cast< aiString* >( data ); delete static_cast<aiString *>(data);
break; break;
case AI_AIVECTOR3D: case AI_AIVECTOR3D:
delete static_cast< aiVector3D* >( data ); delete static_cast<aiVector3D *>(data);
break; break;
#ifndef SWIG #ifndef SWIG
case FORCE_32BIT: case FORCE_32BIT:
@ -243,7 +246,7 @@ struct aiMetadata {
} }
// Delete the metadata array // Delete the metadata array
delete [] mValues; delete[] mValues;
mValues = nullptr; mValues = nullptr;
} }
} }
@ -252,16 +255,15 @@ struct aiMetadata {
* @brief Allocates property fields + keys. * @brief Allocates property fields + keys.
* @param numProperties Number of requested properties. * @param numProperties Number of requested properties.
*/ */
static inline static inline aiMetadata *Alloc(unsigned int numProperties) {
aiMetadata *Alloc( unsigned int numProperties ) { if (0 == numProperties) {
if ( 0 == numProperties ) {
return nullptr; return nullptr;
} }
aiMetadata *data = new aiMetadata; aiMetadata *data = new aiMetadata;
data->mNumProperties = numProperties; data->mNumProperties = numProperties;
data->mKeys = new aiString[ data->mNumProperties ](); data->mKeys = new aiString[data->mNumProperties]();
data->mValues = new aiMetadataEntry[ data->mNumProperties ](); data->mValues = new aiMetadataEntry[data->mNumProperties]();
return data; return data;
} }
@ -269,44 +271,40 @@ struct aiMetadata {
/** /**
* @brief Deallocates property fields + keys. * @brief Deallocates property fields + keys.
*/ */
static inline static inline void Dealloc(aiMetadata *metadata) {
void Dealloc( aiMetadata *metadata ) {
delete metadata; delete metadata;
} }
template<typename T> template <typename T>
inline inline void Add(const std::string &key, const T &value) {
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];
for(unsigned int i = 0; i < mNumProperties; ++i) for (unsigned int i = 0; i < mNumProperties; ++i) {
{ new_keys[i] = mKeys[i];
new_keys[i] = mKeys[i]; new_values[i] = mValues[i];
new_values[i] = mValues[i]; }
}
delete[] mKeys; delete[] mKeys;
delete[] mValues; delete[] mValues;
mKeys = new_keys; mKeys = new_keys;
mValues = new_values; mValues = new_values;
mNumProperties++; mNumProperties++;
Set(mNumProperties - 1, key, value); Set(mNumProperties - 1, key, value);
} }
template<typename T> template <typename T>
inline inline bool Set(unsigned index, const std::string &key, const T &value) {
bool Set( unsigned index, const std::string& key, const T& value ) {
// In range assertion // In range assertion
if ( index >= mNumProperties ) { if (index >= mNumProperties) {
return false; return false;
} }
// Ensure that we have a valid key. // Ensure that we have a valid key.
if ( key.empty() ) { if (key.empty()) {
return false; return false;
} }
@ -321,73 +319,86 @@ struct aiMetadata {
return true; return true;
} }
template<typename T> template <typename T>
inline inline bool Set( const std::string &key, const T &value ) {
bool Get( unsigned index, T& value ) const { if (key.empty()) {
return false;
}
bool result = false;
for (unsigned int i = 0; i < mNumProperties; ++i) {
if (key == mKeys[i].C_Str()) {
Set(i, key, value);
result = true;
break;
}
}
return result;
}
template <typename T>
inline bool Get(unsigned index, T &value) const {
// In range assertion // In range assertion
if ( index >= mNumProperties ) { if (index >= mNumProperties) {
return false; return false;
} }
// Return false if the output data type does // Return false if the output data type does
// not match the found value's data type // not match the found value's data type
if ( GetAiType( value ) != mValues[ index ].mType ) { if (GetAiType(value) != mValues[index].mType) {
return false; return false;
} }
// Otherwise, output the found value and // Otherwise, output the found value and
// return true // return true
value = *static_cast<T*>(mValues[index].mData); value = *static_cast<T *>(mValues[index].mData);
return true; return true;
} }
template<typename T> template <typename T>
inline inline bool Get(const aiString &key, T &value) const {
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) {
return Get( i, value ); return Get(i, value);
} }
} }
return false; return false;
} }
template<typename T> template <typename T>
inline inline bool Get(const std::string &key, T &value) const {
bool Get( const std::string& key, T& value ) const {
return Get(aiString(key), value); return Get(aiString(key), value);
} }
/// Return metadata entry for analyzing it by user. /// Return metadata entry for analyzing it by user.
/// \param [in] pIndex - index of the entry. /// \param [in] pIndex - index of the entry.
/// \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 inline bool Get(size_t index, const aiString *&key, const aiMetadataEntry *&entry) const {
bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) const { if (index >= mNumProperties) {
if ( index >= mNumProperties ) {
return false; return false;
} }
key = &mKeys[index]; key = &mKeys[index];
entry = &mValues[index]; entry = &mValues[index];
return true; return true;
} }
/// Check whether there is a metadata entry for the given key. /// Check whether there is a metadata entry for the given key.
/// \param [in] Key - the key value value to check for. /// \param [in] Key - the key value value to check for.
inline inline bool HasKey(const char *key) {
bool HasKey(const char* key) { if (nullptr == key) {
if ( nullptr == key ) {
return false; return false;
} }
// 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 ( 0 == strncmp(mKeys[i].C_Str(), key, mKeys[i].length ) ) { if (0 == strncmp(mKeys[i].C_Str(), key, mKeys[i].length)) {
return true; return true;
} }
} }
@ -395,7 +406,6 @@ struct aiMetadata {
} }
#endif // __cplusplus #endif // __cplusplus
}; };
#endif // AI_METADATA_H_INC #endif // AI_METADATA_H_INC

View File

@ -213,6 +213,10 @@ TEST_F(utFBXImporterExporter, importUnitScaleFactor) {
double factor(0.0); double factor(0.0);
scene->mMetaData->Get("UnitScaleFactor", factor); scene->mMetaData->Get("UnitScaleFactor", factor);
EXPECT_DOUBLE_EQ(500.0, factor); EXPECT_DOUBLE_EQ(500.0, factor);
scene->mMetaData->Set("UnitScaleFactor", factor * 2);
scene->mMetaData->Get("UnitScaleFactor", factor);
EXPECT_DOUBLE_EQ(1000.0, factor);
} }
TEST_F(utFBXImporterExporter, importEmbeddedAsciiTest) { TEST_F(utFBXImporterExporter, importEmbeddedAsciiTest) {