New: Hotkey/menu access in 3D window to add constraints. Works in PoseMode
authorTon Roosendaal <ton@blender.org>
Sun, 23 Oct 2005 12:18:32 +0000 (12:18 +0000)
committerTon Roosendaal <ton@blender.org>
Sun, 23 Oct 2005 12:18:32 +0000 (12:18 +0000)
as well as for Objects. Hotkey: CTRL+ALT+C (bit clumsy I know, but I like
to use the Ckey).

Constraints are added to the active Object or Bone.
Based on selection context, the menu has three versions:

Pose Mode:
  - if another bone is selected, bone becomes target
  - else if another Object is selected, Object becomes target
  - else it adds a new Empty as target
Object Mode
  - if another Object is selected: Object becomes target
  - else it adds a new Empty as target

Same works this way now for CTRL+I, "Add IK".

To be solved: ALT+C in PoseMode is "Clear Constraints", but in Object Mode
it does "Convert" still...

source/blender/include/BIF_editconstraint.h
source/blender/src/editconstraint.c
source/blender/src/poseobject.c
source/blender/src/space.c

index 4d14919ddaac46fef253d602964b7acc351fb102..2ab72a304c2642c0587d85d13c531d28eed80f3b 100644 (file)
@@ -50,6 +50,8 @@ struct bConstraintChannel *get_active_constraint_channel(struct Object *ob);
 
 void object_test_constraints(struct Object *owner);
 
+void add_constraint(int only_IK);
+
 char *get_con_subtarget_name(struct bConstraint *con, struct Object *target);
 
 #endif
index bac3099a71857475b97ee37dabb5a1470cecb0c0..95d037850c3e3c050b220365d43a45daa0a9d4ca 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_poseobject.h"
 #include "BIF_interface.h"
 #include "BIF_screen.h"
+#include "BIF_space.h"
 #include "BIF_toolbox.h"
 
 #include "blendef.h"
 #include "nla.h"
+#include "mydevice.h"
 
 
 ListBase *get_active_constraint_channels (Object *ob, int forcevalid)
@@ -571,4 +576,185 @@ void object_test_constraints (Object *owner)
 
 }
 
