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 "FCDocument/FCDocument.h"
11 #include "FCDocument/FCDAnimated.h"
12 #include "FCDocument/FCDExtra.h"
13 #include "FColladaPlugin.h"
14
15
16 namespace FCollada { extern FColladaPluginManager* pluginManager; }
17
18 //
19 // FCDExtra
20 //
21
22 ImplementObjectType(FCDExtra);
23 ImplementParameterObject(FCDExtra, FCDEType, types, new FCDEType(parent->GetDocument(), parent, emptyCharString));
24
FCDExtra(FCDocument * document,FUObject * _parent)25 FCDExtra::FCDExtra(FCDocument* document, FUObject* _parent)
26 : FCDObject(document)
27 , parent(_parent)
28 , InitializeParameterNoArg(types)
29 {
30 // Create the default extra type.
31 types.push_back(new FCDEType(document, this, emptyCharString));
32 document->RegisterExtraTree(this);
33 }
34
~FCDExtra()35 FCDExtra::~FCDExtra()
36 {
37 GetDocument()->UnregisterExtraTree(this);
38 }
39
40 // Adds a type of the given name (or return the existing type with this name).
AddType(const char * name)41 FCDEType* FCDExtra::AddType(const char* name)
42 {
43 FCDEType* type = FindType(name);
44 if (type == NULL)
45 {
46 type = new FCDEType(GetDocument(), this, emptyCharString);
47 types.push_back(type);
48 type->SetName(name);
49 SetNewChildFlag();
50 }
51 return type;
52 }
53
54 // Search for a profile-specific type
FindType(const char * name) const55 const FCDEType* FCDExtra::FindType(const char* name) const
56 {
57 for (const FCDEType** itT = types.begin(); itT != types.end(); ++itT)
58 {
59 if (IsEquivalent((*itT)->GetName(), name)) return *itT;
60 }
61 return NULL;
62 }
63
HasContent() const64 bool FCDExtra::HasContent() const
65 {
66 if (types.empty()) return false;
67 for (const FCDEType** itT = types.begin(); itT != types.end(); ++itT)
68 {
69 size_t techniqueCount = (*itT)->GetTechniqueCount();
70 for (size_t i = 0; i < techniqueCount; ++i)
71 {
72 const FCDETechnique* technique = (*itT)->GetTechnique(i);
73 if (technique->GetChildNodeCount() > 0) return true;
74 }
75 }
76 return false;
77 }
78
Clone(FCDExtra * clone) const79 FCDExtra* FCDExtra::Clone(FCDExtra* clone) const
80 {
81 if (clone == NULL) clone = new FCDExtra(const_cast<FCDocument*>(GetDocument()), NULL);
82
83 // Create all the types
84 clone->types.reserve(types.size());
85 for (const FCDEType** itT = types.begin(); itT != types.end(); ++itT)
86 {
87 FCDEType* cloneT = clone->AddType((*itT)->GetName());
88 (*itT)->Clone(cloneT);
89 }
90 return clone;
91 }
92
93 //
94 // FCDEType
95 //
96
97 ImplementObjectType(FCDEType);
98 ImplementParameterObject(FCDEType, FCDETechnique, techniques, new FCDETechnique(parent->GetDocument(), parent, emptyCharString));
99
FCDEType(FCDocument * document,FCDExtra * _parent,const char * _name)100 FCDEType::FCDEType(FCDocument* document, FCDExtra* _parent, const char* _name)
101 : FCDObject(document)
102 , parent(_parent)
103 , InitializeParameter(name, _name)
104 , InitializeParameterNoArg(techniques)
105 {
106 }
107
~FCDEType()108 FCDEType::~FCDEType()
109 {
110 }
111
112 // Adds a technique of the given profile (or return the existing technique with this profile).
AddTechnique(const char * profile)113 FCDETechnique* FCDEType::AddTechnique(const char* profile)
114 {
115 FCDETechnique* technique = FindTechnique(profile);
116 if (technique == NULL)
117 {
118 technique = new FCDETechnique(GetDocument(), this, profile);
119 techniques.push_back(technique);
120 SetNewChildFlag();
121 }
122 return technique;
123 }
124
125 // Search for a profile-specific technique
FindTechnique(const char * profile) const126 const FCDETechnique* FCDEType::FindTechnique(const char* profile) const
127 {
128 for (const FCDETechnique** itT = techniques.begin(); itT != techniques.end(); ++itT)
129 {
130 if (IsEquivalent((*itT)->GetProfile(), profile)) return *itT;
131 }
132 return NULL;
133 }
134
135 // Search for a root node with a specific element name
FindRootNode(const char * name) const136 const FCDENode* FCDEType::FindRootNode(const char* name) const
137 {
138 const FCDENode* rootNode = NULL;
139 for (const FCDETechnique** itT = techniques.begin(); itT != techniques.end(); ++itT)
140 {
141 rootNode = (*itT)->FindChildNode(name);
142 if (rootNode != NULL) break;
143 }
144 return rootNode;
145 }
146
Clone(FCDEType * clone) const147 FCDEType* FCDEType::Clone(FCDEType* clone) const
148 {
149 // If no clone is given: create one
150 if (clone == NULL)
151 {
152 clone = new FCDEType(const_cast<FCDocument*>(GetDocument()), NULL, name->c_str());
153 }
154
155 clone->techniques.reserve(techniques.size());
156 for (const FCDETechnique** itT = techniques.begin(); itT != techniques.end(); ++itT)
157 {
158 FCDETechnique* cloneT = clone->AddTechnique((*itT)->GetProfile());
159 (*itT)->Clone(cloneT);
160 }
161 return clone;
162 }
163
164 //
165 // FCDENode
166 //
167
168 ImplementObjectType(FCDENode);
169 ImplementParameterObject(FCDENode, FCDENode, children, new FCDENode(parent->GetDocument(), parent));
170 ImplementParameterObjectNoArg(FCDENode, FCDEAttribute, attributes);
171 ImplementParameterObject(FCDENode, FCDAnimatedCustom, animated, new FCDAnimatedCustom(parent->GetDocument()));
172
FCDENode(FCDocument * document,FCDENode * _parent)173 FCDENode::FCDENode(FCDocument* document, FCDENode* _parent)
174 : FCDObject(document), parent(_parent)
175 , InitializeParameterNoArg(name)
176 , InitializeParameterNoArg(content)
177 , InitializeParameterNoArg(children)
178 , InitializeParameterNoArg(attributes)
179 , InitializeParameterNoArg(animated)
180 {
181 animated = new FCDAnimatedCustom(this);
182 }
183
~FCDENode()184 FCDENode::~FCDENode()
185 {
186 parent = NULL;
187 }
188
SetContent(const fchar * _content)189 void FCDENode::SetContent(const fchar* _content)
190 {
191 // As COLLADA doesn't allow for mixed content, release all the children.
192 while (!children.empty())
193 {
194 children.back()->Release();
195 }
196
197 content = _content;
198 SetDirtyFlag();
199 }
200
SetAnimated(FCDAnimatedCustom * animatedCustom)201 void FCDENode::SetAnimated(FCDAnimatedCustom* animatedCustom)
202 {
203 SAFE_RELEASE(animated);
204 animated = animatedCustom;
205 }
206
207 // Search for a children with a specific name
FindChildNode(const char * name) const208 const FCDENode* FCDENode::FindChildNode(const char* name) const
209 {
210 for (const FCDENode** itN = children.begin(); itN != children.end(); ++itN)
211 {
212 if (IsEquivalent((*itN)->GetName(), name)) return (*itN);
213 }
214 return NULL;
215 }
216
FindChildrenNodes(const char * name,FCDENodeList & nodes) const217 void FCDENode::FindChildrenNodes(const char* name, FCDENodeList& nodes) const
218 {
219 for (const FCDENode** itN = children.begin(); itN != children.end(); ++itN)
220 {
221 if (IsEquivalent((*itN)->GetName(), name)) nodes.push_back(const_cast<FCDENode*>(*itN));
222 }
223 }
224
FindParameter(const char * name) const225 const FCDENode* FCDENode::FindParameter(const char* name) const
226 {
227 for (const FCDENode** itN = children.begin(); itN != children.end(); ++itN)
228 {
229 const FCDENode* node = (*itN);
230 if (IsEquivalent(node->GetName(), name)) return node;
231 }
232 return NULL;
233 }
234
FindParameters(FCDENodeList & nodes,StringList & names)235 void FCDENode::FindParameters(FCDENodeList& nodes, StringList& names)
236 {
237 for (const FCDENode** itN = (const FCDENode**) children.begin(); itN != children.end(); ++itN)
238 {
239 const FCDENode* node = (*itN);
240 if (node->GetChildNodeCount() == 0)
241 {
242 nodes.push_back(const_cast<FCDENode*>(node));
243 names.push_back(node->GetName());
244 }
245 }
246 }
247
SetName(fm::string & _name)248 void FCDENode::SetName(fm::string& _name)
249 {
250 name = _name;
251 CleanName(name);
252 SetDirtyFlag();
253 }
254
CleanName(fm::string & n)255 void FCDENode::CleanName(fm::string& n)
256 {
257 size_t length = n.length();
258 if (length == 0) return;
259
260 // First character must be alphabetic or the underscore.
261 if (n[0] != '_' && !(n[0] >= 'a' && n[0] <= 'z') && !(n[0] >= 'A' && n[0] <= 'Z'))
262 {
263 n[0] = '_';
264 }
265
266 // Other characters must be alpha-numeric or the underscore.
267 for (size_t i = 1; i < length; ++i)
268 {
269 char& c = n[i];
270 if (c != '_' && !(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9'))
271 {
272 c = '_';
273 }
274 }
275 }
276
GetContent() const277 const fchar* FCDENode::GetContent() const
278 {
279 return content->c_str();
280 }
281
282 // Adds a new attribute to this extra tree node.
AddAttribute(fm::string & _name,const fchar * _value)283 FCDEAttribute* FCDENode::AddAttribute(fm::string& _name, const fchar* _value)
284 {
285 CleanName(_name);
286 FCDEAttribute* attribute = FindAttribute(_name.c_str());
287 if (attribute == NULL)
288 {
289 attribute = new FCDEAttribute();
290 attributes.push_back(attribute);
291 attribute->SetName(_name);
292 }
293
294 attribute->SetValue(_value);
295 SetNewChildFlag();
296 return attribute;
297 }
298
299 // Search for an attribute with a specific name
FindAttribute(const char * name) const300 const FCDEAttribute* FCDENode::FindAttribute(const char* name) const
301 {
302 for (const FCDEAttribute** itA = attributes.begin(); itA != attributes.end(); ++itA)
303 {
304 if (IsEquivalent((*itA)->GetName(), name)) return (*itA);
305 }
306 return NULL;
307 }
308
ReadAttribute(const char * name) const309 const fstring& FCDENode::ReadAttribute(const char* name) const
310 {
311 const FCDEAttribute* attribute = FindAttribute(name);
312 return (attribute != NULL) ? attribute->GetValue() : emptyFString;
313 }
314
AddParameter(const char * name,const fchar * value)315 FCDENode* FCDENode::AddParameter(const char* name, const fchar* value)
316 {
317 FCDENode* parameter = AddChildNode();
318 parameter->SetName(name);
319 parameter->SetContent(value);
320 SetNewChildFlag();
321 return parameter;
322 }
323
Clone(FCDENode * clone) const324 FCDENode* FCDENode::Clone(FCDENode* clone) const
325 {
326 if (clone == NULL) return NULL;
327
328 clone->name = name;
329 clone->content = content;
330
331 clone->attributes.reserve(attributes.size());
332 for (const FCDEAttribute** itA = attributes.begin(); itA != attributes.end(); ++itA)
333 {
334 clone->AddAttribute((*itA)->GetName(), (*itA)->GetValue());
335 }
336
337 clone->children.reserve(children.size());
338 for (const FCDENode** itC = children.begin(); itC != children.end(); ++itC)
339 {
340 FCDENode* clonedChild = clone->AddChildNode();
341 (*itC)->Clone(clonedChild);
342 }
343
344 // TODO: Clone the animated custom..
345
346 return clone;
347 }
348
AddChildNode()349 FCDENode* FCDENode::AddChildNode()
350 {
351 FCDENode* node = new FCDENode(GetDocument(), this);
352 children.push_back(node);
353 SetNewChildFlag();
354 return node;
355 }
356
AddChildNode(const char * name)357 FCDENode* FCDENode::AddChildNode(const char* name)
358 {
359 FCDENode* node = new FCDENode(GetDocument(), this);
360 children.push_back(node);
361 node->SetName(name);
362 SetNewChildFlag();
363 return node;
364 }
365
366 //
367 // FCDETechnique
368 //
369
370 ImplementObjectType(FCDETechnique);
371 ImplementParameterObjectNoCtr(FCDETechnique, FUObject, pluginOverride);
372
FCDETechnique(FCDocument * document,FCDEType * _parent,const char * _profile)373 FCDETechnique::FCDETechnique(FCDocument* document, FCDEType* _parent, const char* _profile)
374 : FCDENode(document, NULL), parent(_parent)
375 , InitializeParameterNoArg(pluginOverride)
376 , InitializeParameter(profile, _profile)
377 {
378 }
379
~FCDETechnique()380 FCDETechnique::~FCDETechnique() {}
381
Clone(FCDENode * clone) const382 FCDENode* FCDETechnique::Clone(FCDENode* clone) const
383 {
384 if (clone == NULL)
385 {
386 clone = new FCDETechnique(const_cast<FCDocument*>(GetDocument()), NULL, profile->c_str());
387 }
388 else if (clone->GetObjectType().Includes(FCDETechnique::GetClassType()))
389 {
390 ((FCDETechnique*) clone)->profile = profile;
391 }
392
393 FCDENode::Clone(clone);
394 return clone;
395 }
396
397 //
398 // FCDEAttribute
399 //
400
FCDEAttribute()401 FCDEAttribute::FCDEAttribute()
402 : FUParameterizable()
403 , InitializeParameterNoArg(name)
404 , InitializeParameterNoArg(value)
405 {
406 }
407
FCDEAttribute(const char * _name,const fchar * _value)408 FCDEAttribute::FCDEAttribute(const char* _name, const fchar* _value)
409 : FUParameterizable()
410 , InitializeParameter(name, _name)
411 , InitializeParameter(value, _value)
412 {
413 }
414