Depsgraph: remove EvaluationContext, pass Depsgraph instead.
[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 Main *bc_get_main()
146 {
147         return G.main;
148 }
149
150
151 void bc_update_scene(Depsgraph *depsgraph, Scene *scene, float ctime)
152 {
153         BKE_scene_frame_set(scene, ctime);
154         Main *bmain = bc_get_main();
155         BKE_scene_graph_update_for_newframe(depsgraph, bmain);
156 }
157
158 Object *bc_add_object(Scene *scene, ViewLayer *view_layer, int type, const char *name)
159 {
160         Object *ob = BKE_object_add_only_object(G.main, type, name);
161
162         ob->data = BKE_object_obdata_add_from_type(G.main, type, name);
163         ob->lay = scene->lay;
164         DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
165
166         LayerCollection *layer_collection = BKE_layer_collection_get_active_ensure(scene, view_layer);
167         BKE_collection_object_add(&scene->id, layer_collection->scene_collection, ob);
168
169         Base *base = BKE_view_layer_base_find(view_layer, ob);
170         BKE_view_layer_base_select(view_layer, base);
171
172         return ob;
173 }
174
175 Mesh *bc_get_mesh_copy(struct Depsgraph *depsgraph, Scene *scene, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate)
176 {
177         Mesh *tmpmesh;
178         CustomDataMask mask = CD_MASK_MESH;
179         Mesh *mesh = (Mesh *)ob->data;
180         DerivedMesh *dm = NULL;
181         if (apply_modifiers) {
182                 switch (export_mesh_type) {
183                         case BC_MESH_TYPE_VIEW:
184                         {
185                                 dm = mesh_create_derived_view(depsgraph, scene, ob, mask);
186                                 break;
187                         }
188                         case BC_MESH_TYPE_RENDER:
189                         {
190                                 dm = mesh_create_derived_render(depsgraph, scene, ob, mask);
191                                 break;
192                         }
193                 }
194         }
195         else {
196                 dm = mesh_create_derived((Mesh *)ob->data, NULL);
197         }
198
199         tmpmesh = BKE_mesh_add(G.main, "ColladaMesh"); // name is not important here
200         DM_to_mesh(dm, tmpmesh, ob, CD_MASK_MESH, true);
201         tmpmesh->flag = mesh->flag;
202
203         if (triangulate) {
204                 bc_triangulate_mesh(tmpmesh);
205         }
206         BKE_mesh_tessface_ensure(tmpmesh);
207         return tmpmesh;
208 }
209
210 Object *bc_get_assigned_armature(Object *ob)
211 {
212         Object *ob_arm = NULL;
213
214         if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) {
215                 ob_arm = ob->parent;
216         }
217         else {
218                 ModifierData *mod;
219                 for (mod = (ModifierData *)ob->modifiers.first; mod; mod = mod->next) {
220                         if (mod->type == eModifierType_Armature) {
221                                 ob_arm = ((ArmatureModifierData *)mod)->object;
222                         }
223                 }
224         }
225
226         return ob_arm;
227 }
228
229 // Returns the highest selected ancestor
230 // returns NULL if no ancestor is selected
231 // IMPORTANT: This function expects that
232 // all exported objects have set:
233 // ob->id.tag & LIB_TAG_DOIT
234 Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob) 
235 {
236         Object *ancestor = ob;
237         while (ob->parent && bc_is_marked(ob->parent)) {
238                 ob = ob->parent;
239                 ancestor = ob;
240         }
241         return ancestor;
242 }
243
244
245 bool bc_is_base_node(LinkNode *export_set, Object *ob)
246 {
247         Object *root = bc_get_highest_selected_ancestor_or_self(export_set, ob);
248         return (root == ob);
249 }
250
251 bool bc_is_in_Export_set(LinkNode *export_set, Object *ob)
252 {
253         return (BLI_linklist_index(export_set, ob) != -1);
254 }
255
256 bool bc_has_object_type(LinkNode *export_set, short obtype)
257 {
258         LinkNode *node;
259         
260         for (node = export_set; node; node = node->next) {
261                 Object *ob = (Object *)node->link;
262                 /* XXX - why is this checking for ob->data? - we could be looking for empties */
263                 if (ob->type == obtype && ob->data) {
264                         return true;
265                 }
266         }
267         return false;
268 }
269
270 int bc_is_marked(Object *ob)
271 {
272         return ob && (ob->id.tag & LIB_TAG_DOIT);
273 }
274
275 void bc_remove_mark(Object *ob)
276 {
277         ob->id.tag &= ~LIB_TAG_DOIT;
278 }
279
280 void bc_set_mark(Object *ob)
281 {
282         ob->id.tag |= LIB_TAG_DOIT;
283 }
284
285 // Use bubble sort algorithm for sorting the export set
286 void bc_bubble_sort_by_Object_name(LinkNode *export_set)
287 {
288         bool sorted = false;
289         LinkNode *node;
290         for (node = export_set; node->next && !sorted; node = node->next) {
291
292                 sorted = true;
293                 
294                 LinkNode *current;
295                 for (current = export_set; current->next; current = current->next) {
296                         Object *a = (Object *)current->link;
297                         Object *b = (Object *)current->next->link;
298
299                         if (strcmp(a->id.name, b->id.name) > 0) {
300                                 current->link       = b;
301                                 current->next->link = a;
302                                 sorted = false;
303                         }
304                         
305                 }
306         }
307 }
308
309 /* Check if a bone is the top most exportable bone in the bone hierarchy. 
310  * When deform_bones_only == false, then only bones with NO parent 
311  * can be root bones. Otherwise the top most deform bones in the hierarchy
312  * are root bones.
313  */
314 bool bc_is_root_bone(Bone *aBone, bool deform_bones_only)
315 {
316         if (deform_bones_only) {
317                 Bone *root = NULL;
318                 Bone *bone = aBone;
319                 while (bone) {
320                         if (!(bone->flag & BONE_NO_DEFORM))
321                                 root = bone;
322                         bone = bone->parent;
323                 }
324                 return (aBone == root);
325         }
326         else
327                 return !(aBone->parent);
328 }
329
330 int bc_get_active_UVLayer(Object *ob)
331 {
332         Mesh *me = (Mesh *)ob->data;
333         return CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
334 }
335
336 std::string bc_url_encode(std::string data)
337 {
338         /* XXX We probably do not need to do a full encoding.
339          * But in case that is necessary,then it can be added here.
340          */
341         return bc_replace_string(data,"#", "%23");
342 }
343
344 std::string bc_replace_string(std::string data, const std::string& pattern,
345                               const std::string& replacement)
346 {
347         size_t pos = 0;
348         while ((pos = data.find(pattern, pos)) != std::string::npos) {
349                 data.replace(pos, pattern.length(), replacement);
350                 pos += replacement.length();
351         }
352         return data;
353 }
354
355 /**
356  * Calculate a rescale factor such that the imported scene's scale
357  * is preserved. I.e. 1 meter in the import will also be
358  * 1 meter in the current scene.
359  */
360
361 void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene)
362 {
363         if (scale_to_scene) {
364                 mul_m4_m4m4(ob->obmat, bc_unit.get_scale(), ob->obmat);
365         }
366         mul_m4_m4m4(ob->obmat, bc_unit.get_rotation(), ob->obmat);
367         BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
368 }
369
370 void bc_match_scale(std::vector<Object *> *objects_done, 
371                         UnitConverter &bc_unit,
372                         bool scale_to_scene)
373 {
374         for (std::vector<Object *>::iterator it = objects_done->begin();
375                         it != objects_done->end();
376                         ++it) 
377         {
378                 Object *ob = *it;
379                 if (ob -> parent == NULL) {
380                         bc_match_scale(*it, bc_unit, scale_to_scene);
381                 }
382         }
383 }
384
385 /*
386     Convenience function to get only the needed components of a matrix
387 */
388 void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
389 {
390         if (size) {
391                 mat4_to_size(size, mat);
392         }
393
394         if (eul) {
395                 mat4_to_eul(eul, mat);
396         }
397
398         if (quat) {
399                 mat4_to_quat(quat, mat);
400         }
401
402         if (loc) {
403                 copy_v3_v3(loc, mat[3]);
404         }
405 }
406
407 /*
408 * Create rotation_quaternion from a delta rotation and a reference quat
409 *
410 * Input:
411 * mat_from: The rotation matrix before rotation
412 * mat_to  : The rotation matrix after rotation
413 * qref    : the quat corresponding to mat_from
414 *
415 * Output:
416 * rot     : the calculated result (quaternion)
417 *
418 */
419 void bc_rotate_from_reference_quat(float quat_to[4], float quat_from[4], float mat_to[4][4])
420 {
421         float qd[4];
422         float matd[4][4];
423         float mati[4][4];
424         float mat_from[4][4];
425         quat_to_mat4(mat_from, quat_from);
426
427         // Calculate the difference matrix matd between mat_from and mat_to
428         invert_m4_m4(mati, mat_from);
429         mul_m4_m4m4(matd, mati, mat_to);
430
431         mat4_to_quat(qd, matd);
432
433         mul_qt_qtqt(quat_to, qd, quat_from); // rot is the final rotation corresponding to mat_to
434 }
435
436 void bc_triangulate_mesh(Mesh *me)
437 {
438         bool use_beauty  = false;
439         bool tag_only    = false;
440         int  quad_method = MOD_TRIANGULATE_QUAD_SHORTEDGE; /* XXX: The triangulation method selection could be offered in the UI */
441
442         const struct BMeshCreateParams bm_create_params = {0};
443         BMesh *bm = BM_mesh_create(
444                 &bm_mesh_allocsize_default,
445                 &bm_create_params);
446         BMeshFromMeshParams bm_from_me_params = {0};
447         bm_from_me_params.calc_face_normal = true;
448         BM_mesh_bm_from_me(bm, me, &bm_from_me_params);
449         BM_mesh_triangulate(bm, quad_method, use_beauty, tag_only, NULL, NULL, NULL);
450
451         BMeshToMeshParams bm_to_me_params = {0};
452         BM_mesh_bm_to_me(bm, me, &bm_to_me_params);
453         BM_mesh_free(bm);
454 }
455
456 /*
457  * A bone is a leaf when it has no children or all children are not connected.
458  */
459 bool bc_is_leaf_bone(Bone *bone)
460 {
461         for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
462                 if (child->flag & BONE_CONNECTED)
463                         return false;
464         }
465         return true;
466 }
467
468 EditBone *bc_get_edit_bone(bArmature * armature, char *name) {
469         EditBone  *eBone;
470
471         for (eBone = (EditBone *)armature->edbo->first; eBone; eBone = eBone->next) {
472                 if (STREQ(name, eBone->name))
473                         return eBone;
474         }
475
476         return NULL;
477
478 }
479 int bc_set_layer(int bitfield, int layer)
480 {
481         return bc_set_layer(bitfield, layer, true); /* enable */
482 }
483
484 int bc_set_layer(int bitfield, int layer, bool enable)
485 {
486         int bit = 1u << layer;
487
488         if (enable)
489                 bitfield |= bit;
490         else
491                 bitfield &= ~bit;
492
493         return bitfield;
494 }
495
496 /*
497  | This method creates a new extension map when needed.
498  | Note: The ~BoneExtensionManager destructor takes care
499  | to delete the created maps when the manager is removed.
500 */
501 BoneExtensionMap &BoneExtensionManager::getExtensionMap(bArmature *armature)
502 {
503         std::string key = armature->id.name;
504         BoneExtensionMap *result = extended_bone_maps[key];
505         if (result == NULL)
506         {
507                 result = new BoneExtensionMap();
508                 extended_bone_maps[key] = result;
509         }
510         return *result;
511 }
512
513 BoneExtensionManager::~BoneExtensionManager()
514 {
515         std::map<std::string, BoneExtensionMap *>::iterator map_it;
516         for (map_it = extended_bone_maps.begin(); map_it != extended_bone_maps.end(); ++map_it)
517         {
518                 BoneExtensionMap *extended_bones = map_it->second;
519                 for (BoneExtensionMap::iterator ext_it = extended_bones->begin(); ext_it != extended_bones->end(); ++ext_it) {
520                         if (ext_it->second != NULL)
521                                 delete ext_it->second;
522                 }
523                 extended_bones->clear();
524                 delete extended_bones;
525         }
526 }
527
528 /**
529  * BoneExtended is a helper class needed for the Bone chain finder
530  * See ArmatureImporter::fix_leaf_bones()
531  * and ArmatureImporter::connect_bone_chains()
532  */
533
534 BoneExtended::BoneExtended(EditBone *aBone)
535 {
536         this->set_name(aBone->name);
537         this->chain_length = 0;
538         this->is_leaf = false;
539         this->tail[0] = 0.0f;
540         this->tail[1] = 0.5f;
541         this->tail[2] = 0.0f;
542         this->use_connect = -1;
543         this->roll = 0;
544         this->bone_layers = 0;
545
546         this->has_custom_tail = false;
547         this->has_custom_roll = false;
548 }
549
550 char *BoneExtended::get_name()
551 {
552         return name;
553 }
554
555 void BoneExtended::set_name(char *aName)
556 {
557         BLI_strncpy(name, aName, MAXBONENAME);
558 }
559
560 int BoneExtended::get_chain_length()
561 {
562         return chain_length;
563 }
564
565 void BoneExtended::set_chain_length(const int aLength)
566 {
567         chain_length = aLength;
568 }
569
570 void BoneExtended::set_leaf_bone(bool state)
571 {
572         is_leaf = state;
573 }
574
575 bool BoneExtended::is_leaf_bone()
576 {
577         return is_leaf;
578 }
579
580 void BoneExtended::set_roll(float roll)
581 {
582         this->roll = roll;
583         this->has_custom_roll = true;
584 }
585
586 bool BoneExtended::has_roll()
587 {
588         return this->has_custom_roll;
589 }
590
591 float BoneExtended::get_roll()
592 {
593         return this->roll;
594 }
595
596 void BoneExtended::set_tail(float vec[])
597 {
598         this->tail[0] = vec[0];
599         this->tail[1] = vec[1];
600         this->tail[2] = vec[2];
601         this->has_custom_tail = true;
602 }
603
604 bool BoneExtended::has_tail()
605 {
606         return this->has_custom_tail;
607 }
608
609 float *BoneExtended::get_tail()
610 {
611         return this->tail;
612 }
613
614 inline bool isInteger(const std::string & s)
615 {
616         if (s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false;
617
618         char * p;
619         strtol(s.c_str(), &p, 10);
620
621         return (*p == 0);
622 }
623
624 void BoneExtended::set_bone_layers(std::string layerString, std::vector<std::string> &layer_labels)
625 {
626         std::stringstream ss(layerString);
627         std::string layer;
628         int pos;
629
630         while (ss >> layer) {
631
632                 /* Blender uses numbers to specify layers*/
633                 if (isInteger(layer))
634                 {
635                         pos = atoi(layer.c_str());
636                         if (pos >= 0 && pos < 32) {
637                                 this->bone_layers = bc_set_layer(this->bone_layers, pos);
638                                 continue;
639                         }
640                 }
641
642                 /* layer uses labels (not supported by blender). Map to layer numbers:*/
643                 pos = find(layer_labels.begin(), layer_labels.end(), layer) - layer_labels.begin();
644                 if (pos >= layer_labels.size()) {
645                         layer_labels.push_back(layer); /* remember layer number for future usage*/
646                 }
647
648                 if (pos > 31)
649                 {
650                         fprintf(stderr, "Too many layers in Import. Layer %s mapped to Blender layer 31\n", layer.c_str());
651                         pos = 31;
652                 }
653
654                 /* If numeric layers and labeled layers are used in parallel (unlikely),
655                  * we get a potential mixup. Just leave as is for now.
656                  */
657                 this->bone_layers = bc_set_layer(this->bone_layers, pos);
658
659         }
660 }
661
662 std::string BoneExtended::get_bone_layers(int bitfield)
663 {
664         std::string result = "";
665         std::string sep = "";
666         int bit = 1u;
667
668         std::ostringstream ss;
669         for (int i = 0; i < 32; i++)
670         {
671                 if (bit & bitfield)
672                 {
673                         ss << sep << i;
674                         sep = " ";
675                 }
676                 bit = bit << 1;
677         }
678         return ss.str();
679 }
680
681 int BoneExtended::get_bone_layers()
682 {
683         return (bone_layers == 0) ? 1 : bone_layers; // ensure that the bone is in at least one bone layer!
684 }
685
686
687 void BoneExtended::set_use_connect(int use_connect)
688 {
689         this->use_connect = use_connect;
690 }
691
692 int BoneExtended::get_use_connect()
693 {
694         return this->use_connect;
695 }
696
697 /**
698 * Stores a 4*4 matrix as a custom bone property array of size 16
699 */
700 void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4])
701 {
702         IDProperty *idgroup = (IDProperty *)ebone->prop;
703         if (idgroup == NULL)
704         {
705                 IDPropertyTemplate val = { 0 };
706                 idgroup = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
707                 ebone->prop = idgroup;
708         }
709
710         IDPropertyTemplate val = { 0 };
711         val.array.len = 16;
712         val.array.type = IDP_FLOAT;
713
714         IDProperty *data = IDP_New(IDP_ARRAY, &val, key);
715         float *array = (float *)IDP_Array(data);
716         for (int i = 0; i < 4; i++)
717                 for (int j = 0; j < 4; j++)
718                         array[4 * i + j] = mat[i][j];
719
720         IDP_AddToGroup(idgroup, data);
721 }
722
723 #if 0
724 /**
725 * Stores a Float value as a custom bone property
726 *
727 * Note: This function is currently not needed. Keep for future usage
728 */
729 static void bc_set_IDProperty(EditBone *ebone, const char *key, float value)
730 {
731         if (ebone->prop == NULL)
732         {
733                 IDPropertyTemplate val = { 0 };
734                 ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
735         }
736
737         IDProperty *pgroup = (IDProperty *)ebone->prop;
738         IDPropertyTemplate val = { 0 };
739         IDProperty *prop = IDP_New(IDP_FLOAT, &val, key);
740         IDP_Float(prop) = value;
741         IDP_AddToGroup(pgroup, prop);
742
743 }
744 #endif
745
746 /*
747 * Get a custom property when it exists.
748 * This function is also used to check if a property exists.
749 */
750 IDProperty *bc_get_IDProperty(Bone *bone, std::string key)
751 {
752         return (bone->prop == NULL) ? NULL : IDP_GetPropertyFromGroup(bone->prop, key.c_str());
753 }
754
755 /**
756 * Read a custom bone property and convert to float
757 * Return def if the property does not exist.
758 */
759 float bc_get_property(Bone *bone, std::string key, float def)
760 {
761         float result = def;
762         IDProperty *property = bc_get_IDProperty(bone, key);
763         if (property) {
764                 switch (property->type) {
765                         case IDP_INT:
766                                 result = (float)(IDP_Int(property));
767                                 break;
768                         case IDP_FLOAT:
769                                 result = (float)(IDP_Float(property));
770                                 break;
771                         case IDP_DOUBLE:
772                                 result = (float)(IDP_Double(property));
773                                 break;
774                         default:
775                                 result = def;
776                 }
777         }
778         return result;
779 }
780
781 /**
782 * Read a custom bone property and convert to matrix
783 * Return true if conversion was succesfull
784
785 * Return false if:
786 * - the property does not exist
787 * - is not an array of size 16
788 */
789 bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
790 {
791         IDProperty *property = bc_get_IDProperty(bone, key);
792         if (property && property->type == IDP_ARRAY && property->len == 16) {
793                 float *array = (float *)IDP_Array(property);
794                 for (int i = 0; i < 4; i++)
795                         for (int j = 0; j < 4; j++)
796                                 mat[i][j] = array[4 * i + j];
797                 return true;
798         }
799         return false;
800 }
801
802 /**
803 * get a vector that is stored in 3 custom properties (used in Blender <= 2.78)
804 */
805 void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3])
806 {
807         val[0] = bc_get_property(bone, key + "_x", def[0]);
808         val[1] = bc_get_property(bone, key + "_y", def[1]);
809         val[2] = bc_get_property(bone, key + "_z", def[2]);
810 }
811
812 /**
813 * Check if vector exist stored in 3 custom properties (used in Blender <= 2.78)
814 */
815 static bool has_custom_props(Bone *bone, bool enabled, std::string key)
816 {
817         if (!enabled)
818                 return false;
819
820         return (bc_get_IDProperty(bone, key + "_x")
821                 ||      bc_get_IDProperty(bone, key + "_y")
822                 ||      bc_get_IDProperty(bone, key + "_z"));
823
824 }
825
826 /**
827 * Check if custom information about bind matrix exists and modify the from_mat
828 * accordingly.
829 *
830 * Note: This is old style for Blender <= 2.78 only kept for compatibility
831 */
832 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)
833 {
834         float loc[3];
835         float rot[3];
836         float scale[3];
837         static const float V0[3] = { 0, 0, 0 };
838
839         if (!has_custom_props(bone, export_settings->keep_bind_info, "restpose_loc") &&
840                 !has_custom_props(bone, export_settings->keep_bind_info, "restpose_rot") &&
841                 !has_custom_props(bone, export_settings->keep_bind_info, "restpose_scale"))
842         {
843                 /* No need */
844                 copy_m4_m4(to_mat, from_mat);
845                 return;
846         }
847
848         bc_decompose(from_mat, loc, rot, NULL, scale);
849         loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
850
851         if (export_settings->keep_bind_info) {
852                 bc_get_property_vector(bone, "restpose_loc", loc, loc);
853
854                 if (use_local_space && bone->parent) {
855                         Bone *b = bone;
856                         while (b->parent) {
857                                 b = b->parent;
858                                 float ploc[3];
859                                 bc_get_property_vector(b, "restpose_loc", ploc, V0);
860                                 loc[0] += ploc[0];
861                                 loc[1] += ploc[1];
862                                 loc[2] += ploc[2];
863                         }
864                 }
865         }
866
867         if (export_settings->keep_bind_info) {
868                 if (bc_get_IDProperty(bone, "restpose_rot_x"))
869                     rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0));
870                 if (bc_get_IDProperty(bone, "restpose_rot_y"))
871                         rot[1] = DEG2RADF(bc_get_property(bone, "restpose_rot_y", 0));
872                 if (bc_get_IDProperty(bone, "restpose_rot_z"))
873                         rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0));
874         }
875
876         if (export_settings->keep_bind_info) {
877                 bc_get_property_vector(bone, "restpose_scale", scale, scale);
878         }
879
880         loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
881
882 }
883
884 /*
885     Make 4*4 matrices better readable
886 */
887 void bc_sanitize_mat(float mat[4][4], int precision)
888 {
889         for (int i = 0; i < 4; i++)
890                 for (int j = 0; j < 4; j++)
891                         mat[i][j] = double_round(mat[i][j], precision);
892 }
893
894 void bc_sanitize_mat(double mat[4][4], int precision)
895 {
896         for (int i = 0; i < 4; i++)
897                 for (int j = 0; j < 4; j++)
898                         mat[i][j] = double_round(mat[i][j], precision);
899 }
900
901 void bc_copy_m4_farray(float r[4][4], float *a)
902 {
903         for (int i = 0; i < 4; i++)
904                 for (int j = 0; j < 4; j++)
905                         r[i][j] = *a++;
906 }
907
908 void bc_copy_farray_m4(float *r, float a[4][4])
909 {
910         for (int i = 0; i < 4; i++)
911                 for (int j = 0; j < 4; j++)
912                         *r++ = a[i][j];
913
914 }
915
916 /*
917  * Returns name of Active UV Layer or empty String if no active UV Layer defined
918  */
919 std::string bc_get_active_uvlayer_name(Mesh *me)
920 {
921         int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
922         if (num_layers) {
923                 char *layer_name = bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE);
924                 if (layer_name) {
925                         return std::string(layer_name);
926                 }
927         }
928         return "";
929 }
930
931 /*
932 * Returns name of Active UV Layer or empty String if no active UV Layer defined.
933 * Assuming the Object is of type MESH
934 */
935 std::string bc_get_active_uvlayer_name(Object *ob)
936 {
937         Mesh *me = (Mesh *)ob->data;
938         return bc_get_active_uvlayer_name(me);
939 }
940
941 /*
942  * Returns UV Layer name or empty string if layer index is out of range
943  */
944 std::string bc_get_uvlayer_name(Mesh *me, int layer)
945 {
946         int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
947         if (num_layers && layer < num_layers) {
948                 char *layer_name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, layer);
949                 if (layer_name) {
950                         return std::string(layer_name);
951                 }
952         }
953         return "";
954 }
955
956 #if 0
957 /**********************************************************************
958 *
959 * Return the list of Mesh objects with assigned UVtextures and Images
960 * Note: We need to create artificaial materials for each of them
961 *
962 ***********************************************************************/
963 std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers)
964 {
965         std::set <Object *> UVObjects;
966         Base *base = (Base *)sce->base.first;
967
968         while (base) {
969                 Object *ob = base->object;
970                 bool has_uvimage = false;
971                 if (ob->type == OB_MESH) {
972                         Mesh *me = (Mesh *)ob->data;
973                         int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
974
975                         for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
976                                 if (all_uv_layers || active_uv_layer == i)
977                                 {
978                                         if (me->pdata.layers[i].type == CD_MTEXPOLY) {
979                                                 MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
980                                                 MPoly *mpoly = me->mpoly;
981                                                 for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
982
983                                                         Image *ima = txface->tpage;
984                                                         if (ima != NULL) {
985                                                                 has_uvimage = true;
986                                                                 break;
987                                                         }
988                                                 }
989                                         }
990                                 }
991                         }
992
993                         if (has_uvimage) {
994                                 UVObjects.insert(ob);
995                         }
996                 }
997                 base = base->next;
998         }
999         return UVObjects;
1000 }
1001
1002 /**********************************************************************
1003 *
1004 * Return the list of UV Texture images from all exported Mesh Items
1005 * Note: We need to create one artificial material for each Image.
1006 *
1007 ***********************************************************************/
1008 std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers)
1009 {
1010         std::set <Image *> UVImages;
1011         Base *base = (Base *)sce->base.first;
1012
1013         while (base) {
1014                 Object *ob = base->object;
1015                 bool has_uvimage = false;
1016                 if (ob->type == OB_MESH) {
1017                         Mesh *me = (Mesh *)ob->data;
1018                         int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
1019
1020                         for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
1021                                 if (all_uv_layers || active_uv_layer == i)
1022                                 {
1023                                         if (me->pdata.layers[i].type == CD_MTEXPOLY) {
1024                                                 MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
1025                                                 MPoly *mpoly = me->mpoly;
1026                                                 for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
1027
1028                                                         Image *ima = txface->tpage;
1029                                                         if (ima != NULL) {
1030                                                                 if (UVImages.find(ima) == UVImages.end())
1031                                                                         UVImages.insert(ima);
1032                                                         }
1033                                                 }
1034                                         }
1035                                 }
1036                         }
1037                 }
1038                 base = base->next;
1039         }
1040         return UVImages;
1041 }
1042
1043 /**********************************************************************
1044 *
1045 * Return the list of UV Texture images for the given Object
1046 * Note: We need to create one artificial material for each Image.
1047 *
1048 ***********************************************************************/
1049 std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers)
1050 {
1051         std::set <Image *> UVImages;
1052
1053         bool has_uvimage = false;
1054         if (ob->type == OB_MESH) {
1055                 Mesh *me = (Mesh *)ob->data;
1056                 int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
1057
1058                 for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
1059                         if (all_uv_layers || active_uv_layer == i)
1060                         {
1061                                 if (me->pdata.layers[i].type == CD_MTEXPOLY) {
1062                                         MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
1063                                         MPoly *mpoly = me->mpoly;
1064                                         for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
1065
1066                                                 Image *ima = txface->tpage;
1067                                                 if (ima != NULL) {
1068                                                         if (UVImages.find(ima) == UVImages.end())
1069                                                                 UVImages.insert(ima);
1070                                                 }
1071                                         }
1072                                 }
1073                         }
1074                 }
1075         }
1076         return UVImages;
1077 }
1078 #endif