Blender V2.61 - r43446

AnimationExporter.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed.
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00023 #include "GeometryExporter.h"
00024 #include "AnimationExporter.h"
00025 #include "MaterialExporter.h"
00026 
00027 template<class Functor>
00028 void forEachObjectInScene(Scene *sce, Functor &f)
00029 {
00030     Base *base= (Base*) sce->base.first;
00031 
00032     while(base) {
00033         Object *ob = base->object;
00034 
00035         f(ob);
00036 
00037         base= base->next;
00038     }
00039 }
00040 
00041 void AnimationExporter::exportAnimations(Scene *sce)
00042 {
00043     if(hasAnimations(sce)) {
00044         this->scene = sce;
00045 
00046         openLibrary();
00047 
00048         forEachObjectInScene(sce, *this);
00049 
00050         closeLibrary();
00051     }
00052 }
00053 
00054 // called for each exported object
00055 void AnimationExporter::operator() (Object *ob) 
00056 {
00057     FCurve *fcu;
00058     char * transformName ;
00059     /* bool isMatAnim = false; */ /* UNUSED */
00060 
00061     //Export transform animations
00062     if(ob->adt && ob->adt->action)
00063     {
00064         fcu = (FCurve*)ob->adt->action->curves.first;
00065 
00066         //transform matrix export for bones are temporarily disabled here.
00067         if ( ob->type == OB_ARMATURE )
00068         {
00069             bArmature *arm = (bArmature*)ob->data;
00070             for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next)
00071                 write_bone_animation_matrix(ob, bone);
00072         }
00073 
00074         while (fcu) {
00075             //for armature animations as objects
00076             if ( ob->type == OB_ARMATURE )
00077                 transformName =  fcu->rna_path;
00078             else 
00079                 transformName = extract_transform_name( fcu->rna_path );
00080 
00081             if ((!strcmp(transformName, "location") || !strcmp(transformName, "scale")) ||
00082                 (!strcmp(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL)||
00083                 (!strcmp(transformName, "rotation_quaternion"))) 
00084                 dae_animation(ob ,fcu, transformName, false);
00085             fcu = fcu->next;
00086         }
00087 
00088     }
00089 
00090     //Export Lamp parameter animations
00091     if( (ob->type == OB_LAMP ) && ((Lamp*)ob ->data)->adt && ((Lamp*)ob ->data)->adt->action )
00092     {
00093         fcu = (FCurve*)(((Lamp*)ob ->data)->adt->action->curves.first);
00094         while (fcu) {
00095             transformName = extract_transform_name( fcu->rna_path );
00096 
00097             if ((!strcmp(transformName, "color")) || (!strcmp(transformName, "spot_size"))|| (!strcmp(transformName, "spot_blend"))||
00098                 (!strcmp(transformName, "distance")) ) 
00099                 dae_animation(ob , fcu, transformName, true );
00100             fcu = fcu->next;
00101         }
00102     }
00103 
00104     //Export Camera parameter animations
00105     if( (ob->type == OB_CAMERA ) && ((Camera*)ob ->data)->adt && ((Camera*)ob ->data)->adt->action )
00106     {       
00107         fcu = (FCurve*)(((Camera*)ob ->data)->adt->action->curves.first);
00108         while (fcu) {
00109             transformName = extract_transform_name( fcu->rna_path );
00110 
00111             if ((!strcmp(transformName, "lens"))||
00112                 (!strcmp(transformName, "ortho_scale"))||
00113                 (!strcmp(transformName, "clip_end"))||(!strcmp(transformName, "clip_start"))) 
00114                 dae_animation(ob , fcu, transformName, true );
00115             fcu = fcu->next;
00116         }
00117     }
00118 
00119     //Export Material parameter animations.
00120     for(int a = 0; a < ob->totcol; a++)
00121     {
00122         Material *ma = give_current_material(ob, a+1);
00123         if (!ma) continue;
00124         if(ma->adt && ma->adt->action)
00125         {
00126             /* isMatAnim = true; */
00127             fcu = (FCurve*)ma->adt->action->curves.first;
00128             while (fcu) {
00129                 transformName = extract_transform_name( fcu->rna_path );
00130 
00131                 if ((!strcmp(transformName, "specular_hardness"))||(!strcmp(transformName, "specular_color"))
00132                     ||(!strcmp(transformName, "diffuse_color"))||(!strcmp(transformName, "alpha"))||
00133                     (!strcmp(transformName, "ior"))) 
00134                     dae_animation(ob ,fcu, transformName, true, ma );
00135                 fcu = fcu->next;
00136             }
00137         }
00138 
00139     }
00140 }
00141 
00142 //euler sources from quternion sources
00143 float * AnimationExporter::get_eul_source_for_quat(Object *ob )
00144 {
00145     FCurve *fcu = (FCurve*)ob->adt->action->curves.first;
00146     const int keys = fcu->totvert;  
00147     float *quat = (float*)MEM_callocN(sizeof(float) * fcu->totvert * 4, "quat output source values");  
00148     float *eul = (float*)MEM_callocN(sizeof(float) * fcu->totvert * 3, "quat output source values");
00149     float temp_quat[4];
00150     float temp_eul[3];
00151     while(fcu)
00152     {
00153         char * transformName = extract_transform_name( fcu->rna_path );
00154 
00155         if( !strcmp(transformName, "rotation_quaternion") ) { 
00156             for ( int i = 0 ; i < fcu->totvert ; i++){
00157                 *(quat + ( i * 4 ) + fcu->array_index) = fcu->bezt[i].vec[1][1];
00158             }
00159         }
00160         fcu = fcu->next;
00161     }
00162 
00163     for ( int i = 0 ; i < keys ; i++){
00164         for ( int j = 0;j<4;j++)
00165             temp_quat[j] = quat[(i*4)+j];
00166 
00167         quat_to_eul(temp_eul,temp_quat);
00168 
00169         for (int k = 0;k<3;k++)
00170             eul[i*3 + k] = temp_eul[k];
00171 
00172     }
00173     MEM_freeN(quat);
00174     return eul;
00175 
00176 }
00177 
00178 //Get proper name for bones
00179 std::string AnimationExporter::getObjectBoneName( Object* ob,const FCurve* fcu ) 
00180 {
00181     //hard-way to derive the bone name from rna_path. Must find more compact method
00182     std::string rna_path = std::string(fcu->rna_path);
00183 
00184     char* boneName = strtok((char *)rna_path.c_str(), "\"");
00185     boneName = strtok(NULL,"\"");
00186 
00187     if( boneName != NULL )
00188         return /*id_name(ob) + "_" +*/ std::string(boneName);
00189     else        
00190         return id_name(ob);
00191 }
00192 
00193 //convert f-curves to animation curves and write
00194 void AnimationExporter::dae_animation(Object* ob, FCurve *fcu, char* transformName , bool is_param, Material * ma )
00195 {
00196     const char *axis_name = NULL;
00197     char anim_id[200];
00198 
00199     bool has_tangents = false;
00200     bool quatRotation = false;
00201 
00202     if ( !strcmp(transformName, "rotation_quaternion") )
00203     {
00204         fprintf(stderr, "quaternion rotation curves are not supported. rotation curve will not be exported\n");
00205         quatRotation = true;
00206         return;
00207     }
00208 
00209     //axis names for colors
00210     else if ( !strcmp(transformName, "color")||!strcmp(transformName, "specular_color")||!strcmp(transformName, "diffuse_color")||
00211         (!strcmp(transformName, "alpha")))
00212     {
00213         const char *axis_names[] = {"R", "G", "B"};
00214         if (fcu->array_index < 3)
00215             axis_name = axis_names[fcu->array_index];
00216     }
00217 
00218     //axis names for transforms
00219     else if ((!strcmp(transformName, "location") || !strcmp(transformName, "scale")) ||
00220         (!strcmp(transformName, "rotation_euler"))||(!strcmp(transformName, "rotation_quaternion")))
00221     {
00222         const char *axis_names[] = {"X", "Y", "Z"};
00223         if (fcu->array_index < 3)
00224             axis_name = axis_names[fcu->array_index];
00225     }
00226 
00227     //no axis name. single parameter.
00228     else{
00229         axis_name = "";
00230     }
00231 
00232     std::string ob_name = std::string("null");
00233 
00234     //Create anim Id
00235     if (ob->type == OB_ARMATURE) 
00236     {   
00237         ob_name =  getObjectBoneName( ob , fcu);
00238         BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s.%s", (char*)translate_id(ob_name).c_str(),
00239             transformName, axis_name);
00240     }
00241     else 
00242     {
00243         if (ma)
00244             ob_name = id_name(ob) + "_material";
00245         else
00246             ob_name = id_name(ob);
00247         BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(),
00248             fcu->rna_path, axis_name);
00249     }
00250 
00251     openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
00252 
00253     // create input source
00254     std::string input_id = create_source_from_fcurve(COLLADASW::InputSemantic::INPUT, fcu, anim_id, axis_name);
00255 
00256     // create output source
00257     std::string output_id ;
00258 
00259     //quat rotations are skipped for now, because of complications with determining axis.
00260     if(quatRotation) 
00261     {
00262         float * eul  = get_eul_source_for_quat(ob);
00263         float * eul_axis = (float*)MEM_callocN(sizeof(float) * fcu->totvert, "quat output source values");
00264         for ( int i = 0 ; i< fcu->totvert ; i++)
00265             eul_axis[i] = eul[i*3 + fcu->array_index];
00266         output_id= create_source_from_array(COLLADASW::InputSemantic::OUTPUT, eul_axis , fcu->totvert, quatRotation, anim_id, axis_name);
00267         MEM_freeN(eul);
00268         MEM_freeN(eul_axis);
00269     }
00270     else 
00271     {
00272         output_id= create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name);
00273     }
00274     // create interpolations source
00275     std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name, &has_tangents);
00276 
00277     // handle tangents (if required)
00278     std::string intangent_id;
00279     std::string outtangent_id;
00280 
00281     if (has_tangents) {
00282         // create in_tangent source
00283         intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name);
00284 
00285         // create out_tangent source
00286         outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name);
00287     }
00288 
00289     std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
00290     COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
00291     std::string empty;
00292     sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
00293     sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
00294 
00295     // this input is required
00296     sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
00297 
00298     if (has_tangents) {
00299         sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, COLLADABU::URI(empty, intangent_id));
00300         sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, COLLADABU::URI(empty, outtangent_id));
00301     }
00302 
00303     addSampler(sampler);
00304 
00305     std::string target ;
00306 
00307     if ( !is_param )
00308         target = translate_id(ob_name)
00309         + "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true);
00310     else 
00311     {
00312         if ( ob->type == OB_LAMP )
00313             target = get_light_id(ob)
00314             + "/" + get_light_param_sid(fcu->rna_path, -1, axis_name, true);
00315 
00316         if ( ob->type == OB_CAMERA )
00317             target = get_camera_id(ob)
00318             + "/" + get_camera_param_sid(fcu->rna_path, -1, axis_name, true);
00319 
00320         if( ma ) 
00321             target = translate_id(id_name(ma)) + "-effect"
00322             +"/common/" /*profile common is only supported */ + get_transform_sid(fcu->rna_path, -1, axis_name, true);
00323     }
00324     addChannel(COLLADABU::URI(empty, sampler_id), target);
00325 
00326     closeAnimation();
00327 }
00328 
00329 
00330 
00331 //write bone animations in transform matrix sources
00332 void AnimationExporter::write_bone_animation_matrix(Object *ob_arm, Bone *bone)
00333 {
00334     if (!ob_arm->adt)
00335         return;
00336 
00337     //This will only export animations of bones in deform group.
00338     /*if(!is_bone_deform_group(bone))
00339     return;*/
00340 
00341     sample_and_write_bone_animation_matrix(ob_arm, bone);
00342 
00343     for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next)
00344         write_bone_animation_matrix(ob_arm, child);
00345 }
00346 
00347 bool AnimationExporter::is_bone_deform_group(Bone * bone)
00348 {   
00349     bool is_def;
00350     //Check if current bone is deform
00351     if((bone->flag & BONE_NO_DEFORM) == 0 ) return true;
00352     //Check child bones
00353     else 
00354     {   
00355         for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next){
00356             //loop through all the children until deform bone is found, and then return
00357             is_def = is_bone_deform_group(child);
00358             if (is_def) return true;
00359         }
00360     }
00361     //no deform bone found in children also
00362     return false;
00363 }
00364 
00365 void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone)
00366 {
00367     bArmature *arm = (bArmature*)ob_arm->data;
00368     int flag = arm->flag;
00369     std::vector<float> fra;
00370     //char prefix[256];
00371 
00372     FCurve* fcu = (FCurve*)ob_arm->adt->action->curves.first;
00373     while(fcu)
00374     {
00375         std::string bone_name = getObjectBoneName(ob_arm,fcu);
00376         int val = BLI_strcasecmp((char*)bone_name.c_str(),bone->name);
00377         if(val==0) break;
00378         fcu = fcu->next;
00379     }
00380 
00381     if(!(fcu)) return; 
00382     bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name);
00383     if (!pchan)
00384         return;
00385 
00386     find_frames(ob_arm, fra);
00387 
00388     if (flag & ARM_RESTPOS) {
00389         arm->flag &= ~ARM_RESTPOS;
00390         where_is_pose(scene, ob_arm);
00391     }
00392 
00393     if (fra.size()) {
00394         dae_baked_animation(fra ,ob_arm, bone );
00395     }
00396 
00397     if (flag & ARM_RESTPOS) 
00398         arm->flag = flag;
00399     where_is_pose(scene, ob_arm);
00400 }
00401 
00402 void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_arm , Bone *bone)
00403 {
00404     std::string ob_name = id_name(ob_arm);
00405     std::string bone_name = bone->name;
00406     char anim_id[200];
00407 
00408     if (!fra.size())
00409         return;
00410 
00411     BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(),
00412         (char*)translate_id(bone_name).c_str(), "pose_matrix");
00413 
00414     openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
00415 
00416     // create input source
00417     std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
00418 
00419     // create output source
00420     std::string output_id;
00421     output_id = create_4x4_source( fra, ob_arm , bone ,  anim_id);
00422 
00423     // create interpolations source
00424     std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
00425 
00426     std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
00427     COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
00428     std::string empty;
00429     sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
00430     sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
00431 
00432     // TODO create in/out tangents source
00433 
00434     // this input is required
00435     sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
00436 
00437     addSampler(sampler);
00438 
00439     std::string target = translate_id(bone_name) + "/transform";
00440     addChannel(COLLADABU::URI(empty, sampler_id), target);
00441 
00442     closeAnimation();
00443 }
00444 
00445 // dae_bone_animation -> add_bone_animation
00446 // (blend this into dae_bone_animation)
00447 void AnimationExporter::dae_bone_animation(std::vector<float> &fra, float *values, int tm_type, int axis, std::string ob_name, std::string bone_name)
00448 {
00449     const char *axis_names[] = {"X", "Y", "Z"};
00450     const char *axis_name = NULL;
00451     char anim_id[200];
00452     bool is_rot = tm_type == 0;
00453 
00454     if (!fra.size())
00455         return;
00456 
00457     char rna_path[200];
00458     BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(),
00459         tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location"));
00460 
00461     if (axis > -1)
00462         axis_name = axis_names[axis];
00463 
00464     std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name, false);
00465 
00466     BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(),
00467         (char*)translate_id(bone_name).c_str(), (char*)transform_sid.c_str());
00468 
00469     openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
00470 
00471     // create input source
00472     std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, is_rot, anim_id, axis_name);
00473 
00474     // create output source
00475     std::string output_id;
00476     if (axis == -1)
00477         output_id = create_xyz_source(values, fra.size(), anim_id);
00478     else
00479         output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, values, fra.size(), is_rot, anim_id, axis_name);
00480 
00481     // create interpolations source
00482     std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, axis_name);
00483 
00484     std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
00485     COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
00486     std::string empty;
00487     sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
00488     sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
00489 
00490     // TODO create in/out tangents source
00491 
00492     // this input is required
00493     sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
00494 
00495     addSampler(sampler);
00496 
00497     std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid;
00498     addChannel(COLLADABU::URI(empty, sampler_id), target);
00499 
00500     closeAnimation();
00501 }
00502 
00503 float AnimationExporter::convert_time(float frame)
00504 {
00505     return FRA2TIME(frame);
00506 }
00507 
00508 float AnimationExporter::convert_angle(float angle)
00509 {
00510     return COLLADABU::Math::Utils::radToDegF(angle);
00511 }
00512 
00513 std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
00514 {
00515     switch(semantic) {
00516         case COLLADASW::InputSemantic::INPUT:
00517             return INPUT_SOURCE_ID_SUFFIX;
00518         case COLLADASW::InputSemantic::OUTPUT:
00519             return OUTPUT_SOURCE_ID_SUFFIX;
00520         case COLLADASW::InputSemantic::INTERPOLATION:
00521             return INTERPOLATION_SOURCE_ID_SUFFIX;
00522         case COLLADASW::InputSemantic::IN_TANGENT:
00523             return INTANGENT_SOURCE_ID_SUFFIX;
00524         case COLLADASW::InputSemantic::OUT_TANGENT:
00525             return OUTTANGENT_SOURCE_ID_SUFFIX;
00526         default:
00527             break;
00528     }
00529     return "";
00530 }
00531 
00532 void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
00533                                               COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform)
00534 {
00535     switch(semantic) {
00536         case COLLADASW::InputSemantic::INPUT:
00537             param.push_back("TIME");
00538             break;
00539         case COLLADASW::InputSemantic::OUTPUT:
00540             if (is_rot) {
00541                 param.push_back("ANGLE");
00542             }
00543             else {
00544                 if (axis) {
00545                     param.push_back(axis);
00546                 }
00547                 else 
00548                     if ( transform )
00549                     {
00550                         param.push_back("TRANSFORM");  
00551                     }else{ //assumes if axis isn't specified all axises are added
00552                         param.push_back("X");
00553                         param.push_back("Y");
00554                         param.push_back("Z");
00555                     }
00556             }
00557             break;
00558         case COLLADASW::InputSemantic::IN_TANGENT:
00559         case COLLADASW::InputSemantic::OUT_TANGENT:
00560             param.push_back("X");
00561             param.push_back("Y");
00562             break;
00563         default:
00564             break;
00565     }
00566 }
00567 
00568 void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length)
00569 {
00570     switch (semantic) {
00571         case COLLADASW::InputSemantic::INPUT:
00572             *length = 1;
00573             values[0] = convert_time(bezt->vec[1][0]);
00574             break;
00575         case COLLADASW::InputSemantic::OUTPUT:
00576             *length = 1;
00577             if (rotation) {
00578                 values[0] = RAD2DEGF(bezt->vec[1][1]);
00579             }
00580             else {
00581                 values[0] = bezt->vec[1][1];
00582             }
00583             break;
00584 
00585         case COLLADASW::InputSemantic::IN_TANGENT:
00586             *length = 2;
00587             values[0] = convert_time(bezt->vec[0][0]);
00588             if (bezt->ipo != BEZT_IPO_BEZ) {
00589                 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
00590                 values[0] = 0;  
00591                 values[1] = 0;  
00592             }
00593             else if (rotation) {
00594                 values[1] = RAD2DEGF(bezt->vec[0][1]);
00595             } else {
00596                 values[1] = bezt->vec[0][1];
00597             }
00598             break;
00599 
00600         case COLLADASW::InputSemantic::OUT_TANGENT:
00601             *length = 2;
00602             values[0] = convert_time(bezt->vec[2][0]);
00603             if (bezt->ipo != BEZT_IPO_BEZ) {
00604                 // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
00605                 values[0] = 0;  
00606                 values[1] = 0;  
00607             }
00608             else if (rotation) {
00609                 values[1] = RAD2DEGF(bezt->vec[2][1]);
00610             } else {
00611                 values[1] = bezt->vec[2][1];
00612             }
00613             break;
00614             break;
00615         default:
00616             *length = 0;
00617             break;
00618     }
00619 }
00620 
00621 std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name)
00622 {
00623     std::string source_id = anim_id + get_semantic_suffix(semantic);
00624 
00625     //bool is_rotation = !strcmp(fcu->rna_path, "rotation");
00626     bool is_angle = false;
00627 
00628     if (strstr(fcu->rna_path, "rotation")) is_angle = true;
00629 
00630     COLLADASW::FloatSourceF source(mSW);
00631     source.setId(source_id);
00632     source.setArrayId(source_id + ARRAY_ID_SUFFIX);
00633     source.setAccessorCount(fcu->totvert);
00634 
00635     switch (semantic) {
00636         case COLLADASW::InputSemantic::INPUT:
00637         case COLLADASW::InputSemantic::OUTPUT:
00638             source.setAccessorStride(1);            
00639             break;
00640         case COLLADASW::InputSemantic::IN_TANGENT:
00641         case COLLADASW::InputSemantic::OUT_TANGENT:
00642             source.setAccessorStride(2);            
00643             break;
00644         default:
00645             break;
00646     }
00647 
00648 
00649     COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
00650     add_source_parameters(param, semantic, is_angle, axis_name, false);
00651 
00652     source.prepareToAppendValues();
00653 
00654     for (unsigned int i = 0; i < fcu->totvert; i++) {
00655         float values[3]; // be careful!
00656         int length = 0;
00657         get_source_values(&fcu->bezt[i], semantic, is_angle, values, &length);
00658         for (int j = 0; j < length; j++)
00659             source.appendValues(values[j]);
00660     }
00661 
00662     source.finish();
00663 
00664     return source_id;
00665 }
00666 
00667 //Currently called only to get OUTPUT source values ( if rotation and hence the axis is also specified )
00668 std::string AnimationExporter::create_source_from_array(COLLADASW::InputSemantic::Semantics semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name)
00669 {
00670     std::string source_id = anim_id + get_semantic_suffix(semantic);
00671 
00672     COLLADASW::FloatSourceF source(mSW);
00673     source.setId(source_id);
00674     source.setArrayId(source_id + ARRAY_ID_SUFFIX);
00675     source.setAccessorCount(tot);
00676     source.setAccessorStride(1);
00677 
00678     COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
00679     add_source_parameters(param, semantic, is_rot, axis_name,  false);
00680 
00681     source.prepareToAppendValues();
00682 
00683     for (int i = 0; i < tot; i++) {
00684         float val = v[i];
00686         //  val = convert_time(val);
00687         //else
00688         if (is_rot)
00689             val = RAD2DEGF(val);
00690         source.appendValues(val);
00691     }
00692 
00693     source.finish();
00694 
00695     return source_id;
00696 }
00697 // only used for sources with INPUT semantic
00698 std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name)
00699 {
00700     std::string source_id = anim_id + get_semantic_suffix(semantic);
00701 
00702     COLLADASW::FloatSourceF source(mSW);
00703     source.setId(source_id);
00704     source.setArrayId(source_id + ARRAY_ID_SUFFIX);
00705     source.setAccessorCount(fra.size());
00706     source.setAccessorStride(1);
00707 
00708     COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
00709     add_source_parameters(param, semantic, is_rot, axis_name, false);
00710 
00711     source.prepareToAppendValues();
00712 
00713     std::vector<float>::iterator it;
00714     for (it = fra.begin(); it != fra.end(); it++) {
00715         float val = *it;
00716         //if (semantic == COLLADASW::InputSemantic::INPUT)
00717         val = convert_time(val);
00718         /*else if (is_rot)
00719         val = convert_angle(val);*/
00720         source.appendValues(val);
00721     }
00722 
00723     source.finish();
00724 
00725     return source_id;
00726 }
00727 
00728 std::string AnimationExporter::create_4x4_source(std::vector<float> &frames , Object * ob_arm, Bone *bone , const std::string& anim_id)
00729 {
00730     COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
00731     std::string source_id = anim_id + get_semantic_suffix(semantic);
00732 
00733     COLLADASW::Float4x4Source source(mSW);
00734     source.setId(source_id);
00735     source.setArrayId(source_id + ARRAY_ID_SUFFIX);
00736     source.setAccessorCount(frames.size());
00737     source.setAccessorStride(16);
00738 
00739     COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
00740     add_source_parameters(param, semantic, false, NULL, true);
00741 
00742     source.prepareToAppendValues();
00743 
00744     bPoseChannel *parchan = NULL;
00745     bPoseChannel *pchan = NULL;
00746     bPose *pose = ob_arm->pose;
00747 
00748     pchan = get_pose_channel(pose, bone->name);
00749 
00750     if (!pchan)
00751         return "";
00752 
00753     parchan = pchan->parent;
00754 
00755     enable_fcurves(ob_arm->adt->action, bone->name);
00756 
00757     std::vector<float>::iterator it;
00758     int j = 0;
00759     for (it = frames.begin(); it != frames.end(); it++) {
00760         float mat[4][4], ipar[4][4];
00761 
00762         float ctime = BKE_frame_to_ctime(scene, *it);
00763 
00764         BKE_animsys_evaluate_animdata(scene , &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
00765         where_is_pose_bone(scene, ob_arm, pchan, ctime, 1);
00766 
00767         // compute bone local mat
00768         if (bone->parent) {
00769             invert_m4_m4(ipar, parchan->pose_mat);
00770             mult_m4_m4m4(mat, ipar, pchan->pose_mat);
00771         }
00772         else
00773             copy_m4_m4(mat, pchan->pose_mat);
00774         UnitConverter converter;
00775 
00776         float outmat[4][4];
00777         converter.mat4_to_dae(outmat,mat);
00778 
00779 
00780         source.appendValues(outmat);
00781 
00782 
00783         j++;
00784     }
00785 
00786     enable_fcurves(ob_arm->adt->action, NULL);
00787 
00788     source.finish();
00789 
00790     return source_id;
00791 }
00792 // only used for sources with OUTPUT semantic ( locations and scale)
00793 std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id)
00794 {
00795     COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
00796     std::string source_id = anim_id + get_semantic_suffix(semantic);
00797 
00798     COLLADASW::FloatSourceF source(mSW);
00799     source.setId(source_id);
00800     source.setArrayId(source_id + ARRAY_ID_SUFFIX);
00801     source.setAccessorCount(tot);
00802     source.setAccessorStride(3);
00803 
00804     COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
00805     add_source_parameters(param, semantic, false, NULL, false);
00806 
00807     source.prepareToAppendValues();
00808 
00809     for (int i = 0; i < tot; i++) {
00810         source.appendValues(*v, *(v + 1), *(v + 2));
00811         v += 3;
00812     }
00813 
00814     source.finish();
00815 
00816     return source_id;
00817 }
00818 
00819 std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents)
00820 {
00821     std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
00822 
00823     COLLADASW::NameSource source(mSW);
00824     source.setId(source_id);
00825     source.setArrayId(source_id + ARRAY_ID_SUFFIX);
00826     source.setAccessorCount(fcu->totvert);
00827     source.setAccessorStride(1);
00828 
00829     COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
00830     param.push_back("INTERPOLATION");
00831 
00832     source.prepareToAppendValues();
00833 
00834     *has_tangents = false;
00835 
00836     for (unsigned int i = 0; i < fcu->totvert; i++) {
00837         if (fcu->bezt[i].ipo==BEZT_IPO_BEZ) {
00838             source.appendValues(BEZIER_NAME);
00839             *has_tangents = true;
00840         } else if (fcu->bezt[i].ipo==BEZT_IPO_CONST) {
00841             source.appendValues(STEP_NAME);
00842         } else { // BEZT_IPO_LIN
00843             source.appendValues(LINEAR_NAME);
00844         }
00845     }
00846     // unsupported? -- HERMITE, CARDINAL, BSPLINE, NURBS
00847 
00848     source.finish();
00849 
00850     return source_id;
00851 }
00852 
00853 std::string AnimationExporter::fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name)
00854 {
00855     std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
00856 
00857     COLLADASW::NameSource source(mSW);
00858     source.setId(source_id);
00859     source.setArrayId(source_id + ARRAY_ID_SUFFIX);
00860     source.setAccessorCount(tot);
00861     source.setAccessorStride(1);
00862 
00863     COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
00864     param.push_back("INTERPOLATION");
00865 
00866     source.prepareToAppendValues();
00867 
00868     for (int i = 0; i < tot; i++) {
00869         source.appendValues(LINEAR_NAME);
00870     }
00871 
00872     source.finish();
00873 
00874     return source_id;
00875 }
00876 
00877 std::string AnimationExporter::get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
00878 {
00879     std::string tm_name;
00880     // when given rna_path, determine tm_type from it
00881     if (rna_path) {
00882         char *name = extract_transform_name(rna_path);
00883 
00884         if (!strcmp(name, "color"))
00885             tm_type = 1;
00886         else if (!strcmp(name, "spot_size"))
00887             tm_type = 2;
00888         else if (!strcmp(name, "spot_blend"))
00889             tm_type = 3;
00890         else if (!strcmp(name, "distance"))
00891             tm_type = 4;
00892         else
00893             tm_type = -1;
00894     }
00895 
00896     switch (tm_type) {
00897         case 1:
00898             tm_name = "color";
00899             break;
00900         case 2:
00901             tm_name = "fall_off_angle";
00902             break;
00903         case 3:
00904             tm_name = "fall_off_exponent";
00905             break;
00906         case 4:
00907             tm_name = "blender/blender_dist";
00908             break;
00909 
00910         default:
00911             tm_name = "";
00912             break;
00913     }
00914 
00915     if (tm_name.size()) {
00916         if (axis_name[0])
00917             return tm_name + "." + std::string(axis_name);
00918         else 
00919             return tm_name;
00920     }
00921 
00922     return std::string("");
00923 }
00924 
00925 std::string AnimationExporter::get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
00926 {
00927     std::string tm_name;
00928     // when given rna_path, determine tm_type from it
00929     if (rna_path) {
00930         char *name = extract_transform_name(rna_path);
00931 
00932         if (!strcmp(name, "lens"))
00933             tm_type = 0;
00934         else if (!strcmp(name, "ortho_scale"))
00935             tm_type = 1;
00936         else if (!strcmp(name, "clip_end"))
00937             tm_type = 2;
00938         else if (!strcmp(name, "clip_start"))
00939             tm_type = 3;
00940 
00941         else
00942             tm_type = -1;
00943     }
00944 
00945     switch (tm_type) {
00946         case 0:
00947             tm_name = "xfov";
00948             break;
00949         case 1:
00950             tm_name = "xmag";
00951             break;
00952         case 2:
00953             tm_name = "zfar";
00954             break;
00955         case 3:
00956             tm_name = "znear";
00957             break;
00958 
00959         default:
00960             tm_name = "";
00961             break;
00962     }
00963 
00964     if (tm_name.size()) {
00965         if (axis_name[0])
00966             return tm_name + "." + std::string(axis_name);
00967         else 
00968             return tm_name;
00969     }
00970 
00971     return std::string("");
00972 }
00973 
00974 // Assign sid of the animated parameter or transform 
00975 // for rotation, axis name is always appended and the value of append_axis is ignored
00976 std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
00977 {
00978     std::string tm_name;
00979     bool is_rotation =false;
00980     // when given rna_path, determine tm_type from it
00981     if (rna_path) {
00982         char *name = extract_transform_name(rna_path);
00983 
00984         if (!strcmp(name, "rotation_euler"))
00985             tm_type = 0;
00986         else if (!strcmp(name, "rotation_quaternion"))
00987             tm_type = 1;
00988         else if (!strcmp(name, "scale"))
00989             tm_type = 2;
00990         else if (!strcmp(name, "location"))
00991             tm_type = 3;
00992         else if (!strcmp(name, "specular_hardness"))
00993             tm_type = 4;
00994         else if (!strcmp(name, "specular_color"))
00995             tm_type = 5;
00996         else if (!strcmp(name, "diffuse_color"))
00997             tm_type = 6;
00998         else if (!strcmp(name, "alpha"))
00999             tm_type = 7;
01000         else if (!strcmp(name, "ior"))
01001             tm_type = 8;
01002 
01003         else
01004             tm_type = -1;
01005     }
01006 
01007     switch (tm_type) {
01008         case 0:
01009         case 1:
01010             tm_name = "rotation";
01011             is_rotation = true;
01012             break;
01013         case 2:
01014             tm_name = "scale";
01015             break;
01016         case 3:
01017             tm_name = "location";
01018             break;
01019         case 4:
01020             tm_name = "shininess";
01021             break;
01022         case 5:
01023             tm_name = "specular";
01024             break;
01025         case 6:
01026             tm_name = "diffuse";
01027             break;  
01028         case 7:
01029             tm_name = "transparency";
01030             break;  
01031         case 8:
01032             tm_name = "index_of_refraction";
01033             break;  
01034 
01035         default:
01036             tm_name = "";
01037             break;
01038     }
01039 
01040     if (tm_name.size()) {
01041         if (is_rotation)
01042             return tm_name + std::string(axis_name) + ".ANGLE";
01043         else
01044             if (axis_name[0])
01045                 return tm_name + "." + std::string(axis_name);
01046             else 
01047                 return tm_name;
01048     }
01049 
01050     return std::string("");
01051 }
01052 
01053 char* AnimationExporter::extract_transform_name(char *rna_path)
01054 {
01055     char *dot = strrchr(rna_path, '.');
01056     return dot ? (dot + 1) : rna_path;
01057 }
01058 
01059 //find keyframes of all the objects animations
01060 void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra)
01061 {
01062     FCurve *fcu= (FCurve*)ob->adt->action->curves.first;
01063 
01064     for (; fcu; fcu = fcu->next) {
01065 
01066         for (unsigned int i = 0; i < fcu->totvert; i++) {
01067             float f = fcu->bezt[i].vec[1][0];
01068             if (std::find(fra.begin(), fra.end(), f) == fra.end())   
01069                 fra.push_back(f);
01070         }
01071     }
01072 
01073     // keep the keys in ascending order
01074     std::sort(fra.begin(), fra.end());
01075 }
01076 
01077 
01078 
01079 // enable fcurves driving a specific bone, disable all the rest
01080 // if bone_name = NULL enable all fcurves
01081 void AnimationExporter::enable_fcurves(bAction *act, char *bone_name)
01082 {
01083     FCurve *fcu;
01084     char prefix[200];
01085 
01086     if (bone_name)
01087         BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
01088 
01089     for (fcu = (FCurve*)act->curves.first; fcu; fcu = fcu->next) {
01090         if (bone_name) {
01091             if (!strncmp(fcu->rna_path, prefix, strlen(prefix)))
01092                 fcu->flag &= ~FCURVE_DISABLED;
01093             else
01094                 fcu->flag |= FCURVE_DISABLED;
01095         }
01096         else {
01097             fcu->flag &= ~FCURVE_DISABLED;
01098         }
01099     }
01100 }
01101 
01102 bool AnimationExporter::hasAnimations(Scene *sce)
01103 {
01104     Base *base= (Base*) sce->base.first;
01105 
01106     while(base) {
01107         Object *ob = base->object;
01108 
01109         FCurve *fcu = 0;
01110         //Check for object transform animations
01111         if(ob->adt && ob->adt->action)
01112             fcu = (FCurve*)ob->adt->action->curves.first;
01113         //Check for Lamp parameter animations
01114         else if( (ob->type == OB_LAMP ) && ((Lamp*)ob ->data)->adt && ((Lamp*)ob ->data)->adt->action )
01115             fcu = (FCurve*)(((Lamp*)ob ->data)->adt->action->curves.first);
01116         //Check for Camera parameter animations
01117         else if( (ob->type == OB_CAMERA ) && ((Camera*)ob ->data)->adt && ((Camera*)ob ->data)->adt->action )
01118             fcu = (FCurve*)(((Camera*)ob ->data)->adt->action->curves.first);
01119 
01120         //Check Material Effect parameter animations.
01121         for(int a = 0; a < ob->totcol; a++)
01122         {
01123             Material *ma = give_current_material(ob, a+1);
01124             if (!ma) continue;
01125             if(ma->adt && ma->adt->action)
01126             {
01127                 fcu = (FCurve*)ma->adt->action->curves.first;   
01128             }
01129         }
01130 
01131         if ( fcu) 
01132             return true;
01133         base= base->next;
01134     }
01135     return false;
01136 }
01137 
01138 //------------------------------- Not used in the new system.--------------------------------------------------------
01139 void AnimationExporter::find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
01140 {
01141     if (rotmode > 0)
01142         find_frames(ob, fra, prefix, "rotation_euler");
01143     else if (rotmode == ROT_MODE_QUAT)
01144         find_frames(ob, fra, prefix, "rotation_quaternion");
01145     /*else if (rotmode == ROT_MODE_AXISANGLE)
01146     ;*/
01147 }
01148 
01149 void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
01150 {
01151     FCurve *fcu= (FCurve*)ob->adt->action->curves.first;
01152 
01153     for (; fcu; fcu = fcu->next) {
01154         if (prefix && strncmp(prefix, fcu->rna_path, strlen(prefix)))
01155             continue;
01156 
01157         char *name = extract_transform_name(fcu->rna_path);
01158         if (!strcmp(name, tm_name)) {
01159             for (unsigned int i = 0; i < fcu->totvert; i++) {
01160                 float f = fcu->bezt[i].vec[1][0];
01161                 if (std::find(fra.begin(), fra.end(), f) == fra.end())   
01162                     fra.push_back(f);
01163             }
01164         }
01165     }
01166 
01167     // keep the keys in ascending order
01168     std::sort(fra.begin(), fra.end());
01169 }
01170 
01171 void AnimationExporter::write_bone_animation(Object *ob_arm, Bone *bone)
01172 {
01173     if (!ob_arm->adt)
01174         return;
01175 
01176     //write bone animations for 3 transform types
01177     //i=0 --> rotations
01178     //i=1 --> scale
01179     //i=2 --> location
01180     for (int i = 0; i < 3; i++)
01181         sample_and_write_bone_animation(ob_arm, bone, i);
01182 
01183     for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next)
01184         write_bone_animation(ob_arm, child);
01185 }
01186 
01187 void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type)
01188 {
01189     bArmature *arm = (bArmature*)ob_arm->data;
01190     int flag = arm->flag;
01191     std::vector<float> fra;
01192     char prefix[256];
01193 
01194     BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name);
01195 
01196     bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name);
01197     if (!pchan)
01198         return;
01199     //Fill frame array with key frame values framed at @param:transform_type
01200     switch (transform_type) {
01201         case 0:
01202             find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
01203             break;
01204         case 1:
01205             find_frames(ob_arm, fra, prefix, "scale");
01206             break;
01207         case 2:
01208             find_frames(ob_arm, fra, prefix, "location");
01209             break;
01210         default:
01211             return;
01212     }
01213 
01214     // exit rest position
01215     if (flag & ARM_RESTPOS) {
01216         arm->flag &= ~ARM_RESTPOS;
01217         where_is_pose(scene, ob_arm);
01218     }
01219     //v array will hold all values which will be exported. 
01220     if (fra.size()) {
01221         float *values = (float*)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames");
01222         sample_animation(values, fra, transform_type, bone, ob_arm, pchan);
01223 
01224         if (transform_type == 0) {
01225             // write x, y, z curves separately if it is rotation
01226             float *axisValues = (float*)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames");   
01227 
01228             for (int i = 0; i < 3; i++) {
01229                 for (unsigned int j = 0; j < fra.size(); j++)
01230                     axisValues[j] = values[j * 3 + i];
01231 
01232                 dae_bone_animation(fra, axisValues, transform_type, i, id_name(ob_arm), bone->name);
01233             }
01234             MEM_freeN(axisValues);
01235         }
01236         else {
01237             // write xyz at once if it is location or scale
01238             dae_bone_animation(fra, values, transform_type, -1, id_name(ob_arm), bone->name);
01239         }
01240 
01241         MEM_freeN(values);
01242     }
01243 
01244     // restore restpos
01245     if (flag & ARM_RESTPOS) 
01246         arm->flag = flag;
01247     where_is_pose(scene, ob_arm);
01248 }
01249 
01250 void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan)
01251 {
01252     bPoseChannel *parchan = NULL;
01253     bPose *pose = ob_arm->pose;
01254 
01255     pchan = get_pose_channel(pose, bone->name);
01256 
01257     if (!pchan)
01258         return;
01259 
01260     parchan = pchan->parent;
01261 
01262     enable_fcurves(ob_arm->adt->action, bone->name);
01263 
01264     std::vector<float>::iterator it;
01265     for (it = frames.begin(); it != frames.end(); it++) {
01266         float mat[4][4], ipar[4][4];
01267 
01268         float ctime = BKE_frame_to_ctime(scene, *it);
01269 
01270 
01271         BKE_animsys_evaluate_animdata(scene , &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
01272         where_is_pose_bone(scene, ob_arm, pchan, ctime, 1);
01273 
01274         // compute bone local mat
01275         if (bone->parent) {
01276             invert_m4_m4(ipar, parchan->pose_mat);
01277             mult_m4_m4m4(mat, ipar, pchan->pose_mat);
01278         }
01279         else
01280             copy_m4_m4(mat, pchan->pose_mat);
01281 
01282         switch (type) {
01283             case 0:
01284                 mat4_to_eul(v, mat);
01285                 break;
01286             case 1:
01287                 mat4_to_size(v, mat);
01288                 break;
01289             case 2:
01290                 copy_v3_v3(v, mat[3]);
01291                 break;
01292         }
01293 
01294         v += 3;
01295     }
01296 
01297     enable_fcurves(ob_arm->adt->action, NULL);
01298 }