diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp
index 37a6ba4e0..e7cc6907d 100644
--- a/code/ColladaExporter.cpp
+++ b/code/ColladaExporter.cpp
@@ -238,7 +238,11 @@ void ColladaExporter::WriteHeader()
mOutput << startstr << "" << endstr;
PushTag();
- aiMetadata* meta = mScene->mRootNode->mMetaData;
+ // If no Scene metadata, use root node metadata
+ aiMetadata* meta = mScene->mMetaData;
+ if (!meta)
+ meta = mScene->mRootNode->mMetaData;
+
aiString value;
if (!meta || !meta->Get("Author", value))
mOutput << startstr << "" << "Assimp" << "" << endstr;
@@ -250,13 +254,39 @@ void ColladaExporter::WriteHeader()
else
mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr;
- //mOutput << startstr << "" << mScene->author.C_Str() << "" << endstr;
- //mOutput << startstr << "" << mScene->authoringTool.C_Str() << "" << endstr;
+ if (meta)
+ {
+ if (meta->Get("Comments", value))
+ mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr;
+ if (meta->Get("Copyright", value))
+ mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr;
+ if (meta->Get("SourceData", value))
+ mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr;
+ }
PopTag();
mOutput << startstr << "" << endstr;
- mOutput << startstr << "" << date_str << "" << endstr;
+
+ if (!meta || !meta->Get("Created", value))
+ mOutput << startstr << "" << date_str << "" << endstr;
+ else
+ mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr;
+
+ // Modified date is always the date saved
mOutput << startstr << "" << date_str << "" << endstr;
+
+ if (meta)
+ {
+ if (meta->Get("Keywords", value))
+ mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr;
+ if (meta->Get("Revision", value))
+ mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr;
+ if (meta->Get("Subject", value))
+ mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr;
+ if (meta->Get("Title", value))
+ mOutput << startstr << "
" << XMLEscape(value.C_Str()) << "" << endstr;
+ }
+
mOutput << startstr << "" << endstr;
mOutput << startstr << "" << up_axis << "" << endstr;
PopTag();
diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp
index 6837dca4a..cf548e890 100644
--- a/code/ColladaLoader.cpp
+++ b/code/ColladaLoader.cpp
@@ -207,6 +207,17 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
0, 0, 0, 1);
}
+ // Store scene metadata
+ if (!parser.mAssetMetaData.empty()) {
+ const size_t numMeta(parser.mAssetMetaData.size());
+ pScene->mMetaData = aiMetadata::Alloc(static_cast(numMeta));
+ size_t i = 0;
+ for (auto it = parser.mAssetMetaData.cbegin(); it != parser.mAssetMetaData.cend(); ++it, ++i)
+ {
+ pScene->mMetaData->Set(static_cast(i), (*it).first, (*it).second);
+ }
+ }
+
// store all meshes
StoreSceneMeshes( pScene);
diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp
index 0fa59362b..2106bf01c 100644
--- a/code/ColladaParser.cpp
+++ b/code/ColladaParser.cpp
@@ -264,14 +264,19 @@ void ColladaParser::ReadAssetInfo()
// check element end
TestClosing( "up_axis");
- } else
+ }
+ else if(IsElement("contributor"))
{
- SkipElement();
+ ReadContributorInfo();
+ }
+ else
+ {
+ ReadMetaDataItem(mAssetMetaData);
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
- if( strcmp( mReader->getNodeName(), "asset") != 0)
+ if (strcmp( mReader->getNodeName(), "asset") != 0)
ThrowException( "Expected end of element.");
break;
@@ -279,6 +284,75 @@ void ColladaParser::ReadAssetInfo()
}
}
+// ------------------------------------------------------------------------------------------------
+// Reads the contributor info
+void ColladaParser::ReadContributorInfo()
+{
+ if (mReader->isEmptyElement())
+ return;
+
+ while (mReader->read())
+ {
+ if (mReader->getNodeType() == irr::io::EXN_ELEMENT)
+ {
+ ReadMetaDataItem(mAssetMetaData);
+ }
+ else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+ {
+ if (strcmp(mReader->getNodeName(), "contributor") != 0)
+ ThrowException("Expected end of element.");
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Reads a single string metadata item
+void ColladaParser::ReadMetaDataItem(StringMetaData &metadata)
+{
+ // Metadata such as created, keywords, subject etc
+ const char* key_char = mReader->getNodeName();
+ if (key_char != nullptr)
+ {
+ const std::string key_str(key_char);
+ const char* value_char = TestTextContent();
+ if (value_char != nullptr)
+ {
+ std::string camel_key_str = key_str;
+ ToCamelCase(camel_key_str);
+ aiString aistr;
+ aistr.Set(value_char);
+ metadata.emplace(camel_key_str, aistr);
+ TestClosing(key_str.c_str());
+ }
+ else
+ SkipElement();
+ }
+ else
+ SkipElement();
+}
+
+// ------------------------------------------------------------------------------------------------
+// Convert underscore_seperated to CamelCase: "authoring_tool" becomes "AuthoringTool"
+void ColladaParser::ToCamelCase(std::string &text)
+{
+ if (text.empty())
+ return;
+ // Capitalise first character
+ text[0] = ToUpper(text[0]);
+ for (auto it = text.begin(); it != text.end(); /*iterated below*/)
+ {
+ if ((*it) == '_')
+ {
+ it = text.erase(it);
+ if (it != text.end())
+ (*it) = ToUpper(*it);
+ }
+ else
+ ++it;
+ }
+}
+
// ------------------------------------------------------------------------------------------------
// Reads the animation clips
void ColladaParser::ReadAnimationClipLibrary()
diff --git a/code/ColladaParser.h b/code/ColladaParser.h
index 232d85654..22b96c5e0 100644
--- a/code/ColladaParser.h
+++ b/code/ColladaParser.h
@@ -66,6 +66,9 @@ namespace Assimp
friend class ColladaLoader;
protected:
+ /** Map for generic metadata as aiString */
+ typedef std::map StringMetaData;
+
/** Constructor from XML file */
ColladaParser( IOSystem* pIOHandler, const std::string& pFile);
@@ -81,6 +84,15 @@ namespace Assimp
/** Reads asset information such as coordinate system information and legal blah */
void ReadAssetInfo();
+ /** Reads contributor information such as author and legal blah */
+ void ReadContributorInfo();
+
+ /** Reads generic metadata into provided map */
+ void ReadMetaDataItem(StringMetaData &metadata);
+
+ /** Convert underscore_seperated to CamelCase "authoring_tool" becomes "AuthoringTool" */
+ static void ToCamelCase(std::string &text);
+
/** Reads the animation library */
void ReadAnimationLibrary();
@@ -343,6 +355,9 @@ namespace Assimp
/** Which is the up vector */
enum { UP_X, UP_Y, UP_Z } mUpDirection;
+ /** Asset metadata (global for scene) */
+ StringMetaData mAssetMetaData;
+
/** Collada file format version */
Collada::FormatVersion mFormat;
};