Blender V2.61 - r43446

editarmature_retarget.c

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): Martin Poirier
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  * autoarmature.c: Interface for automagically manipulating armature (retarget, created, ...)
00022  */
00023 
00029 #include <ctype.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <math.h> 
00033 #include <float.h>
00034 
00035 #include "MEM_guardedalloc.h"
00036 
00037 #include "PIL_time.h"
00038 
00039 #include "DNA_armature_types.h"
00040 #include "DNA_constraint_types.h"
00041 #include "DNA_scene_types.h"
00042 #include "DNA_object_types.h"
00043 
00044 #include "BLI_blenlib.h"
00045 #include "BLI_math.h"
00046 #include "BLI_editVert.h"
00047 #include "BLI_utildefines.h"
00048 #include "BLI_ghash.h"
00049 #include "BLI_graph.h"
00050 #include "BLI_rand.h"
00051 #include "BLI_threads.h"
00052 
00053 //#include "BDR_editobject.h"
00054 
00055 #include "BKE_constraint.h"
00056 #include "BKE_armature.h"
00057 #include "BKE_context.h"
00058 
00059 #include "ED_armature.h"
00060 #include "ED_util.h"
00061 
00062 #include "BIF_retarget.h"
00063 
00064 
00065 //#include "mydevice.h"
00066 #include "reeb.h" // FIX ME
00067 //#include "blendef.h"
00068 
00069 #include "armature_intern.h"
00070 
00071 /************ RIG RETARGET DATA STRUCTURES ***************/
00072 
00073 typedef struct MemoNode {
00074     float   weight;
00075     int     next;
00076 } MemoNode;
00077 
00078 typedef struct RetargetParam {
00079     RigGraph    *rigg;
00080     RigArc      *iarc;
00081     RigNode     *inode_start;
00082     bContext    *context;
00083 } RetargetParam;
00084 
00085 typedef enum 
00086 {
00087     RETARGET_LENGTH,
00088     RETARGET_AGGRESSIVE
00089 } RetargetMode; 
00090 
00091 typedef enum
00092 {
00093     METHOD_BRUTE_FORCE = 0,
00094     METHOD_MEMOIZE = 1
00095 } RetargetMethod;
00096 
00097 typedef enum
00098 {
00099     ARC_FREE = 0,
00100     ARC_TAKEN = 1,
00101     ARC_USED = 2
00102 } ArcUsageFlags;
00103 
00104 static RigGraph *GLOBAL_RIGG = NULL;
00105 
00106 /*******************************************************************************************************/
00107 
00108 void *exec_retargetArctoArc(void *param);
00109 
00110 static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second);
00111 float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4]);
00112 
00113 /* two levels */
00114 #define SHAPE_LEVELS (SHAPE_RADIX * SHAPE_RADIX) 
00115 
00116 /*********************************** EDITBONE UTILS ****************************************************/
00117 
00118 static int countEditBoneChildren(ListBase *list, EditBone *parent)
00119 {
00120     EditBone *ebone;
00121     int count = 0;
00122     
00123     for (ebone = list->first; ebone; ebone = ebone->next)
00124     {
00125         if (ebone->parent == parent)
00126         {
00127             count++;
00128         }
00129     }
00130     
00131     return count;
00132 }
00133 
00134 static EditBone* nextEditBoneChild(ListBase *list, EditBone *parent, int n)
00135 {
00136     EditBone *ebone;
00137     
00138     for (ebone = list->first; ebone; ebone = ebone->next)
00139     {
00140         if (ebone->parent == parent)
00141         {
00142             if (n == 0)
00143             {
00144                 return ebone;
00145             }
00146             n--;
00147         }
00148     }
00149     
00150     return NULL;
00151 }
00152 
00153 static void getEditBoneRollUpAxis(EditBone *bone, float roll, float up_axis[3])
00154 {
00155     float mat[3][3], nor[3];
00156 
00157     sub_v3_v3v3(nor, bone->tail, bone->head);
00158     
00159     vec_roll_to_mat3(nor, roll, mat);
00160     copy_v3_v3(up_axis, mat[2]);
00161 }
00162 
00163 static float rollBoneByQuatAligned(EditBone *bone, float old_up_axis[3], float qrot[4], float qroll[4], float aligned_axis[3])
00164 {
00165     float nor[3], new_up_axis[3], x_axis[3], z_axis[3];
00166     
00167     copy_v3_v3(new_up_axis, old_up_axis);
00168     mul_qt_v3(qrot, new_up_axis);
00169     
00170     sub_v3_v3v3(nor, bone->tail, bone->head);
00171     
00172     cross_v3_v3v3(x_axis, nor, aligned_axis);
00173     cross_v3_v3v3(z_axis, x_axis, nor);
00174     
00175     normalize_v3(new_up_axis);
00176     normalize_v3(x_axis);
00177     normalize_v3(z_axis);
00178     
00179     if (dot_v3v3(new_up_axis, x_axis) < 0)
00180     {
00181         negate_v3(x_axis);
00182     }
00183     
00184     if (dot_v3v3(new_up_axis, z_axis) < 0)
00185     {
00186         negate_v3(z_axis);
00187     }
00188     
00189     if (angle_normalized_v3v3(x_axis, new_up_axis) < angle_normalized_v3v3(z_axis, new_up_axis))
00190     {
00191         rotation_between_vecs_to_quat(qroll, new_up_axis, x_axis); /* set roll rotation quat */
00192         return ED_rollBoneToVector(bone, x_axis, FALSE);
00193     }
00194     else
00195     {
00196         rotation_between_vecs_to_quat(qroll, new_up_axis, z_axis); /* set roll rotation quat */
00197         return ED_rollBoneToVector(bone, z_axis, FALSE);
00198     }
00199 }
00200 
00201 static float rollBoneByQuatJoint(RigEdge *edge, RigEdge *previous, float qrot[4], float qroll[4], float up_axis[3])
00202 {
00203     if (previous == NULL)
00204     {
00205         /* default to up_axis if no previous */
00206         return rollBoneByQuatAligned(edge->bone, edge->up_axis, qrot, qroll, up_axis);
00207     }
00208     else
00209     {
00210         float new_up_axis[3];
00211         float vec_first[3], vec_second[3], normal[3];
00212         
00213         if (previous->bone)
00214         {
00215             sub_v3_v3v3(vec_first, previous->bone->tail, previous->bone->head);
00216         } 
00217         else if (previous->prev->bone)
00218         {
00219             sub_v3_v3v3(vec_first, edge->bone->head, previous->prev->bone->tail);
00220         }
00221         else
00222         {
00223             /* default to up_axis if first bone in the chain is an offset */
00224             return rollBoneByQuatAligned(edge->bone, edge->up_axis, qrot, qroll, up_axis);
00225         }
00226         
00227         sub_v3_v3v3(vec_second, edge->bone->tail, edge->bone->head);
00228     
00229         normalize_v3(vec_first);
00230         normalize_v3(vec_second);
00231         
00232         cross_v3_v3v3(normal, vec_first, vec_second);
00233         normalize_v3(normal);
00234         
00235         axis_angle_to_quat(qroll, vec_second, edge->up_angle);
00236         
00237         mul_qt_v3(qroll, normal);
00238             
00239         copy_v3_v3(new_up_axis, edge->up_axis);
00240         mul_qt_v3(qrot, new_up_axis);
00241         
00242         normalize_v3(new_up_axis);
00243         
00244         /* real qroll between normal and up_axis */
00245         rotation_between_vecs_to_quat(qroll, new_up_axis, normal);
00246 
00247         return ED_rollBoneToVector(edge->bone, normal, FALSE);
00248     }
00249 }
00250 
00251 float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4])
00252 {
00253     float new_up_axis[3];
00254     
00255     copy_v3_v3(new_up_axis, old_up_axis);
00256     mul_qt_v3(qrot, new_up_axis);
00257     
00258     return ED_rollBoneToVector(bone, new_up_axis, FALSE);
00259 }
00260 
00261 /************************************ DESTRUCTORS ******************************************************/
00262 
00263 static void RIG_freeRigArc(BArc *arc)
00264 {
00265     BLI_freelistN(&((RigArc*)arc)->edges);
00266 }
00267 
00268 void RIG_freeRigGraph(BGraph *rg)
00269 {
00270     RigGraph *rigg = (RigGraph*)rg;
00271     BNode *node;
00272     BArc *arc;
00273     
00274 #ifdef USE_THREADS
00275     BLI_destroy_worker(rigg->worker);
00276 #endif
00277     
00278     if (rigg->link_mesh)
00279     {
00280         REEB_freeGraph(rigg->link_mesh);
00281     }
00282     
00283     for (arc = rg->arcs.first; arc; arc = arc->next)
00284     {
00285         RIG_freeRigArc(arc);
00286     }
00287     BLI_freelistN(&rg->arcs);
00288     
00289     for (node = rg->nodes.first; node; node = node->next)
00290     {
00291         BLI_freeNode(rg, (BNode*)node);
00292     }
00293     BLI_freelistN(&rg->nodes);
00294     
00295     BLI_freelistN(&rigg->controls);
00296 
00297     BLI_ghash_free(rigg->bones_map, NULL, NULL);
00298     BLI_ghash_free(rigg->controls_map, NULL, NULL);
00299     
00300     if (rigg->flag & RIG_FREE_BONELIST)
00301     {
00302         BLI_freelistN(rigg->editbones);
00303         MEM_freeN(rigg->editbones);
00304     }
00305     
00306     MEM_freeN(rg);
00307 }
00308 
00309 /************************************* ALLOCATORS ******************************************************/
00310 
00311 static RigGraph *newRigGraph(void)
00312 {
00313     RigGraph *rg;
00314     int totthread;
00315     
00316     rg = MEM_callocN(sizeof(RigGraph), "rig graph");
00317     
00318     rg->head = NULL;
00319     
00320     rg->bones_map = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "newRigGraph bones gh");
00321     rg->controls_map = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "newRigGraph cont gh");
00322     
00323     rg->free_arc = RIG_freeRigArc;
00324     rg->free_node = NULL;
00325     
00326 #ifdef USE_THREADS
00327 //  if(G.scene->r.mode & R_FIXED_THREADS)
00328 //  {
00329 //      totthread = G.scene->r.threads;
00330 //  }
00331 //  else
00332 //  {
00333         totthread = BLI_system_thread_count();
00334 //  }
00335     
00336     rg->worker = BLI_create_worker(exec_retargetArctoArc, totthread, 20); /* fix number of threads */
00337 #endif
00338     
00339     return rg;
00340 }
00341 
00342 static RigArc *newRigArc(RigGraph *rg)
00343 {
00344     RigArc *arc;
00345     
00346     arc = MEM_callocN(sizeof(RigArc), "rig arc");
00347     arc->count = 0;
00348     BLI_addtail(&rg->arcs, arc);
00349     
00350     return arc;
00351 }
00352 
00353 static RigControl *newRigControl(RigGraph *rg)
00354 {
00355     RigControl *ctrl;
00356     
00357     ctrl = MEM_callocN(sizeof(RigControl), "rig control");
00358     
00359     BLI_addtail(&rg->controls, ctrl);
00360     
00361     return ctrl;
00362 }
00363 
00364 static RigNode *newRigNodeHead(RigGraph *rg, RigArc *arc, float p[3])
00365 {
00366     RigNode *node;
00367     node = MEM_callocN(sizeof(RigNode), "rig node");
00368     BLI_addtail(&rg->nodes, node);
00369 
00370     copy_v3_v3(node->p, p);
00371     node->degree = 1;
00372     node->arcs = NULL;
00373     
00374     arc->head = node;
00375     
00376     return node;
00377 }
00378 
00379 static void addRigNodeHead(RigGraph *UNUSED(rg), RigArc *arc, RigNode *node)
00380 {
00381     node->degree++;
00382 
00383     arc->head = node;
00384 }
00385 
00386 static RigNode *newRigNode(RigGraph *rg, float p[3])
00387 {
00388     RigNode *node;
00389     node = MEM_callocN(sizeof(RigNode), "rig node");
00390     BLI_addtail(&rg->nodes, node);
00391 
00392     copy_v3_v3(node->p, p);
00393     node->degree = 0;
00394     node->arcs = NULL;
00395     
00396     return node;
00397 }
00398 
00399 static RigNode *newRigNodeTail(RigGraph *rg, RigArc *arc, float p[3])
00400 {
00401     RigNode *node = newRigNode(rg, p);
00402     
00403     node->degree = 1;
00404     arc->tail = node;
00405 
00406     return node;
00407 }
00408 
00409 static void RIG_appendEdgeToArc(RigArc *arc, RigEdge *edge)
00410 {
00411     BLI_addtail(&arc->edges, edge);
00412 
00413     if (edge->prev == NULL)
00414     {
00415         copy_v3_v3(edge->head, arc->head->p);
00416     }
00417     else
00418     {
00419         RigEdge *last_edge = edge->prev;
00420         copy_v3_v3(edge->head, last_edge->tail);
00421         RIG_calculateEdgeAngles(last_edge, edge);
00422     }
00423     
00424     edge->length = len_v3v3(edge->head, edge->tail);
00425     
00426     arc->length += edge->length;
00427     
00428     arc->count += 1;
00429 }
00430 
00431 static void RIG_addEdgeToArc(RigArc *arc, float tail[3], EditBone *bone)
00432 {
00433     RigEdge *edge;
00434 
00435     edge = MEM_callocN(sizeof(RigEdge), "rig edge");
00436 
00437     copy_v3_v3(edge->tail, tail);
00438     edge->bone = bone;
00439     
00440     if (bone)
00441     {
00442         getEditBoneRollUpAxis(bone, bone->roll, edge->up_axis);
00443     }
00444     
00445     RIG_appendEdgeToArc(arc, edge);
00446 }
00447 /************************************** CLONING TEMPLATES **********************************************/
00448 
00449 static void renameTemplateBone(char *name, char *template_name, ListBase *editbones, char *side_string, char *num_string)
00450 {
00451     int i, j;
00452     
00453     for (i = 0, j = 0; template_name[i] != '\0' && i < (MAXBONENAME-1) && j < (MAXBONENAME-1); i++)
00454     {
00455         if (template_name[i] == '&')
00456         {
00457             if (template_name[i+1] == 'S' || template_name[i+1] == 's')
00458             {
00459                 j += sprintf(name + j, "%s", side_string);
00460                 i++;
00461             }
00462             else if (template_name[i+1] == 'N' || template_name[i+1] == 'n')
00463             {
00464                 j += sprintf(name + j, "%s", num_string);
00465                 i++;
00466             }
00467             else
00468             {
00469                 name[j] = template_name[i];
00470                 j++;
00471             }
00472         }
00473         else
00474         {
00475             name[j] = template_name[i];
00476             j++;
00477         }
00478     }
00479     
00480     name[j] = '\0';
00481     
00482     unique_editbone_name(editbones, name, NULL);
00483 }
00484 
00485 static RigControl *cloneControl(RigGraph *rg, RigGraph *src_rg, RigControl *src_ctrl, GHash *ptr_hash, char *side_string, char *num_string)
00486 {
00487     RigControl *ctrl;
00488     char name[MAXBONENAME];
00489     
00490     ctrl = newRigControl(rg);
00491     
00492     copy_v3_v3(ctrl->head, src_ctrl->head);
00493     copy_v3_v3(ctrl->tail, src_ctrl->tail);
00494     copy_v3_v3(ctrl->up_axis, src_ctrl->up_axis);
00495     copy_v3_v3(ctrl->offset, src_ctrl->offset);
00496     
00497     ctrl->tail_mode = src_ctrl->tail_mode;
00498     ctrl->flag = src_ctrl->flag;
00499 
00500     renameTemplateBone(name, src_ctrl->bone->name, rg->editbones, side_string, num_string);
00501     ctrl->bone = duplicateEditBoneObjects(src_ctrl->bone, name, rg->editbones, src_rg->ob, rg->ob);
00502     ctrl->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
00503     BLI_ghash_insert(ptr_hash, src_ctrl->bone, ctrl->bone);
00504     
00505     ctrl->link = src_ctrl->link;
00506     ctrl->link_tail = src_ctrl->link_tail;
00507     
00508     return ctrl;
00509 }
00510 
00511 static RigArc *cloneArc(RigGraph *rg, RigGraph *src_rg, RigArc *src_arc, GHash *ptr_hash, char *side_string, char *num_string)
00512 {
00513     RigEdge *src_edge;
00514     RigArc  *arc;
00515     
00516     arc = newRigArc(rg);
00517     
00518     arc->head = BLI_ghash_lookup(ptr_hash, src_arc->head);
00519     arc->tail = BLI_ghash_lookup(ptr_hash, src_arc->tail);
00520     
00521     arc->head->degree++;
00522     arc->tail->degree++;
00523     
00524     arc->length = src_arc->length;
00525 
00526     arc->count = src_arc->count;
00527     
00528     for (src_edge = src_arc->edges.first; src_edge; src_edge = src_edge->next)
00529     {
00530         RigEdge *edge;
00531     
00532         edge = MEM_callocN(sizeof(RigEdge), "rig edge");
00533 
00534         copy_v3_v3(edge->head, src_edge->head);
00535         copy_v3_v3(edge->tail, src_edge->tail);
00536         copy_v3_v3(edge->up_axis, src_edge->up_axis);
00537         
00538         edge->length = src_edge->length;
00539         edge->angle = src_edge->angle;
00540         edge->up_angle = src_edge->up_angle;
00541         
00542         if (src_edge->bone != NULL)
00543         {
00544             char name[MAXBONENAME];
00545             renameTemplateBone(name, src_edge->bone->name, rg->editbones, side_string, num_string);
00546             edge->bone = duplicateEditBoneObjects(src_edge->bone, name, rg->editbones, src_rg->ob, rg->ob);
00547             edge->bone->flag &= ~(BONE_TIPSEL|BONE_SELECTED|BONE_ROOTSEL);
00548             BLI_ghash_insert(ptr_hash, src_edge->bone, edge->bone);
00549         }
00550 
00551         BLI_addtail(&arc->edges, edge);
00552     }
00553     
00554     return arc;
00555 }
00556 
00557 static RigGraph *cloneRigGraph(RigGraph *src, ListBase *editbones, Object *ob, char *side_string, char *num_string)
00558 {
00559     GHash   *ptr_hash;  
00560     RigNode *node;
00561     RigArc  *arc;
00562     RigControl *ctrl;
00563     RigGraph *rg;
00564     
00565     ptr_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "cloneRigGraph gh");
00566 
00567     rg = newRigGraph();
00568     
00569     rg->ob = ob;
00570     rg->editbones = editbones;
00571     
00572     preEditBoneDuplicate(rg->editbones); /* prime bones for duplication */
00573     preEditBoneDuplicate(src->editbones); /* prime bones for duplication */
00574     
00575     /* Clone nodes */
00576     for (node = src->nodes.first; node; node = node->next)
00577     {
00578         RigNode *cloned_node = newRigNode(rg, node->p);
00579         BLI_ghash_insert(ptr_hash, node, cloned_node);
00580     }
00581     
00582     rg->head = BLI_ghash_lookup(ptr_hash, src->head);
00583     
00584     /* Clone arcs */
00585     for (arc = src->arcs.first; arc; arc = arc->next)
00586     {
00587         cloneArc(rg, src, arc, ptr_hash, side_string, num_string);
00588     }
00589     
00590     /* Clone controls */
00591     for (ctrl = src->controls.first; ctrl; ctrl = ctrl->next)
00592     {
00593         cloneControl(rg, src, ctrl, ptr_hash, side_string, num_string);
00594     }
00595     
00596     /* Relink bones properly */
00597     for (arc = rg->arcs.first; arc; arc = arc->next)
00598     {
00599         RigEdge *edge;
00600         
00601         for (edge = arc->edges.first; edge; edge = edge->next)
00602         {
00603             if (edge->bone != NULL)
00604             {
00605                 EditBone *bone;
00606                 
00607                 updateDuplicateSubtargetObjects(edge->bone, src->editbones, src->ob, rg->ob);
00608 
00609                 if (edge->bone->parent)
00610                 {               
00611                     bone = BLI_ghash_lookup(ptr_hash, edge->bone->parent);
00612         
00613                     if (bone != NULL)
00614                     {
00615                         edge->bone->parent = bone;
00616                     }
00617                     else
00618                     {
00619                         /* disconnect since parent isn't cloned
00620                          * this will only happen when cloning from selected bones 
00621                          * */
00622                         edge->bone->flag &= ~BONE_CONNECTED;
00623                     }
00624                 }
00625             }
00626         }
00627     }
00628     
00629     for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
00630     {
00631         EditBone *bone;
00632         
00633         updateDuplicateSubtargetObjects(ctrl->bone, src->editbones, src->ob, rg->ob);
00634 
00635         if (ctrl->bone->parent)
00636         {
00637             bone = BLI_ghash_lookup(ptr_hash, ctrl->bone->parent);
00638             
00639             if (bone != NULL)
00640             {
00641                 ctrl->bone->parent = bone;
00642             }
00643             else
00644             {
00645                 /* disconnect since parent isn't cloned
00646                  * this will only happen when cloning from selected bones 
00647                  * */
00648                 ctrl->bone->flag &= ~BONE_CONNECTED;
00649             }
00650         }
00651 
00652         ctrl->link = BLI_ghash_lookup(ptr_hash, ctrl->link);
00653         ctrl->link_tail = BLI_ghash_lookup(ptr_hash, ctrl->link_tail);
00654     }
00655     
00656     BLI_ghash_free(ptr_hash, NULL, NULL);
00657     
00658     return rg;
00659 }
00660 
00661 
00662 /*******************************************************************************************************/
00663 
00664 static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second)
00665 {
00666     float vec_first[3], vec_second[3];
00667     
00668     sub_v3_v3v3(vec_first, edge_first->tail, edge_first->head); 
00669     sub_v3_v3v3(vec_second, edge_second->tail, edge_second->head);
00670 
00671     normalize_v3(vec_first);
00672     normalize_v3(vec_second);
00673     
00674     edge_first->angle = angle_normalized_v3v3(vec_first, vec_second);
00675     
00676     if (edge_second->bone != NULL)
00677     {
00678         float normal[3];
00679 
00680         cross_v3_v3v3(normal, vec_first, vec_second);
00681         normalize_v3(normal);
00682 
00683         edge_second->up_angle = angle_normalized_v3v3(normal, edge_second->up_axis);
00684     }
00685 }
00686 
00687 /************************************ CONTROL BONES ****************************************************/
00688 
00689 static void RIG_addControlBone(RigGraph *rg, EditBone *bone)
00690 {
00691     RigControl *ctrl = newRigControl(rg);
00692     ctrl->bone = bone;
00693     copy_v3_v3(ctrl->head, bone->head);
00694     copy_v3_v3(ctrl->tail, bone->tail);
00695     getEditBoneRollUpAxis(bone, bone->roll, ctrl->up_axis);
00696     ctrl->tail_mode = TL_NONE;
00697     
00698     BLI_ghash_insert(rg->controls_map, bone->name, ctrl);
00699 }
00700 
00701 static int RIG_parentControl(RigControl *ctrl, EditBone *link)
00702 {
00703     if (link)
00704     {
00705         float offset[3];
00706         int flag = 0;
00707         
00708         sub_v3_v3v3(offset, ctrl->bone->head, link->head);
00709 
00710         /* if root matches, check for direction too */      
00711         if (dot_v3v3(offset, offset) < 0.0001f)
00712         {
00713             float vbone[3], vparent[3];
00714             
00715             flag |= RIG_CTRL_FIT_ROOT;
00716             
00717             sub_v3_v3v3(vbone, ctrl->bone->tail, ctrl->bone->head);
00718             sub_v3_v3v3(vparent, link->tail, link->head);
00719             
00720             /* test for opposite direction */
00721             if (dot_v3v3(vbone, vparent) > 0)
00722             {
00723                 float nor[3];
00724                 float len;
00725                 
00726                 cross_v3_v3v3(nor, vbone, vparent);
00727                 
00728                 len = dot_v3v3(nor, nor);
00729                 if (len < 0.0001f)
00730                 {
00731                     flag |= RIG_CTRL_FIT_BONE;
00732                 }
00733             }
00734         }
00735         
00736         /* Bail out if old one is automatically better */
00737         if (flag < ctrl->flag)
00738         {
00739             return 0;
00740         }
00741         
00742         /* if there's already a link
00743          *  overwrite only if new link is higher in the chain */
00744         if (ctrl->link && flag == ctrl->flag)
00745         {
00746             EditBone *bone = NULL;
00747             
00748             for (bone = ctrl->link; bone; bone = bone->parent)
00749             {
00750                 /* if link is in the chain, break and use that one */
00751                 if (bone == link)
00752                 {
00753                     break;
00754                 }
00755             }
00756             
00757             /* not in chain, don't update link */
00758             if (bone == NULL)
00759             {
00760                 return 0;
00761             }
00762         }
00763         
00764         
00765         ctrl->link = link;
00766         ctrl->flag = flag;
00767         
00768         copy_v3_v3(ctrl->offset, offset);
00769         
00770         return 1;
00771     }
00772     
00773     return 0;
00774 }
00775 
00776 static void RIG_reconnectControlBones(RigGraph *rg)
00777 {
00778     RigControl *ctrl;
00779     int change = 1;
00780     
00781     /* first pass, link to deform bones */
00782     for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
00783     {
00784         bPoseChannel *pchan;
00785         bConstraint *con;
00786         int found = 0;
00787         
00788         /* DO SOME MAGIC HERE */
00789         for (pchan= rg->ob->pose->chanbase.first; pchan; pchan= pchan->next)
00790         {
00791             for (con= pchan->constraints.first; con; con= con->next) 
00792             {
00793                 bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
00794                 ListBase targets = {NULL, NULL};
00795                 bConstraintTarget *ct;
00796                 
00797                 /* constraint targets */
00798                 if (cti && cti->get_constraint_targets)
00799                 {
00800                     int target_index;
00801                     
00802                     cti->get_constraint_targets(con, &targets);
00803                     
00804                     for (target_index = 0, ct= targets.first; ct; target_index++, ct= ct->next)
00805                     {
00806                         if ((ct->tar == rg->ob) && strcmp(ct->subtarget, ctrl->bone->name) == 0)
00807                         {
00808                             /* SET bone link to bone corresponding to pchan */
00809                             EditBone *link = BLI_ghash_lookup(rg->bones_map, pchan->name);
00810                             
00811                             /* Making sure bone is in this armature */
00812                             if (link != NULL)
00813                             {
00814                                 /* for pole targets, link to parent bone instead, if possible */
00815                                 if (con->type == CONSTRAINT_TYPE_KINEMATIC && target_index == 1)
00816                                 {
00817                                     if (link->parent && BLI_ghash_haskey(rg->bones_map, link->parent->name))
00818                                     {
00819                                         link = link->parent;
00820                                     }
00821                                 }
00822                                 
00823                                 found = RIG_parentControl(ctrl, link);
00824                             }
00825                         }
00826                     }
00827                     
00828                     if (cti->flush_constraint_targets)
00829                         cti->flush_constraint_targets(con, &targets, 0);
00830                 }
00831             }
00832         }
00833 
00834         /* if not found yet, check parent */
00835         if (found == 0)
00836         {       
00837             if (ctrl->bone->parent)
00838             {
00839                 /* make sure parent is a deforming bone
00840                  * NULL if not
00841                  *  */
00842                 EditBone *link = BLI_ghash_lookup(rg->bones_map, ctrl->bone->parent->name);
00843                 
00844                 found = RIG_parentControl(ctrl, link);
00845             }
00846             
00847             /* check if bone is not superposed on another one */
00848             {
00849                 RigArc *arc;
00850                 RigArc *best_arc = NULL;
00851                 EditBone *link = NULL;
00852                 
00853                 for (arc = rg->arcs.first; arc; arc = arc->next)
00854                 {
00855                     RigEdge *edge;
00856                     for (edge = arc->edges.first; edge; edge = edge->next)
00857                     {
00858                         if (edge->bone)
00859                         {
00860                             int fit = 0;
00861                             
00862                             fit = len_v3v3(ctrl->bone->head, edge->bone->head) < 0.0001f;
00863                             fit = fit || len_v3v3(ctrl->bone->tail, edge->bone->tail) < 0.0001f;
00864                             
00865                             if (fit)
00866                             {
00867                                 /* pick the bone on the arc with the lowest symmetry level
00868                                  * means you connect control to the trunk of the skeleton */
00869                                 if (best_arc == NULL || arc->symmetry_level < best_arc->symmetry_level)
00870                                 {
00871                                     best_arc = arc;
00872                                     link = edge->bone;
00873                                 }
00874                             }
00875                         }
00876                     }
00877                 }
00878                 
00879                 found = RIG_parentControl(ctrl, link);
00880             }
00881         }
00882         
00883         /* if not found yet, check child */     
00884         if (found == 0)
00885         {
00886             RigArc *arc;
00887             RigArc *best_arc = NULL;
00888             EditBone *link = NULL;
00889             
00890             for (arc = rg->arcs.first; arc; arc = arc->next)
00891             {
00892                 RigEdge *edge;
00893                 for (edge = arc->edges.first; edge; edge = edge->next)
00894                 {
00895                     if (edge->bone && edge->bone->parent == ctrl->bone)
00896                     {
00897                         /* pick the bone on the arc with the lowest symmetry level
00898                          * means you connect control to the trunk of the skeleton */
00899                         if (best_arc == NULL || arc->symmetry_level < best_arc->symmetry_level)
00900                         {
00901                             best_arc = arc;
00902                             link = edge->bone;
00903                         }
00904                     }
00905                 }
00906             }
00907             
00908             found = RIG_parentControl(ctrl, link);
00909         }
00910 
00911     }
00912     
00913     
00914     /* second pass, make chains in control bones */
00915     while (change)
00916     {
00917         change = 0;
00918         
00919         for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
00920         {
00921             /* if control is not linked yet */
00922             if (ctrl->link == NULL)
00923             {
00924                 bPoseChannel *pchan;
00925                 bConstraint *con;
00926                 RigControl *ctrl_parent = NULL;
00927                 RigControl *ctrl_child;
00928                 int found = 0;
00929 
00930                 if (ctrl->bone->parent)
00931                 {
00932                     ctrl_parent = BLI_ghash_lookup(rg->controls_map, ctrl->bone->parent->name);
00933                 }
00934 
00935                 /* check constraints first */
00936                 
00937                 /* DO SOME MAGIC HERE */
00938                 for (pchan= rg->ob->pose->chanbase.first; pchan; pchan= pchan->next)
00939                 {
00940                     for (con= pchan->constraints.first; con; con= con->next) 
00941                     {
00942                         bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
00943                         ListBase targets = {NULL, NULL};
00944                         bConstraintTarget *ct;
00945                         
00946                         /* constraint targets */
00947                         if (cti && cti->get_constraint_targets)
00948                         {
00949                             cti->get_constraint_targets(con, &targets);
00950                             
00951                             for (ct= targets.first; ct; ct= ct->next)
00952                             {
00953                                 if ((ct->tar == rg->ob) && strcmp(ct->subtarget, ctrl->bone->name) == 0)
00954                                 {
00955                                     /* SET bone link to ctrl corresponding to pchan */
00956                                     RigControl *link = BLI_ghash_lookup(rg->controls_map, pchan->name);
00957 
00958                                     /* if owner is a control bone, link with it */                                  
00959                                     if (link && link->link)
00960                                     {
00961                                         RIG_parentControl(ctrl, link->bone);
00962                                         found = 1;
00963                                         break;
00964                                     }
00965                                 }
00966                             }
00967                             
00968                             if (cti->flush_constraint_targets)
00969                                 cti->flush_constraint_targets(con, &targets, 0);
00970                         }
00971                     }
00972                 }           
00973 
00974                 if (found == 0)
00975                 {
00976                     /* check if parent is already linked */
00977                     if (ctrl_parent && ctrl_parent->link)
00978                     {
00979                         RIG_parentControl(ctrl, ctrl_parent->bone);
00980                         change = 1;
00981                     }
00982                     else
00983                     {
00984                         /* check childs */
00985                         for (ctrl_child = rg->controls.first; ctrl_child; ctrl_child = ctrl_child->next)
00986                         {
00987                             /* if a child is linked, link to that one */
00988                             if (ctrl_child->link && ctrl_child->bone->parent == ctrl->bone)
00989                             {
00990                                 RIG_parentControl(ctrl, ctrl_child->bone);
00991                                 change = 1;
00992                                 break;
00993                             }
00994                         }
00995                     }
00996                 }
00997             }
00998         }
00999     }
01000     
01001     /* third pass, link control tails */
01002     for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
01003     {
01004         /* fit bone already means full match, so skip those */
01005         if ((ctrl->flag & RIG_CTRL_FIT_BONE) == 0)
01006         {
01007             GHashIterator ghi;
01008             
01009             /* look on deform bones first */
01010             BLI_ghashIterator_init(&ghi, rg->bones_map);
01011             
01012             for( ; !BLI_ghashIterator_isDone(&ghi); BLI_ghashIterator_step(&ghi))
01013             {
01014                 EditBone *bone = (EditBone*)BLI_ghashIterator_getValue(&ghi);
01015                 
01016                 /* don't link with parent */
01017                 if (bone->parent != ctrl->bone)
01018                 {
01019                     if (len_v3v3(ctrl->bone->tail, bone->head) < 0.01f)
01020                     {
01021                         ctrl->tail_mode = TL_HEAD;
01022                         ctrl->link_tail = bone;
01023                         break;
01024                     }
01025                     else if (len_v3v3(ctrl->bone->tail, bone->tail) < 0.01f)
01026                     {
01027                         ctrl->tail_mode = TL_TAIL;
01028                         ctrl->link_tail = bone;
01029                         break;
01030                     }
01031                 }
01032             }
01033             
01034             /* if we haven't found one yet, look in control bones */
01035             if (ctrl->tail_mode == TL_NONE)
01036             {
01037             }
01038         }
01039     }
01040     
01041 }
01042 
01043 /*******************************************************************************************************/
01044 
01045 static void RIG_joinArcs(RigGraph *rg, RigNode *node, RigArc *joined_arc1, RigArc *joined_arc2)
01046 {
01047     RigEdge *edge, *next_edge;
01048     
01049     /* ignore cases where joint is at start or end */
01050     if (joined_arc1->head == joined_arc2->head || joined_arc1->tail == joined_arc2->tail)
01051     {
01052         return;
01053     }
01054     
01055     /* swap arcs to make sure arc1 is before arc2 */
01056     if (joined_arc1->head == joined_arc2->tail)
01057     {
01058         RigArc *tmp = joined_arc1;
01059         joined_arc1 = joined_arc2;
01060         joined_arc2 = tmp;
01061     }
01062     
01063     for (edge = joined_arc2->edges.first; edge; edge = next_edge)
01064     {
01065         next_edge = edge->next;
01066         
01067         RIG_appendEdgeToArc(joined_arc1, edge);
01068     }
01069     
01070     joined_arc1->tail = joined_arc2->tail;
01071     
01072     joined_arc2->edges.first = joined_arc2->edges.last = NULL;
01073     
01074     BLI_removeArc((BGraph*)rg, (BArc*)joined_arc2);
01075     
01076     BLI_removeNode((BGraph*)rg, (BNode*)node);
01077 }
01078 
01079 static void RIG_removeNormalNodes(RigGraph *rg)
01080 {
01081     RigNode *node, *next_node;
01082     
01083     for (node = rg->nodes.first; node; node = next_node)
01084     {
01085         next_node = node->next;
01086         
01087         if (node->degree == 2)
01088         {
01089             RigArc *arc, *joined_arc1 = NULL, *joined_arc2 = NULL;
01090             
01091             for (arc = rg->arcs.first; arc; arc = arc->next)
01092             {
01093                 if (arc->head == node || arc->tail == node)
01094                 {
01095                     if (joined_arc1 == NULL)
01096                     {
01097                         joined_arc1 = arc;
01098                     }
01099                     else
01100                     {
01101                         joined_arc2 = arc;
01102                         break;
01103                     }
01104                 }
01105             }
01106             
01107             RIG_joinArcs(rg, node, joined_arc1, joined_arc2);
01108         }
01109     }
01110 }
01111 
01112 static void RIG_removeUneededOffsets(RigGraph *rg)
01113 {
01114     RigArc *arc;
01115     
01116     for (arc = rg->arcs.first; arc; arc = arc->next)
01117     {
01118         RigEdge *first_edge, *last_edge;
01119         
01120         first_edge = arc->edges.first;
01121         last_edge = arc->edges.last;
01122         
01123         if (first_edge->bone == NULL)
01124         {
01125             if (first_edge->bone == NULL && len_v3v3(first_edge->tail, arc->head->p) <= 0.001f)
01126             {
01127                 BLI_remlink(&arc->edges, first_edge);
01128                 MEM_freeN(first_edge);
01129             }
01130             else if (arc->head->degree == 1)
01131             {
01132                 RigNode *new_node = (RigNode*)BLI_FindNodeByPosition((BGraph*)rg, first_edge->tail, 0.001f);
01133                 
01134                 if (new_node)
01135                 {
01136                     BLI_remlink(&arc->edges, first_edge);
01137                     MEM_freeN(first_edge);
01138                     BLI_replaceNodeInArc((BGraph*)rg, (BArc*)arc, (BNode*)new_node, (BNode*)arc->head);
01139                 }
01140                 else
01141                 {
01142                     RigEdge *next_edge = first_edge->next;
01143     
01144                     if (next_edge)
01145                     {
01146                         BLI_remlink(&arc->edges, first_edge);
01147                         MEM_freeN(first_edge);
01148                         
01149                         copy_v3_v3(arc->head->p, next_edge->head);
01150                     }
01151                 }
01152             }
01153             else
01154             {
01155                 /* check if all arc connected start with a null edge */
01156                 RigArc *other_arc;
01157                 for (other_arc = rg->arcs.first; other_arc; other_arc = other_arc->next)
01158                 {
01159                     if (other_arc != arc)
01160                     {
01161                         RigEdge *test_edge;
01162                         if (other_arc->head == arc->head)
01163                         {
01164                             test_edge = other_arc->edges.first;
01165                             
01166                             if (test_edge->bone != NULL)
01167                             {
01168                                 break;
01169                             }
01170                         }
01171                         else if (other_arc->tail == arc->head)
01172                         {
01173                             test_edge = other_arc->edges.last;
01174                             
01175                             if (test_edge->bone != NULL)
01176                             {
01177                                 break;
01178                             }
01179                         }
01180                     }
01181                 }
01182                 
01183                 if (other_arc == NULL)
01184                 {
01185                     RigNode *new_node = (RigNode*)BLI_FindNodeByPosition((BGraph*)rg, first_edge->tail, 0.001);
01186                     
01187                     if (new_node)
01188                     {
01189                         /* remove null edge in other arcs too */
01190                         for (other_arc = rg->arcs.first; other_arc; other_arc = other_arc->next)
01191                         {
01192                             if (other_arc != arc)
01193                             {
01194                                 RigEdge *test_edge;
01195                                 if (other_arc->head == arc->head)
01196                                 {
01197                                     BLI_replaceNodeInArc((BGraph*)rg, (BArc*)other_arc, (BNode*)new_node, (BNode*)other_arc->head);
01198                                     test_edge = other_arc->edges.first;
01199                                     BLI_remlink(&other_arc->edges, test_edge);
01200                                     MEM_freeN(test_edge);
01201                                 }
01202                                 else if (other_arc->tail == arc->head)
01203                                 {
01204                                     BLI_replaceNodeInArc((BGraph*)rg, (BArc*)other_arc, (BNode*)new_node, (BNode*)other_arc->tail);
01205                                     test_edge = other_arc->edges.last;
01206                                     BLI_remlink(&other_arc->edges, test_edge);
01207                                     MEM_freeN(test_edge);
01208                                 }
01209                             }
01210                         }
01211                         
01212                         BLI_remlink(&arc->edges, first_edge);
01213                         MEM_freeN(first_edge);
01214                         BLI_replaceNodeInArc((BGraph*)rg, (BArc*)arc, (BNode*)new_node, (BNode*)arc->head);
01215                     }
01216                     else
01217                     {
01218                         RigEdge *next_edge = first_edge->next;
01219         
01220                         if (next_edge)
01221                         {
01222                             BLI_remlink(&arc->edges, first_edge);
01223                             MEM_freeN(first_edge);
01224                             
01225                             copy_v3_v3(arc->head->p, next_edge->head);
01226                             
01227                             /* remove null edge in other arcs too */
01228                             for (other_arc = rg->arcs.first; other_arc; other_arc = other_arc->next)
01229                             {
01230                                 if (other_arc != arc)
01231                                 {
01232                                     RigEdge *test_edge;
01233                                     if (other_arc->head == arc->head)
01234                                     {
01235                                         test_edge = other_arc->edges.first;
01236                                         BLI_remlink(&other_arc->edges, test_edge);
01237                                         MEM_freeN(test_edge);
01238                                     }
01239                                     else if (other_arc->tail == arc->head)
01240                                     {
01241                                         test_edge = other_arc->edges.last;
01242                                         BLI_remlink(&other_arc->edges, test_edge);
01243                                         MEM_freeN(test_edge);
01244                                     }
01245                                 }
01246                             }
01247                         }
01248                     }
01249                 }
01250             }
01251         }
01252         
01253         if (last_edge->bone == NULL)
01254         {
01255             if (len_v3v3(last_edge->head, arc->tail->p) <= 0.001f)
01256             {
01257                 BLI_remlink(&arc->edges, last_edge);
01258                 MEM_freeN(last_edge);
01259             }
01260             else if (arc->tail->degree == 1)
01261             {
01262                 RigNode *new_node = (RigNode*)BLI_FindNodeByPosition((BGraph*)rg, last_edge->head, 0.001f);
01263                 
01264                 if (new_node)
01265                 {
01266                     RigEdge *previous_edge = last_edge->prev;
01267                     
01268                     BLI_remlink(&arc->edges, last_edge);
01269                     MEM_freeN(last_edge);
01270                     BLI_replaceNodeInArc((BGraph*)rg, (BArc*)arc, (BNode*)new_node, (BNode*)arc->tail);
01271                     
01272                     /* set previous angle to 0, since there's no following edges */
01273                     if (previous_edge)
01274                     {
01275                         previous_edge->angle = 0;
01276                     }
01277                 }
01278                 else
01279                 {
01280                     RigEdge *previous_edge = last_edge->prev;
01281     
01282                     if (previous_edge)
01283                     {
01284                         BLI_remlink(&arc->edges, last_edge);
01285                         MEM_freeN(last_edge);
01286                         
01287                         copy_v3_v3(arc->tail->p, previous_edge->tail);
01288                         previous_edge->angle = 0;
01289                     }
01290                 }
01291             }
01292         }
01293     }
01294 }
01295 
01296 static void RIG_arcFromBoneChain(RigGraph *rg, ListBase *list, EditBone *root_bone, RigNode *starting_node, int selected)
01297 {
01298     EditBone *bone, *last_bone = root_bone;
01299     RigArc *arc = NULL;
01300     int contain_head = 0;
01301     
01302     for(bone = root_bone; bone; bone = nextEditBoneChild(list, bone, 0))
01303     {
01304         int nb_children;
01305         
01306         if (selected == 0 || (bone->flag & BONE_SELECTED))
01307         { 
01308             if ((bone->flag & BONE_NO_DEFORM) == 0)
01309             {
01310                 BLI_ghash_insert(rg->bones_map, bone->name, bone);
01311             
01312                 if (arc == NULL)
01313                 {
01314                     arc = newRigArc(rg);
01315                     
01316                     if (starting_node == NULL)
01317                     {
01318                         starting_node = newRigNodeHead(rg, arc, root_bone->head);
01319                     }
01320                     else
01321                     {
01322                         addRigNodeHead(rg, arc, starting_node);
01323                     }
01324                 }
01325                 
01326                 if (bone->parent && (bone->flag & BONE_CONNECTED) == 0)
01327                 {
01328                     RIG_addEdgeToArc(arc, bone->head, NULL);
01329                 }
01330                 
01331                 RIG_addEdgeToArc(arc, bone->tail, bone);
01332                 
01333                 last_bone = bone;
01334                 
01335                 if (strcmp(bone->name, "head") == 0)
01336                 {
01337                     contain_head = 1;
01338                 }
01339             }
01340             else if ((bone->flag & BONE_EDITMODE_LOCKED) == 0) /* ignore locked bones */
01341             {
01342                 RIG_addControlBone(rg, bone);
01343             }
01344         }
01345         
01346         nb_children = countEditBoneChildren(list, bone);
01347         if (nb_children > 1)
01348         {
01349             RigNode *end_node = NULL;
01350             int i;
01351             
01352             if (arc != NULL)
01353             {
01354                 end_node = newRigNodeTail(rg, arc, bone->tail);
01355             }
01356             else
01357             {
01358                 end_node = newRigNode(rg, bone->tail);
01359             }
01360 
01361             for (i = 0; i < nb_children; i++)
01362             {
01363                 root_bone = nextEditBoneChild(list, bone, i);
01364                 RIG_arcFromBoneChain(rg, list, root_bone, end_node, selected);
01365             }
01366             
01367             /* arc ends here, break */
01368             break;
01369         }
01370     }
01371     
01372     /* If the loop exited without forking */
01373     if (arc != NULL && bone == NULL)
01374     {
01375         newRigNodeTail(rg, arc, last_bone->tail);
01376     }
01377 
01378     if (contain_head)
01379     {
01380         rg->head = arc->tail;
01381     }
01382 }
01383 
01384 /*******************************************************************************************************/
01385 static void RIG_findHead(RigGraph *rg)
01386 {
01387     if (rg->head == NULL)
01388     {
01389         if (BLI_countlist(&rg->arcs) == 1)
01390         {
01391             RigArc *arc = rg->arcs.first;
01392             
01393             rg->head = (RigNode*)arc->head;
01394         }
01395         else
01396         {
01397             RigArc *arc;
01398             
01399             for (arc = rg->arcs.first; arc; arc = arc->next)
01400             {
01401                 RigEdge *edge = arc->edges.last;
01402                 
01403                 if (edge->bone->flag & (BONE_TIPSEL|BONE_SELECTED))
01404                 {
01405                     rg->head = arc->tail;
01406                     break;
01407                 }
01408             }
01409         }
01410         
01411         if (rg->head == NULL)
01412         {
01413             rg->head = rg->nodes.first;
01414         }
01415     }
01416 }
01417 
01418 /*******************************************************************************************************/
01419 
01420 static void RIG_printNode(RigNode *node, const char name[])
01421 {
01422     printf("%s %p %i <%0.3f, %0.3f, %0.3f>\n", name, (void *)node, node->degree, node->p[0], node->p[1], node->p[2]);
01423     
01424     if (node->symmetry_flag & SYM_TOPOLOGICAL)
01425     {
01426         if (node->symmetry_flag & SYM_AXIAL)
01427             printf("Symmetry AXIAL\n");
01428         else if (node->symmetry_flag & SYM_RADIAL)
01429             printf("Symmetry RADIAL\n");
01430             
01431         print_v3("symmetry axis", node->symmetry_axis);
01432     }
01433 }
01434 
01435 void RIG_printArcBones(RigArc *arc)
01436 {
01437     RigEdge *edge;
01438 
01439     for (edge = arc->edges.first; edge; edge = edge->next)
01440     {
01441         if (edge->bone)
01442             printf("%s ", edge->bone->name);
01443         else
01444             printf("---- ");
01445     }
01446     printf("\n");
01447 }
01448 
01449 static void RIG_printCtrl(RigControl *ctrl, char *indent)
01450 {
01451     char text[128];
01452     
01453     printf("%sBone: %s\n", indent, ctrl->bone->name);
01454     printf("%sLink: %s\n", indent, ctrl->link ? ctrl->link->name : "!NONE!");
01455     
01456     BLI_snprintf(text, sizeof(text), "%soffset", indent);
01457     print_v3(text, ctrl->offset);
01458     
01459     printf("%sFlag: %i\n", indent, ctrl->flag);
01460 }
01461 
01462 static void RIG_printLinkedCtrl(RigGraph *rg, EditBone *bone, int tabs)
01463 {
01464     RigControl *ctrl;
01465     char indent[64];
01466     char *s = indent;
01467     int i;
01468     
01469     for (i = 0; i < tabs; i++)
01470     {
01471         s[0] = '\t';
01472         s++;
01473     }
01474     s[0] = 0;
01475     
01476     for (ctrl = rg->controls.first; ctrl; ctrl = ctrl->next)
01477     {
01478         if (ctrl->link == bone)
01479         {
01480             RIG_printCtrl(ctrl, indent);
01481             RIG_printLinkedCtrl(rg, ctrl->bone, tabs + 1);
01482         }
01483     }
01484 }
01485 
01486 void RIG_printArc(RigGraph *rg, RigArc *arc)
01487 {
01488     RigEdge *edge;
01489 
01490     RIG_printNode((RigNode*)arc->head, "head");
01491 
01492     for (edge = arc->edges.first; edge; edge = edge->next)
01493     {
01494         printf("\tinner joints %0.3f %0.3f %0.3f\n", edge->tail[0], edge->tail[1], edge->tail[2]);
01495         printf("\t\tlength %f\n", edge->length);
01496         printf("\t\tangle %f\n", edge->angle * 180 / M_PI);
01497         if (edge->bone)
01498         {
01499             printf("\t\t%s\n", edge->bone->name);
01500             RIG_printLinkedCtrl(rg, edge->bone, 3);
01501         }
01502     }   
01503     printf("symmetry level: %i flag: %i group %i\n", arc->symmetry_level, arc->symmetry_flag, arc->symmetry_group);
01504 
01505     RIG_printNode((RigNode*)arc->tail, "tail");
01506 }
01507 
01508 void RIG_printGraph(RigGraph *rg)
01509 {
01510     RigArc *arc;
01511 
01512     printf("---- ARCS ----\n");
01513     for (arc = rg->arcs.first; arc; arc = arc->next)
01514     {
01515         RIG_printArc(rg, arc);  
01516         printf("\n");
01517     }
01518 
01519     if (rg->head)
01520     {
01521         RIG_printNode(rg->head, "HEAD NODE:");
01522     }
01523     else
01524     {
01525         printf("HEAD NODE: NONE\n");
01526     }   
01527 }
01528 
01529 /*******************************************************************************************************/
01530 
01531 RigGraph *RIG_graphFromArmature(const bContext *C, Object *ob, bArmature *arm)
01532 {
01533     Object *obedit = CTX_data_edit_object(C);
01534     Scene *scene = CTX_data_scene(C);
01535     EditBone *ebone;
01536     RigGraph *rg;
01537 
01538     rg = newRigGraph();
01539     
01540     if (obedit == ob)
01541     {
01542         rg->editbones = ((bArmature *)obedit->data)->edbo;
01543     }
01544     else
01545     {
01546         rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones");
01547         make_boneList(rg->editbones, &arm->bonebase, NULL, NULL);
01548         rg->flag |= RIG_FREE_BONELIST;
01549     }
01550     
01551     rg->ob = ob;
01552 
01553     /* Do the rotations */
01554     for (ebone = rg->editbones->first; ebone; ebone=ebone->next){
01555         if (ebone->parent == NULL)
01556         {
01557             RIG_arcFromBoneChain(rg, rg->editbones, ebone, NULL, 0);
01558         }
01559     }
01560     
01561     BLI_removeDoubleNodes((BGraph*)rg, 0.001);
01562     
01563     RIG_removeNormalNodes(rg);
01564     
01565     RIG_removeUneededOffsets(rg);
01566     
01567     BLI_buildAdjacencyList((BGraph*)rg);
01568     
01569     RIG_findHead(rg);
01570 
01571     BLI_markdownSymmetry((BGraph*)rg, (BNode*)rg->head, scene->toolsettings->skgen_symmetry_limit);
01572     
01573     RIG_reconnectControlBones(rg); /* after symmetry, because we use levels to find best match */
01574     
01575     if (BLI_isGraphCyclic((BGraph*)rg))
01576     {
01577         printf("armature cyclic\n");
01578     }
01579     
01580     return rg;
01581 }
01582 
01583 static RigGraph *armatureSelectedToGraph(bContext *C, Object *ob, bArmature *arm)
01584 {
01585     Object *obedit = CTX_data_edit_object(C);
01586     Scene *scene = CTX_data_scene(C);
01587     EditBone *ebone;
01588     RigGraph *rg;
01589 
01590     rg = newRigGraph();
01591     
01592     if (obedit == ob)
01593     {
01594         rg->editbones = arm->edbo;
01595     }
01596     else
01597     {
01598         rg->editbones = MEM_callocN(sizeof(ListBase), "EditBones");
01599         make_boneList(rg->editbones, &arm->bonebase, NULL, NULL);
01600         rg->flag |= RIG_FREE_BONELIST;
01601     }
01602 
01603     rg->ob = ob;
01604 
01605     /* Do the rotations */
01606     for (ebone = rg->editbones->first; ebone; ebone=ebone->next){
01607         if (ebone->parent == NULL)
01608         {
01609             RIG_arcFromBoneChain(rg, rg->editbones, ebone, NULL, 1);
01610         }
01611     }
01612     
01613     BLI_removeDoubleNodes((BGraph*)rg, 0.001);
01614     
01615     RIG_removeNormalNodes(rg);
01616     
01617     RIG_removeUneededOffsets(rg);
01618     
01619     BLI_buildAdjacencyList((BGraph*)rg);
01620     
01621     RIG_findHead(rg);
01622 
01623     BLI_markdownSymmetry((BGraph*)rg, (BNode*)rg->head, scene->toolsettings->skgen_symmetry_limit);
01624     
01625     RIG_reconnectControlBones(rg); /* after symmetry, because we use levels to find best match */
01626     
01627     if (BLI_isGraphCyclic((BGraph*)rg))
01628     {
01629         printf("armature cyclic\n");
01630     }
01631     
01632     return rg;
01633 }
01634 /************************************ GENERATING *****************************************************/
01635 
01636 #if 0
01637 static EditBone *add_editbonetolist(char *name, ListBase *list)
01638 {
01639     EditBone *bone= MEM_callocN(sizeof(EditBone), "eBone");
01640     
01641     BLI_strncpy(bone->name, name, sizeof(bone->name));
01642     unique_editbone_name(list, bone->name, NULL);
01643     
01644     BLI_addtail(list, bone);
01645     
01646     bone->flag |= BONE_TIPSEL;
01647     bone->weight= 1.0F;
01648     bone->dist= 0.25F;
01649     bone->xwidth= 0.1;
01650     bone->zwidth= 0.1;
01651     bone->ease1= 1.0;
01652     bone->ease2= 1.0;
01653     bone->rad_head= 0.10;
01654     bone->rad_tail= 0.05;
01655     bone->segments= 1;
01656     bone->layer=  1;//arm->layer;
01657     
01658     return bone;
01659 }
01660 #endif
01661 
01662 #if 0 /* UNUSED */
01663 static void generateMissingArcsFromNode(RigGraph *rigg, ReebNode *node, int multi_level_limit)
01664 {
01665     while (node->multi_level > multi_level_limit && node->link_up)
01666     {
01667         node = node->link_up;
01668     }
01669     
01670     while (node->multi_level < multi_level_limit && node->link_down)
01671     {
01672         node = node->link_down;
01673     }
01674     
01675     if (node->multi_level == multi_level_limit)
01676     {
01677         int i;
01678         
01679         for (i = 0; i < node->degree; i++)
01680         {
01681             ReebArc *earc = node->arcs[i];
01682             
01683             if (earc->flag == ARC_FREE && earc->head == node)
01684             {
01685                 ReebNode *other = BIF_otherNodeFromIndex(earc, node);
01686                 
01687                 earc->flag = ARC_USED;
01688                 
01689                 //generateBonesForArc(rigg, earc, node, other);
01690                 generateMissingArcsFromNode(rigg, other, multi_level_limit);
01691             }
01692         }
01693     }
01694 }
01695 
01696 static void generateMissingArcs(RigGraph *rigg)
01697 {
01698     ReebGraph *reebg;
01699     int multi_level_limit = 5;
01700     
01701     for (reebg = rigg->link_mesh; reebg; reebg = reebg->link_up)
01702     {
01703         ReebArc *earc;
01704         
01705         for (earc = reebg->arcs.first; earc; earc = earc->next)
01706         {
01707             if (earc->flag == ARC_USED)
01708             {
01709                 generateMissingArcsFromNode(rigg, earc->head, multi_level_limit);
01710                 generateMissingArcsFromNode(rigg, earc->tail, multi_level_limit);
01711             }
01712         }
01713     }
01714 }
01715 #endif
01716 
01717 /************************************ RETARGETTING *****************************************************/
01718 
01719 static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float tail[3], float qrot[4], float resize);
01720 
01721 static void repositionTailControl(RigGraph *rigg, RigControl *ctrl);
01722 
01723 static void finalizeControl(RigGraph *rigg, RigControl *ctrl, float resize)
01724 {
01725     if ((ctrl->flag & RIG_CTRL_DONE) == RIG_CTRL_DONE)
01726     {
01727         RigControl *ctrl_child;
01728 
01729 #if 0       
01730         printf("CTRL: %s LINK: %s", ctrl->bone->name, ctrl->link->name);
01731         
01732         if (ctrl->link_tail)
01733         {
01734             printf(" TAIL: %s", ctrl->link_tail->name);
01735         }
01736         
01737         printf("\n");
01738 #endif
01739         
01740         /* if there was a tail link: apply link, recalc resize factor and qrot */
01741         if (ctrl->tail_mode != TL_NONE)
01742         {
01743             float *tail_vec = NULL;
01744             float v1[3], v2[3], qtail[4];
01745             
01746             if (ctrl->tail_mode == TL_TAIL)
01747             {
01748                 tail_vec = ctrl->link_tail->tail;
01749             }
01750             else if (ctrl->tail_mode == TL_HEAD)
01751             {
01752                 tail_vec = ctrl->link_tail->head;
01753             }
01754             
01755             sub_v3_v3v3(v1, ctrl->bone->tail, ctrl->bone->head);
01756             sub_v3_v3v3(v2, tail_vec, ctrl->bone->head);
01757             
01758             copy_v3_v3(ctrl->bone->tail, tail_vec);
01759             
01760             rotation_between_vecs_to_quat(qtail, v1, v2);
01761             mul_qt_qtqt(ctrl->qrot, qtail, ctrl->qrot);
01762             
01763             resize = len_v3(v2) / len_v3v3(ctrl->head, ctrl->tail);
01764         }
01765         
01766         ctrl->bone->roll = rollBoneByQuat(ctrl->bone, ctrl->up_axis, ctrl->qrot);
01767     
01768         /* Cascade to connected control bones */
01769         for (ctrl_child = rigg->controls.first; ctrl_child; ctrl_child = ctrl_child->next)
01770         {
01771             if (ctrl_child->link == ctrl->bone)
01772             {
01773                 repositionControl(rigg, ctrl_child, ctrl->bone->head, ctrl->bone->tail, ctrl->qrot, resize);
01774             }
01775             if (ctrl_child->link_tail == ctrl->bone)
01776             {
01777                 repositionTailControl(rigg, ctrl_child);
01778             }
01779         }
01780     }   
01781 }
01782 
01783 static void repositionTailControl(RigGraph *rigg, RigControl *ctrl)
01784 {
01785     ctrl->flag |= RIG_CTRL_TAIL_DONE;
01786 
01787     finalizeControl(rigg, ctrl, 1); /* resize will be recalculated anyway so we don't need it */
01788 }
01789 
01790 static void repositionControl(RigGraph *rigg, RigControl *ctrl, float head[3], float UNUSED(tail[3]), float qrot[4], float resize)
01791 {
01792     float parent_offset[3], tail_offset[3];
01793     
01794     copy_v3_v3(parent_offset, ctrl->offset);
01795     mul_v3_fl(parent_offset, resize);
01796     mul_qt_v3(qrot, parent_offset);
01797     
01798     add_v3_v3v3(ctrl->bone->head, head, parent_offset); 
01799 
01800     ctrl->flag |= RIG_CTRL_HEAD_DONE;
01801 
01802     copy_qt_qt(ctrl->qrot, qrot);
01803 
01804     if (ctrl->tail_mode == TL_NONE)
01805     {
01806         sub_v3_v3v3(tail_offset, ctrl->tail, ctrl->head);
01807         mul_v3_fl(tail_offset, resize);
01808         mul_qt_v3(qrot, tail_offset);
01809 
01810         add_v3_v3v3(ctrl->bone->tail, ctrl->bone->head, tail_offset);
01811         
01812         ctrl->flag |= RIG_CTRL_TAIL_DONE;
01813     }
01814 
01815     finalizeControl(rigg, ctrl, resize);
01816 }
01817 
01818 static void repositionBone(bContext *C, RigGraph *rigg, RigEdge *edge, float vec0[3], float vec1[3], float up_axis[3])
01819 {
01820     Scene *scene = CTX_data_scene(C);
01821     EditBone *bone;
01822     RigControl *ctrl;
01823     float qrot[4], resize;
01824     float v1[3], v2[3];
01825     float l1, l2;
01826     
01827     bone = edge->bone;
01828     
01829     sub_v3_v3v3(v1, edge->tail, edge->head);
01830     sub_v3_v3v3(v2, vec1, vec0);
01831     
01832     l1 = normalize_v3(v1);
01833     l2 = normalize_v3(v2);
01834 
01835     resize = l2 / l1;
01836     
01837     rotation_between_vecs_to_quat(qrot, v1, v2);
01838     
01839     copy_v3_v3(bone->head, vec0);
01840     copy_v3_v3(bone->tail, vec1);
01841     
01842     if (!is_zero_v3(up_axis))
01843     {
01844         float qroll[4];
01845 
01846         if (scene->toolsettings->skgen_retarget_roll == SK_RETARGET_ROLL_VIEW)
01847         {
01848             bone->roll = rollBoneByQuatAligned(bone, edge->up_axis, qrot, qroll, up_axis);
01849         }
01850         else if (scene->toolsettings->skgen_retarget_roll == SK_RETARGET_ROLL_JOINT)
01851         {
01852             bone->roll = rollBoneByQuatJoint(edge, edge->prev, qrot, qroll, up_axis);
01853         }
01854         else
01855         {
01856             unit_qt(qroll);
01857         }
01858         
01859         mul_qt_qtqt(qrot, qroll, qrot);
01860     }
01861     else
01862     {
01863         bone->roll = rollBoneByQuat(bone, edge->up_axis, qrot);
01864     }
01865 
01866     for (ctrl = rigg->controls.first; ctrl; ctrl = ctrl->next)
01867     {
01868         if (ctrl->link == bone)
01869         {
01870             repositionControl(rigg, ctrl, vec0, vec1, qrot, resize);
01871         }
01872         if (ctrl->link_tail == bone)
01873         {
01874             repositionTailControl(rigg, ctrl);
01875         }
01876     }
01877 }
01878 
01879 static RetargetMode detectArcRetargetMode(RigArc *arc);
01880 static void retargetArctoArcLength(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start);
01881 
01882 
01883 static RetargetMode detectArcRetargetMode(RigArc *iarc)
01884 {
01885     RetargetMode mode = RETARGET_AGGRESSIVE;
01886     ReebArc *earc = iarc->link_mesh;
01887     RigEdge *edge;
01888     int large_angle = 0;
01889     float avg_angle = 0;
01890     /* float avg_length = 0; */ /* UNUSED */
01891     int nb_edges = 0;
01892     
01893     
01894     for (edge = iarc->edges.first; edge; edge = edge->next)
01895     {
01896         avg_angle += edge->angle;
01897         nb_edges++;
01898     }
01899     
01900     avg_angle /= nb_edges - 1; /* -1 because last edge doesn't have an angle */
01901 
01902     /* avg_length = iarc->length / nb_edges; */  /* UNUSED */
01903     
01904     
01905     if (nb_edges > 2)
01906     {
01907         for (edge = iarc->edges.first; edge; edge = edge->next)
01908         {
01909             if (fabs(edge->angle - avg_angle) > M_PI / 6)
01910             {
01911                 large_angle = 1;
01912             }
01913         }
01914     }
01915     else if (nb_edges == 2 && avg_angle > 0)
01916     {
01917         large_angle = 1;
01918     }
01919         
01920     
01921     if (large_angle == 0)
01922     {
01923         mode = RETARGET_LENGTH;
01924     }
01925     
01926     if (earc->bcount <= (iarc->count - 1))
01927     {
01928         mode = RETARGET_LENGTH;
01929     }
01930     
01931     return mode;
01932 }
01933 
01934 #ifndef USE_THREADS
01935 static void printMovesNeeded(int *positions, int nb_positions)
01936 {
01937     int moves = 0;
01938     int i;
01939     
01940     for (i = 0; i < nb_positions; i++)
01941     {
01942         moves += positions[i] - (i + 1);
01943     }
01944     
01945     printf("%i moves needed\n", moves);
01946 }
01947 
01948 static void printPositions(int *positions, int nb_positions)
01949 {
01950     int i;
01951     
01952     for (i = 0; i < nb_positions; i++)
01953     {
01954         printf("%i ", positions[i]);
01955     }
01956     printf("\n");
01957 }
01958 #endif
01959 
01960 #define MAX_COST FLT_MAX /* FIX ME */
01961 
01962 static float costDistance(BArcIterator *iter, float *vec0, float *vec1, int i0, int i1, float distance_weight)
01963 {
01964     EmbedBucket *bucket = NULL;
01965     float max_dist = 0;
01966     float v1[3], v2[3], c[3];
01967     float v1_inpf;
01968 
01969     if (distance_weight > 0)
01970     {
01971         sub_v3_v3v3(v1, vec0, vec1);
01972         
01973         v1_inpf = dot_v3v3(v1, v1);
01974         
01975         if (v1_inpf > 0)
01976         {
01977             int j;
01978             for (j = i0 + 1; j < i1 - 1; j++)
01979             {
01980                 float dist;
01981                 
01982                 bucket = IT_peek(iter, j);
01983     
01984                 sub_v3_v3v3(v2, bucket->p, vec1);
01985         
01986                 cross_v3_v3v3(c, v1, v2);
01987                 
01988                 dist = dot_v3v3(c, c) / v1_inpf;
01989                 
01990                 max_dist = dist > max_dist ? dist : max_dist;
01991             }
01992             
01993             return distance_weight * max_dist;
01994         }
01995         else
01996         {
01997             return MAX_COST;
01998         }
01999     }
02000     else
02001     {
02002         return 0;
02003     }
02004 }
02005 
02006 static float costAngle(float original_angle, float vec_first[3], float vec_second[3], float angle_weight)
02007 {
02008     if (angle_weight > 0)
02009     {
02010         float current_angle;
02011         
02012         if (!is_zero_v3(vec_first) && !is_zero_v3(vec_second))
02013         {
02014             current_angle = saacos(dot_v3v3(vec_first, vec_second));
02015 
02016             return angle_weight * fabsf(current_angle - original_angle);
02017         }
02018         else
02019         {
02020             return angle_weight * (float)M_PI;
02021         }
02022     }
02023     else
02024     {
02025         return 0;
02026     }
02027 }
02028 
02029 static float costLength(float original_length, float current_length, float length_weight)
02030 {
02031     if (current_length == 0)
02032     {
02033         return MAX_COST;
02034     }
02035     else
02036     {
02037         float length_ratio = fabs((current_length - original_length) / original_length);
02038         return length_weight * length_ratio * length_ratio;
02039     }
02040 }
02041 
02042 #if 0
02043 static float calcCostLengthDistance(BArcIterator *iter, float **vec_cache, RigEdge *edge, float *vec1, float *vec2, int i1, int i2)
02044 {
02045     float vec[3];
02046     float length;
02047 
02048     sub_v3_v3v3(vec, vec2, vec1);
02049     length = normalize_v3(vec);
02050 
02051     return costLength(edge->length, length) + costDistance(iter, vec1, vec2, i1, i2);
02052 }
02053 #endif
02054 
02055 static float calcCostAngleLengthDistance(BArcIterator *iter, float **UNUSED(vec_cache), RigEdge *edge, float *vec0, float *vec1, float *vec2, int i1, int i2, float angle_weight, float length_weight, float distance_weight)
02056 {
02057     float vec_second[3], vec_first[3];
02058     float length2;
02059     float new_cost = 0;
02060 
02061     sub_v3_v3v3(vec_second, vec2, vec1);
02062     length2 = normalize_v3(vec_second);
02063 
02064 
02065     /* Angle cost */    
02066     if (edge->prev)
02067     {
02068         sub_v3_v3v3(vec_first, vec1, vec0); 
02069         normalize_v3(vec_first);
02070         
02071         new_cost += costAngle(edge->prev->angle, vec_first, vec_second, angle_weight);
02072     }
02073 
02074     /* Length cost */
02075     new_cost += costLength(edge->length, length2, length_weight);
02076 
02077     /* Distance cost */
02078     new_cost += costDistance(iter, vec1, vec2, i1, i2, distance_weight);
02079 
02080     return new_cost;
02081 }
02082 
02083 static int indexMemoNode(int nb_positions, int previous, int current, int joints_left)
02084 {
02085     return joints_left * nb_positions * nb_positions + current * nb_positions + previous;
02086 }
02087 
02088 static void copyMemoPositions(int *positions, MemoNode *table, int nb_positions, int joints_left)
02089 {
02090     int previous = 0, current = 0;
02091     int i = 0;
02092     
02093     for (i = 0; joints_left > 0; joints_left--, i++)
02094     {
02095         MemoNode *node;
02096         node = table + indexMemoNode(nb_positions, previous, current, joints_left);
02097         
02098         positions[i] = node->next;
02099         
02100         previous = current;
02101         current = node->next;
02102     }
02103 }
02104 
02105 static MemoNode * solveJoints(MemoNode *table, BArcIterator *iter, float **vec_cache, int nb_joints, int nb_positions, int previous, int current, RigEdge *edge, int joints_left, float angle_weight, float length_weight, float distance_weight)
02106 {
02107     MemoNode *node;
02108     int index = indexMemoNode(nb_positions, previous, current, joints_left);
02109     
02110     node = table + index;
02111     
02112     if (node->weight != 0)
02113     {
02114         return node;
02115     }
02116     else if (joints_left == 0)
02117     {
02118         float *vec0 = vec_cache[previous];
02119         float *vec1 = vec_cache[current];
02120         float *vec2 = vec_cache[nb_positions + 1];
02121 
02122         node->weight = calcCostAngleLengthDistance(iter, vec_cache, edge, vec0, vec1, vec2, current, iter->length, angle_weight, length_weight, distance_weight);
02123 
02124         return node;
02125     }
02126     else
02127     {
02128         MemoNode *min_node = NULL;
02129         float *vec0 = vec_cache[previous];
02130         float *vec1 = vec_cache[current];
02131         float min_weight= 0.0f;
02132         int min_next= 0;
02133         int next;
02134         
02135         for (next = current + 1; next <= nb_positions - (joints_left - 1); next++)
02136         {
02137             MemoNode *next_node;
02138             float *vec2 = vec_cache[next];
02139             float weight = 0.0f;
02140             
02141             /* ADD WEIGHT OF PREVIOUS - CURRENT - NEXT triple */
02142             weight = calcCostAngleLengthDistance(iter, vec_cache, edge, vec0, vec1, vec2, current, next, angle_weight, length_weight, distance_weight);
02143             
02144             if (weight >= MAX_COST)
02145             {
02146                 continue;
02147             }
02148             
02149             /* add node weight */
02150             next_node = solveJoints(table, iter, vec_cache, nb_joints, nb_positions, current, next, edge->next, joints_left - 1, angle_weight, length_weight, distance_weight);
02151             weight += next_node->weight;
02152             
02153             if (min_node == NULL || weight < min_weight)
02154             {
02155                 min_weight = weight;
02156                 min_node = next_node;
02157                 min_next = next;
02158             }
02159         }
02160         
02161         if (min_node)
02162         {
02163             node->weight = min_weight;
02164             node->next = min_next;
02165             return node;
02166         }
02167         else
02168         {
02169             node->weight = MAX_COST;
02170             return node;
02171         }
02172     }
02173     
02174 }
02175 
02176 static int testFlipArc(RigArc *iarc, RigNode *inode_start)
02177 {
02178     ReebArc *earc = iarc->link_mesh;
02179     ReebNode *enode_start = BIF_NodeFromIndex(earc, inode_start->link_mesh);
02180     
02181     /* no flip needed if both nodes are the same */
02182     if ((enode_start == earc->head && inode_start == iarc->head) || (enode_start == earc->tail && inode_start == iarc->tail))
02183     {
02184         return 0;
02185     }
02186     else
02187     {
02188         return 1;
02189     }
02190 }
02191 
02192 static void retargetArctoArcAggresive(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
02193 {
02194     ReebArcIterator arc_iter;
02195     BArcIterator *iter = (BArcIterator*)&arc_iter;
02196     RigEdge *edge;
02197     EmbedBucket *bucket = NULL;
02198     ReebNode *node_start, *node_end;
02199     ReebArc *earc = iarc->link_mesh;
02200     float angle_weight = 1.0; // GET FROM CONTEXT
02201     float length_weight = 1.0;
02202     float distance_weight = 1.0;
02203 #ifndef USE_THREADS
02204     float min_cost = FLT_MAX;
02205 #endif
02206     float *vec0, *vec1;
02207     int *best_positions;
02208     int nb_edges = BLI_countlist(&iarc->edges);
02209     int nb_joints = nb_edges - 1;
02210     RetargetMethod method = METHOD_MEMOIZE;
02211     int i;
02212     
02213     if (nb_joints > earc->bcount)
02214     {
02215         printf("NOT ENOUGH BUCKETS!\n");
02216         return;
02217     }
02218 
02219     best_positions = MEM_callocN(sizeof(int) * nb_joints, "Best positions");
02220     
02221     if (testFlipArc(iarc, inode_start))
02222     {
02223         node_start = earc->tail;
02224         node_end = earc->head;
02225     }
02226     else
02227     {
02228         node_start = earc->head;
02229         node_end = earc->tail;
02230     }
02231 
02232     /* equal number of joints and potential position, just fill them in */
02233     if (nb_joints == earc->bcount)
02234     {
02235         int i;
02236         
02237         /* init with first values */
02238         for (i = 0; i < nb_joints; i++)
02239         {
02240             best_positions[i] = i + 1;
02241         }
02242     }
02243     if (method == METHOD_MEMOIZE)
02244     {
02245         int nb_positions = earc->bcount;
02246         int nb_memo_nodes = nb_positions * nb_positions * (nb_joints + 1);
02247         MemoNode *table = MEM_callocN(nb_memo_nodes * sizeof(MemoNode), "memoization table");
02248 #ifndef USE_THREADS
02249         MemoNode *result;
02250 #endif
02251         float **positions_cache = MEM_callocN(sizeof(float*) * (nb_positions + 2), "positions cache");
02252         int i;
02253         
02254         positions_cache[0] = node_start->p;
02255         positions_cache[nb_positions + 1] = node_end->p;
02256         
02257         initArcIterator(iter, earc, node_start);
02258 
02259         for (i = 1; i <= nb_positions; i++)
02260         {
02261             EmbedBucket *bucket = IT_peek(iter, i);
02262             positions_cache[i] = bucket->p;
02263         }
02264 
02265 #ifndef USE_THREADS
02266         result = solveJoints(table, iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints, angle_weight, length_weight, distance_weight);
02267         min_cost = result->weight;
02268 #else
02269         solveJoints(table, iter, positions_cache, nb_joints, earc->bcount, 0, 0, iarc->edges.first, nb_joints, angle_weight, length_weight, distance_weight);
02270 #endif
02271 
02272         copyMemoPositions(best_positions, table, earc->bcount, nb_joints);
02273 
02274         MEM_freeN(table);
02275         MEM_freeN(positions_cache);
02276     }
02277 
02278     vec0 = node_start->p;
02279     initArcIterator(iter, earc, node_start);
02280     
02281 #ifndef USE_THREADS
02282     printPositions(best_positions, nb_joints);
02283     printMovesNeeded(best_positions, nb_joints);
02284     printf("min_cost %f\n", min_cost);
02285     printf("buckets: %i\n", earc->bcount);
02286 #endif
02287 
02288     /* set joints to best position */
02289     for (edge = iarc->edges.first, i = 0;
02290          edge;
02291          edge = edge->next, i++)
02292     {
02293         float *no = NULL;
02294         if (i < nb_joints)
02295         {
02296             bucket = IT_peek(iter, best_positions[i]);
02297             vec1 = bucket->p;
02298             no = bucket->no;
02299         }
02300         else
02301         {
02302             vec1 = node_end->p;
02303             no = node_end->no;
02304         }
02305         
02306         if (edge->bone)
02307         {
02308             repositionBone(C, rigg, edge, vec0, vec1, no);
02309         }
02310         
02311         vec0 = vec1;
02312     }
02313 
02314     MEM_freeN(best_positions);
02315 }
02316 
02317 static void retargetArctoArcLength(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
02318 {
02319     ReebArcIterator arc_iter;
02320     BArcIterator *iter = (BArcIterator*)&arc_iter;
02321     ReebArc *earc = iarc->link_mesh;
02322     ReebNode *node_start, *node_end;
02323     RigEdge *edge;
02324     EmbedBucket *bucket = NULL;
02325     float embedding_length = 0;
02326     float *vec0 = NULL;
02327     float *vec1 = NULL;
02328     float *previous_vec = NULL;
02329 
02330     
02331     if (testFlipArc(iarc, inode_start))
02332     {
02333         node_start = (ReebNode*)earc->tail;
02334         node_end = (ReebNode*)earc->head;
02335     }
02336     else
02337     {
02338         node_start = (ReebNode*)earc->head;
02339         node_end = (ReebNode*)earc->tail;
02340     }
02341     
02342     initArcIterator(iter, earc, node_start);
02343 
02344     bucket = IT_next(iter);
02345     
02346     vec0 = node_start->p;
02347     
02348     while (bucket != NULL)
02349     {
02350         vec1 = bucket->p;
02351         
02352         embedding_length += len_v3v3(vec0, vec1);
02353         
02354         vec0 = vec1;
02355         bucket = IT_next(iter);
02356     }
02357     
02358     embedding_length += len_v3v3(node_end->p, vec1);
02359     
02360     /* fit bones */
02361     initArcIterator(iter, earc, node_start);
02362 
02363     bucket = IT_next(iter);
02364 
02365     vec0 = node_start->p;
02366     previous_vec = vec0;
02367     vec1 = bucket->p;
02368     
02369     for (edge = iarc->edges.first; edge; edge = edge->next)
02370     {
02371         float new_bone_length = edge->length / iarc->length * embedding_length;
02372         float *no = NULL;
02373         float length = 0;
02374 
02375         while (bucket && new_bone_length > length)
02376         {
02377             length += len_v3v3(previous_vec, vec1);
02378             bucket = IT_next(iter);
02379             previous_vec = vec1;
02380             vec1 = bucket->p;
02381             no = bucket->no;
02382         }
02383         
02384         if (bucket == NULL)
02385         {
02386             vec1 = node_end->p;
02387             no = node_end->no;
02388         }
02389 
02390         /* no need to move virtual edges (space between unconnected bones) */       
02391         if (edge->bone)
02392         {
02393             repositionBone(C, rigg, edge, vec0, vec1, no);
02394         }
02395         
02396         vec0 = vec1;
02397         previous_vec = vec1;
02398     }
02399 }
02400 
02401 static void retargetArctoArc(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start)
02402 {
02403 #ifdef USE_THREADS
02404     RetargetParam *p = MEM_callocN(sizeof(RetargetParam), "RetargetParam");
02405     
02406     p->rigg = rigg;
02407     p->iarc = iarc;
02408     p->inode_start = inode_start;
02409     p->context = C;
02410     
02411     BLI_insert_work(rigg->worker, p);
02412 #else
02413     RetargetParam p;
02414 
02415     p.rigg = rigg;
02416     p.iarc = iarc;
02417     p.inode_start = inode_start;
02418     p.context = C;
02419     
02420     exec_retargetArctoArc(&p);
02421 #endif
02422 }
02423 
02424 void *exec_retargetArctoArc(void *param)
02425 {
02426     RetargetParam *p = (RetargetParam*)param;
02427     RigGraph *rigg = p->rigg;
02428     RigArc *iarc = p->iarc;
02429     bContext *C = p->context;   
02430     RigNode *inode_start = p->inode_start;
02431     ReebArc *earc = iarc->link_mesh;
02432     
02433     if (BLI_countlist(&iarc->edges) == 1)
02434     {
02435         RigEdge *edge = iarc->edges.first;
02436 
02437         if (testFlipArc(iarc, inode_start))
02438         {
02439             repositionBone(C, rigg, edge, earc->tail->p, earc->head->p, earc->head->no);
02440         }
02441         else
02442         {
02443             repositionBone(C, rigg, edge, earc->head->p, earc->tail->p, earc->tail->no);
02444         }
02445     }
02446     else
02447     {
02448         RetargetMode mode = detectArcRetargetMode(iarc);
02449         
02450         if (mode == RETARGET_AGGRESSIVE)
02451         {
02452             retargetArctoArcAggresive(C, rigg, iarc, inode_start);
02453         }
02454         else
02455         {       
02456             retargetArctoArcLength(C, rigg, iarc, inode_start);
02457         }
02458     }
02459 
02460 #ifdef USE_THREADS
02461     MEM_freeN(p);
02462 #endif
02463     
02464     return NULL;
02465 }
02466 
02467 static void matchMultiResolutionNode(RigGraph *rigg, RigNode *inode, ReebNode *top_node)
02468 {
02469     ReebNode *enode = top_node;
02470     ReebGraph *reebg = BIF_graphForMultiNode(rigg->link_mesh, enode);
02471     int ishape, eshape;
02472     
02473     ishape = BLI_subtreeShape((BGraph*)rigg, (BNode*)inode, NULL, 0) % SHAPE_LEVELS;
02474     eshape = BLI_subtreeShape((BGraph*)reebg, (BNode*)enode, NULL, 0) % SHAPE_LEVELS;
02475     
02476     inode->link_mesh = enode;
02477 
02478     while (ishape == eshape && enode->link_down)
02479     {
02480         inode->link_mesh = enode;
02481 
02482         enode = enode->link_down;
02483         reebg = BIF_graphForMultiNode(rigg->link_mesh, enode); /* replace with call to link_down once that exists */
02484         eshape = BLI_subtreeShape((BGraph*)reebg, (BNode*)enode, NULL, 0) % SHAPE_LEVELS;
02485     } 
02486 }
02487 
02488 static void markMultiResolutionChildArc(ReebNode *end_enode, ReebNode *enode)
02489 {
02490     int i;
02491     
02492     for(i = 0; i < enode->degree; i++)
02493     {
02494         ReebArc *earc = (ReebArc*)enode->arcs[i];
02495         
02496         if (earc->flag == ARC_FREE)
02497         {
02498             earc->flag = ARC_TAKEN;
02499             
02500             if (earc->tail->degree > 1 && earc->tail != end_enode)
02501             {
02502                 markMultiResolutionChildArc(end_enode, earc->tail);
02503             }
02504             break;
02505         }
02506     }
02507 }
02508 
02509 static void markMultiResolutionArc(ReebArc *start_earc)
02510 {
02511     if (start_earc->link_up)
02512     {
02513         ReebArc *earc;
02514         for (earc = start_earc->link_up ; earc; earc = earc->link_up)
02515         {
02516             earc->flag = ARC_TAKEN;
02517             
02518             if (earc->tail->index != start_earc->tail->index)
02519             {
02520                 markMultiResolutionChildArc(earc->tail, earc->tail);
02521             }
02522         }
02523     }
02524 }
02525 
02526 static void matchMultiResolutionArc(RigGraph *rigg, RigNode *start_node, RigArc *next_iarc, ReebArc *next_earc)
02527 {
02528     ReebNode *enode = next_earc->head;
02529     ReebGraph *reebg = BIF_graphForMultiNode(rigg->link_mesh, enode);
02530     int ishape, eshape;
02531 
02532     ishape = BLI_subtreeShape((BGraph*)rigg, (BNode*)start_node, (BArc*)next_iarc, 1) % SHAPE_LEVELS;
02533     eshape = BLI_subtreeShape((BGraph*)reebg, (BNode*)enode, (BArc*)next_earc, 1) % SHAPE_LEVELS;
02534     
02535     while (ishape != eshape && next_earc->link_up)
02536     {
02537         next_earc->flag = ARC_TAKEN; // mark previous as taken, to prevent backtrack on lower levels
02538         
02539         next_earc = next_earc->link_up;
02540         reebg = reebg->link_up;
02541         enode = next_earc->head;
02542         eshape = BLI_subtreeShape((BGraph*)reebg, (BNode*)enode, (BArc*)next_earc, 1) % SHAPE_LEVELS;
02543     } 
02544 
02545     next_earc->flag = ARC_USED;
02546     next_iarc->link_mesh = next_earc;
02547     
02548     /* mark all higher levels as taken too */
02549     markMultiResolutionArc(next_earc);
02550 //  while (next_earc->link_up)
02551 //  {
02552 //      next_earc = next_earc->link_up;
02553 //      next_earc->flag = ARC_TAKEN;
02554 //  }
02555 }
02556 
02557 static void matchMultiResolutionStartingNode(RigGraph *rigg, ReebGraph *reebg, RigNode *inode)
02558 {
02559     ReebNode *enode;
02560     int ishape, eshape;
02561     
02562     enode = reebg->nodes.first;
02563     
02564     ishape = BLI_subtreeShape((BGraph*)rigg, (BNode*)inode, NULL, 0) % SHAPE_LEVELS;
02565     eshape = BLI_subtreeShape((BGraph*)rigg->link_mesh, (BNode*)enode, NULL, 0) % SHAPE_LEVELS;
02566     
02567     while (ishape != eshape && reebg->link_up)
02568     {
02569         reebg = reebg->link_up;
02570         
02571         enode = reebg->nodes.first;
02572         
02573         eshape = BLI_subtreeShape((BGraph*)reebg, (BNode*)enode, NULL, 0) % SHAPE_LEVELS;
02574     } 
02575 
02576     inode->link_mesh = enode;
02577 }
02578 
02579 static void findCorrespondingArc(RigGraph *rigg, RigArc *start_arc, RigNode *start_node, RigArc *next_iarc, int root)
02580 {
02581     ReebNode *enode = start_node->link_mesh;
02582     ReebArc *next_earc;
02583     int symmetry_level = next_iarc->symmetry_level;
02584     int symmetry_group = next_iarc->symmetry_group;
02585     int symmetry_flag = next_iarc->symmetry_flag;
02586     int i;
02587     
02588     next_iarc->link_mesh = NULL;
02589         
02590 //  if (root)
02591 //  {
02592 //      printf("-----------------------\n");
02593 //      printf("MATCHING LIMB\n");
02594 //      RIG_printArcBones(next_iarc);
02595 //  }
02596     
02597     for(i = 0; i < enode->degree; i++)
02598     {
02599         next_earc = (ReebArc*)enode->arcs[i];
02600         
02601 //      if (next_earc->flag == ARC_FREE)
02602 //      {
02603 //          printf("candidate (level %i ?= %i) (flag %i ?= %i) (group %i ?= %i)\n",
02604 //          symmetry_level, next_earc->symmetry_level,
02605 //          symmetry_flag, next_earc->symmetry_flag, 
02606 //          symmetry_group, next_earc->symmetry_flag);
02607 //      }
02608         
02609         if (next_earc->flag == ARC_FREE &&
02610             next_earc->symmetry_flag == symmetry_flag &&
02611             next_earc->symmetry_group == symmetry_group &&
02612             next_earc->symmetry_level == symmetry_level)
02613         {
02614 //          printf("CORRESPONDING ARC FOUND\n");
02615 //          printf("flag %i -- level %i -- flag %i -- group %i\n", next_earc->flag, next_earc->symmetry_level, next_earc->symmetry_flag, next_earc->symmetry_group);
02616             
02617             matchMultiResolutionArc(rigg, start_node, next_iarc, next_earc);
02618             break;
02619         }
02620     }
02621     
02622     /* not found, try at higher nodes (lower node might have filtered internal arcs, messing shape of tree */
02623     if (next_iarc->link_mesh == NULL)
02624     {
02625 //      printf("NO CORRESPONDING ARC FOUND - GOING TO HIGHER LEVELS\n");
02626         
02627         if (enode->link_up)
02628         {
02629             start_node->link_mesh = enode->link_up;
02630             findCorrespondingArc(rigg, start_arc, start_node, next_iarc, 0);
02631         }
02632     }
02633 
02634     /* still not found, print debug info */
02635     if (root && next_iarc->link_mesh == NULL)
02636     {
02637         start_node->link_mesh = enode; /* linking back with root node */
02638         
02639 //      printf("NO CORRESPONDING ARC FOUND\n");
02640 //      RIG_printArcBones(next_iarc);
02641 //      
02642 //      printf("ON NODE %i, multilevel %i\n", enode->index, enode->multi_level);
02643 //      
02644 //      printf("LOOKING FOR\n");
02645 //      printf("flag %i -- level %i -- flag %i -- group %i\n", ARC_FREE, symmetry_level, symmetry_flag, symmetry_group);
02646 //      
02647 //      printf("CANDIDATES\n");
02648 //      for(i = 0; i < enode->degree; i++)
02649 //      {
02650 //          next_earc = (ReebArc*)enode->arcs[i];
02651 //          printf("flag %i -- level %i -- flag %i -- group %i\n", next_earc->flag, next_earc->symmetry_level, next_earc->symmetry_flag, next_earc->symmetry_group);
02652 //      }
02653         
02654         /* Emergency matching */
02655         for(i = 0; i < enode->degree; i++)
02656         {
02657             next_earc = (ReebArc*)enode->arcs[i];
02658             
02659             if (next_earc->flag == ARC_FREE && next_earc->symmetry_level == symmetry_level)
02660             {
02661 //              printf("USING: \n");
02662 //              printf("flag %i -- level %i -- flag %i -- group %i\n", next_earc->flag, next_earc->symmetry_level, next_earc->symmetry_flag, next_earc->symmetry_group);
02663                 matchMultiResolutionArc(rigg, start_node, next_iarc, next_earc);
02664                 break;
02665             }
02666         }
02667     }
02668 
02669 }
02670 
02671 static void retargetSubgraph(bContext *C, RigGraph *rigg, RigArc *start_arc, RigNode *start_node)
02672 {
02673     RigNode *inode = start_node;
02674     int i;
02675 
02676     /* no start arc on first node */
02677     if (start_arc)
02678     {       
02679         ReebNode *enode = start_node->link_mesh;
02680         ReebArc *earc = start_arc->link_mesh;
02681         
02682         retargetArctoArc(C, rigg, start_arc, start_node);
02683         
02684         enode = BIF_otherNodeFromIndex(earc, enode);
02685         inode = (RigNode*)BLI_otherNode((BArc*)start_arc, (BNode*)inode);
02686     
02687         /* match with lowest node with correct shape */
02688         matchMultiResolutionNode(rigg, inode, enode);
02689     }
02690     
02691     for(i = 0; i < inode->degree; i++)
02692     {
02693         RigArc *next_iarc = (RigArc*)inode->arcs[i];
02694         
02695         /* no back tracking */
02696         if (next_iarc != start_arc)
02697         {
02698             findCorrespondingArc(rigg, start_arc, inode, next_iarc, 1);
02699             if (next_iarc->link_mesh)
02700             {
02701                 retargetSubgraph(C, rigg, next_iarc, inode);
02702             }
02703         }
02704     }
02705 }
02706 
02707 static void finishRetarget(RigGraph *rigg)
02708 {
02709 #ifdef USE_THREADS
02710     BLI_end_worker(rigg->worker);
02711 #endif
02712 }
02713 
02714 static void adjustGraphs(bContext *C, RigGraph *rigg)
02715 {
02716     bArmature *arm= rigg->ob->data;
02717     RigArc *arc;
02718     
02719     for (arc = rigg->arcs.first; arc; arc = arc->next)
02720     {
02721         if (arc->link_mesh)
02722         {
02723             retargetArctoArc(C, rigg, arc, arc->head);
02724         }
02725     }
02726 
02727     finishRetarget(rigg);
02728 
02729     /* Turn the list into an armature */
02730     arm->edbo = rigg->editbones;
02731     ED_armature_from_edit(rigg->ob);
02732     
02733     ED_undo_push(C, "Retarget Skeleton");
02734 }
02735 
02736 static void retargetGraphs(bContext *C, RigGraph *rigg)
02737 {
02738     bArmature *arm= rigg->ob->data;
02739     ReebGraph *reebg = rigg->link_mesh;
02740     RigNode *inode;
02741     
02742     /* flag all ReebArcs as free */
02743     BIF_flagMultiArcs(reebg, ARC_FREE);
02744     
02745     /* return to first level */
02746     inode = rigg->head;
02747     
02748     matchMultiResolutionStartingNode(rigg, reebg, inode);
02749 
02750     retargetSubgraph(C, rigg, NULL, inode);
02751     
02752     //generateMissingArcs(rigg);
02753     
02754     finishRetarget(rigg);
02755 
02756     /* Turn the list into an armature */
02757     arm->edbo = rigg->editbones;
02758     ED_armature_from_edit(rigg->ob);
02759 }
02760 
02761 const char *RIG_nameBone(RigGraph *rg, int arc_index, int bone_index)
02762 {
02763     RigArc *arc = BLI_findlink(&rg->arcs, arc_index);
02764     RigEdge *iedge;
02765 
02766     if (arc == NULL)
02767     {
02768         return "None";
02769     }
02770     
02771     if (bone_index == BLI_countlist(&arc->edges))
02772     {
02773         return "Last joint";
02774     }
02775 
02776     iedge = BLI_findlink(&arc->edges, bone_index);
02777     
02778     if (iedge == NULL)
02779     {
02780         return "Done";
02781     }
02782     
02783     if (iedge->bone == NULL)
02784     {
02785         return "Bone offset";
02786     }
02787     
02788     return iedge->bone->name;
02789 }
02790 
02791 int RIG_nbJoints(RigGraph *rg)
02792 {
02793     RigArc *arc;
02794     int total = 0;
02795     
02796     total += BLI_countlist(&rg->nodes);
02797     
02798     for (arc = rg->arcs.first; arc; arc = arc->next)
02799     {
02800         total += BLI_countlist(&arc->edges) - 1; /* -1 because end nodes are already counted */
02801     }
02802     
02803     return total;
02804 }
02805 
02806 static void BIF_freeRetarget(void)
02807 {
02808     if (GLOBAL_RIGG)
02809     {
02810         RIG_freeRigGraph((BGraph*)GLOBAL_RIGG);
02811         GLOBAL_RIGG = NULL;
02812     }
02813 }
02814 
02815 void BIF_retargetArmature(bContext *C)
02816 {
02817     ReebGraph *reebg;
02818     double start_time, end_time;
02819     double gstart_time, gend_time;
02820     double reeb_time, rig_time=0.0, retarget_time=0.0, total_time;
02821     
02822     gstart_time = start_time = PIL_check_seconds_timer();
02823     
02824     reebg = BIF_ReebGraphMultiFromEditMesh(C);
02825     
02826     end_time = PIL_check_seconds_timer();
02827     reeb_time = end_time - start_time;
02828     
02829     printf("Reeb Graph created\n");
02830 
02831     CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
02832         Object *ob = base->object;
02833 
02834         if (ob->type==OB_ARMATURE)
02835         {
02836             RigGraph *rigg;
02837             bArmature *arm;
02838 
02839             arm = ob->data;
02840         
02841             /* Put the armature into editmode */
02842             
02843         
02844             start_time = PIL_check_seconds_timer();
02845 
02846             rigg = RIG_graphFromArmature(C, ob, arm);
02847             
02848             end_time = PIL_check_seconds_timer();
02849             rig_time = end_time - start_time;
02850 
02851             printf("Armature graph created\n");
02852     
02853             //RIG_printGraph(rigg);
02854             
02855             rigg->link_mesh = reebg;
02856             
02857             printf("retargetting %s\n", ob->id.name);
02858             
02859             start_time = PIL_check_seconds_timer();
02860 
02861             retargetGraphs(C, rigg);
02862             
02863             end_time = PIL_check_seconds_timer();
02864             retarget_time = end_time - start_time;
02865 
02866             BIF_freeRetarget();
02867             
02868             GLOBAL_RIGG = rigg;
02869             
02870             break; /* only one armature at a time */
02871         }
02872     }
02873     CTX_DATA_END;
02874 
02875     
02876     gend_time = PIL_check_seconds_timer();
02877 
02878     total_time = gend_time - gstart_time;
02879 
02880     printf("-----------\n");
02881     printf("runtime: \t%.3f\n", total_time);
02882     printf("reeb: \t\t%.3f (%.1f%%)\n", reeb_time, reeb_time / total_time * 100);
02883     printf("rig: \t\t%.3f (%.1f%%)\n", rig_time, rig_time / total_time * 100);
02884     printf("retarget: \t%.3f (%.1f%%)\n", retarget_time, retarget_time / total_time * 100);
02885     printf("-----------\n");
02886     
02887     ED_undo_push(C, "Retarget Skeleton");
02888 
02889     // XXX  
02890 //  allqueue(REDRAWVIEW3D, 0);
02891 }
02892 
02893 void BIF_retargetArc(bContext *C, ReebArc *earc, RigGraph *template_rigg)
02894 {
02895     Object *obedit = CTX_data_edit_object(C);
02896     Scene *scene = CTX_data_scene(C);
02897     bArmature *armedit = obedit->data;
02898     Object *ob;
02899     RigGraph *rigg;
02900     RigArc *iarc;
02901     char *side_string = scene->toolsettings->skgen_side_string;
02902     char *num_string = scene->toolsettings->skgen_num_string;
02903     int free_template = 0;
02904     
02905     if (template_rigg)
02906     {
02907         ob = template_rigg->ob;     
02908     }
02909     else
02910     {
02911         free_template = 1;
02912         ob = obedit;
02913         template_rigg = armatureSelectedToGraph(C, ob, ob->data);
02914     }
02915     
02916     if (template_rigg->arcs.first == NULL)
02917     {
02918 //      XXX
02919 //      error("No Template and no deforming bones selected");
02920         return;
02921     }
02922     
02923     rigg = cloneRigGraph(template_rigg, armedit->edbo, obedit, side_string, num_string);
02924     
02925     iarc = rigg->arcs.first;
02926     
02927     iarc->link_mesh = earc;
02928     iarc->head->link_mesh = earc->head;
02929     iarc->tail->link_mesh = earc->tail;
02930     
02931     retargetArctoArc(C, rigg, iarc, iarc->head);
02932     
02933     finishRetarget(rigg);
02934     
02935     /* free template if it comes from the edit armature */
02936     if (free_template)
02937     {
02938         RIG_freeRigGraph((BGraph*)template_rigg);
02939     }
02940     RIG_freeRigGraph((BGraph*)rigg);
02941     
02942     ED_armature_validate_active(armedit);
02943 
02944 //  XXX
02945 //  allqueue(REDRAWVIEW3D, 0);
02946 }
02947 
02948 void BIF_adjustRetarget(bContext *C)
02949 {
02950     if (GLOBAL_RIGG)
02951     {
02952         adjustGraphs(C, GLOBAL_RIGG);
02953     }
02954 }