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