Cleanup: BKE_library: remove 'test' param of id_copy.
[blender.git] / source / blender / collada / collada_utils.cpp
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file blender/collada/collada_utils.cpp
18  *  \ingroup collada
19  */
20
21
22 /* COLLADABU_ASSERT, may be able to remove later */
23 #include "COLLADABUPlatform.h"
24
25 #include "COLLADAFWGeometry.h"
26 #include "COLLADAFWMeshPrimitive.h"
27 #include "COLLADAFWMeshVertexData.h"
28
29 #include <set>
30 #include <string>
31 extern "C" {
32 #include "DNA_modifier_types.h"
33 #include "DNA_customdata_types.h"
34 #include "DNA_key_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_constraint_types.h"
37 #include "DNA_mesh_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_armature_types.h"
40
41 #include "BLI_math.h"
42 #include "BLI_linklist.h"
43 #include "BLI_listbase.h"
44
45 #include "BKE_action.h"
46 #include "BKE_context.h"
47 #include "BKE_customdata.h"
48 #include "BKE_constraint.h"
49 #include "BKE_key.h"
50 #include "BKE_material.h"
51 #include "BKE_node.h"
52 #include "BKE_object.h"
53 #include "BKE_global.h"
54 #include "BKE_layer.h"
55 #include "BKE_library.h"
56 #include "BKE_mesh.h"
57 #include "BKE_mesh_runtime.h"
58 #include "BKE_object.h"
59 #include "BKE_scene.h"
60
61 #include "ED_armature.h"
62 #include "ED_screen.h"
63 #include "ED_node.h"
64
65 #include "MEM_guardedalloc.h"
66
67 #include "WM_api.h" // XXX hrm, see if we can do without this
68 #include "WM_types.h"
69
70 #include "bmesh.h"
71 #include "bmesh_tools.h"
72
73 #include "DEG_depsgraph.h"
74 #include "DEG_depsgraph_query.h"
75 #if 0
76 #include "NOD_common.h"
77 #endif
78 }
79
80 #include "collada_utils.h"
81 #include "ExportSettings.h"
82 #include "BlenderContext.h"
83
84 float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index)
85 {
86         if (index >= array.getValuesCount())
87                 return 0.0f;
88
89         if (array.getType() == COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT)
90                 return array.getFloatValues()->getData()[index];
91         else
92                 return array.getDoubleValues()->getData()[index];
93 }
94
95 // copied from /editors/object/object_relations.c
96 int bc_test_parent_loop(Object *par, Object *ob)
97 {
98         /* test if 'ob' is a parent somewhere in par's parents */
99
100         if (par == NULL) return 0;
101         if (ob == par) return 1;
102
103         return bc_test_parent_loop(par->parent, ob);
104 }
105
106 void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer)
107 {
108         Base *base;
109         for (base = (Base *)view_layer->object_bases.first; base; base = base->next) {
110                 Object *cob = base->object;
111                 if (cob->parent == ob) {
112                         switch (ob->type) {
113                         case OB_MESH:
114                         case OB_CAMERA:
115                         case OB_LAMP:
116                         case OB_EMPTY:
117                         case OB_ARMATURE:
118                                 child_set.push_back(cob);
119                         default: break;
120                         }
121                 }
122         }
123 }
124
125 bool bc_validateConstraints(bConstraint *con)
126 {
127         const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
128
129         /* these we can skip completely (invalid constraints...) */
130         if (cti == NULL)
131                 return false;
132         if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF))
133                 return false;
134
135         /* these constraints can't be evaluated anyway */
136         if (cti->evaluate_constraint == NULL)
137                 return false;
138
139         /* influence == 0 should be ignored */
140         if (con->enforce == 0.0f)
141                 return false;
142
143         /* validation passed */
144         return true;
145 }
146
147 // a shortened version of parent_set_exec()
148 // if is_parent_space is true then ob->obmat will be multiplied by par->obmat before parenting
149 int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
150 {
151         Object workob;
152         Depsgraph *depsgraph = CTX_data_depsgraph(C);
153         Scene *sce = CTX_data_scene(C);
154
155         if (!par || bc_test_parent_loop(par, ob))
156                 return false;
157
158         ob->parent = par;
159         ob->partype = PAROBJECT;
160
161         ob->parsubstr[0] = 0;
162
163         if (is_parent_space) {
164                 float mat[4][4];
165                 // calc par->obmat
166                 BKE_object_where_is_calc(depsgraph, sce, par);
167
168                 // move child obmat into world space
169                 mul_m4_m4m4(mat, par->obmat, ob->obmat);
170                 copy_m4_m4(ob->obmat, mat);
171         }
172
173         // apply child obmat (i.e. decompose it into rot/loc/size)
174         BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
175
176         // compute parentinv
177         BKE_object_workob_calc_parent(depsgraph, sce, ob, &workob);
178         invert_m4_m4(ob->parentinv, workob.obmat);
179
180         DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
181         DEG_id_tag_update(&par->id, ID_RECALC_TRANSFORM);
182
183         return true;
184 }
185
186 std::vector<bAction *> bc_getSceneActions(const bContext *C, Object *ob, bool all_actions)
187 {
188         std::vector<bAction *> actions;
189         if (all_actions) {
190                 Main *bmain = CTX_data_main(C);
191                 ID *id;
192
193                 for (id = (ID *)bmain->action.first; id; id = (ID *)(id->next)) {
194                         bAction *act = (bAction *)id;
195                         /* XXX This currently creates too many actions.
196                            TODO Need to check if the action is compatible to the given object
197                         */
198                         actions.push_back(act);
199                 }
200         }
201         else
202         {
203                 bAction *action = bc_getSceneObjectAction(ob);
204                 actions.push_back(action);
205         }
206
207         return actions;
208 }
209
210 std::string bc_get_action_id(std::string action_name, std::string ob_name, std::string channel_type, std::string axis_name, std::string axis_separator)
211 {
212         std::string result = action_name + "_" + channel_type;
213         if (ob_name.length() > 0)
214                 result = ob_name + "_" + result;
215         if (axis_name.length() > 0)
216                 result += axis_separator + axis_name;
217         return translate_id(result);
218 }
219
220 void bc_update_scene(BlenderContext &blender_context, float ctime)
221 {
222         Main *bmain = blender_context.get_main();
223         Scene *scene = blender_context.get_scene();
224         Depsgraph *depsgraph = blender_context.get_depsgraph();
225
226         /*
227          * See remark in physics_fluid.c lines 395...)
228          * BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay);
229         */
230         BKE_scene_frame_set(scene, ctime);
231         ED_update_for_newframe(bmain, depsgraph);
232 }
233
234 Object *bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name)
235 {
236         Object *ob = BKE_object_add_only_object(bmain, type, name);
237
238         ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
239         ob->lay = scene->lay;
240         DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
241
242         LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
243         BKE_collection_object_add(bmain, layer_collection->collection, ob);
244
245         Base *base = BKE_view_layer_base_find(view_layer, ob);
246         /* TODO: is setting active needed? */
247         BKE_view_layer_base_select_and_set_active(view_layer, base);
248
249         return ob;
250 }
251
252 Mesh *bc_get_mesh_copy(
253     BlenderContext &blender_context,
254         Object *ob,
255         BC_export_mesh_type export_mesh_type,
256         bool apply_modifiers,
257         bool triangulate)
258 {
259         CustomDataMask mask = CD_MASK_MESH;
260         Mesh *tmpmesh = NULL;
261         if (apply_modifiers) {
262 #if 0  /* Not supported by new system currently... */
263                 switch (export_mesh_type) {
264                         case BC_MESH_TYPE_VIEW:
265                         {
266                                 dm = mesh_create_derived_view(depsgraph, scene, ob, mask);
267                                 break;
268                         }
269                         case BC_MESH_TYPE_RENDER:
270                         {
271                                 dm = mesh_create_derived_render(depsgraph, scene, ob, mask);
272                                 break;
273                         }
274                 }
275 #else
276                 Depsgraph *depsgraph = blender_context.get_depsgraph();
277                 Scene *scene_eval = blender_context.get_evaluated_scene();
278                 Object *ob_eval = blender_context.get_evaluated_object(ob);
279                 tmpmesh = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, mask);
280 #endif
281         }
282         else {
283                 tmpmesh = (Mesh *)ob->data;
284         }
285
286         BKE_id_copy_ex(NULL, &tmpmesh->id, (ID **)&tmpmesh,
287                        LIB_ID_CREATE_NO_MAIN |
288                        LIB_ID_CREATE_NO_USER_REFCOUNT |
289                        LIB_ID_CREATE_NO_DEG_TAG |
290                        LIB_ID_COPY_NO_PREVIEW);
291
292         if (triangulate) {
293                 bc_triangulate_mesh(tmpmesh);
294         }
295         BKE_mesh_tessface_ensure(tmpmesh);
296         return tmpmesh;
297 }
298
299 Object *bc_get_assigned_armature(Object *ob)
300 {
301         Object *ob_arm = NULL;
302
303         if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) {
304                 ob_arm = ob->parent;
305         }
306         else {
307                 ModifierData *mod;
308                 for (mod = (ModifierData *)ob->modifiers.first; mod; mod = mod->next) {
309                         if (mod->type == eModifierType_Armature) {
310                                 ob_arm = ((ArmatureModifierData *)mod)->object;
311                         }
312                 }
313         }
314
315         return ob_arm;
316 }
317
318 /*
319 * Returns the highest selected ancestor
320 * returns NULL if no ancestor is selected
321 * IMPORTANT: This function expects that all exported objects have set:
322 * ob->id.tag & LIB_TAG_DOIT
323 */
324 Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob)
325
326 {
327         Object *ancestor = ob;
328         while (ob->parent && bc_is_marked(ob->parent)) {
329                 ob = ob->parent;
330                 ancestor = ob;
331         }
332         return ancestor;
333 }
334
335 bool bc_is_base_node(LinkNode *export_set, Object *ob)
336 {
337         Object *root = bc_get_highest_selected_ancestor_or_self(export_set, ob);
338         return (root == ob);
339 }
340
341 bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer)
342 {
343         bool to_export = (BLI_linklist_index(export_set, ob) != -1);
344
345         if (!to_export)
346         {
347                 /* Mark this object as to_export even if it is not in the
348                 export list, but it contains children to export */
349
350                 std::vector<Object *> children;
351                 bc_get_children(children, ob, view_layer);
352                 for (int i = 0; i < children.size(); i++) {
353                         if (bc_is_in_Export_set(export_set, children[i], view_layer)) {
354                                 to_export = true;
355                                 break;
356                         }
357                 }
358         }
359         return to_export;
360 }
361
362 bool bc_has_object_type(LinkNode *export_set, short obtype)
363 {
364         LinkNode *node;
365
366         for (node = export_set; node; node = node->next) {
367                 Object *ob = (Object *)node->link;
368                 /* XXX - why is this checking for ob->data? - we could be looking for empties */
369                 if (ob->type == obtype && ob->data) {
370                         return true;
371                 }
372         }
373         return false;
374 }
375
376 int bc_is_marked(Object *ob)
377 {
378         return ob && (ob->id.tag & LIB_TAG_DOIT);
379 }
380
381 void bc_remove_mark(Object *ob)
382 {
383         ob->id.tag &= ~LIB_TAG_DOIT;
384 }
385
386 void bc_set_mark(Object *ob)
387 {
388         ob->id.tag |= LIB_TAG_DOIT;
389 }
390
391 // Use bubble sort algorithm for sorting the export set
392 void bc_bubble_sort_by_Object_name(LinkNode *export_set)
393 {
394         bool sorted = false;
395         LinkNode *node;
396         for (node = export_set; node->next && !sorted; node = node->next) {
397
398                 sorted = true;
399
400                 LinkNode *current;
401                 for (current = export_set; current->next; current = current->next) {
402                         Object *a = (Object *)current->link;
403                         Object *b = (Object *)current->next->link;
404
405                         if (strcmp(a->id.name, b->id.name) > 0) {
406                                 current->link       = b;
407                                 current->next->link = a;
408                                 sorted = false;
409                         }
410
411                 }
412         }
413 }
414
415 /* Check if a bone is the top most exportable bone in the bone hierarchy.
416  * When deform_bones_only == false, then only bones with NO parent
417  * can be root bones. Otherwise the top most deform bones in the hierarchy
418  * are root bones.
419  */
420 bool bc_is_root_bone(Bone *aBone, bool deform_bones_only)
421 {
422         if (deform_bones_only) {
423                 Bone *root = NULL;
424                 Bone *bone = aBone;
425                 while (bone) {
426                         if (!(bone->flag & BONE_NO_DEFORM))
427                                 root = bone;
428                         bone = bone->parent;
429                 }
430                 return (aBone == root);
431         }
432         else
433                 return !(aBone->parent);
434 }
435
436 int bc_get_active_UVLayer(Object *ob)
437 {
438         Mesh *me = (Mesh *)ob->data;
439         return CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV);
440 }
441
442 std::string bc_url_encode(std::string data)
443 {
444         /* XXX We probably do not need to do a full encoding.
445          * But in case that is necessary,then it can be added here.
446          */
447         return bc_replace_string(data,"#", "%23");
448 }
449
450 std::string bc_replace_string(std::string data, const std::string& pattern,
451                               const std::string& replacement)
452 {
453         size_t pos = 0;
454         while ((pos = data.find(pattern, pos)) != std::string::npos) {
455                 data.replace(pos, pattern.length(), replacement);
456                 pos += replacement.length();
457         }
458         return data;
459 }
460
461 /**
462  * Calculate a rescale factor such that the imported scene's scale
463  * is preserved. I.e. 1 meter in the import will also be
464  * 1 meter in the current scene.
465  */
466
467 void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene)
468 {
469         if (scale_to_scene) {
470                 mul_m4_m4m4(ob->obmat, bc_unit.get_scale(), ob->obmat);
471         }
472         mul_m4_m4m4(ob->obmat, bc_unit.get_rotation(), ob->obmat);
473         BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
474 }
475
476 void bc_match_scale(std::vector<Object *> *objects_done,
477                         UnitConverter &bc_unit,
478                         bool scale_to_scene)
479 {
480         for (std::vector<Object *>::iterator it = objects_done->begin();
481                         it != objects_done->end();
482                         ++it)
483         {
484                 Object *ob = *it;
485                 if (ob -> parent == NULL) {
486                         bc_match_scale(*it, bc_unit, scale_to_scene);
487                 }
488         }
489 }
490
491 /*
492  * Convenience function to get only the needed components of a matrix
493  */
494 void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
495 {
496         if (size) {
497                 mat4_to_size(size, mat);
498         }
499
500         if (eul) {
501                 mat4_to_eul(eul, mat);
502         }
503
504         if (quat) {
505                 mat4_to_quat(quat, mat);
506         }
507
508         if (loc) {
509                 copy_v3_v3(loc, mat[3]);
510         }
511 }
512
513 /*
514  * Create rotation_quaternion from a delta rotation and a reference quat
515  *
516  * Input:
517  * mat_from: The rotation matrix before rotation
518  * mat_to  : The rotation matrix after rotation
519  * qref    : the quat corresponding to mat_from
520  *
521  * Output:
522  * rot     : the calculated result (quaternion)
523  */
524 void bc_rotate_from_reference_quat(float quat_to[4], float quat_from[4], float mat_to[4][4])
525 {
526         float qd[4];
527         float matd[4][4];
528         float mati[4][4];
529         float mat_from[4][4];
530         quat_to_mat4(mat_from, quat_from);
531
532         // Calculate the difference matrix matd between mat_from and mat_to
533         invert_m4_m4(mati, mat_from);
534         mul_m4_m4m4(matd, mati, mat_to);
535
536         mat4_to_quat(qd, matd);
537
538         mul_qt_qtqt(quat_to, qd, quat_from); // rot is the final rotation corresponding to mat_to
539 }
540
541 void bc_triangulate_mesh(Mesh *me)
542 {
543         bool use_beauty  = false;
544         bool tag_only    = false;
545         int  quad_method = MOD_TRIANGULATE_QUAD_SHORTEDGE; /* XXX: The triangulation method selection could be offered in the UI */
546
547         const struct BMeshCreateParams bm_create_params = {0};
548         BMesh *bm = BM_mesh_create(
549                 &bm_mesh_allocsize_default,
550                 &bm_create_params);
551         BMeshFromMeshParams bm_from_me_params = {0};
552         bm_from_me_params.calc_face_normal = true;
553         BM_mesh_bm_from_me(bm, me, &bm_from_me_params);
554         BM_mesh_triangulate(bm, quad_method, use_beauty, tag_only, NULL, NULL, NULL);
555
556         BMeshToMeshParams bm_to_me_params = {0};
557         bm_to_me_params.calc_object_remap = false;
558         BM_mesh_bm_to_me(NULL, bm, me, &bm_to_me_params);
559         BM_mesh_free(bm);
560 }
561
562 /*
563  * A bone is a leaf when it has no children or all children are not connected.
564  */
565 bool bc_is_leaf_bone(Bone *bone)
566 {
567         for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
568                 if (child->flag & BONE_CONNECTED)
569                         return false;
570         }
571         return true;
572 }
573
574 EditBone *bc_get_edit_bone(bArmature * armature, char *name) {
575         EditBone  *eBone;
576
577         for (eBone = (EditBone *)armature->edbo->first; eBone; eBone = eBone->next) {
578                 if (STREQ(name, eBone->name))
579                         return eBone;
580         }
581
582         return NULL;
583
584 }
585 int bc_set_layer(int bitfield, int layer)
586 {
587         return bc_set_layer(bitfield, layer, true); /* enable */
588 }
589
590 int bc_set_layer(int bitfield, int layer, bool enable)
591 {
592         int bit = 1u << layer;
593
594         if (enable)
595                 bitfield |= bit;
596         else
597                 bitfield &= ~bit;
598
599         return bitfield;
600 }
601
602 /**
603  * This method creates a new extension map when needed.
604  * \note The ~BoneExtensionManager destructor takes care
605  * to delete the created maps when the manager is removed.
606  */
607 BoneExtensionMap &BoneExtensionManager::getExtensionMap(bArmature *armature)
608 {
609         std::string key = armature->id.name;
610         BoneExtensionMap *result = extended_bone_maps[key];
611         if (result == NULL)
612         {
613                 result = new BoneExtensionMap();
614                 extended_bone_maps[key] = result;
615         }
616         return *result;
617 }
618
619 BoneExtensionManager::~BoneExtensionManager()
620 {
621         std::map<std::string, BoneExtensionMap *>::iterator map_it;
622         for (map_it = extended_bone_maps.begin(); map_it != extended_bone_maps.end(); ++map_it)
623         {
624                 BoneExtensionMap *extended_bones = map_it->second;
625                 for (BoneExtensionMap::iterator ext_it = extended_bones->begin(); ext_it != extended_bones->end(); ++ext_it) {
626                         if (ext_it->second != NULL)
627                                 delete ext_it->second;
628                 }
629                 extended_bones->clear();
630                 delete extended_bones;
631         }
632 }
633
634 /**
635  * BoneExtended is a helper class needed for the Bone chain finder
636  * See ArmatureImporter::fix_leaf_bones()
637  * and ArmatureImporter::connect_bone_chains()
638  */
639
640 BoneExtended::BoneExtended(EditBone *aBone)
641 {
642         this->set_name(aBone->name);
643         this->chain_length = 0;
644         this->is_leaf = false;
645         this->tail[0] = 0.0f;
646         this->tail[1] = 0.5f;
647         this->tail[2] = 0.0f;
648         this->use_connect = -1;
649         this->roll = 0;
650         this->bone_layers = 0;
651
652         this->has_custom_tail = false;
653         this->has_custom_roll = false;
654 }
655
656 char *BoneExtended::get_name()
657 {
658         return name;
659 }
660
661 void BoneExtended::set_name(char *aName)
662 {
663         BLI_strncpy(name, aName, MAXBONENAME);
664 }
665
666 int BoneExtended::get_chain_length()
667 {
668         return chain_length;
669 }
670
671 void BoneExtended::set_chain_length(const int aLength)
672 {
673         chain_length = aLength;
674 }
675
676 void BoneExtended::set_leaf_bone(bool state)
677 {
678         is_leaf = state;
679 }
680
681 bool BoneExtended::is_leaf_bone()
682 {
683         return is_leaf;
684 }
685
686 void BoneExtended::set_roll(float roll)
687 {
688         this->roll = roll;
689         this->has_custom_roll = true;
690 }
691
692 bool BoneExtended::has_roll()
693 {
694         return this->has_custom_roll;
695 }
696
697 float BoneExtended::get_roll()
698 {
699         return this->roll;
700 }
701
702 void BoneExtended::set_tail(float vec[])
703 {
704         this->tail[0] = vec[0];
705         this->tail[1] = vec[1];
706         this->tail[2] = vec[2];
707         this->has_custom_tail = true;
708 }
709
710 bool BoneExtended::has_tail()
711 {
712         return this->has_custom_tail;
713 }
714
715 float *BoneExtended::get_tail()
716 {
717         return this->tail;
718 }
719
720 inline bool isInteger(const std::string & s)
721 {
722         if (s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false;
723
724         char *p;
725         strtol(s.c_str(), &p, 10);
726
727         return (*p == 0);
728 }
729
730 void BoneExtended::set_bone_layers(std::string layerString, std::vector<std::string> &layer_labels)
731 {
732         std::stringstream ss(layerString);
733         std::string layer;
734         int pos;
735
736         while (ss >> layer) {
737
738                 /* Blender uses numbers to specify layers*/
739                 if (isInteger(layer))
740                 {
741                         pos = atoi(layer.c_str());
742                         if (pos >= 0 && pos < 32) {
743                                 this->bone_layers = bc_set_layer(this->bone_layers, pos);
744                                 continue;
745                         }
746                 }
747
748                 /* layer uses labels (not supported by blender). Map to layer numbers:*/
749                 pos = find(layer_labels.begin(), layer_labels.end(), layer) - layer_labels.begin();
750                 if (pos >= layer_labels.size()) {
751                         layer_labels.push_back(layer); /* remember layer number for future usage*/
752                 }
753
754                 if (pos > 31)
755                 {
756                         fprintf(stderr, "Too many layers in Import. Layer %s mapped to Blender layer 31\n", layer.c_str());
757                         pos = 31;
758                 }
759
760                 /* If numeric layers and labeled layers are used in parallel (unlikely),
761                  * we get a potential mixup. Just leave as is for now.
762                  */
763                 this->bone_layers = bc_set_layer(this->bone_layers, pos);
764
765         }
766 }
767
768 std::string BoneExtended::get_bone_layers(int bitfield)
769 {
770         std::string result = "";
771         std::string sep = "";
772         int bit = 1u;
773
774         std::ostringstream ss;
775         for (int i = 0; i < 32; i++)
776         {
777                 if (bit & bitfield)
778                 {
779                         ss << sep << i;
780                         sep = " ";
781                 }
782                 bit = bit << 1;
783         }
784         return ss.str();
785 }
786
787 int BoneExtended::get_bone_layers()
788 {
789         return (bone_layers == 0) ? 1 : bone_layers; // ensure that the bone is in at least one bone layer!
790 }
791
792
793 void BoneExtended::set_use_connect(int use_connect)
794 {
795         this->use_connect = use_connect;
796 }
797
798 int BoneExtended::get_use_connect()
799 {
800         return this->use_connect;
801 }
802
803 /**
804  * Stores a 4*4 matrix as a custom bone property array of size 16
805  */
806 void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4])
807 {
808         IDProperty *idgroup = (IDProperty *)ebone->prop;
809         if (idgroup == NULL)
810         {
811                 IDPropertyTemplate val = { 0 };
812                 idgroup = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
813                 ebone->prop = idgroup;
814         }
815
816         IDPropertyTemplate val = { 0 };
817         val.array.len = 16;
818         val.array.type = IDP_FLOAT;
819
820         IDProperty *data = IDP_New(IDP_ARRAY, &val, key);
821         float *array = (float *)IDP_Array(data);
822         for (int i = 0; i < 4; i++)
823                 for (int j = 0; j < 4; j++)
824                         array[4 * i + j] = mat[i][j];
825
826         IDP_AddToGroup(idgroup, data);
827 }
828
829 #if 0
830 /**
831  * Stores a Float value as a custom bone property
832  *
833  * Note: This function is currently not needed. Keep for future usage
834  */
835 static void bc_set_IDProperty(EditBone *ebone, const char *key, float value)
836 {
837         if (ebone->prop == NULL)
838         {
839                 IDPropertyTemplate val = { 0 };
840                 ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
841         }
842
843         IDProperty *pgroup = (IDProperty *)ebone->prop;
844         IDPropertyTemplate val = { 0 };
845         IDProperty *prop = IDP_New(IDP_FLOAT, &val, key);
846         IDP_Float(prop) = value;
847         IDP_AddToGroup(pgroup, prop);
848
849 }
850 #endif
851
852 /**
853  * Get a custom property when it exists.
854  * This function is also used to check if a property exists.
855  */
856 IDProperty *bc_get_IDProperty(Bone *bone, std::string key)
857 {
858         return (bone->prop == NULL) ? NULL : IDP_GetPropertyFromGroup(bone->prop, key.c_str());
859 }
860
861 /**
862  * Read a custom bone property and convert to float
863  * Return def if the property does not exist.
864  */
865 float bc_get_property(Bone *bone, std::string key, float def)
866 {
867         float result = def;
868         IDProperty *property = bc_get_IDProperty(bone, key);
869         if (property) {
870                 switch (property->type) {
871                         case IDP_INT:
872                                 result = (float)(IDP_Int(property));
873                                 break;
874                         case IDP_FLOAT:
875                                 result = (float)(IDP_Float(property));
876                                 break;
877                         case IDP_DOUBLE:
878                                 result = (float)(IDP_Double(property));
879                                 break;
880                         default:
881                                 result = def;
882                 }
883         }
884         return result;
885 }
886
887 /**
888  * Read a custom bone property and convert to matrix
889  * Return true if conversion was successful
890  *
891  * Return false if:
892  * - the property does not exist
893  * - is not an array of size 16
894  */
895 bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
896 {
897         IDProperty *property = bc_get_IDProperty(bone, key);
898         if (property && property->type == IDP_ARRAY && property->len == 16) {
899                 float *array = (float *)IDP_Array(property);
900                 for (int i = 0; i < 4; i++)
901                         for (int j = 0; j < 4; j++)
902                                 mat[i][j] = array[4 * i + j];
903                 return true;
904         }
905         return false;
906 }
907
908 /**
909  * get a vector that is stored in 3 custom properties (used in Blender <= 2.78)
910  */
911 void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3])
912 {
913         val[0] = bc_get_property(bone, key + "_x", def[0]);
914         val[1] = bc_get_property(bone, key + "_y", def[1]);
915         val[2] = bc_get_property(bone, key + "_z", def[2]);
916 }
917
918 /**
919  * Check if vector exist stored in 3 custom properties (used in Blender <= 2.78)
920  */
921 static bool has_custom_props(Bone *bone, bool enabled, std::string key)
922 {
923         if (!enabled)
924                 return false;
925
926         return (bc_get_IDProperty(bone, key + "_x")
927                 ||      bc_get_IDProperty(bone, key + "_y")
928                 ||      bc_get_IDProperty(bone, key + "_z"));
929
930 }
931
932 void bc_enable_fcurves(bAction *act, char *bone_name)
933 {
934         FCurve *fcu;
935         char prefix[200];
936
937         if (bone_name)
938                 BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
939
940         for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) {
941                 if (bone_name) {
942                         if (STREQLEN(fcu->rna_path, prefix, strlen(prefix)))
943                                 fcu->flag &= ~FCURVE_DISABLED;
944                         else
945                                 fcu->flag |= FCURVE_DISABLED;
946                 }
947                 else {
948                         fcu->flag &= ~FCURVE_DISABLED;
949                 }
950         }
951 }
952
953 bool bc_bone_matrix_local_get(Object *ob, Bone *bone, Matrix &mat, bool for_opensim)
954 {
955
956         /* Ok, lets be super cautious and check if the bone exists */
957         bPose *pose = ob->pose;
958         bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
959         if (!pchan) {
960                 return false;
961         }
962
963         bAction *action = bc_getSceneObjectAction(ob);
964         bPoseChannel *parchan = pchan->parent;
965
966         bc_enable_fcurves(action, bone->name);
967         float ipar[4][4];
968
969         if (bone->parent) {
970                 invert_m4_m4(ipar, parchan->pose_mat);
971                 mul_m4_m4m4(mat, ipar, pchan->pose_mat);
972         }
973         else
974                 copy_m4_m4(mat, pchan->pose_mat);
975
976         /* OPEN_SIM_COMPATIBILITY
977         * AFAIK animation to second life is via BVH, but no
978         * reason to not have the collada-animation be correct
979         */
980         if (for_opensim) {
981                 float temp[4][4];
982                 copy_m4_m4(temp, bone->arm_mat);
983                 temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
984                 invert_m4(temp);
985
986                 mul_m4_m4m4(mat, mat, temp);
987
988                 if (bone->parent) {
989                         copy_m4_m4(temp, bone->parent->arm_mat);
990                         temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
991
992                         mul_m4_m4m4(mat, temp, mat);
993                 }
994         }
995         bc_enable_fcurves(action, NULL);
996         return true;
997 }
998
999 bool bc_is_animated(BCMatrixSampleMap &values)
1000 {
1001         static float MIN_DISTANCE = 0.00001;
1002
1003         if (values.size() < 2)
1004                 return false; // need at least 2 entries to be not flat
1005
1006         BCMatrixSampleMap::iterator it;
1007         const BCMatrix *refmat = NULL;
1008         for (it = values.begin(); it != values.end(); ++it) {
1009                 const BCMatrix *matrix = it->second;
1010
1011                 if (refmat == NULL) {
1012                         refmat = matrix;
1013                         continue;
1014                 }
1015
1016                 if (!matrix->in_range(*refmat, MIN_DISTANCE))
1017                         return true;
1018         }
1019         return false;
1020 }
1021
1022 bool bc_has_animations(Object *ob)
1023 {
1024         /* Check for object,lamp and camera transform animations */
1025         if ((bc_getSceneObjectAction(ob) && bc_getSceneObjectAction(ob)->curves.first) ||
1026                 (bc_getSceneLampAction(ob) && bc_getSceneLampAction(ob)->curves.first) ||
1027                 (bc_getSceneCameraAction(ob) && bc_getSceneCameraAction(ob)->curves.first))
1028                 return true;
1029
1030         //Check Material Effect parameter animations.
1031         for (int a = 0; a < ob->totcol; a++) {
1032                 Material *ma = give_current_material(ob, a + 1);
1033                 if (!ma) continue;
1034                 if (ma->adt && ma->adt->action && ma->adt->action->curves.first)
1035                         return true;
1036         }
1037
1038         Key *key = BKE_key_from_object(ob);
1039         if ((key && key->adt && key->adt->action) && key->adt->action->curves.first)
1040                 return true;
1041
1042         return false;
1043 }
1044
1045
1046 bool bc_has_animations(Scene *sce, LinkNode &export_set)
1047 {
1048         LinkNode *node;
1049
1050         for (node = &export_set; node; node = node->next) {
1051                 Object *ob = (Object *)node->link;
1052
1053                 if (bc_has_animations(ob))
1054                         return true;
1055         }
1056         return false;
1057 }
1058
1059 /**
1060  * Check if custom information about bind matrix exists and modify the from_mat
1061  * accordingly.
1062  *
1063  * Note: This is old style for Blender <= 2.78 only kept for compatibility
1064  */
1065 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)
1066 {
1067         float loc[3];
1068         float rot[3];
1069         float scale[3];
1070         static const float V0[3] = { 0, 0, 0 };
1071
1072         if (!has_custom_props(bone, export_settings->keep_bind_info, "restpose_loc") &&
1073                 !has_custom_props(bone, export_settings->keep_bind_info, "restpose_rot") &&
1074                 !has_custom_props(bone, export_settings->keep_bind_info, "restpose_scale"))
1075         {
1076                 /* No need */
1077                 copy_m4_m4(to_mat, from_mat);
1078                 return;
1079         }
1080
1081         bc_decompose(from_mat, loc, rot, NULL, scale);
1082         loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
1083
1084         if (export_settings->keep_bind_info) {
1085                 bc_get_property_vector(bone, "restpose_loc", loc, loc);
1086
1087                 if (use_local_space && bone->parent) {
1088                         Bone *b = bone;
1089                         while (b->parent) {
1090                                 b = b->parent;
1091                                 float ploc[3];
1092                                 bc_get_property_vector(b, "restpose_loc", ploc, V0);
1093                                 loc[0] += ploc[0];
1094                                 loc[1] += ploc[1];
1095                                 loc[2] += ploc[2];
1096                         }
1097                 }
1098         }
1099
1100         if (export_settings->keep_bind_info) {
1101                 if (bc_get_IDProperty(bone, "restpose_rot_x"))
1102                     rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0));
1103                 if (bc_get_IDProperty(bone, "restpose_rot_y"))
1104                         rot[1] = DEG2RADF(bc_get_property(bone, "restpose_rot_y", 0));
1105                 if (bc_get_IDProperty(bone, "restpose_rot_z"))
1106                         rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0));
1107         }
1108
1109         if (export_settings->keep_bind_info) {
1110                 bc_get_property_vector(bone, "restpose_scale", scale, scale);
1111         }
1112
1113         loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
1114
1115 }
1116
1117 /*
1118  * Make 4*4 matrices better readable
1119  */
1120 void bc_sanitize_mat(float mat[4][4], int precision)
1121 {
1122         for (int i = 0; i < 4; i++)
1123                 for (int j = 0; j < 4; j++) {
1124                         double val = (double)mat[i][j];
1125                         val = double_round(val, precision);
1126                         mat[i][j] = (float)val;
1127                 }
1128 }
1129
1130 void bc_sanitize_v3(float v[3], int precision)
1131 {
1132         for (int i = 0; i < 3; i++) {
1133                 double val = (double)v[i];
1134                 val = double_round(val, precision);
1135                 v[i] = (float)val;
1136         }
1137 }
1138
1139 void bc_sanitize_mat(double mat[4][4], int precision)
1140 {
1141         for (int i = 0; i < 4; i++)
1142                 for (int j = 0; j < 4; j++)
1143                         mat[i][j] = double_round(mat[i][j], precision);
1144 }
1145
1146 void bc_sanitize_v3(double v[3], int precision)
1147 {
1148         for (int i = 0; i < 3; i++) {
1149                 v[i] = double_round(v[i], precision);
1150         }
1151 }
1152
1153 void bc_copy_m4_farray(float r[4][4], float *a)
1154 {
1155         for (int i = 0; i < 4; i++)
1156                 for (int j = 0; j < 4; j++)
1157                         r[i][j] = *a++;
1158 }
1159
1160 void bc_copy_farray_m4(float *r, float a[4][4])
1161 {
1162         for (int i = 0; i < 4; i++)
1163                 for (int j = 0; j < 4; j++)
1164                         *r++ = a[i][j];
1165 }
1166
1167 void bc_copy_darray_m4d(double *r, double a[4][4])
1168 {
1169         for (int i = 0; i < 4; i++)
1170                 for (int j = 0; j < 4; j++)
1171                         *r++ = a[i][j];
1172 }
1173
1174 void bc_copy_v44_m4d(std::vector<std::vector<double>> &r, double(&a)[4][4])
1175 {
1176         for (int i = 0; i < 4; i++) {
1177                 for (int j = 0; j < 4; j++) {
1178                         r[i][j] = a[i][j];
1179                 }
1180         }
1181 }
1182
1183 void bc_copy_m4d_v44(double (&r)[4][4], std::vector<std::vector<double>> &a)
1184 {
1185         for (int i = 0; i < 4; i++) {
1186                 for (int j = 0; j < 4; j++) {
1187                         r[i][j] = a[i][j];
1188                 }
1189         }
1190 }
1191
1192 /**
1193  * Returns name of Active UV Layer or empty String if no active UV Layer defined
1194  */
1195 std::string bc_get_active_uvlayer_name(Mesh *me)
1196 {
1197         int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
1198         if (num_layers) {
1199                 char *layer_name = bc_CustomData_get_active_layer_name(&me->ldata, CD_MLOOPUV);
1200                 if (layer_name) {
1201                         return std::string(layer_name);
1202                 }
1203         }
1204         return "";
1205 }
1206
1207 /**
1208  * Returns name of Active UV Layer or empty String if no active UV Layer defined.
1209  * Assuming the Object is of type MESH
1210  */
1211 std::string bc_get_active_uvlayer_name(Object *ob)
1212 {
1213         Mesh *me = (Mesh *)ob->data;
1214         return bc_get_active_uvlayer_name(me);
1215 }
1216
1217 /**
1218  * Returns UV Layer name or empty string if layer index is out of range
1219  */
1220 std::string bc_get_uvlayer_name(Mesh *me, int layer)
1221 {
1222         int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
1223         if (num_layers && layer < num_layers) {
1224                 char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPUV, layer);
1225                 if (layer_name) {
1226                         return std::string(layer_name);
1227                 }
1228         }
1229         return "";
1230 }
1231
1232 std::string bc_find_bonename_in_path(std::string path, std::string probe)
1233 {
1234         std::string result;
1235         char *boneName = BLI_str_quoted_substrN(path.c_str(), probe.c_str());
1236         if (boneName) {
1237                 result = std::string(boneName);
1238                 MEM_freeN(boneName);
1239         }
1240         return result;
1241 }
1242
1243 static bNodeTree *prepare_material_nodetree(Material *ma)
1244 {
1245         if (ma->nodetree == NULL) {
1246                 ma->nodetree = ntreeAddTree(NULL, "Shader Nodetree", "ShaderNodeTree");
1247                 ma->use_nodes = true;
1248         }
1249         return ma->nodetree;
1250 }
1251
1252 bNode *bc_add_node(bContext *C, bNodeTree *ntree, int node_type, int locx, int locy, std::string label)
1253 {
1254         bNode *node = nodeAddStaticNode(C, ntree, node_type);
1255         if (node) {
1256                 if (label.length() > 0) {
1257                         strcpy(node->label, label.c_str());
1258                 }
1259                 node->locx = locx;
1260                 node->locy = locy;
1261                 node->flag |= NODE_SELECT;
1262         }
1263         return node;
1264 }
1265
1266
1267 bNode *bc_add_node(bContext *C, bNodeTree *ntree, int node_type, int locx, int locy)
1268 {
1269         return bc_add_node(C, ntree, node_type, locx, locy, "");
1270 }
1271
1272 #if 0
1273 // experimental, probably not used
1274 static bNodeSocket *bc_group_add_input_socket(bNodeTree *ntree, bNode *to_node, int to_index, std::string label)
1275 {
1276         bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index);
1277
1278         //bNodeSocket *socket = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket);
1279         //return socket;
1280
1281         bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket);
1282         bNode *inputGroup = ntreeFindType(ntree, NODE_GROUP_INPUT);
1283         node_group_input_verify(ntree, inputGroup, (ID *)ntree);
1284         bNodeSocket *newsock = node_group_input_find_socket(inputGroup, gsock->identifier);
1285         nodeAddLink(ntree, inputGroup, newsock, to_node, to_socket);
1286         strcpy(newsock->name, label.c_str());
1287         return newsock;
1288 }
1289
1290 static bNodeSocket *bc_group_add_output_socket(bNodeTree *ntree, bNode *from_node, int from_index, std::string label)
1291 {
1292         bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index);
1293
1294         //bNodeSocket *socket = ntreeAddSocketInterfaceFromSocket(ntree, to_node, to_socket);
1295         //return socket;
1296
1297         bNodeSocket *gsock = ntreeAddSocketInterfaceFromSocket(ntree, from_node, from_socket);
1298         bNode *outputGroup = ntreeFindType(ntree, NODE_GROUP_OUTPUT);
1299         node_group_output_verify(ntree, outputGroup, (ID *)ntree);
1300         bNodeSocket *newsock = node_group_output_find_socket(outputGroup, gsock->identifier);
1301         nodeAddLink(ntree, from_node, from_socket, outputGroup, newsock);
1302         strcpy(newsock->name, label.c_str());
1303         return newsock;
1304 }
1305
1306
1307 void bc_make_group(bContext *C, bNodeTree *ntree, std::map<std::string, bNode *> nmap)
1308 {
1309         bNode *gnode = node_group_make_from_selected(C, ntree, "ShaderNodeGroup", "ShaderNodeTree");
1310         bNodeTree *gtree = (bNodeTree *)gnode->id;
1311
1312         bc_group_add_input_socket(gtree, nmap["main"], 0, "Diffuse");
1313         bc_group_add_input_socket(gtree, nmap["emission"], 0, "Emission");
1314         bc_group_add_input_socket(gtree, nmap["mix"], 0, "Transparency");
1315         bc_group_add_input_socket(gtree, nmap["emission"], 1, "Emission");
1316         bc_group_add_input_socket(gtree, nmap["main"], 4, "Metallic");
1317         bc_group_add_input_socket(gtree, nmap["main"], 5, "Specular");
1318
1319         bc_group_add_output_socket(gtree, nmap["mix"], 0, "Shader");
1320 }
1321 #endif
1322
1323 static void bc_node_add_link(bNodeTree *ntree, bNode *from_node, int from_index, bNode *to_node, int to_index)
1324 {
1325         bNodeSocket *from_socket = (bNodeSocket *)BLI_findlink(&from_node->outputs, from_index);
1326         bNodeSocket *to_socket = (bNodeSocket *)BLI_findlink(&to_node->inputs, to_index);
1327
1328         nodeAddLink(ntree, from_node, from_socket, to_node, to_socket);
1329 }
1330
1331 void bc_add_default_shader(bContext *C, Material *ma)
1332 {
1333         bNodeTree *ntree = prepare_material_nodetree(ma);
1334         std::map<std::string, bNode *> nmap;
1335 #if 0
1336         nmap["main"] = bc_add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED, -300, 300);
1337         nmap["emission"] = bc_add_node(C, ntree, SH_NODE_EMISSION, -300, 500, "emission");
1338         nmap["add"] = bc_add_node(C, ntree, SH_NODE_ADD_SHADER, 100, 400);
1339         nmap["transparent"] = bc_add_node(C, ntree, SH_NODE_BSDF_TRANSPARENT, 100, 200);
1340         nmap["mix"] = bc_add_node(C, ntree, SH_NODE_MIX_SHADER, 400, 300, "transparency");
1341         nmap["out"] = bc_add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 600, 300);
1342         nmap["out"]->flag &= ~NODE_SELECT;
1343
1344         bc_node_add_link(ntree, nmap["emission"], 0, nmap["add"], 0);
1345         bc_node_add_link(ntree, nmap["main"], 0, nmap["add"], 1);
1346         bc_node_add_link(ntree, nmap["add"], 0, nmap["mix"], 1);
1347         bc_node_add_link(ntree, nmap["transparent"], 0, nmap["mix"], 2);
1348
1349         bc_node_add_link(ntree, nmap["mix"], 0, nmap["out"], 0);
1350         // experimental, probably not used.
1351         bc_make_group(C, ntree, nmap);
1352 #else
1353 nmap["main"] = bc_add_node(C, ntree, SH_NODE_BSDF_PRINCIPLED,  0, 300);
1354 nmap["out"] = bc_add_node(C, ntree, SH_NODE_OUTPUT_MATERIAL, 300, 300);
1355 bc_node_add_link(ntree, nmap["main"], 0, nmap["out"], 0);
1356 #endif
1357 }
1358
1359 COLLADASW::ColorOrTexture bc_get_base_color(Material *ma)
1360 {
1361         bNode *master_shader = bc_get_master_shader(ma);
1362         if (master_shader) {
1363                 return bc_get_base_color(master_shader);
1364         }
1365         else {
1366                 return bc_get_cot(ma->r, ma->g, ma->b, ma->alpha);
1367         }
1368 }
1369
1370 COLLADASW::ColorOrTexture bc_get_specular_color(Material *ma, bool use_fallback)
1371 {
1372         bNode *master_shader = bc_get_master_shader(ma);
1373         if (master_shader) {
1374                 return bc_get_specular_color(master_shader);
1375         }
1376         else if (use_fallback) {
1377                 return bc_get_cot(ma->specr * ma->spec, ma->specg * ma->spec, ma->specb * ma->spec, 1.0f);
1378         }
1379         else {
1380                 return bc_get_cot(0.0, 0.0, 0.0, 1.0); // no specular
1381         }
1382 }
1383
1384 COLLADASW::ColorOrTexture bc_get_base_color(bNode *shader)
1385 {
1386         bNodeSocket *socket = nodeFindSocket(shader, SOCK_IN, "Base Color");
1387         if (socket)
1388         {
1389                 bNodeSocketValueRGBA *dcol = (bNodeSocketValueRGBA *)socket->default_value;
1390                 float* col = dcol->value;
1391                 return bc_get_cot(col[0], col[1], col[2], col[3]);
1392         }
1393         else {
1394                 return bc_get_cot(0.8, 0.8, 0.8, 1.0); //default white
1395         }
1396 }
1397
1398 COLLADASW::ColorOrTexture bc_get_specular_color(bNode *shader)
1399 {
1400         bNodeSocket *socket = nodeFindSocket(shader, SOCK_IN, "Specular");
1401         if (socket)
1402         {
1403                 bNodeSocketValueRGBA *dcol = (bNodeSocketValueRGBA *)socket->default_value;
1404                 float* col = dcol->value;
1405                 return bc_get_cot(col[0], col[1], col[2], col[3]);
1406         }
1407         else {
1408                 return bc_get_cot(0.8, 0.8, 0.8, 1.0); //default white
1409         }
1410 }
1411
1412 bNode *bc_get_master_shader(Material *ma)
1413 {
1414         bNodeTree *nodetree = ma->nodetree;
1415         if (nodetree) {
1416                 for (bNode *node = (bNode *)nodetree->nodes.first; node; node = node->next) {
1417                         if (node->typeinfo->type == SH_NODE_BSDF_PRINCIPLED) {
1418                                 return node;
1419                         }
1420                 }
1421         }
1422         return NULL;
1423 }
1424
1425 COLLADASW::ColorOrTexture bc_get_cot(float r, float g, float b, float a)
1426 {
1427         COLLADASW::Color color(r, g, b, a);
1428         COLLADASW::ColorOrTexture cot(color);
1429         return cot;
1430 }