Index: /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/blenkernel/intern/action.c =================================================================== --- /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/blenkernel/intern/action.c (revision 12502) +++ /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/blenkernel/intern/action.c (working copy) @@ -305,8 +305,10 @@ pchan->flag= chan->flag; con= chan->constraints.first; - for(pcon= pchan->constraints.first; pcon; pcon= pcon->next) + for(pcon= pchan->constraints.first; pcon; pcon= pcon->next) { pcon->enforce= con->enforce; + pcon->headtail= con->headtail; + } } /* checks for IK constraint, can do more constraints flags later */ Index: /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/blenkernel/intern/constraint.c =================================================================== --- /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/blenkernel/intern/constraint.c (revision 12502) +++ /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/blenkernel/intern/constraint.c (working copy) @@ -194,6 +194,11 @@ con->enforce = CLAMPIS(icu->curval, 0.0f, 1.0f); } break; + case CO_HEADTAIL: + { + con->headtail = icu->curval; + } + break; } } } @@ -710,7 +715,7 @@ /* generic function to get the appropriate matrix for most target cases */ /* The cases where the target can be object data have not been implemented */ -static void constraint_target_to_mat4 (Object *ob, char *substring, float mat[][4], short from, short to) +static void constraint_target_to_mat4 (Object *ob, char *substring, float mat[][4], short from, short to, float headtail) { /* Case OBJECT */ if (!strlen(substring)) { @@ -744,7 +749,18 @@ * PoseChannel by the Armature Object's Matrix to get a worldspace * matrix. */ - Mat4MulMat4(mat, pchan->pose_mat, ob->obmat); + if (headtail<0.000001) { /* skip length interpolation if set to head */ + Mat4MulMat4(mat, pchan->pose_mat, ob->obmat); + } + else + { + float tempmat[4][4],locvec[3]; + + VecLerpf(locvec,pchan->pose_head,pchan->pose_tail,headtail); /* interpolate along length of bone */ + Mat4CpyMat4(tempmat, pchan->pose_mat); + VecCopyf(tempmat[3],locvec); /* use interpolated distance for subtarget */ + Mat4MulMat4(mat, tempmat, ob->obmat); + } } else Mat4CpyMat4(mat, ob->obmat); @@ -794,11 +810,39 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime) { if (VALID_CONS_TARGET(ct)) - constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space); + constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space,0); else if (ct) Mat4One(ct->matrix); } +/* This function should be used for the get_target_matrix member of all + * constraints that allow variable location between head and tail on a subtarget. + */ +static void get_tarmat_headtail (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime) +{ + float headtail; + + if (VALID_CONS_TARGET(ct)) { + switch (con->type) { + case CONSTRAINT_TYPE_TRACKTO: + case CONSTRAINT_TYPE_STRETCHTO: + case CONSTRAINT_TYPE_MINMAX: + { + headtail=con->headtail; + } + break; + default: + { + headtail=0.0f; + } + break; + } + constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space,headtail); + } + else if (ct) + Mat4One(ct->matrix); +} + /* This following macro should be used for all standard single-target *_get_tars functions * to save typing and reduce maintainance woes. * (Hopefully all compilers will be happy with the lines with just a space on them. Those are @@ -1146,7 +1190,7 @@ trackto_new_data, /* new data */ trackto_get_tars, /* get constraint targets */ trackto_flush_tars, /* flush constraint targets */ - default_get_tarmat, /* get target matrix */ + get_tarmat_headtail, /* get target matrix */ trackto_evaluate /* evaluate */ }; @@ -1192,7 +1236,7 @@ bKinematicConstraint *data= con->data; if (VALID_CONS_TARGET(ct)) - constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space); + constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space,0); else if (ct) { if (data->flag & CONSTRAINT_IK_AUTO) { Object *ob= cob->ob; @@ -1573,29 +1617,12 @@ /* Pose-Channels for the CopyLoc target are handled specially, so that * we can support using the bone-tip as an option. */ - bPoseChannel *pchan; - float tmat[4][4]; - - pchan = get_pose_channel(ct->tar->pose, ct->subtarget); - if (pchan) { - Mat4CpyMat4(tmat, pchan->pose_mat); - - if (data->flag & LOCLIKE_TIP) { - VECCOPY(tmat[3], pchan->pose_tail); - } - - Mat4MulMat4(ct->matrix, tmat, ct->tar->obmat); + if (data->flag & LOCLIKE_TIP) { + con->headtail=1.0; } - else - Mat4CpyMat4(ct->matrix, ct->tar->obmat); - - /* convert matrix space as required */ - constraint_mat_convertspace(ct->tar, pchan, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space); } - else { - /* get target matrix as is done normally for other constraints */ - constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space); - } + /* get target matrix as is done normally for other constraints */ + constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space,con->headtail); } else if (ct) Mat4One(ct->matrix); @@ -1896,7 +1923,7 @@ /* firstly calculate the matrix the normal way, then let the py-function override * this matrix if it needs to do so */ - constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space); + constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space,0); BPY_pyconstraint_target(data, ct); } else if (ct) @@ -1987,7 +2014,7 @@ Mat4One(ct->matrix); /* get the transform matrix of the target */ - constraint_target_to_mat4(ct->tar, ct->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, ct->space); + constraint_target_to_mat4(ct->tar, ct->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, ct->space,0); /* determine where in transform range target is */ /* data->type is mapped as follows for backwards compatability: @@ -2602,7 +2629,7 @@ stretchto_new_data, /* new data */ stretchto_get_tars, /* get constraint targets */ stretchto_flush_tars, /* flush constraint targets */ - default_get_tarmat, /* get target matrix */ + get_tarmat_headtail, /* get target matrix */ stretchto_evaluate /* evaluate */ }; @@ -2734,7 +2761,7 @@ minmax_new_data, /* new data */ minmax_get_tars, /* get constraint targets */ minmax_flush_tars, /* flush constraint targets */ - default_get_tarmat, /* get target matrix */ + get_tarmat_headtail, /* get target matrix */ minmax_evaluate /* evaluate */ }; Index: /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/blenkernel/intern/ipo.c =================================================================== --- /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/blenkernel/intern/ipo.c (revision 12502) +++ /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/blenkernel/intern/ipo.c (working copy) @@ -85,7 +85,7 @@ */ int co_ar[CO_TOTIPO]= { - CO_ENFORCE + CO_ENFORCE, CO_HEADTAIL }; int ob_ar[OB_TOTIPO]= { Index: /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/makesdna/DNA_constraint_types.h =================================================================== --- /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/makesdna/DNA_constraint_types.h (revision 12502) +++ /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/makesdna/DNA_constraint_types.h (working copy) @@ -64,6 +64,9 @@ char name[30]; /* Constraint name */ float enforce; /* Amount of influence exherted by constraint (0.0-1.0) */ + float headtail; /* Point along subtarget bone where the actual target is. Only needed for certain + constraints, but placed here for later animatability */ + int pad; } bConstraint; @@ -140,8 +143,8 @@ int reserved1; /* I'll be using reserved1 and reserved2 as Track and Up flags, not sure if that's what they were intented for anyway. Not sure either if it would create backward incompatibility if I were to rename them. - theeth*/ int reserved2; int flags; + char subtarget[32]; int pad; - char subtarget[32]; } bTrackToConstraint; /* Copy Rotation Constraint */ Index: /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/makesdna/DNA_ipo_types.h =================================================================== --- /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/makesdna/DNA_ipo_types.h (revision 12502) +++ /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/makesdna/DNA_ipo_types.h (working copy) @@ -319,10 +319,11 @@ #define AC_QUAT_Z 28 /* ******************** */ -#define CO_TOTIPO 1 /* Constraint Ipos */ -#define CO_TOTNAM 1 +#define CO_TOTIPO 2 /* Constraint Ipos */ +#define CO_TOTNAM 2 #define CO_ENFORCE 1 +#define CO_HEADTAIL 2 /* #define CO_TIME 2 #define CO_OFFSET_X 3 Index: /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/src/editipo_lib.c =================================================================== --- /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/src/editipo_lib.c (revision 12502) +++ /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/src/editipo_lib.c (working copy) @@ -61,7 +61,7 @@ "Layer", "Time", "ColR", "ColG", "ColB", "ColA", "FStreng", "FFall", "RDamp", "Damping", "Perm" }; -char *co_ic_names[CO_TOTNAM] = { "Inf" }; +char *co_ic_names[CO_TOTNAM] = { "Inf", "HeadTail" }; char *mtex_ic_names[TEX_TOTNAM] = { "OfsX", "OfsY", "OfsZ", "SizeX", "SizeY", "SizeZ", "texR", "texG", "texB", "DefVar", "Col", "Nor", "Var", "Disp" }; @@ -191,6 +191,7 @@ { switch(nr){ case CO_ENFORCE: + case CO_HEADTAIL: return co_ic_names[nr-1]; } return ic_name_empty[0]; Index: /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/src/buttons_object.c =================================================================== --- /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/src/buttons_object.c (revision 12502) +++ /Users/rolandhess/Documents/bf-blender-cvs/blender/source/blender/src/buttons_object.c (working copy) @@ -807,7 +807,7 @@ /* Draw options */ uiDefButBitI(block, TOG, LOCLIKE_OFFSET, B_CONSTRAINT_TEST, "Offset", *xco, *yco-89, (width/2), 18, &data->flag, 0, 24, 0, 0, "Add original location onto copied location"); if (is_armature_target(data->tar)) { - uiDefButBitI(block, TOG, LOCLIKE_TIP, B_CONSTRAINT_TEST, "Target Bone Tail", *xco+(width/2), *yco-89, (width/2), 18, &data->flag, 0, 24, 0, 0, "Copy Location of Target Bone's Tail"); + uiDefButF(block,NUM,B_CONSTRAINT_TEST,"Head/Tail:",*xco+(width/2), *yco-89,(width/2),18,&(con->headtail),0.0,1,0.1,0.1,"Target along length of bone: Head=0, Tail=1"); } /* constraint space settings */ @@ -1159,7 +1159,7 @@ { bStretchToConstraint *data = con->data; - height = 105; + height = 127; uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); @@ -1181,26 +1181,26 @@ } uiBlockEndAlign(block); - uiBlockBeginAlign(block); - uiDefButF(block,BUTM,B_CONSTRAINT_TEST,"R",*xco, *yco-60,20,18,&(data->orglength),0.0,0,0,0,"Recalculate RLength"); - uiDefButF(block,NUM,B_CONSTRAINT_TEST,"Rest Length:",*xco+18, *yco-60,237,18,&(data->orglength),0.0,100,0.5,0.5,"Length at Rest Position"); + uiDefButF(block,NUM,B_CONSTRAINT_TEST,"Head<->Tail:",*xco, *yco-60,255,18,&(con->headtail),0.0,1,0.1,0.1,"Target along length of bone: Head=0, Tail=1"); + uiDefButF(block,BUTM,B_CONSTRAINT_TEST,"R",*xco, *yco-82,20,18,&(data->orglength),0.0,0,0,0,"Recalculate RLength"); + uiDefButF(block,NUM,B_CONSTRAINT_TEST,"Rest Length:",*xco+18, *yco-82,237,18,&(data->orglength),0.0,100,0.5,0.5,"Length at Rest Position"); uiBlockEndAlign(block); - uiDefButF(block,NUM,B_CONSTRAINT_TEST,"Volume Variation:",*xco+18, *yco-82,237,18,&(data->bulge),0.0,100,0.5,0.5,"Factor between volume variation and stretching"); + uiDefButF(block,NUM,B_CONSTRAINT_TEST,"Volume Variation:",*xco+18, *yco-104,237,18,&(data->bulge),0.0,100,0.5,0.5,"Factor between volume variation and stretching"); uiBlockBeginAlign(block); - uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Vol:",*xco+14, *yco-104,30,18, NULL, 0.0, 0.0, 0.0, 0.0, ""); - uiDefButI(block, ROW,B_CONSTRAINT_TEST,"XZ", *xco+44, *yco-104,30,18, &data->volmode, 12.0, 0.0, 0, 0, "Keep Volume: Scaling X & Z"); - uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+74, *yco-104,20,18, &data->volmode, 12.0, 1.0, 0, 0, "Keep Volume: Scaling X"); - uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+94, *yco-104,20,18, &data->volmode, 12.0, 2.0, 0, 0, "Keep Volume: Scaling Z"); - uiDefButI(block, ROW,B_CONSTRAINT_TEST,"NONE", *xco+114, *yco-104,50,18, &data->volmode, 12.0, 3.0, 0, 0, "Ignore Volume"); + uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Vol:",*xco+14, *yco-126,30,18, NULL, 0.0, 0.0, 0.0, 0.0, ""); + uiDefButI(block, ROW,B_CONSTRAINT_TEST,"XZ", *xco+44, *yco-126,30,18, &data->volmode, 12.0, 0.0, 0, 0, "Keep Volume: Scaling X & Z"); + uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+74, *yco-126,20,18, &data->volmode, 12.0, 1.0, 0, 0, "Keep Volume: Scaling X"); + uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+94, *yco-126,20,18, &data->volmode, 12.0, 2.0, 0, 0, "Keep Volume: Scaling Z"); + uiDefButI(block, ROW,B_CONSTRAINT_TEST,"NONE", *xco+114, *yco-126,50,18, &data->volmode, 12.0, 3.0, 0, 0, "Ignore Volume"); uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefBut(block, LABEL, B_CONSTRAINT_TEST,"Plane:",*xco+175, *yco-104,40,18, NULL, 0.0, 0.0, 0.0, 0.0, ""); - uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+215, *yco-104,20,18, &data->plane, 12.0, 0.0, 0, 0, "Keep X axis"); - uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+235, *yco-104,20,18, &data->plane, 12.0, 2.0, 0, 0, "Keep Z axis"); + uiDefBut(block, LABEL, B_CONSTRAINT_TEST,"Plane:",*xco+175, *yco-126,40,18, NULL, 0.0, 0.0, 0.0, 0.0, ""); + uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+215, *yco-126,20,18, &data->plane, 12.0, 0.0, 0, 0, "Keep X axis"); + uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+235, *yco-126,20,18, &data->plane, 12.0, 2.0, 0, 0, "Keep Z axis"); uiBlockEndAlign(block); } break;