+/* 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)) {
+       
+               /* find active channel */
+               for(pchanact= ob->pose->chanbase.first; pchanact; pchanact= pchanact->next)
+                       if(pchanact->bone->flag & BONE_ACTIVE) break;
+               if(pchanact==NULL) return;
+       
+               /* find selected bone */
+               for(pchansel= ob->pose->chanbase.first; pchansel; pchansel= pchansel->next) {
+                       if(pchansel!=pchanact)
+                               if(pchansel->bone->flag & BONE_SELECTED) break;
+               }
+       }
+       
+       /* 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;
+               }
+               if(con) {
+                       error("Pose Channel already has IK");
+                       return;
+               }
+               
+               if(pchansel)
+                       nr= pupmenu("Add IK Constraint%t|To New Empty Object%x10");
+               else if(obsel)
+                       nr= pupmenu("Add IK Constraint%t|To Selected Object%x10");
+               else 
+                       nr= pupmenu("Add IK Constraint%t|To New Empty Object%x10");
+       }
+       else {
+               if(pchanact) {
+                       if(pchansel)
+                               nr= pupmenu("Add Constraint to selected Bone%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
+                       else if(obsel && obsel->type==OB_CURVE)
+                               nr= pupmenu("Add Constraint to selected Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Stretch To%x7");
+                       else if(obsel)
+                               nr= pupmenu("Add Constraint to selected Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
+                       else
+                               nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
+               }
+               else {
+                       if(obsel && obsel->type==OB_CURVE)
+                               nr= pupmenu("Add Constraint to selected Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6");
+                       else if(obsel)
+                               nr= pupmenu("Add Constraint to selected Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5");
+                       else
+                               nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5");
+               }
+       }
+       
+       if(nr<1) return;
+       
+       /* handle IK separate */
+       if(nr==10) {
+               
+               /* 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);
+               pchanact->constflag |= PCHAN_HAS_IK;    // for draw, but also for detecting while pose solving
+       }
+       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) con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
+               else if(nr==7) con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
+               
+               if(con==NULL) return;   /* paranoia */
+               
+               if(pchanact) {
+                       BLI_addtail(&pchanact->constraints, con);
+                       pchanact->constflag |= PCHAN_HAS_CONST; /* for draw */
+               }
+               else {
+                       BLI_addtail(&ob->constraints, con);
+               }
+       }
+       
+       /* set the target */
+       if(pchansel) {
+               set_constraint_target(con, ob, pchansel->name);
+       }
+       else if(obsel) {
+               set_constraint_target(con, obsel, NULL);
+       }
+       else {  /* 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");
+
+}
+
 
index bc3012f343ca8d342025f47132a7327ebbc41f96..501c95bbd3dd90e6ff739c34b9b739b9efbdb15f 100644 (file)
@@ -320,110 +320,15 @@ void pose_special_editmenu(void)
        }
 }
 
-/* context: active object, active channel, optional selected channel */
 void pose_add_IK(void)
 {
        Object *ob= OBACT;
-       bPoseChannel *pchanact, *pchansel;
-       bConstraint *con;
-       short nr;
        
        /* paranoia checks */
        if(!ob && !ob->pose) return;
        if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
        
-       /* find active */
-       for(pchanact= ob->pose->chanbase.first; pchanact; pchanact= pchanact->next)
-               if(pchanact->bone->flag & BONE_ACTIVE) break;
-       if(pchanact==NULL) return;
-       
-       /* find selected */
-       for(pchansel= ob->pose->chanbase.first; pchansel; pchansel= pchansel->next) {
-               if(pchansel!=pchanact)
-                       if(pchansel->bone->flag & BONE_SELECTED) break;
-       }
-       
-       for(con= pchanact->constraints.first; con; con= con->next) {
-               if(con->type==CONSTRAINT_TYPE_KINEMATIC) break;
-       }
-       if(con) {
-               error("Pose Channel already has IK");
-               return;
-       }
-       
-       if(pchansel)
-               nr= pupmenu("Add IK Constraint%t|To new Empty Object%x1|To selected Bone%x2");
-       else
-               nr= pupmenu("Add IK Constraint%t|To new Empty Object%x1");
-
-       if(nr<1) return;
-       
-       /* prevent weird chains... */
-       if(nr==2) {
-               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);
-       pchanact->constflag |= PCHAN_HAS_IK;    // for draw, but also for detecting while pose solving
-       
-       /* add new empty as target */
-       if(nr==1) {
-               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 */
-               VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_tail);
-               
-               set_constraint_target(con, obt, NULL);
-               
-               /* restore, add_object sets active */
-               BASACT= base;
-               base->flag |= SELECT;
-       }
-       else if(nr==2) {
-               set_constraint_target(con, ob, pchansel->name);
-       }
-       
-       /* active flag */
-       con->flag |= CONSTRAINT_ACTIVE;
-       for(con= con->prev; con; con= con->prev)
-               con->flag &= ~CONSTRAINT_ACTIVE;
-       
-       
-       ob->pose->flag |= POSE_RECALC;  // sort pose channels
-       DAG_scene_sort(G.scene);                // sort order of objects
-       
-       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);   // and all its relations
-       
-       allqueue (REDRAWVIEW3D, 0);
-       allqueue (REDRAWBUTSOBJECT, 0);
-       allqueue (REDRAWOOPS, 0);
-       
-       BIF_undo_push("Add IK constraint");
+       add_constraint(1);      /* 1 means only IK */
 }
 
 /* context: all selected channels */
index 84ddf2c6aa77a83e8516aabce9c66115557918bb..db2ae93cb0add386b04e052e1d5f2c964c4346f7 100644 (file)
@@ -87,6 +87,7 @@
 #include "BIF_drawtext.h"
 #include "BIF_drawscript.h"
 #include "BIF_editarmature.h"
+#include "BIF_editconstraint.h"
 #include "BIF_editfont.h"
 #include "BIF_editkey.h"
 #include "BIF_editlattice.h"
@@ -1157,6 +1158,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                        else
                                                convertmenu();  /* editobject.c */
                                }
+                               else if(G.qual==(LR_ALTKEY|LR_CTRLKEY)) 
+                                       add_constraint(0);      /* editconstraint.c, generic for objects and posemode */
                                else if((G.qual==LR_SHIFTKEY)) {
                                        view3d_home(1);
                                        curs= give_cursor();