Save/Load Collada 1.4 Root Asset Metadata

Add Collada 1.4 <asset/> metadata to export and import.
Can store in the Scene or the Root Node for export, will be loaded into the Scene during Import
pull/2417/head
RichardTea 2019-04-09 16:28:15 +01:00
parent 49459435df
commit 1f55bdd9a7
4 changed files with 128 additions and 20 deletions

View File

@ -238,7 +238,11 @@ void ColladaExporter::WriteHeader()
mOutput << startstr << "<contributor>" << 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 << "<author>" << "Assimp" << "</author>" << endstr;
@ -250,13 +254,39 @@ void ColladaExporter::WriteHeader()
else
mOutput << startstr << "<authoring_tool>" << XMLEscape(value.C_Str()) << "</authoring_tool>" << endstr;
//mOutput << startstr << "<author>" << mScene->author.C_Str() << "</author>" << endstr;
//mOutput << startstr << "<authoring_tool>" << mScene->authoringTool.C_Str() << "</authoring_tool>" << endstr;
if (meta)
{
if (meta->Get("Comments", value))
mOutput << startstr << "<comments>" << XMLEscape(value.C_Str()) << "</comments>" << endstr;
if (meta->Get("Copyright", value))
mOutput << startstr << "<copyright>" << XMLEscape(value.C_Str()) << "</copyright>" << endstr;
if (meta->Get("SourceData", value))
mOutput << startstr << "<source_data>" << XMLEscape(value.C_Str()) << "</source_data>" << endstr;
}
PopTag();
mOutput << startstr << "</contributor>" << endstr;
mOutput << startstr << "<created>" << date_str << "</created>" << endstr;
if (!meta || !meta->Get("Created", value))
mOutput << startstr << "<created>" << date_str << "</created>" << endstr;
else
mOutput << startstr << "<created>" << XMLEscape(value.C_Str()) << "</created>" << endstr;
// Modified date is always the date saved
mOutput << startstr << "<modified>" << date_str << "</modified>" << endstr;
if (meta)
{
if (meta->Get("Keywords", value))
mOutput << startstr << "<keywords>" << XMLEscape(value.C_Str()) << "</keywords>" << endstr;
if (meta->Get("Revision", value))
mOutput << startstr << "<revision>" << XMLEscape(value.C_Str()) << "</revision>" << endstr;
if (meta->Get("Subject", value))
mOutput << startstr << "<subject>" << XMLEscape(value.C_Str()) << "</subject>" << endstr;
if (meta->Get("Title", value))
mOutput << startstr << "<title>" << XMLEscape(value.C_Str()) << "</title>" << endstr;
}
mOutput << startstr << "<unit name=\"meter\" meter=\"" << scale << "\" />" << endstr;
mOutput << startstr << "<up_axis>" << up_axis << "</up_axis>" << endstr;
PopTag();

View File

@ -208,9 +208,14 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
}
// Store scene metadata
for (auto it = parser.mAssetMetaData.cbegin(); it != parser.mAssetMetaData.cend(); ++it)
{
pScene->mMetaData->Add((*it).first, (*it).second);
if (!parser.mAssetMetaData.empty()) {
const size_t numMeta(parser.mAssetMetaData.size());
pScene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
size_t i = 0;
for (auto it = parser.mAssetMetaData.cbegin(); it != parser.mAssetMetaData.cend(); ++it, ++i)
{
pScene->mMetaData->Set(static_cast<unsigned int>(i), (*it).first, (*it).second);
}
}
// store all meshes

View File

@ -267,24 +267,16 @@ void ColladaParser::ReadAssetInfo()
}
else if(IsElement("contributor"))
{
// This has no data of its own, will get children next time through
ReadContributorInfo();
}
else
{
const char* metadata_key = mReader->getNodeName();
const char* metadata_value = TestTextContent();
if (metadata_key != nullptr && metadata_value != nullptr)
{
aiString aistr;
aistr.Set(metadata_value);
mAssetMetaData.emplace(metadata_key, aistr);
}
//SkipElement();
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 <asset> element.");
break;
@ -292,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 <contributor> 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()

View File

@ -66,6 +66,9 @@ namespace Assimp
friend class ColladaLoader;
protected:
/** Map for generic metadata as aiString */
typedef std::map<std::string, aiString> 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,8 +355,8 @@ namespace Assimp
/** Which is the up vector */
enum { UP_X, UP_Y, UP_Z } mUpDirection;
typedef std::map<std::string, aiString> AssetMetaData;
AssetMetaData mAssetMetaData;
/** Asset metadata (global for scene) */
StringMetaData mAssetMetaData;
/** Collada file format version */
Collada::FormatVersion mFormat;