Merge branch 'master' into blender2.8
[blender.git] / source / blender / collada / collada_utils.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/collada_utils.cpp
24  *  \ingroup collada
25  */
26
27
28 /* COLLADABU_ASSERT, may be able to remove later */
29 #include "COLLADABUPlatform.h"
30
31 #include "COLLADAFWGeometry.h"
32 #include "COLLADAFWMeshPrimitive.h"
33 #include "COLLADAFWMeshVertexData.h"
34
35 #include <set>
36
37 extern "C" {
38 #include "DNA_modifier_types.h"
39 #include "DNA_customdata_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_mesh_types.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_armature_types.h"
44
45 #include "BLI_math.h"
46 #include "BLI_linklist.h"
47
48 #include "BKE_context.h"
49 #include "BKE_customdata.h"
50 #include "BKE_object.h"
51 #include "BKE_global.h"
52 #include "BKE_layer.h"
53 #include "BKE_mesh.h"
54 #include "BKE_scene.h"
55 #include "BKE_DerivedMesh.h"
56 #include "BKE_main.h"
57
58 #include "ED_armature.h"
59
60 #include "WM_api.h" // XXX hrm, see if we can do without this
61 #include "WM_types.h"
62
63 #include "bmesh.h"
64 #include "bmesh_tools.h"
65 }
66
67 #include "DEG_depsgraph.h"
68 #include "DEG_depsgraph_query.h"
69
70 #include "collada_utils.h"
71 #include "ExportSettings.h"
72
73 float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index)
74 {
75         if (index >= array.getValuesCount())
76                 return 0.0f;
77
78         if (array.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT)
79                 return array.getFloatValues()->getData()[index];
80         else
81                 return array.getDoubleValues()->getData()[index];
82 }
83
84 // copied from /editors/object/object_relations.c
85 int bc_test_parent_loop(Object *par, Object *ob)
86 {
87         /* test if 'ob' is a parent somewhere in par's parents */
88
89         if (par == NULL) return 0;
90         if (ob == par) return 1;
91
92         return bc_test_parent_loop(par->parent, ob);
93 }
94
95 // a shortened version of parent_set_exec()
96 // if is_parent_space is true then ob->obmat will be multiplied by par->obmat before parenting
97 int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
98 {
99         Object workob;
100         Depsgraph *depsgraph = CTX_data_depsgraph(C);
101         Scene *sce = CTX_data_scene(C);
102
103         if (!par || bc_test_parent_loop(par, ob))
104                 return false;
105
106         ob->parent = par;
107         ob->partype = PAROBJECT;
108
109         ob->parsubstr[0] = 0;
110
111         if (is_parent_space) {
112                 float mat[4][4];
113                 // calc par->obmat
114                 BKE_object_where_is_calc(depsgraph, sce, par);
115
116                 // move child obmat into world space
117                 mul_m4_m4m4(mat, par->obmat, ob->obmat);
118                 copy_m4_m4(ob->obmat, mat);
119         }
120
121         // apply child obmat (i.e. decompose it into rot/loc/size)
122         BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
123
124         // compute parentinv
125         BKE_object_workob_calc_parent(depsgraph, sce, ob, &workob);
126         invert_m4_m4(ob->parentinv, workob.obmat);
127
128         DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
129         DEG_id_tag_update(&par->id, OB_RECALC_OB);
130
131         /** done once after import */
132 #if 0
133         DEG_relations_tag_update(bmain);
134         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
135 #endif
136
137         return true;
138 }
139
140 Scene *bc_get_scene(bContext *C)
141 {
142         return CTX_data_scene(C);
143 }
144
145 void bc_update_scene(Main *bmain, Depsgraph *depsgraph, Scene *scene, float ctime)
146 {
147         BKE_scene_frame_set(scene, ctime);
148         BKE_scene_graph_update_for_newframe(depsgraph, bmain);
149 }
150
151 Object *bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name)
152 {
153         Object *ob = BKE_object_add_only_object(bmain, type, name);
154
155         ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
156         ob->lay = scene->lay;
157         DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
158
159         LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
160         BKE_collection_object_add(G.main, layer_collection->collection, ob);
161
162         Base *base = BKE_view_layer_base_find(view_layer, ob);
163         BKE_view_layer_base_select(view_layer, base);
164
165         return ob;
166 }
167
168 Mesh *bc_get_mesh_copy(
169         Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate)
170 {
171         Mesh *tmpmesh;
172         CustomDataMask mask = CD_MASK_MESH;
173         Mesh *mesh = (Mesh *)ob->data;
174         DerivedMesh *dm = NULL;
175         if (apply_modifiers) {
176                 switch (export_mesh_type) {
177                         case BC_MESH_TYPE_VIEW:
178                         {
179                                 dm = mesh_create_derived_view(depsgraph, scene, ob, mask);
180                                 break;
181                         }
182                         case BC_MESH_TYPE_RENDER:
183                         {
184                                 dm = mesh_create_derived_render(depsgraph, scene, ob, mask);
185                                 break;
186                         }
187                 }
188         }
189         else {
190                 dm = mesh_create_derived((Mesh *)ob->data, NULL);
191         }
192
193         tmpmesh = BKE_mesh_add(bmain, "ColladaMesh"); // name is not important here
194         DM_to_mesh(dm, tmpmesh, ob, CD_MASK_MESH, true);
195         tmpmesh->flag = mesh->flag;
196
197         if (triangulate) {
198                 bc_triangulate_mesh(tmpmesh);
199         }
200         BKE_mesh_tessface_ensure(tmpmesh);
201         return tmpmesh;
202 }
203
204 Object *bc_get_assigned_armature(Object *ob)
205 {
206         Object *ob_arm = NULL;
207
208         if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) {
209                 ob_arm = ob->parent;
210         }
211         else {
212                 ModifierData *mod;
213                 for (mod = (ModifierData *)ob->modifiers.first; mod; mod = mod->next) {
214                         if (mod->type == eModifierType_Armature) {
215                                 ob_arm = ((ArmatureModifierData *)mod)->object;
216                         }
217                 }
218         }
219
220         return ob_arm;
221 }
222
223 // Returns the highest selected ancestor
224 // returns NULL if no ancestor is selected
225 // IMPORTANT: This function expects that
226 // all exported objects have set:
227 // ob->id.tag & LIB_TAG_DOIT
228 Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob)
229 {
230         Object *ancestor = ob;
231         while (ob->parent && bc_is_marked(ob->parent)) {
232                 ob = ob->parent;
233                 ancestor = ob;
234         }
235         return ancestor;
236 }
237
238
239 bool bc_is_base_node(LinkNode *export_set, Object *ob)
240 {
241         Object *root = bc_get_highest_selected_ancestor_or_self(export_set, ob);
242         return (root == ob);
243 }
244
245 bool bc_is_in_Export_set(LinkNode *export_set, Object *ob)
246 {
247         return (BLI_linklist_index(export_set, ob) != -1);
248 }
249
250 bool bc_has_object_type(LinkNode *export_set, short obtype)
251 {
252         LinkNode *node;
253
254         for (node = export_set; node; node = node->next) {
255                 Object *ob = (Object *)node->link;
256                 /* XXX - why is this checking for ob->data? - we could be looking for empties */
257                 if (ob->type == obtype && ob->data) {
258                         return true;
259                 }
260         }
261         return false;
262 }
263
264 int bc_is_marked(Object *ob)
265 {
266         return ob && (ob->id.tag & LIB_TAG_DOIT);
267 }
268
269 void bc_remove_mark(Object *ob)
270 {
271         ob->id.tag &= ~LIB_TAG_DOIT;
272 }
273
274 void bc_set_mark(Object *ob)
275 {
276         ob->id.tag |= LIB_TAG_DOIT;
277 }
278
279 // Use bubble sort algorithm for sorting the export set
280 void bc_bubble_sort_by_Object_name(LinkNode *export_set)
281 {
282         bool sorted = false;
283         LinkNode *node;
284         for (node = export_set; node->next && !sorted; node = node->next) {
285
286                 sorted = true;
287
288                 LinkNode *current;
289                 for (current = export_set; current->next; current = current->next) {
290                         Object *a = (Object *)current->link;
291                         Object *b = (Object *)current->next->link;
292
293                         if (strcmp(a->id.name, b->id.name) > 0) {
294                                 current->link       = b;
295                                 current->next->link = a;
296                                 sorted = false;
297                         }
298
299                 }
300         }
301 }
302
303 /* Check if a bone is the top most exportable bone in the bone hierarchy.
304  * When deform_bones_only == false, then only bones with NO parent
305  * can be root bones. Otherwise the top most deform bones in the hierarchy
306  * are root bones.
307  */
308 bool bc_is_root_bone(Bone *aBone, bool deform_bones_only)
309 {
310         if (deform_bones_only) {
311                 Bone *root = NULL;
312                 Bone *bone = aBone;
313                 while (bone) {
314                         if (!(bone->flag & BONE_NO_DEFORM))
315                                 root = bone;
316                         bone = bone->parent;
317                 }
318                 return (aBone == root);
319         }
320         else
321                 return !(aBone->parent);
322 }
323
324 int bc_get_active_UVLayer(Object *ob)
325 {
326         Mesh *me = (Mesh *)ob->data;
327         return CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
328 }
329
330 std::string bc_url_encode(std::string data)
331 {
332         /* XXX We probably do not need to do a full encoding.
333          * But in case that is necessary,then it can be added here.
334          */
335         return bc_replace_string(data,"#", "%23");
336 }
337
338 std::string bc_replace_string(std::string data, const std::string& pattern,
339                               const std::string& replacement)
340 {
341         size_t pos = 0;
342         while ((pos = data.find(pattern, pos)) != std::string::npos) {
343                 data.replace(pos, pattern.length(), replacement);
344                 pos += replacement.length();
345         }
346         return data;
347 }
348
349 /**
350  * Calculate a rescale factor such that the imported scene's scale
351  * is preserved. I.e. 1 meter in the import will also be
352  * 1 meter in the current scene.
353  */
354
355 void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene)
356 {
357         if (scale_to_scene) {
358                 mul_m4_m4m4(ob->obmat, bc_unit.get_scale(), ob->obmat);
359         }
360         mul_m4_m4m4(ob->obmat, bc_unit.get_rotation(), ob->obmat);
361         BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
362 }
363
364 void bc_match_scale(std::vector<Object *> *objects_done,
365                         UnitConverter &bc_unit,
366                         bool scale_to_scene)
367 {
368         for (std::vector<Object *>::iterator it = objects_done->begin();
369                         it != objects_done->end();
370                         ++it)
371         {
372                 Object *ob = *it;
373                 if (ob -> parent == NULL) {
374                         bc_match_scale(*it, bc_unit, scale_to_scene);
375                 }
376         }
377 }
378
379 /*
380     Convenience function to get only the needed components of a matrix
381 */
382 void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
383 {
384         if (size) {
385                 mat4_to_size(size, mat);
386         }
387
388         if (eul) {
389                 mat4_to_eul(eul, mat);
390         }
391
392         if (quat) {
393                 mat4_to_quat(quat, mat);
394         }
395
396         if (loc) {
397                 copy_v3_v3(loc, mat[3]);
398         }
399 }
400
401 /*
402 * Create rotation_quaternion from a delta rotation and a reference quat
403 *
404 * Input:
405 * mat_from: The rotation matrix before rotation
406 * mat_to  : The rotation matrix after rotation
407 * qref    : the quat corresponding to mat_from
408 *
409 * Output:
410 * rot     : the calculated result (quaternion)
411 *
412 */
413 void bc_rotate_from_reference_quat(float quat_to[4], float quat_from[4], float mat_to[4][4])
414 {
415         float qd[4];
416         float matd[4][4];
417         float mati[4][4];
418         float mat_from[4][4];
419         quat_to_mat4(mat_from, quat_from);
420
421         // Calculate the difference matrix matd between mat_from and mat_to
422         invert_m4_m4(mati, mat_from);
423         mul_m4_m4m4(matd, mati, mat_to);
424
425         mat4_to_quat(qd, matd);
426
427         mul_qt_qtqt(quat_to, qd, quat_from); // rot is the final rotation corresponding to mat_to
428 }
429
430 void bc_triangulate_mesh(Mesh *me)
431 {
432         bool use_beauty  = false;
433         bool tag_only    = false;
434         int  quad_method = MOD_TRIANGULATE_QUAD_SHORTEDGE; /* XXX: The triangulation method selection could be offered in the UI */
435
436         const struct BMeshCreateParams bm_create_params = {0};
437         BMesh *bm = BM_mesh_create(
438                 &bm_mesh_allocsize_default,
439                 &bm_create_params);
440         BMeshFromMeshParams bm_from_me_params = {0};
441         bm_from_me_params.calc_face_normal = true;
442         BM_mesh_bm_from_me(bm, me, &bm_from_me_params);
443         BM_mesh_triangulate(bm, quad_method, use_beauty, tag_only, NULL, NULL, NULL);
444
445         BMeshToMeshParams bm_to_me_params = {0};
446         bm_to_me_params.calc_object_remap = false;
447         BM_mesh_bm_to_me(NULL, bm, me, &bm_to_me_params);
448         BM_mesh_free(bm);
449 }
450
451 /*
452  * A bone is a leaf when it has no children or all children are not connected.
453  */
454 bool bc_is_leaf_bone(Bone *bone)
455 {
456         for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
457                 if (child->flag & BONE_CONNECTED)
458                         return false;
459         }
460         return true;
461 }
462
463 EditBone *bc_get_edit_bone(bArmature * armature, char *name) {
464         EditBone  *eBone;
465
466         for (eBone = (EditBone *)armature->edbo->first; eBone; eBone = eBone->next) {
467                 if (STREQ(name, eBone->name))
468                         return eBone;
469         }
470
471         return NULL;
472
473 }
474 int bc_set_layer(int bitfield, int layer)
475 {
476         return bc_set_layer(bitfield, layer, true); /* enable */
477 }
478
479 int bc_set_layer(int bitfield, int layer, bool enable)
480 {
481         int bit = 1u << layer;
482
483         if (enable)
484                 bitfield |= bit;
485         else
486                 bitfield &= ~bit;
487
488         return bitfield;
489 }
490
491 /*
492  | This method creates a new extension map when needed.
493  | Note: The ~BoneExtensionManager destructor takes care
494  | to delete the created maps when the manager is removed.
495 */
496 BoneExtensionMap &BoneExtensionManager::getExtensionMap(bArmature *armature)
497 {
498         std::string key = armature->id.name;
499         BoneExtensionMap *result = extended_bone_maps[key];
500         if (result == NULL)
501         {
502                 result = new BoneExtensionMap();
503                 extended_bone_maps[key] = result;
504         }
505         return *result;
506 }
507
508 BoneExtensionManager::~BoneExtensionManager()
509 {
510         std::map<std::string, BoneExtensionMap *>::iterator map_it;
511         for (map_it = extended_bone_maps.begin(); map_it != extended_bone_maps.end(); ++map_it)
512         {
513                 BoneExtensionMap *extended_bones = map_it->second;
514                 for (BoneExtensionMap::iterator ext_it = extended_bones->begin(); ext_it != extended_bones->end(); ++ext_it) {
515                         if (ext_it->second != NULL)
516                                 delete ext_it->second;
517                 }
518                 extended_bones->clear();
519                 delete extended_bones;
520         }
521 }
522
523 /**
524  * BoneExtended is a helper class needed for the Bone chain finder
525  * See ArmatureImporter::fix_leaf_bones()
526  * and ArmatureImporter::connect_bone_chains()
527  */
528
529 BoneExtended::BoneExtended(EditBone *aBone)
530 {
531         this->set_name(aBone->name);
532         this->chain_length = 0;
533         this->is_leaf = false;
534         this->tail[0] = 0.0f;
535         this->tail[1] = 0.5f;
536         this->tail[2] = 0.0f;
537         this->use_connect = -1;
538         this->roll = 0;
539         this->bone_layers = 0;
540
541         this->has_custom_tail = false;
542         this->has_custom_roll = false;
543 }
544
545 char *BoneExtended::get_name()
546 {
547         return name;
548 }
549
550 void BoneExtended::set_name(char *aName)
551 {
552         BLI_strncpy(name, aName, MAXBONENAME);
553 }
554
555 int BoneExtended::get_chain_length()
556 {
557         return chain_length;
558 }
559
560 void BoneExtended::set_chain_length(const int aLength)
561 {
562         chain_length = aLength;
563 }
564
565 void BoneExtended::set_leaf_bone(bool state)
566 {
567         is_leaf = state;
568 }
569
570 bool BoneExtended::is_leaf_bone()
571 {
572         return is_leaf;
573 }
574
575 void BoneExtended::set_roll(float roll)
576 {
577         this->roll = roll;
578         this->has_custom_roll = true;
579 }
580
581 bool BoneExtended::has_roll()
582 {
583         return this->has_custom_roll;
584 }
585
586 float BoneExtended::get_roll()
587 {
588         return this->roll;
589 }
590
591 void BoneExtended::set_tail(float vec[])
592 {
593         this->tail[0] = vec[0];
594         this->tail[1] = vec[1];
595         this->tail[2] = vec[2];
596         this->has_custom_tail = true;
597 }
598
599 bool BoneExtended::has_tail()
600 {
601         return this->has_custom_tail;
602 }
603
604 float *BoneExtended::get_tail()
605 {
606         return this->tail;
607 }
608
609 inline bool isInteger(const std::string & s)
610 {
611         if (s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false;
612
613         char * p;
614         strtol(s.c_str(), &p, 10);
615
616         return (*p == 0);
617 }
618
619 void BoneExtended::set_bone_layers(std::string layerString, std::vector<std::string> &layer_labels)
620 {
621         std::stringstream ss(layerString);
622         std::string layer;
623         int pos;
624
625         while (ss >> layer) {
626
627                 /* Blender uses numbers to specify layers*/
628                 if (isInteger(layer))
629                 {
630                         pos = atoi(layer.c_str());
631                         if (pos >= 0 && pos < 32) {
632                                 this->bone_layers = bc_set_layer(this->bone_layers, pos);
633                                 continue;
634                         }
635                 }
636
637                 /* layer uses labels (not supported by blender). Map to layer numbers:*/
638                 pos = find(layer_labels.begin(), layer_labels.end(), layer) - layer_labels.begin();
639                 if (pos >= layer_labels.size()) {
640                         layer_labels.push_back(layer); /* remember layer number for future usage*/
641                 }
642
643                 if (pos > 31)
644                 {
645                         fprintf(stderr, "Too many layers in Import. Layer %s mapped to Blender layer 31\n", layer.c_str());
646                         pos = 31;
647                 }
648
649                 /* If numeric layers and labeled layers are used in parallel (unlikely),
650                  * we get a potential mixup. Just leave as is for now.
651                  */
652                 this->bone_layers = bc_set_layer(this->bone_layers, pos);
653
654         }
655 }
656
657 std::string BoneExtended::get_bone_layers(int bitfield)
658 {
659         std::string result = "";
660         std::string sep = "";
661         int bit = 1u;
662
663         std::ostringstream ss;
664         for (int i = 0; i < 32; i++)
665         {
666                 if (bit & bitfield)
667                 {
668                         ss << sep << i;
669                         sep = " ";
670                 }
671                 bit = bit << 1;
672         }
673         return ss.str();
674 }
675
676 int BoneExtended::get_bone_layers()
677 {
678         return (bone_layers == 0) ? 1 : bone_layers; // ensure that the bone is in at least one bone layer!
679 }
680
681
682 void BoneExtended::set_use_connect(int use_connect)
683 {
684         this->use_connect = use_connect;
685 }
686
687 int BoneExtended::get_use_connect()
688 {
689         return this->use_connect;
690 }
691
692 /**
693 * Stores a 4*4 matrix as a custom bone property array of size 16
694 */
695 void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4])
696 {
697         IDProperty *idgroup = (IDProperty *)ebone->prop;
698         if (idgroup == NULL)
699         {
700                 IDPropertyTemplate val = { 0 };
701                 idgroup = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
702                 ebone->prop = idgroup;
703         }
704
705         IDPropertyTemplate val = { 0 };
706         val.array.len = 16;
707         val.array.type = IDP_FLOAT;
708
709         IDProperty *data = IDP_New(IDP_ARRAY, &val, key);
710         float *array = (float *)IDP_Array(data);
711         for (int i = 0; i < 4; i++)
712                 for (int j = 0; j < 4; j++)
713                         array[4 * i + j] = mat[i][j];
714
715         IDP_AddToGroup(idgroup, data);
716 }
717
718 #if 0
719 /**
720 * Stores a Float value as a custom bone property
721 *
722 * Note: This function is currently not needed. Keep for future usage
723 */
724 static void bc_set_IDProperty(EditBone *ebone, const char *key, float value)
725 {
726         if (ebone->prop == NULL)
727         {
728                 IDPropertyTemplate val = { 0 };
729                 ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
730         }
731
732         IDProperty *pgroup = (IDProperty *)ebone->prop;
733         IDPropertyTemplate val = { 0 };
734         IDProperty *prop = IDP_New(IDP_FLOAT, &val, key);
735         IDP_Float(prop) = value;
736         IDP_AddToGroup(pgroup, prop);
737
738 }
739 #endif
740
741 /*
742 * Get a custom property when it exists.
743 * This function is also used to check if a property exists.
744 */
745 IDProperty *bc_get_IDProperty(Bone *bone, std::string key)
746 {
747         return (bone->prop == NULL) ? NULL : IDP_GetPropertyFromGroup(bone->prop, key.c_str());
748 }
749
750 /**
751 * Read a custom bone property and convert to float
752 * Return def if the property does not exist.
753 */
754 float bc_get_property(Bone *bone, std::string key, float def)
755 {
756         float result = def;
757         IDProperty *property = bc_get_IDProperty(bone, key);
758         if (property) {
759                 switch (property->type) {
760                         case IDP_INT:
761                                 result = (float)(IDP_Int(property));
762                                 break;
763                         case IDP_FLOAT:
764                                 result = (float)(IDP_Float(property));
765                                 break;
766                         case IDP_DOUBLE:
767                                 result = (float)(IDP_Double(property));
768                                 break;
769                         default:
770                                 result = def;
771                 }
772         }
773         return result;
774 }
775
776 /**
777 * Read a custom bone property and convert to matrix
778 * Return true if conversion was succesfull
779 *
780 * Return false if:
781 * - the property does not exist
782 * - is not an array of size 16
783 */
784 bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
785 {
786         IDProperty *property = bc_get_IDProperty(bone, key);
787         if (property && property->type == IDP_ARRAY && property->len == 16) {
788                 float *array = (float *)IDP_Array(property);
789                 for (int i = 0; i < 4; i++)
790                         for (int j = 0; j < 4; j++)
791                                 mat[i][j] = array[4 * i + j];
792                 return true;
793         }
794         return false;
795 }
796
797 /**
798 * get a vector that is stored in 3 custom properties (used in Blender <= 2.78)
799 */
800 void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3])
801 {
802         val[0] = bc_get_property(bone, key + "_x", def[0]);
803         val[1] = bc_get_property(bone, key + "_y", def[1]);
804         val[2] = bc_get_property(bone, key + "_z", def[2]);
805 }
806
807 /**
808 * Check if vector exist stored in 3 custom properties (used in Blender <= 2.78)
809 */
810 static bool has_custom_props(Bone *bone, bool enabled, std::string key)
811 {
812         if (!enabled)
813                 return false;
814
815         return (bc_get_IDProperty(bone, key + "_x")
816                 ||      bc_get_IDProperty(bone, key + "_y")
817                 ||      bc_get_IDProperty(bone, key + "_z"));
818
819 }
820
821 /**
822 * Check if custom information about bind matrix exists and modify the from_mat
823 * accordingly.
824 *
825 * Note: This is old style for Blender <= 2.78 only kept for compatibility
826 */
827 void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float from_mat[4][4], bool use_local_space)
828 {
829         float loc[3];
830         float rot[3];
831         float scale[3];
832         static const float V0[3] = { 0, 0, 0 };
833
834         if (!has_custom_props(bone, export_settings->keep_bind_info, "restpose_loc") &&
835                 !has_custom_props(bone, export_settings->keep_bind_info, "restpose_rot") &&
836                 !has_custom_props(bone, export_settings->keep_bind_info, "restpose_scale"))
837         {
838                 /* No need */
839                 copy_m4_m4(to_mat, from_mat);
840                 return;
841         }
842
843         bc_decompose(from_mat, loc, rot, NULL, scale);
844         loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
845
846         if (export_settings->keep_bind_info) {
847                 bc_get_property_vector(bone, "restpose_loc", loc, loc);
848
849                 if (use_local_space && bone->parent) {
850                         Bone *b = bone;
851                         while (b->parent) {
852                                 b = b->parent;
853                                 float ploc[3];
854                                 bc_get_property_vector(b, "restpose_loc", ploc, V0);
855                                 loc[0] += ploc[0];
856                                 loc[1] += ploc[1];
857                                 loc[2] += ploc[2];
858                         }
859                 }
860         }
861
862         if (export_settings->keep_bind_info) {
863                 if (bc_get_IDProperty(bone, "restpose_rot_x"))
864                     rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0));
865                 if (bc_get_IDProperty(bone, "restpose_rot_y"))
866                         rot[1] = DEG2RADF(bc_get_property(bone, "restpose_rot_y", 0));
867                 if (bc_get_IDProperty(bone, "restpose_rot_z"))
868                         rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0));
869         }
870
871         if (export_settings->keep_bind_info) {
872                 bc_get_property_vector(bone, "restpose_scale", scale, scale);
873         }
874
875         loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
876
877 }
878
879 /*
880     Make 4*4 matrices better readable
881 */
882 void bc_sanitize_mat(float mat[4][4], int precision)
883 {
884         for (int i = 0; i < 4; i++)
885                 for (int j = 0; j < 4; j++)
886                         mat[i][j] = double_round(mat[i][j], precision);
887 }
888
889 void bc_sanitize_mat(double mat[4][4], int precision)
890 {
891         for (int i = 0; i < 4; i++)
892                 for (int j = 0; j < 4; j++)
893                         mat[i][j] = double_round(mat[i][j], precision);
894 }
895
896 void bc_copy_m4_farray(float r[4][4], float *a)
897 {
898         for (int i = 0; i < 4; i++)
899                 for (int j = 0; j < 4; j++)
900                         r[i][j] = *a++;
901 }
902
903 void bc_copy_farray_m4(float *r, float a[4][4])
904 {
905         for (int i = 0; i < 4; i++)
906                 for (int j = 0; j < 4; j++)
907                         *r++ = a[i][j];
908
909 }
910
911 /*
912  * Returns name of Active UV Layer or empty String if no active UV Layer defined
913  */
914 std::string bc_get_active_uvlayer_name(Mesh *me)
915 {
916         int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
917         if (num_layers) {
918                 char *layer_name = bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE);
919                 if (layer_name) {
920                         return std::string(layer_name);
921                 }
922         }
923         return "";
924 }
925
926 /*
927 * Returns name of Active UV Layer or empty String if no active UV Layer defined.
928 * Assuming the Object is of type MESH
929 */
930 std::string bc_get_active_uvlayer_name(Object *ob)
931 {
932         Mesh *me = (Mesh *)ob->data;
933         return bc_get_active_uvlayer_name(me);
934 }
935
936 /*
937  * Returns UV Layer name or empty string if layer index is out of range
938  */
939 std::string bc_get_uvlayer_name(Mesh *me, int layer)
940 {
941         int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
942         if (num_layers && layer < num_layers) {
943                 char *layer_name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, layer);
944                 if (layer_name) {
945                         return std::string(layer_name);
946                 }
947         }
948         return "";
949 }