diff options
author | Ton Roosendaal <ton@blender.org> | 2005-10-23 16:18:32 +0400 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2005-10-23 16:18:32 +0400 |
commit | d4f47002b835fb299fab05425456d34a8d24807e (patch) | |
tree | 37ab1325510105bb9b590bed8d982e1e67ec5d47 /source | |
parent | 84f66424379734dfd40c1f2cd69ff2f6e8652333 (diff) |
New: Hotkey/menu access in 3D window to add constraints. Works in PoseMode
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...
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/include/BIF_editconstraint.h | 2 | ||||
-rw-r--r-- | source/blender/src/editconstraint.c | 196 | ||||
-rw-r--r-- | source/blender/src/poseobject.c | 97 | ||||
-rw-r--r-- | source/blender/src/space.c | 3 |
4 files changed, 197 insertions, 101 deletions
diff --git a/source/blender/include/BIF_editconstraint.h b/source/blender/include/BIF_editconstraint.h index 4d14919ddaa..2ab72a304c2 100644 --- a/source/blender/include/BIF_editconstraint.h +++ b/source/blender/include/BIF_editconstraint.h @@ -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 diff --git a/source/blender/src/editconstraint.c b/source/blender/src/editconstraint.c index bac3099a718..95d037850c3 100644 --- a/source/blender/src/editconstraint.c +++ b/source/blender/src/editconstraint.c @@ -36,22 +36,25 @@ #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" @@ -59,10 +62,12 @@ #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"); + +} + diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index bc3012f343c..501c95bbd3d 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -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 */ diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 84ddf2c6aa7..db2ae93cb0a 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -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(); |