/* Copyright (C) 2005-2007 Feeling Software Inc. Portions of the code are: Copyright (C) 2005-2007 Sony Computer Entertainment America MIT License: http://www.opensource.org/licenses/mit-license.php */ #include "StdAfx.h" #include "FArchiveXML.h" #include "FCDocument/FCDocument.h" #include "FCDocument/FCDEntity.h" #include "FCDocument/FCDTargetedEntity.h" #include "FCDocument/FCDAsset.h" #include "FCDocument/FCDExtra.h" #include "FCDocument/FCDAnimated.h" #include "FCDocument/FCDAnimationChannel.h" #include "FCDocument/FCDExternalReferenceManager.h" #include "FCDocument/FCDPlaceHolder.h" bool FArchiveXML::LoadObject(FCDObject* UNUSED(object), xmlNode* UNUSED(node)) { return true; } bool FArchiveXML::LoadExtra(FCDObject* object, xmlNode* extraNode) { FCDExtra* extra = (FCDExtra*)object; bool status = true; // Do NOT assume that we have an element: we may be parsing a type switch instead. FCDEType* parsingType = NULL; if (IsEquivalent(extraNode->name, DAE_EXTRA_ELEMENT)) { parsingType = extra->AddType(ReadNodeProperty(extraNode, DAE_TYPE_ATTRIBUTE)); } if (parsingType == NULL) parsingType = extra->GetDefaultType(); FArchiveXML::LoadSwitch(parsingType, &parsingType->GetObjectType(), extraNode); extra->SetDirtyFlag(); return status; } bool FArchiveXML::LoadExtraNode(FCDObject* object, xmlNode* customNode) { FCDENode* fcdenode = (FCDENode*)object; bool status = true; // Read in the node's name and children fcdenode->SetName((const char*) customNode->name); FArchiveXML::LoadExtraNodeChildren(fcdenode, customNode); // If there are no child nodes, we have a tree leaf: parse in the content and its animation if (fcdenode->GetChildNodeCount() == 0) { fstring content = TO_FSTRING(ReadNodeContentFull(customNode)); if (!content.empty()) fcdenode->SetContent(content); } FArchiveXML::LinkAnimatedCustom(fcdenode->GetAnimated(), customNode); // Read in the node's attributes for (xmlAttr* a = customNode->properties; a != NULL; a = a->next) { fcdenode->AddAttribute((const char*) a->name, (a->children != NULL) ? TO_FSTRING((const char*) (a->children->content)) : FS("")); } fcdenode->SetDirtyFlag(); return status; } bool FArchiveXML::LoadExtraTechnique(FCDObject* object, xmlNode* techniqueNode) { // Read in only the child elements: none of the attributes return FArchiveXML::LoadExtraNodeChildren((FCDENode*) object, techniqueNode); } bool FArchiveXML::LoadExtraType(FCDObject* object, xmlNode* extraNode) { FCDEType* eType = (FCDEType*)object; bool status = true; // Do NOT verify that we have an element: we may be parsing a technique switch instead. // Read in the techniques xmlNodeList techniqueNodes; FindChildrenByType(extraNode, DAE_TECHNIQUE_ELEMENT, techniqueNodes); for (xmlNodeList::iterator itN = techniqueNodes.begin(); itN != techniqueNodes.end(); ++itN) { xmlNode* techniqueNode = (*itN); fm::string profile = ReadNodeProperty(techniqueNode, DAE_PROFILE_ATTRIBUTE); FCDETechnique* technique = eType->AddTechnique(profile); status &= (FArchiveXML::LoadExtraTechnique(technique, techniqueNode)); } eType->SetDirtyFlag(); return status; } bool FArchiveXML::LoadAsset(FCDObject* object, xmlNode* assetNode) { FCDAsset* asset = (FCDAsset*)object; bool status = true; for (xmlNode* child = assetNode->children; child != NULL; child = child->next) { if (child->type != XML_ELEMENT_NODE) continue; fm::string content = ReadNodeContentFull(child); if (IsEquivalent(child->name, DAE_CONTRIBUTOR_ASSET_ELEMENT)) { FCDAssetContributor* contributor = asset->AddContributor(); status &= FArchiveXML::LoadAssetContributor(contributor, child); } else if (IsEquivalent(child->name, DAE_CREATED_ASSET_PARAMETER)) { FUStringConversion::ToDateTime(content, asset->GetCreationDateTime()); } else if (IsEquivalent(child->name, DAE_KEYWORDS_ASSET_PARAMETER)) { asset->SetKeywords(TO_FSTRING(content)); } else if (IsEquivalent(child->name, DAE_MODIFIED_ASSET_PARAMETER)) { FUStringConversion::ToDateTime(content, asset->GetModifiedDateTime()); } else if (IsEquivalent(child->name, DAE_REVISION_ASSET_PARAMETER)) { asset->SetRevision(TO_FSTRING(content)); } else if (IsEquivalent(child->name, DAE_SUBJECT_ASSET_PARAMETER)) { asset->SetSubject(TO_FSTRING(content)); } else if (IsEquivalent(child->name, DAE_TITLE_ASSET_PARAMETER)) { asset->SetTitle(TO_FSTRING(content)); } else if (IsEquivalent(child->name, DAE_UNITS_ASSET_PARAMETER)) { asset->SetUnitName(TO_FSTRING(ReadNodeName(child))); asset->SetUnitConversionFactor(FUStringConversion::ToFloat(ReadNodeProperty(child, DAE_METERS_ATTRIBUTE))); if (asset->GetUnitName().empty()) asset->SetUnitName(FC("UNKNOWN")); if (IsEquivalent(asset->GetUnitConversionFactor(), 0.0f) || asset->GetUnitConversionFactor() < 0.0f) asset->SetUnitConversionFactor(1.0f); } else if (IsEquivalent(child->name, DAE_UPAXIS_ASSET_PARAMETER)) { if (IsEquivalent(content, DAE_X_UP)) asset->SetUpAxis(FMVector3::XAxis); else if (IsEquivalent(content, DAE_Y_UP)) asset->SetUpAxis(FMVector3::YAxis); else if (IsEquivalent(content, DAE_Z_UP)) asset->SetUpAxis(FMVector3::ZAxis); } else { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_CHILD_ELEMENT, child->line); } } asset->SetDirtyFlag(); return status; } bool FArchiveXML::LoadAssetContributor(FCDObject* object, xmlNode* contributorNode) { FCDAssetContributor* assetContributor = (FCDAssetContributor*)object; bool status = true; for (xmlNode* child = contributorNode->children; child != NULL; child = child->next) { if (child->type != XML_ELEMENT_NODE) continue; fm::string content = ReadNodeContentFull(child); if (IsEquivalent(child->name, DAE_AUTHOR_ASSET_PARAMETER)) { assetContributor->SetAuthor(TO_FSTRING(content)); } else if (IsEquivalent(child->name, DAE_AUTHORINGTOOL_ASSET_PARAMETER)) { assetContributor->SetAuthoringTool(TO_FSTRING(content)); } else if (IsEquivalent(child->name, DAE_COMMENTS_ASSET_PARAMETER)) { assetContributor->SetComments(TO_FSTRING(content)); } else if (IsEquivalent(child->name, DAE_COPYRIGHT_ASSET_PARAMETER)) { assetContributor->SetCopyright(TO_FSTRING(content)); } else if (IsEquivalent(child->name, DAE_SOURCEDATA_ASSET_PARAMETER)) { assetContributor->SetSourceData(TO_FSTRING(content)); } else { FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_AC_CHILD_ELEMENT, child->line); } } assetContributor->SetDirtyFlag(); return status; } bool FArchiveXML::LoadEntityReference(FCDObject* UNUSED(object), xmlNode* UNUSED(node)) { // // Should never reach here // FUBreak; return true; } bool FArchiveXML::LoadExternalReferenceManager(FCDObject* UNUSED(object), xmlNode* UNUSED(node)) { // // Should never reach here // FUBreak; return true; } bool FArchiveXML::LoadPlaceHolder(FCDObject* UNUSED(object), xmlNode* UNUSED(node)) { // // Should never reach here. // FUBreak; return true; } bool FArchiveXML::LoadExtraNodeChildren(FCDENode* fcdenode, xmlNode* customNode) { bool status = true; // Read in the node's children for (xmlNode* k = customNode->children; k != NULL; k = k->next) { if (k->type != XML_ELEMENT_NODE) continue; FCDENode* node = fcdenode->AddChildNode(); status &= (FArchiveXML::LoadSwitch(node, &node->GetObjectType(), k)); } fcdenode->SetDirtyFlag(); return status; } void FArchiveXML::FindAnimationChannelsArrayIndices(FCDocument* fcdocument, xmlNode* targetArray, Int32List& animatedIndices) { // Calculte the node's pointer fm::string pointer; CalculateNodeTargetPointer(targetArray, pointer); if (pointer.empty()) return; // Retrieve the channels for this pointer and extract their matrix indices. FCDAnimationChannelList channels; FArchiveXML::FindAnimationChannels(fcdocument, pointer, channels); for (FCDAnimationChannelList::iterator it = channels.begin(); it != channels.end(); ++it) { FCDAnimationChannelDataMap::iterator itData = FArchiveXML::documentLinkDataMap[(*it)->GetDocument()].animationChannelData.find(*it); FUAssert(itData != FArchiveXML::documentLinkDataMap[(*it)->GetDocument()].animationChannelData.end(),); FCDAnimationChannelData& data = itData->second; int32 animatedIndex = FUStringConversion::ParseQualifier(data.targetQualifier); if (animatedIndex != -1) animatedIndices.push_back(animatedIndex); } } void FArchiveXML::RegisterLoadedDocument(FCDocument* document) { fm::pvector allDocuments; FCollada::GetAllDocuments(allDocuments); for (FCDocument** it = allDocuments.begin(); it != allDocuments.end(); ++it) { if ((*it) != document) { FCDExternalReferenceManager* xrefManager = (*it)->GetExternalReferenceManager(); for (size_t i = 0; i < xrefManager->GetPlaceHolderCount(); ++i) { // Set the document to the placeholders that targets it. FCDPlaceHolder* pHolder = xrefManager->GetPlaceHolder(i); if (pHolder->GetFileUrl() == document->GetFileUrl()) pHolder->LoadTarget(document); } } } // On the newly-loaded document, there may be placeholders to process. FCDExternalReferenceManager* xrefManager = document->GetExternalReferenceManager(); for (size_t i = 0; i < xrefManager->GetPlaceHolderCount(); ++i) { FCDPlaceHolder* pHolder = xrefManager->GetPlaceHolder(i); // Set the document to the placeholders that targets it. for (FCDocument** itD = allDocuments.begin(); itD != allDocuments.end(); ++itD) { if (pHolder->GetFileUrl() == (*itD)->GetFileUrl()) pHolder->LoadTarget(*itD); } } }