style cleanup: spaces -> tabs
[blender.git] / source / blender / collada / SceneExporter.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, Jan Diederich, Tod Liverseed.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/collada/SceneExporter.cpp
24  *  \ingroup collada
25  */
26
27 extern "C" {
28         #include "BLI_utildefines.h"
29         #include "BKE_object.h"
30 }
31
32 #include "SceneExporter.h"
33 #include "collada_utils.h"
34
35 SceneExporter::SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings)
36         : COLLADASW::LibraryVisualScenes(sw), arm_exporter(arm), export_settings(export_settings)
37 {
38 }
39         
40 void SceneExporter::exportScene(Scene *sce)
41 {
42         // <library_visual_scenes> <visual_scene>
43         std::string id_naming = id_name(sce);
44         openVisualScene(translate_id(id_naming), id_naming);
45         exportHierarchy(sce);
46         closeVisualScene();
47         closeLibrary();
48 }
49
50 void SceneExporter::exportHierarchy(Scene *sce)
51 {       
52         LinkNode *node;
53         std::vector<Object *> base_objects;
54
55         // Ensure all objects in the export_set are marked
56         for (node = this->export_settings->export_set; node; node = node->next) {
57                 Object *ob = (Object *) node->link;
58                 ob->id.flag |= LIB_DOIT;
59         }
60         
61         // Now find all exportable base ojects (highest in export hierarchy)
62         for (node = this->export_settings->export_set; node; node = node->next) {
63                 Object *ob = (Object *) node->link;
64                 if (bc_is_base_node(this->export_settings->export_set, ob)) {
65                         switch (ob->type) {
66                                 case OB_MESH:
67                                 case OB_CAMERA:
68                                 case OB_LAMP:
69                                 case OB_EMPTY:
70                                 case OB_ARMATURE:
71                                         base_objects.push_back(ob);
72                                         break;
73                         }
74                 }
75         }
76
77         // And now export the base objects:
78         for (int index = 0; index < base_objects.size(); index++) {
79                 Object *ob = base_objects[index];
80                 if (bc_is_marked(ob)) {
81                         bc_remove_mark(ob);
82                         writeNodes(ob, sce);
83                 }
84         }
85 }
86
87 void SceneExporter::writeNodes(Object *ob, Scene *sce)
88 {
89         // Add associated armature first if available
90         bool armature_exported = false;
91         Object *ob_arm = bc_get_assigned_armature(ob);
92         if (ob_arm != NULL) {
93                 armature_exported = bc_is_in_Export_set(this->export_settings->export_set, ob_arm);
94                 if (armature_exported && bc_is_marked(ob_arm)) {
95                         bc_remove_mark(ob_arm);
96                         writeNodes(ob_arm, sce);
97                         armature_exported = true;
98                 }
99         }
100
101         COLLADASW::Node colladaNode(mSW);
102         colladaNode.setNodeId(translate_id(id_name(ob)));
103         colladaNode.setNodeName(translate_id(id_name(ob)));
104         colladaNode.setType(COLLADASW::Node::NODE);
105
106         colladaNode.start();
107
108         std::list<Object *> child_objects;
109
110         // list child objects
111         LinkNode *node;
112         for (node=this->export_settings->export_set; node; node=node->next) {
113                 // cob - child object
114                 Object *cob = (Object *)node->link;
115
116                 if (cob->parent == ob) {
117                         switch (cob->type) {
118                                 case OB_MESH:
119                                 case OB_CAMERA:
120                                 case OB_LAMP:
121                                 case OB_EMPTY:
122                                 case OB_ARMATURE:
123                                         if (bc_is_marked(cob))
124                                                 child_objects.push_back(cob);
125                                         break;
126                         }
127                 }
128         }
129
130         if (ob->type == OB_MESH && armature_exported)
131                 // for skinned mesh we write obmat in <bind_shape_matrix>
132                 TransformWriter::add_node_transform_identity(colladaNode);
133         else
134                 TransformWriter::add_node_transform_ob(colladaNode, ob);
135
136         // <instance_geometry>
137         if (ob->type == OB_MESH) {
138                 bool instance_controller_created = false;
139                 if (armature_exported) {
140                         instance_controller_created = arm_exporter->add_instance_controller(ob);
141                 }
142                 if (!instance_controller_created) {
143                         COLLADASW::InstanceGeometry instGeom(mSW);
144                         instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation)));
145
146                         InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), ob, this->export_settings->active_uv_only);
147
148                         instGeom.add();
149                 }
150         }
151
152         // <instance_controller>
153         else if (ob->type == OB_ARMATURE) {
154                 arm_exporter->add_armature_bones(ob, sce, this, child_objects);
155         }
156
157         // <instance_camera>
158         else if (ob->type == OB_CAMERA) {
159                 COLLADASW::InstanceCamera instCam(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_camera_id(ob)));
160                 instCam.add();
161         }
162
163         // <instance_light>
164         else if (ob->type == OB_LAMP) {
165                 COLLADASW::InstanceLight instLa(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_light_id(ob)));
166                 instLa.add();
167         }
168
169         // empty object
170         else if (ob->type == OB_EMPTY) { // TODO: handle groups (OB_DUPLIGROUP
171                 if ((ob->transflag & OB_DUPLIGROUP) == OB_DUPLIGROUP && ob->dup_group) {
172                         GroupObject *go = NULL;
173                         Group *gr = ob->dup_group;
174                         /* printf("group detected '%s'\n", gr->id.name+2); */
175                         for (go = (GroupObject *)(gr->gobject.first); go; go = go->next) {
176                                 printf("\t%s\n", go->ob->id.name);
177                         }
178                 }
179         }
180
181         if (ob->type == OB_ARMATURE) {
182                 colladaNode.end();
183         }
184
185         if (ob->constraints.first != NULL ){
186                 bConstraint *con = (bConstraint*) ob->constraints.first;
187                 while (con) {
188                         std::string con_name(id_name(con));
189                         std::string con_tag = con_name + "_constraint";
190                         colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"type",con->type);
191                         colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"enforce",con->enforce);
192                         colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"flag",con->flag);
193                         colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"headtail",con->headtail);
194                         colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"lin_error",con->lin_error);
195                         colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"own_space",con->ownspace);
196                         colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"rot_error",con->rot_error);
197                         colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"tar_space",con->tarspace);
198                         colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"lin_error",con->lin_error);
199                         
200                         //not ideal: add the target object name as another parameter. 
201                         //No real mapping in the .dae
202                         //Need support for multiple target objects also.
203                         bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
204                         ListBase targets = {NULL, NULL};
205                         if (cti && cti->get_constraint_targets) {
206                         
207                                 bConstraintTarget *ct;
208                                 Object *obtar;
209                         
210                                 cti->get_constraint_targets(con, &targets);
211                                 if(cti){
212                                         for (ct = (bConstraintTarget*)targets.first; ct; ct = ct->next){
213                                                 obtar = ct->tar;
214                                                 std::string tar_id(id_name(obtar));
215                                                 colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"target_id",tar_id);
216                                         }
217                                 }
218                         }
219
220                         con = con->next;
221                 }
222         }
223
224         for (std::list<Object *>::iterator i = child_objects.begin(); i != child_objects.end(); ++i) {
225                 if (bc_is_marked(*i)) {
226                         bc_remove_mark(*i);
227                         writeNodes(*i, sce);
228                 }
229         }
230
231         if (ob->type != OB_ARMATURE)
232                 colladaNode.end();
233 }
234