1 /*
2 Copyright (C) 2005-2007 Feeling Software Inc.
3 Portions of the code are:
4 Copyright (C) 2005-2007 Sony Computer Entertainment America
5
6 MIT License: http://www.opensource.org/licenses/mit-license.php
7 */
8
9 #include "StdAfx.h"
10 #include "FArchiveXML.h"
11 #include "FCDocument/FCDocument.h"
12 #include "FCDocument/FCDEntity.h"
13 #include "FCDocument/FCDTargetedEntity.h"
14 #include "FCDocument/FCDAsset.h"
15 #include "FCDocument/FCDExtra.h"
16 #include "FCDocument/FCDAnimated.h"
17 #include "FCDocument/FCDAnimationChannel.h"
18 #include "FCDocument/FCDExternalReferenceManager.h"
19 #include "FCDocument/FCDPlaceHolder.h"
20
LoadObject(FCDObject * UNUSED (object),xmlNode * UNUSED (node))21 bool FArchiveXML::LoadObject(FCDObject* UNUSED(object), xmlNode* UNUSED(node))
22 {
23 return true;
24 }
25
LoadExtra(FCDObject * object,xmlNode * extraNode)26 bool FArchiveXML::LoadExtra(FCDObject* object, xmlNode* extraNode)
27 {
28 FCDExtra* extra = (FCDExtra*)object;
29
30 bool status = true;
31
32 // Do NOT assume that we have an <extra> element: we may be parsing a type switch instead.
33 FCDEType* parsingType = NULL;
34 if (IsEquivalent(extraNode->name, DAE_EXTRA_ELEMENT))
35 {
36 parsingType = extra->AddType(ReadNodeProperty(extraNode, DAE_TYPE_ATTRIBUTE));
37 }
38 if (parsingType == NULL) parsingType = extra->GetDefaultType();
39 FArchiveXML::LoadSwitch(parsingType, &parsingType->GetObjectType(), extraNode);
40
41 extra->SetDirtyFlag();
42 return status;
43 }
44
LoadExtraNode(FCDObject * object,xmlNode * customNode)45 bool FArchiveXML::LoadExtraNode(FCDObject* object, xmlNode* customNode)
46 {
47 FCDENode* fcdenode = (FCDENode*)object;
48
49 bool status = true;
50
51 // Read in the node's name and children
52 fcdenode->SetName((const char*) customNode->name);
53 FArchiveXML::LoadExtraNodeChildren(fcdenode, customNode);
54
55 // If there are no child nodes, we have a tree leaf: parse in the content and its animation
56 if (fcdenode->GetChildNodeCount() == 0)
57 {
58 fstring content = TO_FSTRING(ReadNodeContentFull(customNode));
59 if (!content.empty()) fcdenode->SetContent(content);
60 }
61 FArchiveXML::LinkAnimatedCustom(fcdenode->GetAnimated(), customNode);
62
63 // Read in the node's attributes
64 for (xmlAttr* a = customNode->properties; a != NULL; a = a->next)
65 {
66 fcdenode->AddAttribute((const char*) a->name, (a->children != NULL) ? TO_FSTRING((const char*) (a->children->content)) : FS(""));
67 }
68
69 fcdenode->SetDirtyFlag();
70 return status;
71 }
72
LoadExtraTechnique(FCDObject * object,xmlNode * techniqueNode)73 bool FArchiveXML::LoadExtraTechnique(FCDObject* object, xmlNode* techniqueNode)
74 {
75 // Read in only the child elements: none of the attributes
76 return FArchiveXML::LoadExtraNodeChildren((FCDENode*) object, techniqueNode);
77 }
78
LoadExtraType(FCDObject * object,xmlNode * extraNode)79 bool FArchiveXML::LoadExtraType(FCDObject* object, xmlNode* extraNode)
80 {
81 FCDEType* eType = (FCDEType*)object;
82
83 bool status = true;
84
85 // Do NOT verify that we have an <extra> element: we may be parsing a technique switch instead.
86
87 // Read in the techniques
88 xmlNodeList techniqueNodes;
89 FindChildrenByType(extraNode, DAE_TECHNIQUE_ELEMENT, techniqueNodes);
90 for (xmlNodeList::iterator itN = techniqueNodes.begin(); itN != techniqueNodes.end(); ++itN)
91 {
92 xmlNode* techniqueNode = (*itN);
93 fm::string profile = ReadNodeProperty(techniqueNode, DAE_PROFILE_ATTRIBUTE);
94 FCDETechnique* technique = eType->AddTechnique(profile);
95 status &= (FArchiveXML::LoadExtraTechnique(technique, techniqueNode));
96 }
97
98 eType->SetDirtyFlag();
99 return status;
100 }
101
LoadAsset(FCDObject * object,xmlNode * assetNode)102 bool FArchiveXML::LoadAsset(FCDObject* object, xmlNode* assetNode)
103 {
104 FCDAsset* asset = (FCDAsset*)object;
105
106 bool status = true;
107 for (xmlNode* child = assetNode->children; child != NULL; child = child->next)
108 {
109 if (child->type != XML_ELEMENT_NODE) continue;
110
111 fm::string content = ReadNodeContentFull(child);
112 if (IsEquivalent(child->name, DAE_CONTRIBUTOR_ASSET_ELEMENT))
113 {
114 FCDAssetContributor* contributor = asset->AddContributor();
115 status &= FArchiveXML::LoadAssetContributor(contributor, child);
116 }
117 else if (IsEquivalent(child->name, DAE_CREATED_ASSET_PARAMETER))
118 {
119 FUStringConversion::ToDateTime(content, asset->GetCreationDateTime());
120 }
121 else if (IsEquivalent(child->name, DAE_KEYWORDS_ASSET_PARAMETER))
122 {
123 asset->SetKeywords(TO_FSTRING(content));
124 }
125 else if (IsEquivalent(child->name, DAE_MODIFIED_ASSET_PARAMETER))
126 {
127 FUStringConversion::ToDateTime(content, asset->GetModifiedDateTime());
128 }
129 else if (IsEquivalent(child->name, DAE_REVISION_ASSET_PARAMETER))
130 {
131 asset->SetRevision(TO_FSTRING(content));
132 }
133 else if (IsEquivalent(child->name, DAE_SUBJECT_ASSET_PARAMETER))
134 {
135 asset->SetSubject(TO_FSTRING(content));
136 }
137 else if (IsEquivalent(child->name, DAE_TITLE_ASSET_PARAMETER))
138 {
139 asset->SetTitle(TO_FSTRING(content));
140 }
141 else if (IsEquivalent(child->name, DAE_UNITS_ASSET_PARAMETER))
142 {
143 asset->SetUnitName(TO_FSTRING(ReadNodeName(child)));
144 asset->SetUnitConversionFactor(FUStringConversion::ToFloat(ReadNodeProperty(child, DAE_METERS_ATTRIBUTE)));
145 if (asset->GetUnitName().empty()) asset->SetUnitName(FC("UNKNOWN"));
146 if (IsEquivalent(asset->GetUnitConversionFactor(), 0.0f) || asset->GetUnitConversionFactor() < 0.0f) asset->SetUnitConversionFactor(1.0f);
147 }
148 else if (IsEquivalent(child->name, DAE_UPAXIS_ASSET_PARAMETER))
149 {
150 if (IsEquivalent(content, DAE_X_UP)) asset->SetUpAxis(FMVector3::XAxis);
151 else if (IsEquivalent(content, DAE_Y_UP)) asset->SetUpAxis(FMVector3::YAxis);
152 else if (IsEquivalent(content, DAE_Z_UP)) asset->SetUpAxis(FMVector3::ZAxis);
153 }
154 else
155 {
156 FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_CHILD_ELEMENT, child->line);
157 }
158 }
159
160 asset->SetDirtyFlag();
161 return status;
162 }
163
LoadAssetContributor(FCDObject * object,xmlNode * contributorNode)164 bool FArchiveXML::LoadAssetContributor(FCDObject* object, xmlNode* contributorNode)
165 {
166 FCDAssetContributor* assetContributor = (FCDAssetContributor*)object;
167
168 bool status = true;
169 for (xmlNode* child = contributorNode->children; child != NULL; child = child->next)
170 {
171 if (child->type != XML_ELEMENT_NODE) continue;
172
173 fm::string content = ReadNodeContentFull(child);
174 if (IsEquivalent(child->name, DAE_AUTHOR_ASSET_PARAMETER))
175 {
176 assetContributor->SetAuthor(TO_FSTRING(content));
177 }
178 else if (IsEquivalent(child->name, DAE_AUTHORINGTOOL_ASSET_PARAMETER))
179 {
180 assetContributor->SetAuthoringTool(TO_FSTRING(content));
181 }
182 else if (IsEquivalent(child->name, DAE_COMMENTS_ASSET_PARAMETER))
183 {
184 assetContributor->SetComments(TO_FSTRING(content));
185 }
186 else if (IsEquivalent(child->name, DAE_COPYRIGHT_ASSET_PARAMETER))
187 {
188 assetContributor->SetCopyright(TO_FSTRING(content));
189 }
190 else if (IsEquivalent(child->name, DAE_SOURCEDATA_ASSET_PARAMETER))
191 {
192 assetContributor->SetSourceData(TO_FSTRING(content));
193 }
194 else
195 {
196 FUError::Error(FUError::WARNING_LEVEL, FUError::WARNING_UNKNOWN_AC_CHILD_ELEMENT, child->line);
197 }
198 }
199 assetContributor->SetDirtyFlag();
200 return status;
201 }
202
LoadEntityReference(FCDObject * UNUSED (object),xmlNode * UNUSED (node))203 bool FArchiveXML::LoadEntityReference(FCDObject* UNUSED(object), xmlNode* UNUSED(node))
204 {
205 //
206 // Should never reach here
207 //
208 FUBreak;
209 return true;
210 }
211
LoadExternalReferenceManager(FCDObject * UNUSED (object),xmlNode * UNUSED (node))212 bool FArchiveXML::LoadExternalReferenceManager(FCDObject* UNUSED(object), xmlNode* UNUSED(node))
213 {
214 //
215 // Should never reach here
216 //
217 FUBreak;
218 return true;
219 }
220
LoadPlaceHolder(FCDObject * UNUSED (object),xmlNode * UNUSED (node))221 bool FArchiveXML::LoadPlaceHolder(FCDObject* UNUSED(object), xmlNode* UNUSED(node))
222 {
223 //
224 // Should never reach here.
225 //
226 FUBreak;
227 return true;
228 }
229
LoadExtraNodeChildren(FCDENode * fcdenode,xmlNode * customNode)230 bool FArchiveXML::LoadExtraNodeChildren(FCDENode* fcdenode, xmlNode* customNode)
231 {
232 bool status = true;
233
234 // Read in the node's children
235 for (xmlNode* k = customNode->children; k != NULL; k = k->next)
236 {
237 if (k->type != XML_ELEMENT_NODE) continue;
238
239 FCDENode* node = fcdenode->AddChildNode();
240 status &= (FArchiveXML::LoadSwitch(node, &node->GetObjectType(), k));
241 }
242
243 fcdenode->SetDirtyFlag();
244 return status;
245 }
246
FindAnimationChannelsArrayIndices(FCDocument * fcdocument,xmlNode * targetArray,Int32List & animatedIndices)247 void FArchiveXML::FindAnimationChannelsArrayIndices(FCDocument* fcdocument, xmlNode* targetArray, Int32List& animatedIndices)
248 {
249 // Calculte the node's pointer
250 fm::string pointer;
251 CalculateNodeTargetPointer(targetArray, pointer);
252 if (pointer.empty()) return;
253
254 // Retrieve the channels for this pointer and extract their matrix indices.
255 FCDAnimationChannelList channels;
256 FArchiveXML::FindAnimationChannels(fcdocument, pointer, channels);
257 for (FCDAnimationChannelList::iterator it = channels.begin(); it != channels.end(); ++it)
258 {
259 FCDAnimationChannelDataMap::iterator itData = FArchiveXML::documentLinkDataMap[(*it)->GetDocument()].animationChannelData.find(*it);
260 FUAssert(itData != FArchiveXML::documentLinkDataMap[(*it)->GetDocument()].animationChannelData.end(),);
261 FCDAnimationChannelData& data = itData->second;
262
263 int32 animatedIndex = FUStringConversion::ParseQualifier(data.targetQualifier);
264 if (animatedIndex != -1) animatedIndices.push_back(animatedIndex);
265 }
266 }
267
RegisterLoadedDocument(FCDocument * document)268 void FArchiveXML::RegisterLoadedDocument(FCDocument* document)
269 {
270 fm::pvector<FCDocument> allDocuments;
271 FCollada::GetAllDocuments(allDocuments);
272 for (FCDocument** it = allDocuments.begin(); it != allDocuments.end(); ++it)
273 {
274 if ((*it) != document)
275 {
276 FCDExternalReferenceManager* xrefManager = (*it)->GetExternalReferenceManager();
277
278 for (size_t i = 0; i < xrefManager->GetPlaceHolderCount(); ++i)
279 {
280 // Set the document to the placeholders that targets it.
281 FCDPlaceHolder* pHolder = xrefManager->GetPlaceHolder(i);
282 if (pHolder->GetFileUrl() == document->GetFileUrl()) pHolder->LoadTarget(document);
283 }
284 }
285 }
286
287 // On the newly-loaded document, there may be placeholders to process.
288 FCDExternalReferenceManager* xrefManager = document->GetExternalReferenceManager();
289 for (size_t i = 0; i < xrefManager->GetPlaceHolderCount(); ++i)
290 {
291 FCDPlaceHolder* pHolder = xrefManager->GetPlaceHolder(i);
292
293 // Set the document to the placeholders that targets it.
294 for (FCDocument** itD = allDocuments.begin(); itD != allDocuments.end(); ++itD)
295 {
296 if (pHolder->GetFileUrl() == (*itD)->GetFileUrl()) pHolder->LoadTarget(*itD);
297 }
298 }
299 }
300