Two in one:
[blender.git] / source / blender / src / editconstraint.c
index be40b84c40353268070601c5eec7f6774aa21873..bb921906d55bfe28541746a5ad9fb34eb5a34eb5 100644 (file)
 #include "MEM_guardedalloc.h"
 
 #include "BLI_blenlib.h"
+#include "BLI_arithb.h"
 
 #include "DNA_action_types.h"
 #include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_curve_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
-#include "DNA_constraint_types.h"
-#include "DNA_curve_types.h"
+#include "DNA_view3d_types.h"
 
-#include "BKE_utildefines.h"
 #include "BKE_action.h"
 #include "BKE_armature.h"
-#include "BKE_object.h"
-#include "BKE_global.h"
 #include "BKE_constraint.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
 #include "BKE_ipo.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
 
+#include "BIF_editaction.h"
 #include "BIF_editarmature.h"
 #include "BIF_editconstraint.h"
+#include "BIF_poseobject.h"
 #include "BIF_interface.h"
 #include "BIF_screen.h"
+#include "BIF_space.h"
 #include "BIF_toolbox.h"
 
-#include "BSE_editaction.h"
-
 #include "blendef.h"
 #include "nla.h"
+#include "mydevice.h"
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-static short add_constraint_element (Object *owner, const char *substring, Object *parent, const char *parentstring);
-static short detect_constraint_loop (Object *owner, const char* substring, int disable, char type);
-static void test_bonelist_constraints (Object *owner, ListBase *list);
-static void clear_object_constraint_loop_flags(Object *ob);
-//static int is_child_of(struct Object *owner, struct Object *parent);
-//static int is_bonechild_of(struct Bone *bone, struct Bone *parent);
-static int is_child_of_ex(Object *owner, const char *ownersubstr, Object *parent, const char *parsubstr);
 
