2b906fa9ac28a1bda1e9630e45d10fffde4a715d
[blender-staging.git] / source / blender / collada / DocumentImporter.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/collada/DocumentImporter.cpp
24  *  \ingroup collada
25  */
26
27 // TODO:
28 // * name imported objects
29 // * import object rotation as euler
30
31 #include <string>
32 #include <map>
33 #include <algorithm> // sort()
34
35 #include "COLLADAFWRoot.h"
36 #include "COLLADAFWStableHeaders.h"
37 #include "COLLADAFWColorOrTexture.h"
38 #include "COLLADAFWIndexList.h"
39 #include "COLLADAFWMeshPrimitiveWithFaceVertexCount.h"
40 #include "COLLADAFWPolygons.h"
41 #include "COLLADAFWSampler.h"
42 #include "COLLADAFWTypes.h"
43 #include "COLLADAFWVisualScene.h"
44 #include "COLLADAFWArrayPrimitiveType.h"
45 #include "COLLADAFWLibraryNodes.h"
46 #include "COLLADAFWCamera.h"
47 #include "COLLADAFWLight.h"
48
49 #include "COLLADASaxFWLLoader.h"
50 #include "COLLADASaxFWLIExtraDataCallbackHandler.h"
51
52 extern "C" {
53 #include "BLI_listbase.h"
54 #include "BLI_math.h"
55 #include "BLI_string.h"
56 #include "BLI_utildefines.h"
57 #include "BLI_fileops.h"
58
59 #include "BKE_camera.h"
60 #include "BKE_main.h"
61 #include "BKE_lamp.h"
62 #include "BKE_library.h"
63 #include "BKE_texture.h"
64 #include "BKE_fcurve.h"
65 #include "BKE_depsgraph.h"
66 #include "BKE_scene.h"
67 #include "BKE_global.h"
68 #include "BKE_material.h"
69 #include "BKE_image.h"
70
71 #include "BLI_path_util.h"
72
73 #include "DNA_camera_types.h"
74 #include "DNA_lamp_types.h"
75
76 #include "RNA_access.h"
77
78 #include "MEM_guardedalloc.h"
79
80 #include "WM_api.h"
81 #include "WM_types.h"
82
83 }
84
85 #include "ExtraHandler.h"
86 #include "ErrorHandler.h"
87 #include "DocumentImporter.h"
88 #include "TransformReader.h"
89
90 #include "collada_internal.h"
91 #include "collada_utils.h"
92
93
94 /*
95  * COLLADA Importer limitations:
96  * - no multiple scene import, all objects are added to active scene
97  */
98
99 // #define COLLADA_DEBUG
100 // creates empties for each imported bone on layer 2, for debugging
101 // #define ARMATURE_TEST
102
103 DocumentImporter::DocumentImporter(bContext *C, const ImportSettings *import_settings) :
104         import_settings(import_settings),
105         mImportStage(General),
106         mContext(C),
107         armature_importer(&unit_converter, &mesh_importer, &anim_importer, CTX_data_scene(C)),
108         mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C)),
109         anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C))
110 {
111 }
112
113 DocumentImporter::~DocumentImporter()
114 {
115         TagsMap::iterator etit;
116         etit = uid_tags_map.begin();
117         while (etit != uid_tags_map.end()) {
118                 delete etit->second;
119                 etit++;
120         }
121 }
122
123 bool DocumentImporter::import()
124 {
125         ErrorHandler errorHandler;
126         COLLADASaxFWL::Loader loader(&errorHandler);
127         COLLADAFW::Root root(&loader, this);
128         ExtraHandler *ehandler = new ExtraHandler(this, &(this->anim_importer));
129         
130         loader.registerExtraDataCallbackHandler(ehandler);
131
132         // deselect all to select new objects
133         BKE_scene_base_deselect_all(CTX_data_scene(mContext));
134
135         std::string mFilename = std::string(this->import_settings->filepath);
136         const std::string encodedFilename = bc_url_encode(mFilename);
137         if (!root.loadDocument(encodedFilename)) {
138                 fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 1st pass\n");
139                 return false;
140         }
141         
142         if (errorHandler.hasError())
143                 return false;
144         
145         /** TODO set up scene graph and such here */
146         
147         mImportStage = Controller;
148         
149         COLLADASaxFWL::Loader loader2;
150         COLLADAFW::Root root2(&loader2, this);
151         
152         if (!root2.loadDocument(encodedFilename)) {
153                 fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 2nd pass\n");
154                 return false;
155         }
156         
157         
158         delete ehandler;
159
160         mesh_importer.bmeshConversion();
161
162         return true;
163 }
164
165 void DocumentImporter::cancel(const COLLADAFW::String& errorMessage)
166 {
167         // TODO: if possible show error info
168         //
169         // Should we get rid of invisible Meshes that were created so far
170         // or maybe create objects at coordinate space origin?
171         //
172         // The latter sounds better.
173 }
174
175 void DocumentImporter::start()
176 {
177 }
178
179 void DocumentImporter::finish()
180 {
181         if (mImportStage != General)
182                 return;
183
184         Main *bmain = CTX_data_main(mContext);
185         // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it
186         Scene *sce = CTX_data_scene(mContext);
187
188         /** TODO Break up and put into 2-pass parsing of DAE */
189         std::vector<const COLLADAFW::VisualScene *>::iterator it;
190         for (it = vscenes.begin(); it != vscenes.end(); it++) {
191                 PointerRNA sceneptr, unit_settings;
192                 PropertyRNA *system, *scale;
193                 
194                 // for scene unit settings: system, scale_length
195
196                 RNA_id_pointer_create(&sce->id, &sceneptr);
197                 unit_settings = RNA_pointer_get(&sceneptr, "unit_settings");
198                 system = RNA_struct_find_property(&unit_settings, "system");
199                 scale = RNA_struct_find_property(&unit_settings, "scale_length");
200
201                 if (this->import_settings->import_units) {
202                         
203                         switch (unit_converter.isMetricSystem()) {
204                                 case UnitConverter::Metric:
205                                         RNA_property_enum_set(&unit_settings, system, USER_UNIT_METRIC);
206                                         break;
207                                 case UnitConverter::Imperial:
208                                         RNA_property_enum_set(&unit_settings, system, USER_UNIT_IMPERIAL);
209                                         break;
210                                 default:
211                                         RNA_property_enum_set(&unit_settings, system, USER_UNIT_NONE);
212                                         break;
213                         }
214                         float unit_factor = unit_converter.getLinearMeter();
215                         RNA_property_float_set(&unit_settings, scale, unit_factor);
216                         fprintf(stdout, "Collada: Adjusting Blender units to Importset units: %f.\n", unit_factor);
217
218                 }
219
220                 // Write nodes to scene
221                 const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
222                 for (unsigned int i = 0; i < roots.getCount(); i++) {
223                         std::vector<Object *> *objects_done;
224                         objects_done = write_node(roots[i], NULL, sce, NULL, false);
225                         
226                         if (!this->import_settings->import_units) {
227                                 // Match incoming scene with current unit settings
228                                 bc_match_scale(objects_done, *sce, unit_converter);
229                         }
230                 }
231
232                 // update scene
233                 DAG_relations_tag_update(bmain);
234                 WM_event_add_notifier(mContext, NC_OBJECT | ND_TRANSFORM, NULL);
235
236         }
237
238
239         mesh_importer.optimize_material_assignements();
240
241         armature_importer.set_tags_map(this->uid_tags_map);
242         armature_importer.make_armatures(mContext);
243         armature_importer.make_shape_keys();
244         DAG_relations_tag_update(bmain);
245
246 #if 0
247         armature_importer.fix_animation();
248 #endif
249
250         for (std::vector<const COLLADAFW::VisualScene *>::iterator it = vscenes.begin(); it != vscenes.end(); it++) {
251                 const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
252
253                 for (unsigned int i = 0; i < roots.getCount(); i++) {
254                         translate_anim_recursive(roots[i], NULL, NULL);
255                 }
256         }
257
258         if (libnode_ob.size()) {
259                 Scene *sce = CTX_data_scene(mContext);
260
261                 fprintf(stderr, "got %d library nodes to free\n", (int)libnode_ob.size());
262                 // free all library_nodes
263                 std::vector<Object *>::iterator it;
264                 for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) {
265                         Object *ob = *it;
266
267                         Base *base = BKE_scene_base_find(sce, ob);
268                         if (base) {
269                                 BLI_remlink(&sce->base, base);
270                                 BKE_libblock_free_us(&G.main->object, base->object);
271                                 if (sce->basact == base)
272                                         sce->basact = NULL;
273                                 MEM_freeN(base);
274                         }
275                 }
276                 libnode_ob.clear();
277
278                 DAG_relations_tag_update(bmain);
279         }
280 }
281
282
283 void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW::Node *par = NULL, Object *parob = NULL)
284 {
285
286         // The split in #29246, rootmap must point at actual root when
287         // calculating bones in apply_curves_as_matrix. - actual root is the root node.
288         // This has to do with inverse bind poses being world space
289         // (the sources for skinned bones' restposes) and the way
290         // non-skinning nodes have their "restpose" recursively calculated.
291         // XXX TODO: design issue, how to support unrelated joints taking
292         // part in skinning.
293         if (par) { // && par->getType() == COLLADAFW::Node::JOINT) {
294                 // par is root if there's no corresp. key in root_map
295                 if (root_map.find(par->getUniqueId()) == root_map.end())
296                         root_map[node->getUniqueId()] = node;
297                 else
298                         root_map[node->getUniqueId()] = root_map[par->getUniqueId()];
299         }
300
301 #if 0
302         COLLADAFW::Transformation::TransformationType types[] = {
303                 COLLADAFW::Transformation::ROTATE,
304                 COLLADAFW::Transformation::SCALE,
305                 COLLADAFW::Transformation::TRANSLATE,
306                 COLLADAFW::Transformation::MATRIX
307         };
308
309         Object *ob;
310 #endif
311         unsigned int i;
312
313
314         //for (i = 0; i < 4; i++)
315         //    ob =
316         anim_importer.translate_Animations(node, root_map, object_map, FW_object_map);
317
318         if (node->getType() == COLLADAFW::Node::JOINT && par == NULL) {
319                 // For Skeletons without root node we have to simulate the
320                 // root node here and recursively enter the same function
321                 // XXX: maybe this can be made more elegant.
322                 translate_anim_recursive(node, node, parob);
323         }
324         else {
325                 COLLADAFW::NodePointerArray &children = node->getChildNodes();
326                 for (i = 0; i < children.getCount(); i++) {
327                         translate_anim_recursive(children[i], node, NULL);
328                 }
329         }
330 }
331
332 /** When this method is called, the writer must write the global document asset.
333  * \return The writer should return true, if writing succeeded, false otherwise.*/
334 bool DocumentImporter::writeGlobalAsset(const COLLADAFW::FileInfo *asset)
335 {
336         unit_converter.read_asset(asset);
337
338         return true;
339 }
340
341 /** When this method is called, the writer must write the scene.
342  * \return The writer should return true, if writing succeeded, false otherwise.*/
343 bool DocumentImporter::writeScene(const COLLADAFW::Scene *scene)
344 {
345         // XXX could store the scene id, but do nothing for now
346         return true;
347 }
348 Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera, Scene *sce)
349 {
350         const COLLADAFW::UniqueId& cam_uid = camera->getInstanciatedObjectId();
351         if (uid_camera_map.find(cam_uid) == uid_camera_map.end()) {
352                 // fprintf(stderr, "Couldn't find camera by UID.\n");
353                 return NULL;
354         }
355
356         Object *ob = bc_add_object(sce, OB_CAMERA, NULL);
357         Camera *cam = uid_camera_map[cam_uid];
358         Camera *old_cam = (Camera *)ob->data;
359         ob->data = cam;
360         old_cam->id.us--;
361         if (old_cam->id.us == 0)
362                 BKE_libblock_free(&G.main->camera, old_cam);
363         return ob;
364 }
365
366 Object *DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Scene *sce)
367 {
368         const COLLADAFW::UniqueId& lamp_uid = lamp->getInstanciatedObjectId();
369         if (uid_lamp_map.find(lamp_uid) == uid_lamp_map.end()) {
370                 fprintf(stderr, "Couldn't find lamp by UID.\n");
371                 return NULL;
372         }
373
374         Object *ob = bc_add_object(sce, OB_LAMP, NULL);
375         Lamp *la = uid_lamp_map[lamp_uid];
376         Lamp *old_lamp = (Lamp *)ob->data;
377         ob->data = la;
378         old_lamp->id.us--;
379         if (old_lamp->id.us == 0)
380                 BKE_libblock_free(&G.main->lamp, old_lamp);
381         return ob;
382 }
383
384 Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, bool is_library_node)
385 {
386         fprintf(stderr, "create <instance_node> under node id=%s from node id=%s\n", instance_node ? instance_node->getOriginalId().c_str() : NULL, source_node ? source_node->getOriginalId().c_str() : NULL);
387
388         Object *obn = BKE_object_copy(source_ob);
389         DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
390         BKE_scene_base_add(sce, obn);
391
392         if (instance_node) {
393                 anim_importer.read_node_transform(instance_node, obn);
394                 // if we also have a source_node (always ;), take its
395                 // transformation matrix and apply it to the newly instantiated
396                 // object to account for node hierarchy transforms in
397                 // .dae
398                 if (source_node) {
399                         COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix();
400                         COLLADABU::Math::Matrix4 bmat4 = mat4.transpose(); // transpose to get blender row-major order
401                         float mat[4][4];
402                         for (int i = 0; i < 4; i++) {
403                                 for (int j = 0; j < 4; j++) {
404                                         mat[i][j] = bmat4[i][j];
405                                 }
406                         }
407                         // calc new matrix and apply
408                         mult_m4_m4m4(obn->obmat, obn->obmat, mat);
409                         BKE_object_apply_mat4(obn, obn->obmat, 0, 0);
410                 }
411         }
412         else {
413                 anim_importer.read_node_transform(source_node, obn);
414         }
415
416         /*DAG_relations_tag_update(CTX_data_main(mContext));*/
417
418         COLLADAFW::NodePointerArray &children = source_node->getChildNodes();
419         if (children.getCount()) {
420                 for (unsigned int i = 0; i < children.getCount(); i++) {
421                         COLLADAFW::Node *child_node = children[i];
422                         const COLLADAFW::UniqueId& child_id = child_node->getUniqueId();
423                         if (object_map.find(child_id) == object_map.end())
424                                 continue;
425                         COLLADAFW::InstanceNodePointerArray &inodes = child_node->getInstanceNodes();
426                         Object *new_child = NULL;
427                         if (inodes.getCount()) { // \todo loop through instance nodes
428                                 const COLLADAFW::UniqueId& id = inodes[0]->getInstanciatedObjectId();
429                                 fprintf(stderr, "Doing %d child nodes\n", (int)node_map.count(id));
430                                 new_child = create_instance_node(object_map.find(id)->second, node_map[id], child_node, sce, is_library_node);
431                         }
432                         else {
433                                 new_child = create_instance_node(object_map.find(child_id)->second, child_node, NULL, sce, is_library_node);
434                         }
435                         bc_set_parent(new_child, obn, mContext, true);
436
437                         if (is_library_node)
438                                 libnode_ob.push_back(new_child);
439                 }
440         }
441
442         return obn;
443 }
444
445 // to create constraints off node <extra> tags. Assumes only constraint data in
446 // current <extra> with blender profile.
447 void DocumentImporter::create_constraints(ExtraTags *et, Object *ob)
448 {
449         if (et && et->isProfile("blender")) {
450                 std::string name;
451                 short* type = 0;
452                 et->setData("type", type);
453                 BKE_add_ob_constraint(ob, "Test_con", *type);
454                 
455         }
456 }
457
458 std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node)
459 {
460         Object *ob = NULL;
461         bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
462         bool read_transform = true;
463         std::string id   = node->getOriginalId();
464         std::string name = node->getName();
465
466         std::vector<Object *> *objects_done = new std::vector<Object *>();
467
468         fprintf(stderr,
469                         "Writing node id='%s', name='%s'\n",
470                         id.c_str(),
471                         name.c_str());
472
473         if (is_joint) {
474                 if (parent_node == NULL) {
475                         // A Joint on root level is a skeleton without root node.
476                         // Here we add the armature "on the fly":
477                         par = bc_add_object(sce, OB_ARMATURE, std::string("Armature").c_str());
478                         objects_done->push_back(par);
479                         object_map.insert(std::make_pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), par));
480                         node_map[node->getUniqueId()] = node;
481                 }
482                 armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce);
483
484                 if (parent_node == NULL) {
485                         // for skeletons without root node all has been done above.
486                         // Skeletons with root node are handled further down.
487                         return objects_done;
488                 }
489         }
490         else {
491                 COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries();
492                 COLLADAFW::InstanceCameraPointerArray &camera = node->getInstanceCameras();
493                 COLLADAFW::InstanceLightPointerArray &lamp = node->getInstanceLights();
494                 COLLADAFW::InstanceControllerPointerArray &controller = node->getInstanceControllers();
495                 COLLADAFW::InstanceNodePointerArray &inst_node = node->getInstanceNodes();
496                 size_t geom_done = 0;
497                 size_t camera_done = 0;
498                 size_t lamp_done = 0;
499                 size_t controller_done = 0;
500                 size_t inst_done = 0;
501
502                 // XXX linking object with the first <instance_geometry>, though a node may have more of them...
503                 // maybe join multiple <instance_...> meshes into 1, and link object with it? not sure...
504                 // <instance_geometry>
505                 while (geom_done < geom.getCount()) {
506                         ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map,
507                                                               material_texture_mapping_map);
508                         if (ob == NULL) {
509                                 fprintf(stderr,
510                                                 "<node id=\"%s\", name=\"%s\" >...contains a reference to an unknown instance_mesh.\n",
511                                                 id.c_str(),
512                                                 name.c_str());
513                         }
514                         else {
515                                 objects_done->push_back(ob);
516                         }
517                         ++geom_done;
518                 }
519                 while (camera_done < camera.getCount()) {
520                         ob = create_camera_object(camera[camera_done], sce);
521                         if (ob == NULL) {
522                                 std::string id   = node->getOriginalId();
523                                 std::string name = node->getName();
524                                 fprintf(stderr, "<node id=\"%s\", name=\"%s\" >...contains a reference to an unknown instance_camera.\n", id.c_str(), name.c_str());
525                         }
526                         else
527                                 objects_done->push_back(ob);
528                         ++camera_done;
529                 }
530                 while (lamp_done < lamp.getCount()) {
531                         ob = create_lamp_object(lamp[lamp_done], sce);
532                         objects_done->push_back(ob);
533                         ++lamp_done;
534                 }
535                 while (controller_done < controller.getCount()) {
536                         COLLADAFW::InstanceGeometry *geom = (COLLADAFW::InstanceGeometry *)controller[controller_done];
537                         ob = mesh_importer.create_mesh_object(node, geom, true, uid_material_map, material_texture_mapping_map);
538                         objects_done->push_back(ob);
539                         ++controller_done;
540                 }
541                 // XXX instance_node is not supported yet
542                 while (inst_done < inst_node.getCount()) {
543                         const COLLADAFW::UniqueId& node_id = inst_node[inst_done]->getInstanciatedObjectId();
544                         if (object_map.find(node_id) == object_map.end()) {
545                                 fprintf(stderr, "Cannot find object for node referenced by <instance_node name=\"%s\">.\n", inst_node[inst_done]->getName().c_str());
546                                 ob = NULL;
547                         }
548                         else {
549                                 std::pair<std::multimap<COLLADAFW::UniqueId, Object *>::iterator, std::multimap<COLLADAFW::UniqueId, Object *>::iterator> pair_iter = object_map.equal_range(node_id);
550                                 for (std::multimap<COLLADAFW::UniqueId, Object *>::iterator it2 = pair_iter.first; it2 != pair_iter.second; it2++) {
551                                         Object *source_ob = (Object *)it2->second;
552                                         COLLADAFW::Node *source_node = node_map[node_id];
553                                         ob = create_instance_node(source_ob, source_node, node, sce, is_library_node);
554                                 }
555                         }
556                         if (ob != NULL) objects_done->push_back(ob);
557                         ++inst_done;
558
559                         read_transform = false;
560                 }
561
562                 // if node is empty - create empty object
563                 // XXX empty node may not mean it is empty object, not sure about this
564                 if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) {
565                         //Check if Object is armature, by checking if immediate child is a JOINT node.
566                         if (is_armature(node)) {
567                                 ob = bc_add_object(sce, OB_ARMATURE, name.c_str());
568                         }
569                         else {
570                                 ob = bc_add_object(sce, OB_EMPTY, NULL);
571                         }
572                         objects_done->push_back(ob);
573
574                 }
575                 
576                 // XXX: if there're multiple instances, only one is stored
577
578                 if (!ob) return objects_done;
579
580                 for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
581                         ob = *it;
582                         std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId();
583                         rename_id(&ob->id, (char *)nodename.c_str());
584                         object_map.insert(std::make_pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), ob));
585                         node_map[node->getUniqueId()] = node;
586
587                         if (is_library_node)
588                                 libnode_ob.push_back(ob);
589                 }
590
591
592                 //create_constraints(et,ob);
593
594         }
595
596         for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
597                 ob = *it;
598
599                 if (read_transform)
600                         anim_importer.read_node_transform(node, ob);  // overwrites location set earlier
601
602                 if (!is_joint) {
603                         // if par was given make this object child of the previous
604                         if (par && ob)
605                                 bc_set_parent(ob, par, mContext);
606                 }
607         }
608         // if node has child nodes write them
609         COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
610
611         if (objects_done->size() > 0) {
612                 ob = *objects_done->begin();
613         }
614         else {
615                 ob = NULL;
616         }
617
618         for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
619                 write_node(child_nodes[i], node, sce, ob, is_library_node);
620         }
621
622         return objects_done;
623 }
624
625 /** When this method is called, the writer must write the entire visual scene.
626  * \return The writer should return true, if writing succeeded, false otherwise.*/
627 bool DocumentImporter::writeVisualScene(const COLLADAFW::VisualScene *visualScene)
628 {
629         if (mImportStage != General)
630                 return true;
631                 
632         // this method called on post process after writeGeometry, writeMaterial, etc.
633
634         // for each <node> in <visual_scene>:
635         // create an Object
636         // if Mesh (previously created in writeGeometry) to which <node> corresponds exists, link Object with that mesh
637
638         // update: since we cannot link a Mesh with Object in
639         // writeGeometry because <geometry> does not reference <node>,
640         // we link Objects with Meshes here
641
642         vscenes.push_back(visualScene);
643         
644         return true;
645 }
646
647 /** When this method is called, the writer must handle all nodes contained in the 
648  * library nodes.
649  * \return The writer should return true, if writing succeeded, false otherwise.*/
650 bool DocumentImporter::writeLibraryNodes(const COLLADAFW::LibraryNodes *libraryNodes)
651 {
652         if (mImportStage != General)
653                 return true;
654                 
655         Scene *sce = CTX_data_scene(mContext);
656
657         const COLLADAFW::NodePointerArray& nodes = libraryNodes->getNodes();
658
659         for (unsigned int i = 0; i < nodes.getCount(); i++) {
660                 write_node(nodes[i], NULL, sce, NULL, true);
661         }
662
663         return true;
664 }
665
666 /** When this method is called, the writer must write the geometry.
667  * \return The writer should return true, if writing succeeded, false otherwise.*/
668 bool DocumentImporter::writeGeometry(const COLLADAFW::Geometry *geom)
669 {
670         if (mImportStage != General)
671                 return true;
672                 
673         return mesh_importer.write_geometry(geom);
674 }
675
676 /** When this method is called, the writer must write the material.
677  * \return The writer should return true, if writing succeeded, false otherwise.*/
678 bool DocumentImporter::writeMaterial(const COLLADAFW::Material *cmat)
679 {
680         if (mImportStage != General)
681                 return true;
682                 
683         const std::string& str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId();
684         Material *ma = BKE_material_add(G.main, (char *)str_mat_id.c_str());
685         
686         this->uid_effect_map[cmat->getInstantiatedEffect()] = ma;
687         this->uid_material_map[cmat->getUniqueId()] = ma;
688         
689         return true;
690 }
691
692 // create mtex, create texture, set texture image
693 MTex *DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::Texture &ctex, Material *ma,
694                                        int i, TexIndexTextureArrayMap &texindex_texarray_map)
695 {
696         COLLADAFW::SamplerPointerArray& samp_array = ef->getSamplerPointerArray();
697         COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()];
698                 
699         const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage();
700         
701         if (uid_image_map.find(ima_uid) == uid_image_map.end()) {
702                 fprintf(stderr, "Couldn't find an image by UID.\n");
703                 return NULL;
704         }
705         
706         ma->mtex[i] = add_mtex();
707         ma->mtex[i]->texco = TEXCO_UV;
708         ma->mtex[i]->tex = add_texture(G.main, "Texture");
709         ma->mtex[i]->tex->type = TEX_IMAGE;
710         ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
711         
712         texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
713         
714         return ma->mtex[i];
715 }
716
717 void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Material *ma)
718 {
719         COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
720         
721         // blinn
722         if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
723                 ma->spec_shader = MA_SPEC_BLINN;
724                 ma->spec = ef->getShininess().getFloatValue();
725         }
726         // phong
727         else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
728                 ma->spec_shader = MA_SPEC_PHONG;
729                 ma->har = ef->getShininess().getFloatValue();
730         }
731         // lambert
732         else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) {
733                 ma->diff_shader = MA_DIFF_LAMBERT;
734         }
735         // default - lambert
736         else {
737                 ma->diff_shader = MA_DIFF_LAMBERT;
738                 fprintf(stderr, "Current shader type is not supported, default to lambert.\n");
739         }
740         // reflectivity
741         ma->ray_mirror = ef->getReflectivity().getFloatValue();
742         // index of refraction
743         ma->ang = ef->getIndexOfRefraction().getFloatValue();
744         
745         int i = 0;
746         COLLADAFW::Color col;
747         MTex *mtex = NULL;
748         TexIndexTextureArrayMap texindex_texarray_map;
749         
750         // DIFFUSE
751         // color
752         if (ef->getDiffuse().isColor()) {
753                 col = ef->getDiffuse().getColor();
754                 ma->r = col.getRed();
755                 ma->g = col.getGreen();
756                 ma->b = col.getBlue();
757         }
758         // texture
759         else if (ef->getDiffuse().isTexture()) {
760                 COLLADAFW::Texture ctex = ef->getDiffuse().getTexture(); 
761                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
762                 if (mtex != NULL) {
763                         mtex->mapto = MAP_COL;
764                         ma->texact = (int)i;
765                         i++;
766                 }
767         }
768         // AMBIENT
769         // color
770         if (ef->getAmbient().isColor()) {
771                 col = ef->getAmbient().getColor();
772                 ma->ambr = col.getRed();
773                 ma->ambg = col.getGreen();
774                 ma->ambb = col.getBlue();
775         }
776         // texture
777         else if (ef->getAmbient().isTexture()) {
778                 COLLADAFW::Texture ctex = ef->getAmbient().getTexture(); 
779                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
780                 if (mtex != NULL) {
781                         mtex->mapto = MAP_AMB; 
782                         i++;
783                 }
784         }
785         // SPECULAR
786         // color
787         if (ef->getSpecular().isColor()) {
788                 col = ef->getSpecular().getColor();
789                 ma->specr = col.getRed();
790                 ma->specg = col.getGreen();
791                 ma->specb = col.getBlue();
792         }
793         // texture
794         else if (ef->getSpecular().isTexture()) {
795                 COLLADAFW::Texture ctex = ef->getSpecular().getTexture(); 
796                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
797                 if (mtex != NULL) {
798                         mtex->mapto = MAP_SPEC; 
799                         i++;
800                 }
801         }
802         // REFLECTIVE
803         // color
804         if (ef->getReflective().isColor()) {
805                 col = ef->getReflective().getColor();
806                 ma->mirr = col.getRed();
807                 ma->mirg = col.getGreen();
808                 ma->mirb = col.getBlue();
809         }
810         // texture
811         else if (ef->getReflective().isTexture()) {
812                 COLLADAFW::Texture ctex = ef->getReflective().getTexture(); 
813                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
814                 if (mtex != NULL) {
815                         mtex->mapto = MAP_REF; 
816                         i++;
817                 }
818         }
819         // EMISSION
820         // color
821         if (ef->getEmission().isColor()) {
822                 // XXX there is no emission color in blender
823                 // but I am not sure
824         }
825         // texture
826         else if (ef->getEmission().isTexture()) {
827                 COLLADAFW::Texture ctex = ef->getEmission().getTexture(); 
828                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
829                 if (mtex != NULL) {
830                         mtex->mapto = MAP_EMIT; 
831                         i++;
832                 }
833         }
834         
835         if (ef->getOpacity().isTexture()) {
836                 COLLADAFW::Texture ctex = ef->getOpacity().getTexture();
837                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
838                 if (mtex != NULL) {
839                         mtex->mapto = MAP_ALPHA;
840                         i++;
841                         ma->spectra = ma->alpha = 0;
842                         ma->mode |= MA_ZTRANSP | MA_TRANSP;
843                 }
844         }
845         // TRANSPARENT
846         // color
847 #if 0
848         if (ef->getOpacity().isColor()) {
849                 // XXX don't know what to do here
850         }
851         // texture
852         else if (ef->getOpacity().isTexture()) {
853                 ctex = ef->getOpacity().getTexture();
854                 if (mtex != NULL) mtex->mapto &= MAP_ALPHA;
855                 else {
856                         mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
857                         if (mtex != NULL) mtex->mapto = MAP_ALPHA;
858                 }
859         }
860 #endif
861         material_texture_mapping_map[ma] = texindex_texarray_map;
862 }
863
864 /** When this method is called, the writer must write the effect.
865  * \return The writer should return true, if writing succeeded, false otherwise.*/
866
867 bool DocumentImporter::writeEffect(const COLLADAFW::Effect *effect)
868 {
869         if (mImportStage != General)
870                 return true;
871         
872         const COLLADAFW::UniqueId& uid = effect->getUniqueId();
873         
874         if (uid_effect_map.find(uid) == uid_effect_map.end()) {
875                 fprintf(stderr, "Couldn't find a material by UID.\n");
876                 return true;
877         }
878         
879         Material *ma = uid_effect_map[uid];
880         std::map<COLLADAFW::UniqueId, Material *>::iterator iter;
881         for (iter = uid_material_map.begin(); iter != uid_material_map.end(); iter++) {
882                 if (iter->second == ma) {
883                         this->FW_object_map[iter->first] = effect;
884                         break;
885                 }
886         }
887         COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects();
888         if (common_efs.getCount() < 1) {
889                 fprintf(stderr, "Couldn't find <profile_COMMON>.\n");
890                 return true;
891         }
892         // XXX TODO: Take all <profile_common>s
893         // Currently only first <profile_common> is supported
894         COLLADAFW::EffectCommon *ef = common_efs[0];
895         write_profile_COMMON(ef, ma);
896         this->FW_object_map[effect->getUniqueId()] = effect;
897                 
898         return true;
899 }
900
901
902 /** When this method is called, the writer must write the camera.
903  * \return The writer should return true, if writing succeeded, false otherwise.*/
904 bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera)
905 {
906         if (mImportStage != General)
907                 return true;
908                 
909         Camera *cam = NULL;
910         std::string cam_id, cam_name;
911         
912         cam_id = camera->getOriginalId();
913         cam_name = camera->getName();
914         if (cam_name.size()) cam = (Camera *)BKE_camera_add(G.main, (char *)cam_name.c_str());
915         else cam = (Camera *)BKE_camera_add(G.main, (char *)cam_id.c_str());
916         
917         if (!cam) {
918                 fprintf(stderr, "Cannot create camera.\n");
919                 return true;
920         }
921         cam->clipsta = camera->getNearClippingPlane().getValue();
922         cam->clipend = camera->getFarClippingPlane().getValue();
923         
924         COLLADAFW::Camera::CameraType type = camera->getCameraType();
925         switch (type) {
926                 case COLLADAFW::Camera::ORTHOGRAPHIC:
927                 {
928                         cam->type = CAM_ORTHO;
929                 }
930                 break;
931                 case COLLADAFW::Camera::PERSPECTIVE:
932                 {
933                         cam->type = CAM_PERSP;
934                 }
935                 break;
936                 case COLLADAFW::Camera::UNDEFINED_CAMERATYPE:
937                 {
938                         fprintf(stderr, "Current camera type is not supported.\n");
939                         cam->type = CAM_PERSP;
940                 }
941                 break;
942         }
943         
944         switch (camera->getDescriptionType()) {
945                 case COLLADAFW::Camera::ASPECTRATIO_AND_Y:
946                 {
947                         switch (cam->type) {
948                                 case CAM_ORTHO:
949                                 {
950                                         double ymag = 2 * camera->getYMag().getValue();
951                                         double aspect = camera->getAspectRatio().getValue();
952                                         double xmag = aspect * ymag;
953                                         cam->ortho_scale = (float)xmag;
954                                 }
955                                 break;
956                                 case CAM_PERSP:
957                                 default:
958                                 {
959                                         double yfov = camera->getYFov().getValue();
960                                         double aspect = camera->getAspectRatio().getValue();
961
962                                         // NOTE: Needs more testing (As we curretnly have no official test data for this)
963
964                                         double xfov = 2.0f * atanf(aspect * tanf(DEG2RADF(yfov) * 0.5f));
965                                         cam->lens = fov_to_focallength(xfov, cam->sensor_x);
966                                 }
967                                 break;
968                         }
969                 }
970                 break;
971                 /* XXX correct way to do following four is probably to get also render
972                  * size and determine proper settings from that somehow */
973                 case COLLADAFW::Camera::ASPECTRATIO_AND_X:
974                 case COLLADAFW::Camera::SINGLE_X:
975                 case COLLADAFW::Camera::X_AND_Y:
976                 {
977                         switch (cam->type) {
978                                 case CAM_ORTHO:
979                                         cam->ortho_scale = (float)camera->getXMag().getValue() * 2;
980                                         break;
981                                 case CAM_PERSP:
982                                 default:
983                                 {
984                                         double x = camera->getXFov().getValue();
985                                         // x is in degrees, cam->lens is in millimiters
986                                         cam->lens = fov_to_focallength(DEG2RADF(x), cam->sensor_x);
987                                 }
988                                 break;
989                         }
990                 }
991                 break;
992                 case COLLADAFW::Camera::SINGLE_Y:
993                 {
994                         switch (cam->type) {
995                                 case CAM_ORTHO:
996                                         cam->ortho_scale = (float)camera->getYMag().getValue();
997                                         break;
998                                 case CAM_PERSP:
999                                 default:
1000                                 {
1001                                         double yfov = camera->getYFov().getValue();
1002                                         // yfov is in degrees, cam->lens is in millimiters
1003                                         cam->lens = fov_to_focallength(DEG2RADF(yfov), cam->sensor_x);
1004                                 }
1005                                 break;
1006                         }
1007                 }
1008                 break;
1009                 case COLLADAFW::Camera::UNDEFINED:
1010                         // read nothing, use blender defaults.
1011                         break;
1012         }
1013         
1014         this->uid_camera_map[camera->getUniqueId()] = cam;
1015         this->FW_object_map[camera->getUniqueId()] = camera;
1016         // XXX import camera options
1017         return true;
1018 }
1019
1020 /** When this method is called, the writer must write the image.
1021  * \return The writer should return true, if writing succeeded, false otherwise.*/
1022 bool DocumentImporter::writeImage(const COLLADAFW::Image *image)
1023 {
1024         if (mImportStage != General)
1025                 return true;
1026                 
1027         const std::string& imagepath = image->getImageURI().toNativePath();
1028
1029         char dir[FILE_MAX];
1030         char absolute_path[FILE_MAX];
1031         const char *workpath;
1032
1033         BLI_split_dir_part(this->import_settings->filepath, dir, sizeof(dir));
1034         BLI_join_dirfile(absolute_path, sizeof(absolute_path), dir, imagepath.c_str());
1035         if (BLI_exists(absolute_path)) {
1036                 workpath = absolute_path;
1037         } 
1038         else {
1039                 // Maybe imagepath was already absolute ?
1040                 if (!BLI_exists(imagepath.c_str())) {
1041                         fprintf(stderr, "Image not found: %s.\n", imagepath.c_str() );
1042                         return true;
1043                 }
1044                 workpath = imagepath.c_str();
1045         }
1046
1047         Image *ima = BKE_image_load_exists(workpath);
1048         if (!ima) {
1049                 fprintf(stderr, "Cannot create image: %s\n", workpath);
1050                 return true;
1051         }
1052         this->uid_image_map[image->getUniqueId()] = ima;
1053         
1054         return true;
1055 }
1056
1057 /** When this method is called, the writer must write the light.
1058  * \return The writer should return true, if writing succeeded, false otherwise.*/
1059 bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
1060 {
1061         if (mImportStage != General)
1062                 return true;
1063
1064         Lamp *lamp = NULL;
1065         std::string la_id, la_name;
1066
1067         ExtraTags *et = getExtraTags(light->getUniqueId());
1068         /*TagsMap::iterator etit;
1069         ExtraTags *et = 0;
1070         etit = uid_tags_map.find(light->getUniqueId().toAscii());
1071         if (etit != uid_tags_map.end())
1072                 et = etit->second;*/
1073
1074         la_id = light->getOriginalId();
1075         la_name = light->getName();
1076         if (la_name.size()) lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_name.c_str());
1077         else lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_id.c_str());
1078
1079         if (!lamp) {
1080                 fprintf(stderr, "Cannot create lamp.\n");
1081                 return true;
1082         }
1083
1084         // if we find an ExtraTags for this, use that instead.
1085         if (et && et->isProfile("blender")) {
1086                 et->setData("type", &(lamp->type));
1087                 et->setData("flag", &(lamp->flag));
1088                 et->setData("mode", &(lamp->mode));
1089                 et->setData("gamma", &(lamp->k));
1090                 et->setData("red", &(lamp->r));
1091                 et->setData("green", &(lamp->g));
1092                 et->setData("blue", &(lamp->b));
1093                 et->setData("shadow_r", &(lamp->shdwr));
1094                 et->setData("shadow_g", &(lamp->shdwg));
1095                 et->setData("shadow_b", &(lamp->shdwb));
1096                 et->setData("energy", &(lamp->energy));
1097                 et->setData("dist", &(lamp->dist));
1098                 et->setData("spotsize", &(lamp->spotsize));
1099                 et->setData("spotblend", &(lamp->spotblend));
1100                 et->setData("halo_intensity", &(lamp->haint));
1101                 et->setData("att1", &(lamp->att1));
1102                 et->setData("att2", &(lamp->att2));
1103                 et->setData("falloff_type", &(lamp->falloff_type));
1104                 et->setData("clipsta", &(lamp->clipsta));
1105                 et->setData("clipend", &(lamp->clipend));
1106                 et->setData("shadspotsize", &(lamp->shadspotsize));
1107                 et->setData("bias", &(lamp->bias));
1108                 et->setData("soft", &(lamp->soft));
1109                 et->setData("compressthresh", &(lamp->compressthresh));
1110                 et->setData("bufsize", &(lamp->bufsize));
1111                 et->setData("samp", &(lamp->samp));
1112                 et->setData("buffers", &(lamp->buffers));
1113                 et->setData("filtertype", &(lamp->filtertype));
1114                 et->setData("bufflag", &(lamp->bufflag));
1115                 et->setData("buftype", &(lamp->buftype));
1116                 et->setData("ray_samp", &(lamp->ray_samp));
1117                 et->setData("ray_sampy", &(lamp->ray_sampy));
1118                 et->setData("ray_sampz", &(lamp->ray_sampz));
1119                 et->setData("ray_samp_type", &(lamp->ray_samp_type));
1120                 et->setData("area_shape", &(lamp->area_shape));
1121                 et->setData("area_size", &(lamp->area_size));
1122                 et->setData("area_sizey", &(lamp->area_sizey));
1123                 et->setData("area_sizez", &(lamp->area_sizez));
1124                 et->setData("adapt_thresh", &(lamp->adapt_thresh));
1125                 et->setData("ray_samp_method", &(lamp->ray_samp_method));
1126                 et->setData("shadhalostep", &(lamp->shadhalostep));
1127                 et->setData("sun_effect_type", &(lamp->shadhalostep));
1128                 et->setData("skyblendtype", &(lamp->skyblendtype));
1129                 et->setData("horizon_brightness", &(lamp->horizon_brightness));
1130                 et->setData("spread", &(lamp->spread));
1131                 et->setData("sun_brightness", &(lamp->sun_brightness));
1132                 et->setData("sun_size", &(lamp->sun_size));
1133                 et->setData("backscattered_light", &(lamp->backscattered_light));
1134                 et->setData("sun_intensity", &(lamp->sun_intensity));
1135                 et->setData("atm_turbidity", &(lamp->atm_turbidity));
1136                 et->setData("atm_extinction_factor", &(lamp->atm_extinction_factor));
1137                 et->setData("atm_distance_factor", &(lamp->atm_distance_factor));
1138                 et->setData("skyblendfac", &(lamp->skyblendfac));
1139                 et->setData("sky_exposure", &(lamp->sky_exposure));
1140                 et->setData("sky_colorspace", &(lamp->sky_colorspace));
1141         }
1142         else {
1143                 float constatt = light->getConstantAttenuation().getValue();
1144                 float linatt = light->getLinearAttenuation().getValue();
1145                 float quadatt = light->getQuadraticAttenuation().getValue();
1146                 float d = 25.0f;
1147                 float att1 = 0.0f;
1148                 float att2 = 0.0f;
1149                 float e = 1.0f;
1150
1151                 if (light->getColor().isValid()) {
1152                         COLLADAFW::Color col = light->getColor();
1153                         lamp->r = col.getRed();
1154                         lamp->g = col.getGreen();
1155                         lamp->b = col.getBlue();
1156                 }
1157
1158                 if (IS_EQ(linatt, 0.0f) && quadatt > 0.0f) {
1159                         att2 = quadatt;
1160                         d = sqrt(1.0f / quadatt);
1161                 }
1162                 // linear light
1163                 else if (IS_EQ(quadatt, 0.0f) && linatt > 0.0f) {
1164                         att1 = linatt;
1165                         d = (1.0f / linatt);
1166                 }
1167                 else if (IS_EQ(constatt, 1.0f)) {
1168                         att1 = 1.0f;
1169                 }
1170                 else {
1171                         // assuming point light (const att = 1.0);
1172                         att1 = 1.0f;
1173                 }
1174                 
1175                 d *= (1.0f / unit_converter.getLinearMeter());
1176
1177                 lamp->energy = e;
1178                 lamp->dist = d;
1179
1180                 COLLADAFW::Light::LightType type = light->getLightType();
1181                 switch (type) {
1182                         case COLLADAFW::Light::AMBIENT_LIGHT:
1183                         {
1184                                 lamp->type = LA_HEMI;
1185                         }
1186                         break;
1187                         case COLLADAFW::Light::SPOT_LIGHT:
1188                         {
1189                                 lamp->type = LA_SPOT;
1190                                 lamp->att1 = att1;
1191                                 lamp->att2 = att2;
1192                                 if (IS_EQ(att1, 0.0f) && att2 > 0)
1193                                         lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1194                                 if (IS_EQ(att2, 0.0f) && att1 > 0)
1195                                         lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1196                                 lamp->spotsize = light->getFallOffAngle().getValue();
1197                                 lamp->spotblend = light->getFallOffExponent().getValue();
1198                         }
1199                         break;
1200                         case COLLADAFW::Light::DIRECTIONAL_LIGHT:
1201                         {
1202                                 /* our sun is very strong, so pick a smaller energy level */
1203                                 lamp->type = LA_SUN;
1204                                 lamp->mode |= LA_NO_SPEC;
1205                         }
1206                         break;
1207                         case COLLADAFW::Light::POINT_LIGHT:
1208                         {
1209                                 lamp->type = LA_LOCAL;
1210                                 lamp->att1 = att1;
1211                                 lamp->att2 = att2;
1212                                 if (IS_EQ(att1, 0.0f) && att2 > 0)
1213                                         lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1214                                 if (IS_EQ(att2, 0.0f) && att1 > 0)
1215                                         lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1216                         }
1217                         break;
1218                         case COLLADAFW::Light::UNDEFINED:
1219                         {
1220                                 fprintf(stderr, "Current lamp type is not supported.\n");
1221                                 lamp->type = LA_LOCAL;
1222                         }
1223                         break;
1224                 }
1225         }
1226
1227         this->uid_lamp_map[light->getUniqueId()] = lamp;
1228         this->FW_object_map[light->getUniqueId()] = light;
1229         return true;
1230 }
1231
1232 // this function is called only for animations that pass COLLADAFW::validate
1233 bool DocumentImporter::writeAnimation(const COLLADAFW::Animation *anim)
1234 {
1235         if (mImportStage != General)
1236                 return true;
1237                 
1238         // return true;
1239         return anim_importer.write_animation(anim);
1240 }
1241
1242 // called on post-process stage after writeVisualScenes
1243 bool DocumentImporter::writeAnimationList(const COLLADAFW::AnimationList *animationList)
1244 {
1245         if (mImportStage != General)
1246                 return true;
1247                 
1248         // return true;
1249         return anim_importer.write_animation_list(animationList);
1250 }
1251
1252 /** When this method is called, the writer must write the skin controller data.
1253  * \return The writer should return true, if writing succeeded, false otherwise.*/
1254 bool DocumentImporter::writeSkinControllerData(const COLLADAFW::SkinControllerData *skin)
1255 {
1256         return armature_importer.write_skin_controller_data(skin);
1257 }
1258
1259 // this is called on postprocess, before writeVisualScenes
1260 bool DocumentImporter::writeController(const COLLADAFW::Controller *controller)
1261 {
1262         if (mImportStage != General)
1263                 return true;
1264                 
1265         return armature_importer.write_controller(controller);
1266 }
1267
1268 bool DocumentImporter::writeFormulas(const COLLADAFW::Formulas *formulas)
1269 {
1270         return true;
1271 }
1272
1273 bool DocumentImporter::writeKinematicsScene(const COLLADAFW::KinematicsScene *kinematicsScene)
1274 {
1275         return true;
1276 }
1277
1278 ExtraTags *DocumentImporter::getExtraTags(const COLLADAFW::UniqueId &uid)
1279 {
1280         if (uid_tags_map.find(uid.toAscii()) == uid_tags_map.end()) {
1281                 return NULL;
1282         }
1283         return uid_tags_map[uid.toAscii()];
1284 }
1285
1286 bool DocumentImporter::addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *extra_tags)
1287 {
1288         uid_tags_map[uid.toAscii()] = extra_tags;
1289         return true;
1290 }
1291
1292 bool DocumentImporter::is_armature(COLLADAFW::Node *node)
1293 {
1294         COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
1295         for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
1296                 if (child_nodes[i]->getType() == COLLADAFW::Node::JOINT) {
1297                         return true;
1298                 }
1299                 else {
1300                         continue;
1301                 }
1302         }
1303
1304         //no child is JOINT
1305         return false;
1306 }