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