3746ba3b64a9c0d5157a268ea82a9331f03160d8
[blender.git] / source / blender / editors / io / io_collada.c
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  * The Original Code is Copyright (C) 2008 Blender Foundation.
19  * All rights reserved.
20  *
21  * 
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/io/io_collada.c
28  *  \ingroup collada
29  */
30 #ifdef WITH_COLLADA
31 #include "DNA_scene_types.h"
32
33 #include "BLT_translation.h"
34
35 #include "BLI_blenlib.h"
36 #include "BLI_utildefines.h"
37
38 #include "BKE_context.h"
39 #include "BKE_global.h"
40 #include "BKE_main.h"
41 #include "BKE_report.h"
42
43 #include "ED_screen.h"
44 #include "ED_object.h"
45
46 #include "RNA_access.h"
47 #include "RNA_define.h"
48
49 #include "UI_interface.h"
50 #include "UI_resources.h"
51
52 #include "WM_api.h"
53 #include "WM_types.h"
54
55 #include "../../collada/collada.h"
56
57 #include "io_collada.h"
58
59 static int wm_collada_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
60 {       
61         if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
62                 char filepath[FILE_MAX];
63
64                 if (G.main->name[0] == 0)
65                         BLI_strncpy(filepath, "untitled", sizeof(filepath));
66                 else
67                         BLI_strncpy(filepath, G.main->name, sizeof(filepath));
68
69                 BLI_replace_extension(filepath, sizeof(filepath), ".dae");
70                 RNA_string_set(op->ptr, "filepath", filepath);
71         }
72
73         WM_event_add_fileselect(C, op);
74
75         return OPERATOR_RUNNING_MODAL;
76 }
77
78 /* function used for WM_OT_save_mainfile too */
79 static int wm_collada_export_exec(bContext *C, wmOperator *op)
80 {
81         char filepath[FILE_MAX];
82         int apply_modifiers;
83         int export_mesh_type;
84         int selected;
85         int include_children;
86         int include_armatures;
87         int include_shapekeys;
88         int deform_bones_only;
89         int sampling_rate;
90
91         int export_texture_type;
92         int use_texture_copies;
93         int active_uv_only;
94
95         int triangulate;
96         int use_object_instantiation;
97         int use_blender_profile;
98         int sort_by_name;
99         int export_transformation_type;
100
101         int open_sim;
102         int limit_precision;
103         int keep_bind_info;
104
105         int export_count;
106
107         if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
108                 BKE_report(op->reports, RPT_ERROR, "No filename given");
109                 return OPERATOR_CANCELLED;
110         }
111
112         RNA_string_get(op->ptr, "filepath", filepath);
113         BLI_ensure_extension(filepath, sizeof(filepath), ".dae");
114
115
116         /* Avoid File write exceptions in Collada */
117         if (!BLI_exists(filepath)) {
118                 BLI_make_existing_file(filepath);
119                 if (!BLI_file_touch(filepath)) {
120                         BKE_report(op->reports, RPT_ERROR, "Can't create export file");
121                         fprintf(stdout, "Collada export: Can not create: %s\n", filepath);
122                         return OPERATOR_CANCELLED;
123                 }
124         }
125         else if (!BLI_file_is_writable(filepath)) {
126                 BKE_report(op->reports, RPT_ERROR, "Can't overwrite export file");
127                 fprintf(stdout, "Collada export: Can not modify: %s\n", filepath);
128                 return OPERATOR_CANCELLED;
129         }
130
131         /* Now the exporter can create and write the export file */
132
133         /* Options panel */
134         apply_modifiers          = RNA_boolean_get(op->ptr, "apply_modifiers");
135         export_mesh_type         = RNA_enum_get(op->ptr,    "export_mesh_type_selection");
136         selected                 = RNA_boolean_get(op->ptr, "selected");
137         include_children         = RNA_boolean_get(op->ptr, "include_children");
138         include_armatures        = RNA_boolean_get(op->ptr, "include_armatures");
139         include_shapekeys        = RNA_boolean_get(op->ptr, "include_shapekeys");
140         sampling_rate             = RNA_int_get(op->ptr,     "sampling_rate");
141         deform_bones_only        = RNA_boolean_get(op->ptr, "deform_bones_only");
142
143         export_texture_type      = RNA_enum_get(op->ptr, "export_texture_type_selection");
144         use_texture_copies       = RNA_boolean_get(op->ptr, "use_texture_copies");
145         active_uv_only           = RNA_boolean_get(op->ptr, "active_uv_only");
146
147         triangulate                = RNA_boolean_get(op->ptr, "triangulate");
148         use_object_instantiation   = RNA_boolean_get(op->ptr, "use_object_instantiation");
149         use_blender_profile        = RNA_boolean_get(op->ptr, "use_blender_profile");
150         sort_by_name               = RNA_boolean_get(op->ptr, "sort_by_name");
151         export_transformation_type = RNA_enum_get(op->ptr,    "export_transformation_type_selection");
152         open_sim                   = RNA_boolean_get(op->ptr, "open_sim");
153
154         limit_precision = RNA_boolean_get(op->ptr, "limit_precision");
155         keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info");
156
157         /* get editmode results */
158         ED_object_editmode_load(CTX_data_edit_object(C));
159
160
161         export_count = collada_export(CTX_data_scene(C),
162                 filepath,
163                 apply_modifiers,
164                 export_mesh_type,
165                 selected,
166                 include_children,
167                 include_armatures,
168                 include_shapekeys,
169                 deform_bones_only,
170                 sampling_rate,
171
172                 active_uv_only,
173                 export_texture_type,
174                 use_texture_copies,
175
176                 triangulate,
177                 use_object_instantiation,
178                 use_blender_profile,
179                 sort_by_name,
180                 export_transformation_type,
181
182                 open_sim,
183                 limit_precision,
184                 keep_bind_info
185         );
186
187         if (export_count == 0) {
188                 BKE_report(op->reports, RPT_WARNING, "No objects selected -- Created empty export file");
189                 return OPERATOR_CANCELLED;
190         }
191         else if (export_count < 0) {
192                 BKE_report(op->reports, RPT_WARNING, "Error during export (see Console)");
193                 return OPERATOR_CANCELLED;
194         }
195         else {
196                 char buff[100];
197                 sprintf(buff, "Exported %d Objects", export_count);
198                 BKE_report(op->reports, RPT_INFO, buff);
199                 return OPERATOR_FINISHED;
200         }
201 }
202
203 static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
204 {
205         uiLayout *box, *row, *col, *split;
206
207         /* Export Options: */
208         box = uiLayoutBox(layout);
209         row = uiLayoutRow(box, false);
210         uiItemL(row, IFACE_("Export Data Options:"), ICON_MESH_DATA);
211
212         row = uiLayoutRow(box, false);
213         split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
214         col   = uiLayoutColumn(split, false);
215         uiItemR(col, imfptr, "apply_modifiers", 0, NULL, ICON_NONE);
216         col   = uiLayoutColumn(split, false);
217         uiItemR(col, imfptr, "export_mesh_type_selection", 0, "", ICON_NONE);
218         uiLayoutSetEnabled(col, RNA_boolean_get(imfptr, "apply_modifiers"));
219
220         row = uiLayoutRow(box, false);
221         uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE);
222
223         row = uiLayoutRow(box, false);
224         uiItemR(row, imfptr, "include_children", 0, NULL, ICON_NONE);
225         uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
226
227         row = uiLayoutRow(box, false);
228         uiItemR(row, imfptr, "include_armatures", 0, NULL, ICON_NONE);
229         uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
230
231         row = uiLayoutRow(box, false);
232         uiItemR(row, imfptr, "include_shapekeys", 0, NULL, ICON_NONE);
233         uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
234
235         row = uiLayoutRow(box, false);
236         uiItemR(row, imfptr, "sampling_rate", 0, NULL, ICON_NONE);
237
238         
239         /* Texture options */
240         box = uiLayoutBox(layout);
241         row = uiLayoutRow(box, false);
242         uiItemL(row, IFACE_("Texture Options:"), ICON_TEXTURE_DATA);
243
244         row = uiLayoutRow(box, false);
245         uiItemR(row, imfptr, "active_uv_only", 0, NULL, ICON_NONE);
246
247         row = uiLayoutRow(box, false);
248         uiItemR(row, imfptr, "export_texture_type_selection", 0, "", ICON_NONE);
249
250         row = uiLayoutRow(box, false);
251         uiItemR(row, imfptr, "use_texture_copies", 1, NULL, ICON_NONE);
252
253
254         /* Armature options */
255         box = uiLayoutBox(layout);
256         row = uiLayoutRow(box, false);
257         uiItemL(row, IFACE_("Armature Options:"), ICON_ARMATURE_DATA);
258
259         row = uiLayoutRow(box, false);
260         uiItemR(row, imfptr, "deform_bones_only", 0, NULL, ICON_NONE);
261
262         row = uiLayoutRow(box, false);
263         uiItemR(row, imfptr, "open_sim", 0, NULL, ICON_NONE);
264
265         /* Collada options: */
266         box = uiLayoutBox(layout);
267         row = uiLayoutRow(box, false);
268         uiItemL(row, IFACE_("Collada Options:"), ICON_MODIFIER);
269
270         row = uiLayoutRow(box, false);
271         uiItemR(row, imfptr, "triangulate", 1, NULL, ICON_NONE);
272         row = uiLayoutRow(box, false);
273         uiItemR(row, imfptr, "use_object_instantiation", 1, NULL, ICON_NONE);
274         row = uiLayoutRow(box, false);
275         uiItemR(row, imfptr, "use_blender_profile", 1, NULL, ICON_NONE);
276
277         row = uiLayoutRow(box, false);
278         split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
279         uiItemL(split, IFACE_("Transformation Type"), ICON_NONE);
280         uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE);
281
282         row = uiLayoutRow(box, false);
283         uiItemR(row, imfptr, "sort_by_name", 0, NULL, ICON_NONE);
284
285         row = uiLayoutRow(box, false);
286         uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE);
287
288         row = uiLayoutRow(box, false);
289         uiItemR(row, imfptr, "limit_precision", 0, NULL, ICON_NONE);
290
291 }
292
293 static void wm_collada_export_draw(bContext *UNUSED(C), wmOperator *op)
294 {
295         PointerRNA ptr;
296
297         RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
298         uiCollada_exportSettings(op->layout, &ptr);
299 }
300
301 static bool wm_collada_export_check(bContext *UNUSED(C), wmOperator *op)
302 {
303         char filepath[FILE_MAX];
304         RNA_string_get(op->ptr, "filepath", filepath);
305
306         if (!BLI_testextensie(filepath, ".dae")) {
307                 BLI_ensure_extension(filepath, FILE_MAX, ".dae");
308                 RNA_string_set(op->ptr, "filepath", filepath);
309                 return true;
310         }
311
312         return false;
313 }
314
315 void WM_OT_collada_export(wmOperatorType *ot)
316 {
317         struct StructRNA *func = ot->srna;
318
319         static const EnumPropertyItem prop_bc_export_mesh_type[] = {
320                 {BC_MESH_TYPE_VIEW, "view", 0, "View", "Apply modifier's view settings"},
321                 {BC_MESH_TYPE_RENDER, "render", 0, "Render", "Apply modifier's render settings"},
322                 {0, NULL, 0, NULL, NULL}
323         };
324
325         static const EnumPropertyItem prop_bc_export_transformation_type[] = {
326                 { BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations" },
327                 { BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations" },
328                 { 0, NULL, 0, NULL, NULL }
329         };
330
331         static const EnumPropertyItem prop_bc_export_texture_type[] = {
332                 { BC_TEXTURE_TYPE_MAT, "mat", 0, "Materials", "Export Materials" },
333                 { BC_TEXTURE_TYPE_UV, "uv", 0, "UV Textures", "Export UV Textures (Face textures) as materials" },
334                 { 0, NULL, 0, NULL, NULL }
335         };
336
337         ot->name = "Export COLLADA";
338         ot->description = "Save a Collada file";
339         ot->idname = "WM_OT_collada_export";
340
341         ot->invoke = wm_collada_export_invoke;
342         ot->exec = wm_collada_export_exec;
343         ot->poll = WM_operator_winactive;
344         ot->check = wm_collada_export_check;
345
346         ot->flag |= OPTYPE_PRESET;
347
348         ot->ui = wm_collada_export_draw;
349
350         WM_operator_properties_filesel(
351                 ot, FILE_TYPE_FOLDER | FILE_TYPE_COLLADA, FILE_BLENDER, FILE_SAVE,
352                 WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
353
354         RNA_def_boolean(func,
355                         "apply_modifiers", 0, "Apply Modifiers",
356                         "Apply modifiers to exported mesh (non destructive))");
357
358         RNA_def_int(func, "export_mesh_type", 0, INT_MIN, INT_MAX,
359                     "Resolution", "Modifier resolution for export", INT_MIN, INT_MAX);
360
361         RNA_def_enum(func, "export_mesh_type_selection", prop_bc_export_mesh_type, 0,
362                      "Resolution", "Modifier resolution for export");
363
364         RNA_def_boolean(func, "selected", 0, "Selection Only",
365                         "Export only selected elements");
366
367         RNA_def_boolean(func, "include_children", 0, "Include Children",
368                         "Export all children of selected objects (even if not selected)");
369
370         RNA_def_boolean(func, "include_armatures", 0, "Include Armatures",
371                         "Export related armatures (even if not selected)");
372
373         RNA_def_boolean(func, "include_shapekeys", 1, "Include Shape Keys",
374                         "Export all Shape Keys from Mesh Objects");
375
376         RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only",
377                         "Only export deforming bones with armatures");
378
379         RNA_def_int(func, "sampling_rate", 0, -1, INT_MAX,
380                 "Samplintg Rate", "The maximum distance of frames between 2 keyframes. Disabled when value is -1", -1, INT_MAX);
381
382         RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map",
383                         "Export only the selected UV Map");
384
385         RNA_def_boolean(func, "use_texture_copies", 1, "Copy",
386                         "Copy textures to same folder where the .dae file is exported");
387
388
389         RNA_def_boolean(func, "triangulate", 1, "Triangulate",
390                         "Export Polygons (Quads & NGons) as Triangles");
391
392         RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances",
393                 "Instantiate multiple Objects from same Data");
394
395         RNA_def_boolean(func, "use_blender_profile", 1, "Use Blender Profile",
396                 "Export additional Blender specific information (for material, shaders, bones, etc.)");
397
398         RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name",
399                         "Sort exported data by Object name");
400
401
402         RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX,
403                 "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
404
405         RNA_def_enum(func, "export_transformation_type_selection", prop_bc_export_transformation_type, 0,
406                 "Transform", "Transformation type for translation, scale and rotation");
407
408
409         RNA_def_int(func, "export_texture_type", 0, INT_MIN, INT_MAX,
410                 "Texture Type", "Type for exported Textures (UV or MAT)", INT_MIN, INT_MAX);
411
412         RNA_def_enum(func, "export_texture_type_selection", prop_bc_export_texture_type, 0,
413                 "Texture Type", "Type for exported Textures (UV or MAT)");
414
415
416         RNA_def_boolean(func, "open_sim", 0, "Export to SL/OpenSim",
417                         "Compatibility mode for SL, OpenSim and other compatible online worlds");
418
419         RNA_def_boolean(func, "limit_precision", 0,
420                 "Limit Precision", "Reduce the precision of the exported data to 6 digits");
421
422         RNA_def_boolean(func, "keep_bind_info", 0,
423                 "Keep Bind Info", "Store Bindpose information in custom bone properties for later use during Collada export");
424
425 }
426
427
428 /* function used for WM_OT_save_mainfile too */
429 static int wm_collada_import_exec(bContext *C, wmOperator *op)
430 {
431         char filename[FILE_MAX];
432         int import_units;
433         int find_chains;
434         int auto_connect;
435         int fix_orientation;
436         int min_chain_length;
437
438         int keep_bind_info;
439
440         if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
441                 BKE_report(op->reports, RPT_ERROR, "No filename given");
442                 return OPERATOR_CANCELLED;
443         }
444
445         /* Options panel */
446         import_units     = RNA_boolean_get(op->ptr, "import_units");
447         find_chains      = RNA_boolean_get(op->ptr, "find_chains");
448         auto_connect     = RNA_boolean_get(op->ptr, "auto_connect");
449         fix_orientation  = RNA_boolean_get(op->ptr, "fix_orientation");
450
451         keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info");
452
453         min_chain_length = RNA_int_get(op->ptr, "min_chain_length");
454
455         RNA_string_get(op->ptr, "filepath", filename);
456         if (collada_import(
457                 C, filename,
458                 import_units,
459                 find_chains,
460                 auto_connect,
461                 fix_orientation,
462                 min_chain_length,
463                 keep_bind_info) )
464         {
465                 return OPERATOR_FINISHED;
466         }
467         else {
468                 BKE_report(op->reports, RPT_ERROR, "Errors found during parsing COLLADA document (see console for details)");
469                 return OPERATOR_CANCELLED;
470         }
471 }
472
473 static void uiCollada_importSettings(uiLayout *layout, PointerRNA *imfptr)
474 {
475         uiLayout *box, *row;
476
477         /* Import Options: */
478         box = uiLayoutBox(layout);
479         row = uiLayoutRow(box, false);
480         uiItemL(row, IFACE_("Import Data Options:"), ICON_MESH_DATA);
481
482         row = uiLayoutRow(box, false);
483         uiItemR(row, imfptr, "import_units", 0, NULL, ICON_NONE);
484
485         box = uiLayoutBox(layout);
486         row = uiLayoutRow(box, false);
487         uiItemL(row, IFACE_("Armature Options:"), ICON_MESH_DATA);
488
489         row = uiLayoutRow(box, false);
490         uiItemR(row, imfptr, "fix_orientation", 0, NULL, ICON_NONE);
491
492         row = uiLayoutRow(box, false);
493         uiItemR(row, imfptr, "find_chains", 0, NULL, ICON_NONE);
494
495         row = uiLayoutRow(box, false);
496         uiItemR(row, imfptr, "auto_connect", 0, NULL, ICON_NONE);
497
498         row = uiLayoutRow(box, false);
499         uiItemR(row, imfptr, "min_chain_length", 0, NULL, ICON_NONE);
500
501         box = uiLayoutBox(layout);
502         row = uiLayoutRow(box, false);
503
504         row = uiLayoutRow(box, false);
505         uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE);
506
507 }
508
509 static void wm_collada_import_draw(bContext *UNUSED(C), wmOperator *op)
510 {
511         PointerRNA ptr;
512
513         RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
514         uiCollada_importSettings(op->layout, &ptr);
515 }
516
517 void WM_OT_collada_import(wmOperatorType *ot)
518 {
519         ot->name = "Import COLLADA";
520         ot->description = "Load a Collada file";
521         ot->idname = "WM_OT_collada_import";
522
523         ot->invoke = WM_operator_filesel;
524         ot->exec = wm_collada_import_exec;
525         ot->poll = WM_operator_winactive;
526
527         //ot->flag |= OPTYPE_PRESET;
528
529         ot->ui = wm_collada_import_draw;
530
531         WM_operator_properties_filesel(
532                 ot, FILE_TYPE_FOLDER | FILE_TYPE_COLLADA, FILE_BLENDER, FILE_OPENFILE,
533                 WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
534
535         RNA_def_boolean(ot->srna,
536                 "import_units", 0, "Import Units",
537                 "If disabled match import to Blender's current Unit settings, "
538                 "otherwise use the settings from the Imported scene");
539
540         RNA_def_boolean(ot->srna,
541                 "fix_orientation", 0, "Fix Leaf Bones",
542                 "Fix Orientation of Leaf Bones (Collada does only support Joints)");
543
544         RNA_def_boolean(ot->srna,
545                 "find_chains", 0, "Find Bone Chains",
546                 "Find best matching Bone Chains and ensure bones in chain are connected");
547
548         RNA_def_boolean(ot->srna,
549                 "auto_connect", 0, "Auto Connect",
550                 "Set use_connect for parent bones which have exactly one child bone");
551
552         RNA_def_int(ot->srna,
553                 "min_chain_length",
554                 0,
555                 0,
556                 INT_MAX,
557                 "Minimum Chain Length",
558                 "When searching Bone Chains disregard chains of length below this value",
559                 0,
560                 INT_MAX);
561
562         RNA_def_boolean(ot->srna, 
563                 "keep_bind_info", 0, "Keep Bind Info", 
564                 "Store Bindpose information in custom bone properties for later use during Collada export");
565
566 }
567 #endif