-ListBase g_conBase;
-const char *g_conString;
-Object *g_conObj;
-
-
-static int is_child_of_ex(Object *owner, const char *ownersubstr, Object *parent, const char *parsubstr)
+ListBase *get_active_constraint_channels (Object *ob, int forcevalid)
 {
-       Object *curob;
-       Bone *bone = NULL;
-       Bone *parbone= NULL;
-
-       curob=owner;
-
-       /* If this is a bone */
-       if (strlen(ownersubstr))
-               bone = get_named_bone(get_armature(owner->parent), ownersubstr);
-       
-       if (strlen(parsubstr))
-               parbone = get_named_bone(get_armature(parent), parsubstr);
-
-
-       /* Traverse the scene graph */
-       while (curob && !bone){
-               switch (curob->partype){
-               case PARBONE:
-                       if (strlen(parsubstr)){
-                               bone = get_named_bone(get_armature(curob->parent), curob->parsubstr);
-                               break;
-                       }
-                       /* The break is supposed to be missing */
-               default:
-                       if (curob==parent){
-                               if (parbone)
-                                       return 0;
-                               else
-                                       return 1;
-                       }
-               }
-               curob=curob->parent;
-       }
-
-
-       /* Descend into the armature scene graph */
-       while (bone){
-               if (bone==parbone)
-                       return 1;
-               bone=bone->parent;
-       }
+       char ipstr[64];
        
-       return 0;
-}
-/*
-static int is_child_of(Object *owner, Object *parent)
-{
-       Object *curpar;
-
-       for (curpar = owner->parent; curpar; curpar=curpar->parent){
-               if (curpar==parent)
-                       return 1;
-       }
-
-       return 0;
-}
-
-
-static int is_bonechild_of(Bone *bone, Bone *parent)
-{
-       Bone *curpar;
-
-       if (!bone)
-               return 0;
-
-       for (curpar = bone->parent; curpar; curpar=curpar->parent){
-               if (curpar==parent)
-                       return 1;
-       }
-       return 0;
-}
-*/
-static short add_constraint_element (Object *owner, const char *substring, Object *parent, const char *parentstring)
-{
+       if (!ob)
+               return NULL;
        
-       if (!owner)
-               return 0;
-
-       /* See if this is the original object */
-       if (parent == owner){
-               if (!strcmp (parentstring, substring))
-                               return 1;
-       }
+       /* See if we are a bone constraint */
+       if (ob->flag & OB_POSEMODE) {
+               bActionChannel *achan;
+               bPoseChannel *pchan;
 
-       if (owner == g_conObj){
-               if (!strcmp (g_conString, substring))
-                       return 1;
-       }
+               pchan = get_active_posechannel(ob);
+               if (pchan) {
+                       
+                       /* Make sure we have an action */
+                       if (!ob->action){
+                               if (!forcevalid)
+                                       return NULL;
+                               
+                               ob->action=add_empty_action(ID_PO);
+                       }
+                       
+                       /* Make sure we have an actionchannel */
+                       achan = get_action_channel(ob->action, pchan->name);
+                       if (!achan){
+                               if (!forcevalid)
+                                       return NULL;
+                               
+                               achan = MEM_callocN (sizeof(bActionChannel), "actionChannel");
 
-       /* See if this is a child of the adding object */
-       if (parent){
-//             if (is_child_of (owner, parent))
-               if (is_child_of_ex (owner, substring, parent, parentstring))
-                       return 1;
-               /* Parent is a bone */
-/*             if ((owner==parent) && (owner->type == OB_ARMATURE)){
-                       if (strlen (substring) && strlen(parentstring)){
-                               if (is_bonechild_of(get_named_bone(owner->data, substring), get_named_bone(parent->data, parentstring)))
-                                       return 1;
+                               strcpy (achan->name, pchan->name);
+                               sprintf (ipstr, "%s.%s", ob->action->id.name+2, achan->name);
+                               ipstr[23]=0;
+                               achan->ipo=     add_ipo(ipstr, ID_AC);  
+                               
+                               BLI_addtail (&ob->action->chanbase, achan);
                        }
+                       
+                       return &achan->constraintChannels;
                }
-               */
+               else return NULL;
        }
-       return 0;
-}
-
-static void test_bonelist_constraints (Object *owner, ListBase *list)
-{
-       Bone *bone;
-       Base    *base1;
-
-
-       for (bone = list->first; bone; bone=bone->next){
-               for (base1 = G.scene->base.first; base1; base1=base1->next){
-                       clear_object_constraint_loop_flags(base1->object);
+       /* else we return object constraints */
+       else {
+               if(ob->ipoflag & OB_ACTION_OB) {
+                       bActionChannel *achan = get_action_channel(ob->action, "Object");
+                       if(achan)
+                               return &achan->constraintChannels;
+                       else 
+                               return NULL;
                }
-               test_constraints(owner, bone->name, 1);
-               test_bonelist_constraints (owner, &bone->childbase);
+               
+               return &ob->constraintChannels;
        }
 }
 
 
-static void clear_object_constraint_loop_flags(Object *ob)
+/* if object in posemode, active bone constraints, else object constraints */
+ListBase *get_active_constraints(Object *ob)
 {
-       bConstraint *con;
-
        if (!ob)
-               return;
-
-       /* Test object constraints */
-       for (con = ob->constraints.first; con; con=con->next){
-               con->flag &= ~CONSTRAINT_LOOPTESTED;
-       }
-
-       switch (ob->type){
-       case OB_ARMATURE:
-               if (ob->pose){
-                       bPoseChannel *pchan;
-                       for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next){
-                               for (con = pchan->constraints.first; con; con=con->next){
-                                       con->flag &= ~CONSTRAINT_LOOPTESTED;
-                               }
-                       }
-               }
-               break;
-       default:
-               break;
-       }
-}
-void test_scene_constraints (void)
-{
-       Base *base, *base1;
+               return NULL;
 
-/*     Clear the "done" flags of all constraints */
+       if (ob->flag & OB_POSEMODE) {
+               bPoseChannel *pchan;
 
-       for (base = G.scene->base.first; base; base=base->next){
-               clear_object_constraint_loop_flags(base->object);
+               pchan = get_active_posechannel(ob);
+               if (pchan)
+                       return &pchan->constraints;
        }
+       else 
+               return &ob->constraints;
 
-       /*      Test all constraints */
-       for (base = G.scene->base.first; base; base=base->next){
-               /* Test the object */
-               
-               for (base1 = G.scene->base.first; base1; base1=base1->next)
-                       clear_object_constraint_loop_flags(base1->object);
-               
-
-               test_constraints (base->object, "", 1);
-
-       
-               /* Test the subobject constraints */
-               switch (base->object->type){
-               case OB_ARMATURE:
-                       {
-                               bArmature *arm;
-                               arm = get_armature(base->object);
-                               if (arm)
-                                       test_bonelist_constraints (base->object, &arm->bonebase);
-                       }
-                       break;
-               default:
-                       break;
-               }
-
-
-       }
+       return NULL;
 }
 
-int test_constraints (Object *owner, const char *substring, int disable)
+/* single constraint */
+bConstraint *get_active_constraint(Object *ob)
 {
-/*     init_constraint_elements();*/
-       g_conObj = owner;
-       g_conString = substring;
+       ListBase *lb= get_active_constraints(ob);
 
-       if (detect_constraint_loop (owner, substring, disable, 0))
-               return 1;
-       else
-               return 0;
-
-/*     free_constraint_elements();     */
+       if(lb) {
+               bConstraint *con;
+               for(con= lb->first; con; con=con->next)
+                       if(con->flag & CONSTRAINT_ACTIVE)
+                               return con;
+       }
+       return NULL;
 }
 
-static short detect_constraint_loop (Object *owner, const char* substring, int disable, char typefrom)
+/* single channel, for ipo */
+bConstraintChannel *get_active_constraint_channel(Object *ob)
 {
-
-       bConstraint *curcon;
-       ListBase *conlist;
-       int             type;
-       int             result = 0;
-
-       if (!owner)
-               return result;
-
-       /* Check parents */
-       /* Get the constraint list for this object */
-
-       if (strlen (substring)){
-               switch (owner->type){
-               case OB_ARMATURE:
-                       type = TARGET_BONE;
-                       break;
-               default:
-                       type = TARGET_OBJECT;
-                       break;
-               }
-       }
-       else
-               type = TARGET_OBJECT;
-
-
-       switch (type){
-       case TARGET_OBJECT:
-               conlist = &owner->constraints;
-               /* Check parents */
-#if 0
-               if (owner->parent && (ELEM (owner->partype, PAROBJECT, PARBONE))){
-                       if (add_constraint_element (owner->parent, "", NULL, NULL)){
-                               return 1;
-                       }
-               /*      if (detect_constraint_loop (owner->parent, "", disable)){
-                               return 1;
-                       }
-               */
-               }
-               /* Check tracking */
-               if (owner->track && (ELEM (owner->partype, PAROBJECT, PARBONE))){
-                       if (add_constraint_element (owner->track, "", NULL, NULL)){
-                               return 1;
-                       }
-               /*      if (detect_constraint_loop (owner->track, "", disable)){
-                               return 1;
-                       }
-               */
-               }
-#else
-               if (owner->parent && (owner->partype==PAROBJECT))
-                       if (add_constraint_element (owner->parent, "", NULL, NULL))
-                               return 1;
-
-               if (owner->parent && (owner->partype==PARBONE))
-                       if (add_constraint_element (owner->parent, owner->parsubstr, NULL, NULL))
-                               return 1;
-
-               /* Check tracking */
-               if (owner->track)
-                       if (add_constraint_element (owner->track, "", NULL, NULL))
-                               return 1;
-#endif
-
-               break;
-       case TARGET_BONE:
-               {
-                       Bone *bone;
-                       bPoseChannel *chan;
-
-                       bone = get_named_bone(((bArmature*)owner->data), substring);
-                       chan = get_pose_channel (owner->pose, substring);
-                       if (bone){
-                               conlist = &chan->constraints;
-                               if (bone->parent){
-                                       if (add_constraint_element (owner, bone->parent->name, NULL, NULL))
-                                               return 1;
-                                       if (detect_constraint_loop (owner, bone->parent->name, disable, 0))
-                                               return 1;
-                               }
-                               else{
-                                       if (add_constraint_element (owner, "", NULL, NULL))
-                                               return 1;
-                                       if (detect_constraint_loop (owner, "", disable, 0))
-                                               return 1;
-                               }
-                       }
-                       else
-                               conlist = NULL;
-               }
-               break;
-       default:
-               conlist = NULL;
-               break;
-       }
+       bConstraint *con;
+       bConstraintChannel *chan;
        
-       /* Cycle constraints */
-       if (conlist){
-               for (curcon = conlist->first; curcon; curcon=curcon->next){
-                       
-                       /* Clear the disable flag */
+       if (ob->flag & OB_POSEMODE) {
+               if(ob->action) {
+                       bPoseChannel *pchan;
                        
-                       if (curcon->flag & CONSTRAINT_LOOPTESTED){
-                               return 0;
-                       }
-                       else {
-                               curcon->flag &= ~CONSTRAINT_DISABLE;
-                               curcon->flag |= CONSTRAINT_LOOPTESTED;
-                               switch (curcon->type){
-                               case CONSTRAINT_TYPE_ACTION:
-                                       {
-                                               bActionConstraint *data = curcon->data;
-
-                                               if (!exist_object(data->tar)){
-                                                       data->tar = NULL;
-                                                       break;
-                                               }
-                                               
-                                               if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                               if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_ACTION)){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                       }
-                                       break;
-                               case CONSTRAINT_TYPE_LOCLIKE:
-                                       {
-                                               bLocateLikeConstraint *data = curcon->data;
-                                       
-                                               if (!exist_object(data->tar)){
-                                                       data->tar = NULL;
-                                                       break;
-                                               }
-                                               
-                                               if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                               if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_LOCLIKE)){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                       }
-                                       break;
-                               case CONSTRAINT_TYPE_ROTLIKE:
-                                       {
-                                               bRotateLikeConstraint *data = curcon->data;
-                                       
-                                               if (!exist_object(data->tar)){
-                                                       data->tar = NULL;
-                                                       break;
-                                               }
-                                               
-                                               if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                               if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_ROTLIKE)){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                       }
-                                       break;
-                               case CONSTRAINT_TYPE_KINEMATIC:
-                                       {
-                                               bKinematicConstraint *data = curcon->data;
-                                               if (!exist_object(data->tar)){
-                                                       data->tar = NULL;
-                                                       break;
-                                               }
-
-                                               if ( (data->tar == owner) &&
-                                                        (!get_named_bone(get_armature(owner), 
-                                                                                         data->subtarget))) {
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                               }
-
-                                               
-                                               if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //      return 1;
-                                               }
-                                               if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_KINEMATIC)){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                       }
-                                       break;
-                               case CONSTRAINT_TYPE_TRACKTO:
-                                       {
-                                               bTrackToConstraint *data = curcon->data;
-                                               if (!exist_object(data->tar)) {
-                                                       data->tar = NULL;
-                                                       break;
-                                               }
-                                               
-                                               if (typefrom != CONSTRAINT_TYPE_TRACKTO && typefrom != CONSTRAINT_TYPE_LOCKTRACK){
-                                                       if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
-                                                               curcon->flag |= CONSTRAINT_DISABLE;
-                                                               result = 1;
+                       pchan = get_active_posechannel(ob);
+                       if(pchan) {
+                               for(con= pchan->constraints.first; con; con= con->next)
+                                       if(con->flag & CONSTRAINT_ACTIVE)
+                                               break;
+                               if(con) {
+                                       bActionChannel *achan = get_action_channel(ob->action, pchan->name);
+                                       if(achan) {
+                                               for(chan= achan->constraintChannels.first; chan; chan= chan->next)
+                                                       if(!strcmp(chan->name, con->name))
                                                                break;
-                                                               //      return 1;
-                                                       }
-                                               }
-                                               else {
-                                                       curcon->flag |= CONSTRAINT_NOREFRESH;
-                                               }
-
-                                               if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_TRACKTO)){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                               if (data->reserved2==data->reserved1){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                               if (data->reserved2+3==data->reserved1){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                       }
-                                       break;
-                               case CONSTRAINT_TYPE_LOCKTRACK:
-                                       {
-                                               bLockTrackConstraint *data = curcon->data;
-                                       
-                                               if (!exist_object(data->tar)){
-                                                       data->tar = NULL;
-                                                       break;
-                                               }
-                                               
-                                               if (typefrom != CONSTRAINT_TYPE_TRACKTO && typefrom != CONSTRAINT_TYPE_LOCKTRACK){
-                                                       if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
-                                                               curcon->flag |= CONSTRAINT_DISABLE;
-                                                               result = 1;
-                                                               break;
-                                                               //              return 1;
-                                                       }
-                                               }
-                                               else {
-                                                       curcon->flag |= CONSTRAINT_NOREFRESH;
-                                               }
-
-                                               if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_LOCKTRACK)){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                               if (data->lockflag==data->trackflag){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                               if (data->lockflag+3==data->trackflag){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                       }
-                                       break;
-                               case CONSTRAINT_TYPE_FOLLOWPATH:
-                                       {
-                                               bFollowPathConstraint *data = curcon->data;
-                                       
-                                               if (!exist_object(data->tar)){
-                                                       data->tar = NULL;
-                                                       break;
-                                               }
-                                               if (data->tar->type != OB_CURVE){
-                                                       data->tar = NULL;
-                                                       break;
-                                               }
-                                               if (add_constraint_element (data->tar, "", owner, substring)){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                               if (detect_constraint_loop (data->tar, "", disable, CONSTRAINT_TYPE_FOLLOWPATH)){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                               if (data->upflag==data->trackflag){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
-                                               if (data->upflag+3==data->trackflag){
-                                                       curcon->flag |= CONSTRAINT_DISABLE;
-                                                       result = 1;
-                                                       break;
-                                                       //              return 1;
-                                               }
+                                               return chan;
                                        }
-                                       break;
                                }
                        }
                }
        }
-       
-       return result;
-}
-
-ListBase *get_constraint_client_channels (int forcevalid)
-{
-
-       Object *ob;
-       char ipstr[64];
-
-       ob=OBACT;
-       
-       if (!ob)
-               return NULL;
-       
-       /* See if we are a bone constraint */
-       if (G.obpose){
-               switch (G.obpose->type){
-               case OB_ARMATURE:
-                       {
-                               bActionChannel *achan;
-                               Bone *bone;
-
-                               bone = get_first_selected_bone();
-                               if (!bone) break;
-                               
-                               /* Make sure we have an action */
-                               if (!G.obpose->action){
-                                       if (!forcevalid)
-                                               return NULL;
-                                       
-                                       G.obpose->action=add_empty_action();
-                               }
-                               
-                               /* Make sure we have an actionchannel */
-                               achan = get_named_actionchannel(G.obpose->action, bone->name);
-                               if (!achan){
-                                       if (!forcevalid)
-                                               return NULL;
-                                       
-                                       achan = MEM_callocN (sizeof(bActionChannel), "actionChannel");
-
-                                       strcpy (achan->name, bone->name);
-                                       sprintf (ipstr, "%s.%s", G.obpose->action->id.name+2, achan->name);
-                                       ipstr[23]=0;
-                                       achan->ipo=     add_ipo(ipstr, ID_AC);  
-                                       
-                                       BLI_addtail (&G.obpose->action->chanbase, achan);
-                               }
-                               
-                               return &achan->constraintChannels;
+       else {
+               for(con= ob->constraints.first; con; con= con->next)
+                       if(con->flag & CONSTRAINT_ACTIVE)
+                               break;
+               if(con) {
+                       ListBase *lb= get_active_constraint_channels(ob, 0);
+
+                       if(lb) {
+                               for(chan= lb->first; chan; chan= chan->next)
+                                       if(!strcmp(chan->name, con->name))
+                                               break;
+                               return chan;
                        }
                }
        }
        
-       return &ob->constraintChannels;
+       return NULL;
 }
 
-ListBase *get_constraint_client(char *name, short *clientType, void **clientdata)
-{
-       Object *ob;
-       ListBase *list;
-
-       ob=OBACT;
-       if (clientType)
-               *clientType = -1;
-
-       if (!ob)
-               return NULL;
-
-       list = &ob->constraints;
-
-       /* Prep the object's constraint channels */
-       if (clientType)
-               *clientType = TARGET_OBJECT;
-       
-       if (name)
-               strcpy (name, ob->id.name+2);
-
-       if (G.obpose){
-               switch (G.obpose->type){
-               case OB_ARMATURE:
-                       {
-                               Bone *bone;
-
-                               bone = get_first_selected_bone();
-                               if (!bone) break;
-
-                               {
-                                       bPoseChannel    *chan;
-                                       
-                                       /* Is the bone the client? */
-                                       if (clientType)
-                                               *clientType = TARGET_BONE;
-                                       if (clientdata)
-                                               *clientdata = bone;
-                                       if (name)
-                                               sprintf (name, "%s>>%s", name, bone->name);
-                                       chan = verify_pose_channel(G.obpose->pose, bone->name);
-                                       list = &chan->constraints;
-
-                               }                       
-                       }
-                       break;
-               }
-       }
-
-       return list;
-}
 
-bConstraint * add_new_constraint(char type)
+bConstraint *add_new_constraint(short type)
 {
        bConstraint *con;
 
@@ -750,80 +228,77 @@ void add_constraint_to_object(bConstraint *con, Object *ob)
 {
        ListBase *list;
        list = &ob->constraints;
-       if (list)
-       {
-               unique_constraint_name(con, list);
-               BLI_addtail(list, con);
-       }
-}
-
-void add_constraint_to_client(bConstraint *con)
-{
-       ListBase *list;
-       short type;
-       list = get_constraint_client(NULL, &type, NULL);
-       if (list)
-       {
+       
+       if (list) {
                unique_constraint_name(con, list);
                BLI_addtail(list, con);
+               
+               con->flag |= CONSTRAINT_ACTIVE;
+               for(con= con->prev; con; con= con->prev)
+                       con->flag &= ~CONSTRAINT_ACTIVE;
        }
 }
 
-bConstraintChannel *add_new_constraint_channel(const char* name)
-{
-       bConstraintChannel *chan = NULL;
-
-       chan = MEM_callocN(sizeof(bConstraintChannel), "constraintChannel");
-       strcpy(chan->name, name);
-       
-       return chan;
-}
-
-void add_influence_key_to_constraint (bConstraint *con){
-       printf("doesn't do anything yet\n");
-}
 
-char *get_con_subtarget_name(bConstraint *constraint, Object *target)
+char *get_con_subtarget_name(bConstraint *con, Object *target)
 {
        /*
         * If the target for this constraint is target, return a pointer 
         * to the name for this constraints subtarget ... NULL otherwise
         */
-       switch (constraint->type) {
+       switch (con->type) {
 
                case CONSTRAINT_TYPE_ACTION:
                {
-                       bActionConstraint *data = constraint->data;
+                       bActionConstraint *data = con->data;
                        if (data->tar==target) return data->subtarget;
                }
                break;
                case CONSTRAINT_TYPE_LOCLIKE:
                {
-                       bLocateLikeConstraint *data = constraint->data;
+                       bLocateLikeConstraint *data = con->data;
                        if (data->tar==target) return data->subtarget;
                }
                break;
                case CONSTRAINT_TYPE_ROTLIKE:
                {
-                       bRotateLikeConstraint *data = constraint->data;
+                       bRotateLikeConstraint *data = con->data;
+                       if (data->tar==target) return data->subtarget;
+               }
+               break;
+               case CONSTRAINT_TYPE_SIZELIKE:
+               {
+                       bSizeLikeConstraint *data = con->data;
                        if (data->tar==target) return data->subtarget;
                }
                break;
                case CONSTRAINT_TYPE_KINEMATIC:
                {
-                       bKinematicConstraint *data = constraint->data;
+                       bKinematicConstraint *data = con->data;
                        if (data->tar==target) return data->subtarget;
                }
                break;
                case CONSTRAINT_TYPE_TRACKTO:
                {
-                       bTrackToConstraint *data = constraint->data;
+                       bTrackToConstraint *data = con->data;
+                       if (data->tar==target) return data->subtarget;
+               }
+               break;
+               case CONSTRAINT_TYPE_MINMAX:
+               {
+                       bMinMaxConstraint *data = con->data;
                        if (data->tar==target) return data->subtarget;
                }
                break;
                case CONSTRAINT_TYPE_LOCKTRACK:
                {
-                       bLockTrackConstraint *data = constraint->data;
+                       bLockTrackConstraint *data = con->data;
+                       if (data->tar==target) return data->subtarget;
+               }
+               break;
+               case CONSTRAINT_TYPE_STRETCHTO:
+               {
+                       bStretchToConstraint *data = con->data;
                        if (data->tar==target) return data->subtarget;
                }
                break;
@@ -833,7 +308,7 @@ char *get_con_subtarget_name(bConstraint *constraint, Object *target)
                         */
                {
                        /*
-                        * bFollowPathConstraint *data = constraint->data;
+                        * bFollowPathConstraint *data = con->data;
                         */
                        return NULL;
                }
@@ -843,57 +318,572 @@ char *get_con_subtarget_name(bConstraint *constraint, Object *target)
        return NULL;  
 }
 
-Object *get_con_target(bConstraint *constraint)
+/* checks validity of object pointers, and NULLs,
+   if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag */
+static void test_constraints (Object *owner, const char* substring)
 {
-       /*
-        * If the target for this constraint is target, return a pointer 
-        * to the name for this constraints subtarget ... NULL otherwise
-        */
-       switch (constraint->type) {
+       
+       bConstraint *curcon;
+       ListBase *conlist= NULL;
+       int type;
+       
+       if (owner==NULL) return;
+       
+       /* Check parents */
+       /* Get the constraint list for this object */
+       
+       if (strlen (substring)){
+               switch (owner->type){
+                       case OB_ARMATURE:
+                               type = TARGET_BONE;
+                               break;
+                       default:
+                               type = TARGET_OBJECT;
+                               break;
+               }
+       }
+       else
+               type = TARGET_OBJECT;
+       
+       
+       switch (type){
+               case TARGET_OBJECT:
+                       conlist = &owner->constraints;
+                       break;
+               case TARGET_BONE:
+                       {
+                               Bone *bone;
+                               bPoseChannel *chan;
+                               
+                               bone = get_named_bone(((bArmature*)owner->data), substring);
+                               chan = get_pose_channel (owner->pose, substring);
+                               if (bone && chan){
+                                       conlist = &chan->constraints;
+                               }
+                       }
+                       break;
+       }
+       
+       /* Cycle constraints */
+       if (conlist){
+               for (curcon = conlist->first; curcon; curcon=curcon->next){
+                       curcon->flag &= ~CONSTRAINT_DISABLE;
+                       
+                       switch (curcon->type){
+                               case CONSTRAINT_TYPE_ACTION:
+                               {
+                                       bActionConstraint *data = curcon->data;
+                                       
+                                       if (!exist_object(data->tar)){
+                                               data->tar = NULL;
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       
+                                       if ( (data->tar == owner) &&
+                                                (!get_named_bone(get_armature(owner), 
+                                                                                 data->subtarget))) {
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                               }
+                                       break;
+                               case CONSTRAINT_TYPE_LOCLIKE:
+                               {
+                                       bLocateLikeConstraint *data = curcon->data;
+                                       
+                                       if (!exist_object(data->tar)){
+                                               data->tar = NULL;
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       
+                                       if ( (data->tar == owner) &&
+                                                (!get_named_bone(get_armature(owner), 
+                                                                                 data->subtarget))) {
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                               }
+                                       break;
+                               case CONSTRAINT_TYPE_MINMAX:
+                               {
+                                       bMinMaxConstraint *data = curcon->data;
+                                       
+                                       if (!exist_object(data->tar)){
+                                               data->tar = NULL;
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       
+                                       if ( (data->tar == owner) &&
+                                                (!get_named_bone(get_armature(owner), 
+                                                                                 data->subtarget))) {
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                               }
+                                       break;
+                               case CONSTRAINT_TYPE_ROTLIKE:
+                               {
+                                       bRotateLikeConstraint *data = curcon->data;
+                                       
+                                       if (!exist_object(data->tar)){
+                                               data->tar = NULL;
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       
+                                       if ( (data->tar == owner) &&
+                                                (!get_named_bone(get_armature(owner), 
+                                                                                 data->subtarget))) {
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                               }
+                                       break;
+                               case CONSTRAINT_TYPE_SIZELIKE:
+                               {
+                                       bSizeLikeConstraint *data = curcon->data;
+                               
+                                       if (!exist_object(data->tar)){
+                                               data->tar = NULL;
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       
+                                       if ( (data->tar == owner) &&
+                                                (!get_named_bone(get_armature(owner), 
+                                                                                 data->subtarget))) {
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                               }
+                                       break;
+                               case CONSTRAINT_TYPE_KINEMATIC:
+                               {
+                                       bKinematicConstraint *data = curcon->data;
+                                       if (!exist_object(data->tar)){
+                                               data->tar = NULL;
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       
+                                       if ( (data->tar == owner) &&
+                                                (!get_named_bone(get_armature(owner), 
+                                                                                 data->subtarget))) {
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                               }
+                                       break;
+                               case CONSTRAINT_TYPE_TRACKTO:
+                               {
+                                       bTrackToConstraint *data = curcon->data;
+                                       if (!exist_object(data->tar)) {
+                                               data->tar = NULL;
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       
+                                       if ( (data->tar == owner) &&
+                                                (!get_named_bone(get_armature(owner), 
+                                                                                 data->subtarget))) {
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       if (data->reserved2==data->reserved1){
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       if (data->reserved2+3==data->reserved1){
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                               }
+                                       break;
+                               case CONSTRAINT_TYPE_LOCKTRACK:
+                               {
+                                       bLockTrackConstraint *data = curcon->data;
+                                       
+                                       if (!exist_object(data->tar)){
+                                               data->tar = NULL;
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       
+                                       if ( (data->tar == owner) &&
+                                                (!get_named_bone(get_armature(owner), 
+                                                                                 data->subtarget))) {
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
 
-               case CONSTRAINT_TYPE_ACTION:
-               {
-                       bActionConstraint *data = constraint->data;
-                       return data->tar;
+                                       if (data->lockflag==data->trackflag){
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       if (data->lockflag+3==data->trackflag){
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                               }
+                                       break;
+                               case CONSTRAINT_TYPE_STRETCHTO:
+                               {
+                                       bStretchToConstraint *data = curcon->data;
+                                       
+                                       if (!exist_object(data->tar)){
+                                               data->tar = NULL;
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       
+                                       if ( (data->tar == owner) &&
+                                                (!get_named_bone(get_armature(owner), 
+                                                                                 data->subtarget))) {
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                               }
+                                       break;
+                               case CONSTRAINT_TYPE_FOLLOWPATH:
+                               {
+                                       bFollowPathConstraint *data = curcon->data;
+                                       
+                                       if (!exist_object(data->tar)){
+                                               data->tar = NULL;
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       if (data->tar->type != OB_CURVE){
+                                               data->tar = NULL;
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       if (data->upflag==data->trackflag){
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       if (data->upflag+3==data->trackflag){
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                               }
+                                       break;
+                       }
                }
-               break;
-               case CONSTRAINT_TYPE_LOCLIKE:
-               {
-                       bLocateLikeConstraint *data = constraint->data;
-                       return data->tar;
+       }
+}
+
+static void test_bonelist_constraints (Object *owner, ListBase *list)
+{
+       Bone *bone;
+
+       for (bone = list->first; bone; bone=bone->next) {
+               
+               test_constraints(owner, bone->name);
+               test_bonelist_constraints (owner, &bone->childbase);
+       }
+}
+
+void object_test_constraints (Object *owner)
+{
+       test_constraints(owner, "");
+
+       if(owner->type==OB_ARMATURE) {
+               bArmature *arm;
+               arm = get_armature(owner);
+               if (arm)
+                       test_bonelist_constraints (owner, &arm->bonebase);
+       }
+
+}
+
+/* context: active object in posemode, active channel, optional selected channel */
+void add_constraint(int only_IK)
+{
+       Object *ob= OBACT, *obsel=NULL;
+       bPoseChannel *pchanact=NULL, *pchansel=NULL;
+       bConstraint *con=NULL;
+       Base *base;
+       short nr;
+       
+       /* paranoia checks */
+       if(ob==NULL || ob==G.obedit) return;
+
+       if(ob->pose && (ob->flag & OB_POSEMODE)) {
+               bArmature *arm= ob->data;
+               
+               /* find active channel */
+               pchanact= get_active_posechannel(ob);
+               if(pchanact==NULL) return;
+       
+               /* check protection */
+               if(ob->proxy && (pchanact->bone->layer & arm->layer_protected)) {
+                       error("Bone is Proxy protected");
+                       return;
                }
-               break;
-               case CONSTRAINT_TYPE_ROTLIKE:
-               {
-                       bRotateLikeConstraint *data = constraint->data;
-                       return data->tar;
+               
+               /* find selected bone */
+               for(pchansel= ob->pose->chanbase.first; pchansel; pchansel= pchansel->next) {
+                       if(pchansel!=pchanact)
+                               if(pchansel->bone->flag & BONE_SELECTED) 
+                                       if(pchansel->bone->layer & arm->layer)
+                                               break;
                }
-               break;
-               case CONSTRAINT_TYPE_KINEMATIC:
-               {
-                       bKinematicConstraint *data = constraint->data;
-                       return data->tar;
+       }
+       
+       /* find selected object */
+       for(base= FIRSTBASE; base; base= base->next)
+               if( TESTBASE(base) && base->object!=ob ) 
+                       obsel= base->object;
+       
+       /* the only_IK caller has checked for posemode! */
+       if(only_IK) {
+               for(con= pchanact->constraints.first; con; con= con->next) {
+                       if(con->type==CONSTRAINT_TYPE_KINEMATIC) break;
                }
-               break;
-               case CONSTRAINT_TYPE_TRACKTO:
-               {
-                       bTrackToConstraint *data = constraint->data;
-                       return data->tar;
+               if(con) {
+                       error("Pose Channel already has IK");
+                       return;
                }
-               break;
-               case CONSTRAINT_TYPE_LOCKTRACK:
-               {
-                       bLockTrackConstraint *data = constraint->data;
-                       return data->tar;
+               
+               if(pchansel)
+                       nr= pupmenu("Add IK Constraint%t|To Active Bone%x10");
+               else if(obsel)
+                       nr= pupmenu("Add IK Constraint%t|To Active Object%x10");
+               else 
+                       nr= pupmenu("Add IK Constraint%t|To New Empty Object%x10|Without Target%x11");
+       }
+       else {
+               if(pchanact) {
+                       if(pchansel)
+                               nr= pupmenu("Add Constraint to Active Bone%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|Action%x16");
+                       else if(obsel && obsel->type==OB_CURVE)
+                               nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Stretch To%x7|Action%x16");
+                       else if(obsel)
+                               nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|Action%x16");
+                       else
+                               nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
                }
-               break;
-               case CONSTRAINT_TYPE_FOLLOWPATH: 
-               {
-                       bFollowPathConstraint *data = constraint->data;
-                       return data->tar;
+               else {
+                       if(obsel && obsel->type==OB_CURVE)
+                               nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6");
+                       else if(obsel)
+                               nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Track To%x3|Floor%x4|Locked Track%x5");
+                       else
+                               nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Track To%x3|Floor%x4|Locked Track%x5");
+               }
+       }
+       
+       if(nr<1) return;
+       
+       /* handle IK separate */
+       if(nr==10 || nr==11) {
+               
+               /* prevent weird chains... */
+               if(pchansel) {
+                       bPoseChannel *pchan= pchanact;
+                       while(pchan) {
+                               if(pchan==pchansel) break;
+                               pchan= pchan->parent;
+                       }
+                       if(pchan) {
+                               error("IK root cannot be linked to IK tip");
+                               return;
+                       }
+                       pchan= pchansel;
+                       while(pchan) {
+                               if(pchan==pchanact) break;
+                               pchan= pchan->parent;
+                       }
+                       if(pchan) {
+                               error("IK tip cannot be linked to IK root");
+                               return;
+                       }               
+               }
+               
+               con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
+               BLI_addtail(&pchanact->constraints, con);
+               unique_constraint_name(con, &pchanact->constraints);
+               pchanact->constflag |= PCHAN_HAS_IK;    // for draw, but also for detecting while pose solving
+               if(nr==11) pchanact->constflag |= PCHAN_HAS_TARGET;
+       }
+       else {
+               
+               if(nr==1) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE);
+               else if(nr==2) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE);
+               else if(nr==3) con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
+               else if(nr==4) con = add_new_constraint(CONSTRAINT_TYPE_MINMAX);
+               else if(nr==5) con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
+               else if(nr==6) {
+                       Curve *cu= obsel->data;
+                       cu->flag |= CU_PATH;
+                       con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
+               }
+               else if(nr==7) con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
+               else if(nr==8) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIKE);
+               else if(nr==13) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIMIT);
+               else if(nr==14) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIMIT);
+               else if(nr==15) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIMIT);
+               else if(nr==16) con = add_new_constraint(CONSTRAINT_TYPE_ACTION);
+               
+               if(con==NULL) return;   /* paranoia */
+               
+               if(pchanact) {
+                       BLI_addtail(&pchanact->constraints, con);
+                       unique_constraint_name(con, &pchanact->constraints);
+                       pchanact->constflag |= PCHAN_HAS_CONST; /* for draw */
+               }
+               else {
+                       BLI_addtail(&ob->constraints, con);
+                       unique_constraint_name(con, &ob->constraints);
+               }
+       }
+       
+       /* set the target */
+       if(pchansel) {
+               set_constraint_target(con, ob, pchansel->name);
+       }
+       else if(obsel) {
+               set_constraint_target(con, obsel, NULL);
+       }
+       else if(ELEM4(nr, 11, 13, 14, 15)==0) { /* add new empty as target */
+               Base *base= BASACT, *newbase;
+               Object *obt;
+               
+               obt= add_object(OB_EMPTY);
+               /* set layers OK */
+               newbase= BASACT;
+               newbase->lay= base->lay;
+               obt->lay= newbase->lay;
+               
+               /* transform cent to global coords for loc */
+               if(pchanact) {
+                       if(only_IK)
+                               VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_tail);
+                       else
+                               VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_head);
+               }
+               else
+                       VECCOPY(obt->loc, ob->obmat[3]);
+               
+               set_constraint_target(con, obt, NULL);
+               
+               /* restore, add_object sets active */
+               BASACT= base;
+               base->flag |= SELECT;
+       }
+
+
+       /* active flag */
+       con->flag |= CONSTRAINT_ACTIVE;
+       for(con= con->prev; con; con= con->prev)
+               con->flag &= ~CONSTRAINT_ACTIVE;
+
+       DAG_scene_sort(G.scene);                // sort order of objects
+       
+       if(pchanact) {
+               ob->pose->flag |= POSE_RECALC;  // sort pose channels
+               DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);   // and all its relations
+       }
+       else
+               DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);     // and all its relations
+
+       allqueue (REDRAWVIEW3D, 0);
+       allqueue (REDRAWBUTSOBJECT, 0);
+       allqueue (REDRAWOOPS, 0);
+       
+       if(only_IK)
+               BIF_undo_push("Add IK Constraint");
+       else
+               BIF_undo_push("Add Constraint");
+
+}
+
+void ob_clear_constraints(void)
+{
+       Object *ob= OBACT;
+       
+       /* paranoia checks */
+       if(!ob) return;
+       if(ob==G.obedit || (ob->flag & OB_POSEMODE)) return;
+       
+       if(okee("Clear Constraints")==0) return;
+       
+       free_constraints(&ob->constraints);
+       
+       DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
+       
+       allqueue (REDRAWVIEW3D, 0);
+       allqueue (REDRAWBUTSOBJECT, 0);
+       allqueue (REDRAWOOPS, 0);
+       
+       BIF_undo_push("Clear Constraint(s)");
+       
+}
+
+/* con already has the new name */
+void rename_constraint(Object *ob, bConstraint *con, char *oldname)
+{
+       bConstraint *tcon;
+       bConstraintChannel *conchan;
+       ListBase *conlist= NULL;
+       int from_object= 0;
+       char *channame="";
+       
+       /* get context by searching for con (primitive...) */
+       for(tcon= ob->constraints.first; tcon; tcon= tcon->next)
+               if(tcon==con)
+                       break;
+       
+       if(tcon) {
+               conlist= &ob->constraints;
+               channame= "Object";
+               from_object= 1;
+       }
+       else if(ob->pose) {
+               bPoseChannel *pchan;
+               
+               for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+                       for(tcon= pchan->constraints.first; tcon; tcon= tcon->next) {
+                               if(tcon==con)
+                                       break;
+                       }
+                       if(tcon)
+                               break;
+               }
+               if(tcon) {
+                       conlist= &pchan->constraints;
+                       channame= pchan->name;
+               }
+       }
+       
+       if(conlist==NULL) {
+               printf("rename constraint failed\n");   /* should not happen in UI */
+               return;
+       }
+       
+       /* first make sure it's a unique name within context */
+       unique_constraint_name (con, conlist);
+
+       /* own channels */
+       if(from_object) {
+               for(conchan= ob->constraintChannels.first; conchan; conchan= conchan->next) {
+                       if( strcmp(oldname, conchan->name)==0 )
+                               BLI_strncpy(conchan->name, con->name, sizeof(conchan->name));
+               }
+       }
+       /* own action */
+       if(ob->action) {
+               bActionChannel *achan= get_action_channel(ob->action, channame);
+               if(achan) {
+                       conchan= get_constraint_channel(&achan->constraintChannels, oldname);
+                       if(conchan)
+                               BLI_strncpy(conchan->name, con->name, sizeof(conchan->name));
                }
-               break;
        }
        
-       return NULL;  
 }
+