Integration of new IK lib features in Armature Poses.

Best is to forget yesterday's commit and old docs. New docs are underway...

Here's how IK works now;

- IK chains can go all the way to the furthest parent Bone. Disregarding
  the old option "IK to Parent" and disgregarding whether a Bone has an
  offset to its parent (offsets now work for IK, so you can also make
  T-bones).
- The old "IK to Parent" option now only does what it should do: it denotes
  whether a Bone is directly connected to a Parent Bone, or not.
  In the UI and in code this option is now called "Connected".
- You can also define yourself which Bone will become the "Root" for an IK
  chain. This can be any Parent of the IK tip (where the IK constraint is).
  By default it goes all the way, unless you set a value for the new IK
  Constraint Panel option "Chain Lenght".
- "Tree IK" now is detected automatic, when multiple IK Roots are on the
  same Bone, and when there's a branched structure.
  Multiple IK's on a single chain (no branches) is still executed as usual,
  doing the IK's sequentially.
- Note: Branched structures, with _partial_ overlapping IK chains, that don't
  share the same Root will possibly disconnect branches.
- When you select a Bone with IK, it now draws a yellow dashed line to its
  Root.
- The IK options "Location Weight" and "Rotation Weight" are relative,
  in case there's a Tree IK structure. These weights cannot be set to
  zero. To animate or disable IK Targets, use the "Influence" slider.
- This new IK is backwards and upwards compatible for Blender files.
  Of course, the new features won't show in older Blender binaries! :)

Other changes & notes;

- In PoseMode, the Constraint Panel now also draws in Editing Buttons, next
  to the Bones Panel.
- IK Constraint Panel was redesigned... it's still a bit squished
- Buttons "No X DoF" is now called "Lock X". This to follow convention to
  name options positive.
- Added Undo push for Make/Clear Parent in Editmode Armature
- Use CTRL+P "Make Parent" on a single selected Bone to make it become
  connected (ALT+P had already "Disconnect").

On todo next; Visualizing & review of Bone DoF limits and stiffness
This commit is contained in:
Ton Roosendaal 2005-08-28 12:23:06 +00:00
parent fa443a5f01
commit 85efe767f0
21 changed files with 301 additions and 206 deletions

View File

@ -273,7 +273,7 @@ static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan
/* pose should be entirely OK */
void update_pose_constraint_flags(bPose *pose)
{
bPoseChannel *pchan;
bPoseChannel *pchan, *parchan;
bConstraint *con;
/* clear */
@ -284,7 +284,23 @@ void update_pose_constraint_flags(bPose *pose)
for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) {
for(con= pchan->constraints.first; con; con= con->next) {
if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
bKinematicConstraint *data = (bKinematicConstraint*)con->data;
pchan->constflag |= PCHAN_HAS_IK;
/* negative rootbone = recalc rootbone index. used in do_versions */
if(data->rootbone<0) {
data->rootbone= 0;
if(data->flag & CONSTRAINT_IK_TIP) parchan= pchan;
else parchan= pchan->parent;
while(parchan) {
data->rootbone++;
if((parchan->bone->flag & BONE_CONNECTED)==0)
break;
parchan= parchan->parent;
}
}
}
else pchan->constflag |= PCHAN_HAS_CONST;
}

View File

@ -432,7 +432,7 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan)
hlength2= bone->ease2*length*0.390464f;
/* evaluate next and prev bones */
if(bone->flag & BONE_IK_TOPARENT)
if(bone->flag & BONE_CONNECTED)
prev= pchan->parent;
else
prev= NULL;
@ -912,8 +912,8 @@ static int rebuild_pose_bone(bPose *pose, Bone *bone, bPoseChannel *parchan, int
for(bone= bone->childbase.first; bone; bone= bone->next) {
counter= rebuild_pose_bone(pose, bone, pchan, counter);
/* for quick detecting of next bone in chain */
if(bone->flag & BONE_IK_TOPARENT)
/* for quick detecting of next bone in chain, only b-bone uses it now */
if(bone->flag & BONE_CONNECTED)
pchan->child= get_pose_channel(pose, bone->name);
}
@ -990,50 +990,53 @@ static void initialize_posechain(struct Object *ob, bPoseChannel *pchan_tip)
if(data->tar==NULL) return;
if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0) return;
/* exclude tip from chain? */
if(!(data->flag & CONSTRAINT_IK_TIP))
pchan_tip= pchan_tip->parent;
/* Find the chain's root & count the segments needed */
for (curchan = pchan_tip; curchan; curchan=curchan->parent){
pchan_root = curchan;
curchan->flag |= POSE_CHAIN; // don't forget to clear this
chanlist[segcount]=curchan;
segcount++;
/* exclude tip from chain? */
if(curchan==pchan_tip) {
if(!(data->flag & CONSTRAINT_IK_TIP)) segcount--;
}
if(segcount>255) break; // also weak
if (!(curchan->bone->flag & BONE_IK_TOPARENT))
break;
if(segcount==data->rootbone || segcount>255) break; // 255 is weak
}
if (!segcount) return;
/* setup the chain data */
chain = NULL;
/* if tree-IK, look for mathing chain */
if(data->flag & CONSTRAINT_IK_TREE)
for(chain= pchan_root->chain.first; chain; chain= chain->next)
if(chain->tree) break;
/* we make tree-IK, unless all existing targets are in this chain */
for(chain= pchan_root->chain.first; chain; chain= chain->next) {
for(target= chain->targets.first; target; target= target->next) {
curchan= chain->pchanchain[target->tip];
if(curchan->flag & POSE_CHAIN)
curchan->flag &= ~POSE_CHAIN;
else
break;
}
if(target) break;
}
/* create a target */
target= MEM_callocN(sizeof(PoseTarget), "posetarget");
target->con= con;
pchan_tip->flag &= ~POSE_CHAIN;
if(chain==NULL) {
/* make new chain */
chain= MEM_callocN(sizeof(PoseChain), "posechain");
chain->tree= data->flag & CONSTRAINT_IK_TREE;
chain->tolerance= data->tolerance;
chain->iterations= data->iterations;
chain->totchannel= segcount;
chain->pchanchain= MEM_callocN(segcount*sizeof(void *), "channel chain");
for(a=0; a<segcount; a++)
for(a=0; a<segcount; a++) {
chain->pchanchain[a]= chanlist[segcount-a-1];
}
target->tip= segcount-1;
/* AND! link the chain to the root */
@ -1048,7 +1051,6 @@ static void initialize_posechain(struct Object *ob, bPoseChannel *pchan_tip)
for(a=0; a<size && chain->pchanchain[a]==chanlist[segcount-a-1]; a++);
segcount= segcount-a;
target->tip= chain->totchannel + segcount - 1;
if (segcount > 0) {
@ -1063,7 +1065,7 @@ static void initialize_posechain(struct Object *ob, bPoseChannel *pchan_tip)
/* add new pose channels at the end, in reverse order */
for(a=0; a<segcount; a++)
chain->pchanchain[chain->totchannel+a]= chanlist[segcount-a-1];
chain->totchannel= newsize;
}
@ -1129,7 +1131,7 @@ static void execute_posechain(Object *ob, PoseChain *chain)
/* get the matrix that transforms from prevbone into this bone */
Mat3CpyMat4(R_bonemat, pchan->pose_mat);
if(pchan->parent && (bone->flag & BONE_IK_TOPARENT)) {
if(a>0 && pchan->parent) {
Mat3CpyMat4(R_parmat, pchan->parent->pose_mat);
}
else
@ -1138,8 +1140,7 @@ static void execute_posechain(Object *ob, PoseChain *chain)
Mat3Inv(iR_parmat, R_parmat);
/* gather transformations for this IK segment */
start[0]= start[1]= start[2]= 0.0;
/* change length based on bone size */
Mat3ToSize(R_bonemat, bonesize);
length= bone->length*bonesize[1];
@ -1155,6 +1156,14 @@ static void execute_posechain(Object *ob, PoseChain *chain)
Mat3Ortho(rest_basis);
Mat3Ortho(basis);
/* Bone offset */
if(a>0 && pchan->parent) {
VECCOPY(start, bone->head);
// Mat3MulVecfl(R_parmat, start);
}
else
start[0]= start[1]= start[2]= 0.0f;
IK_SetTransform(seg, start, rest_basis, basis, length);
if (pchan->ikflag & BONE_IK_XLIMIT)
@ -1272,7 +1281,7 @@ void chan_calc_mat(bPoseChannel *chan)
/* prevent action channels breaking chains */
/* need to check for bone here, CONSTRAINT_TYPE_ACTION uses this call */
if (chan->bone==NULL || !(chan->bone->flag & BONE_IK_TOPARENT)) {
if (chan->bone==NULL || !(chan->bone->flag & BONE_CONNECTED)) {
VECCOPY(chan->chan_mat[3], chan->loc);
}
@ -1398,7 +1407,7 @@ static void where_is_pose_bone(Object *ob, bPoseChannel *pchan)
Mat4MulMat4 (pchan->pose_mat, conOb.obmat, ob->imat);
/* prevent constraints breaking a chain */
if(pchan->bone->flag & BONE_IK_TOPARENT)
if(pchan->bone->flag & BONE_CONNECTED)
VECCOPY(pchan->pose_mat[3], vec);
}
@ -1444,43 +1453,44 @@ void where_is_pose (Object *ob)
/* 1. construct the PoseChains, clear flags */
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
pchan->flag &= ~POSE_DONE;
pchan->flag &= ~(POSE_DONE|POSE_CHAIN);
if(pchan->constflag & PCHAN_HAS_IK) // flag is set on editing constraints
initialize_posechain(ob, pchan); // will attach it to root!
}
/* 2. the main loop, channels are already hierarchical sorted from root to children */
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
if(!(pchan->flag & POSE_DONE)) {
/* 3. if we find an IK root, we handle it separated */
if(pchan->chain.first) {
while(pchan->chain.first) {
PoseChain *chain= pchan->chain.first;
int a;
/* 4. walk over the chain for regular solving */
for(a=0; a<chain->totchannel; a++) {
if(!(chain->pchanchain[a]->flag & POSE_DONE)) // successive chains can set the flag
where_is_pose_bone(ob, chain->pchanchain[a]);
}
/* 5. execute the IK solver, applying differences to
the channels and setting POSE_DONE */
execute_posechain(ob, chain);
/* 6. apply the differences to the channels, we calculate the original differences first */
for(a=0; a<chain->totchannel; a++)
make_dmats(chain->pchanchain[a]);
for(a=0; a<chain->totchannel; a++)
/* sets POSE_DONE */
where_is_ik_bone(chain->pchanchain[a], chain->basis_change[a]);
/* 7. and free */
BLI_remlink(&pchan->chain, chain);
free_posechain(chain);
/* 3. if we find an IK root, we handle it separated */
if(pchan->chain.first) {
while(pchan->chain.first) {
PoseChain *chain= pchan->chain.first;
int a;
/* 4. walk over the chain for regular solving */
for(a=0; a<chain->totchannel; a++) {
if(!(chain->pchanchain[a]->flag & POSE_DONE)) // successive chains can set the flag
where_is_pose_bone(ob, chain->pchanchain[a]);
}
/* 5. execute the IK solver */
execute_posechain(ob, chain);
/* 6. apply the differences to the channels,
we need to calculate the original differences first */
for(a=0; a<chain->totchannel; a++)
make_dmats(chain->pchanchain[a]);
for(a=0; a<chain->totchannel; a++)
/* sets POSE_DONE */
where_is_ik_bone(chain->pchanchain[a], chain->basis_change[a]);
/* 7. and free */
BLI_remlink(&pchan->chain, chain);
free_posechain(chain);
}
else where_is_pose_bone(ob, pchan);
}
else if(!(pchan->flag & POSE_DONE)) {
where_is_pose_bone(ob, pchan);
}
}
}

View File

@ -1526,15 +1526,25 @@ void DAG_pose_sort(Object *ob)
dag_add_relation(dag, node2, node, 0);
if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
bPoseChannel *par= pchan->parent;
bKinematicConstraint *data = (bKinematicConstraint*)con->data;
bPoseChannel *parchan;
int segcount= 0;
while(par) {
node3= dag_get_node(dag, par);
/* exclude tip from chain? */
if(!(data->flag & CONSTRAINT_IK_TIP))
parchan= pchan->parent;
else
parchan= pchan;
/* Walk to the chain's root */
while (parchan->parent){
segcount++;
if(segcount==data->rootbone || segcount>255) break; // 255 is weak
node3= dag_get_node(dag, parchan);
dag_add_relation(dag, node2, node3, 0);
if(par->bone->flag & BONE_IK_TOPARENT)
par= par->parent;
else break;
parchan= parchan->parent;
}
}
}

View File

@ -1365,17 +1365,6 @@ static void direct_link_constraints(FileData *fd, ListBase *lb)
}
}
/* unused */
static void lib_link_bone(FileData *fd, ID *id, Bone *bone)
{
// Bone *curBone;
// for (curBone=bone->childbase.first; curBone; curBone=curBone->next) {
// lib_link_bone(fd, id, curBone);
// }
}
static void lib_link_pose(FileData *fd, Object *ob, bPose *pose)
{
bPoseChannel *chan;
@ -1393,7 +1382,6 @@ static void lib_link_pose(FileData *fd, Object *ob, bPose *pose)
static void lib_link_armature(FileData *fd, Main *main)
{
bArmature *arm;
// Bone *bone;
arm= main->armature.first;
@ -1401,11 +1389,6 @@ static void lib_link_armature(FileData *fd, Main *main)
if(arm->id.flag & LIB_NEEDLINK) {
arm->id.flag -= LIB_NEEDLINK;
}
// for (bone=arm->bonebase.first; bone; bone=bone->next) {
// lib_link_bone(fd, &arm->id, bone);
// }
arm= arm->id.next;
}
}
@ -4905,9 +4888,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
ob->softflag &= ~OB_SB_ENABLE;
}
if(ob->pose) {
bPoseChannel *pchan;
bPoseChannel *pchan, *parchan;
bConstraint *con;
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
/* 2.38 files can be saved wrong still... */
if(pchan->bone==NULL)
ob->pose->flag |= POSE_RECALC;
if (pchan->limitmin[0] == 0.0f && pchan->limitmax[0] == 0.0f) {
pchan->limitmin[0]= pchan->limitmin[1]= pchan->limitmin[2]= -180.0f;
pchan->limitmax[0]= pchan->limitmax[1]= pchan->limitmax[2]= 180.0f;
@ -4916,12 +4903,18 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
if(con->type == CONSTRAINT_TYPE_KINEMATIC) {
bKinematicConstraint *data = (bKinematicConstraint*)con->data;
data->weight = 1.0f;
data->orientweight = 0.0f;
data->orientweight = 1.0f;
data->flag &= ~CONSTRAINT_IK_ROT;
/* enforce conversion from old IK_TOPARENT to rootbone index */
data->rootbone= -1;
}
}
}
}
/* update_pose_etc handles rootbone==-1 */
if(!(ob->pose->flag & POSE_RECALC))
update_pose_constraint_flags(ob->pose);
}
}

View File

@ -63,6 +63,7 @@ extern void do_soundbuts(unsigned short event);
extern void object_panels(void);
extern void do_object_panels(unsigned short event);
extern void do_constraintbuts(unsigned short event);
extern void object_panel_constraint(char *context);
/* effects */
extern void effects_panels(void);

View File

@ -133,8 +133,8 @@ enum {
POSE_UNUSED3 = 0x0020,
POSE_UNUSED4 = 0x0040,
POSE_UNUSED5 = 0x0080,
POSE_OBMAT = 0x0100,
POSE_PARMAT = 0x0200,
POSE_HAS_IK = 0x0100,
POSE_CHAIN = 0x0200,
POSE_DONE = 0x0400,
POSE_KEY = 0x1000
};

View File

@ -112,7 +112,7 @@ typedef struct bArmature {
#define BONE_TIPSEL 4
/* Used instead of BONE_SELECTED during transform */
#define BONE_TRANSFORM 8
#define BONE_IK_TOPARENT 16
#define BONE_CONNECTED 16
/* 32 used to be quatrot, was always set in files, do not reuse unless you clear it always */
/* hidden Bones when drawing Posechannels */
#define BONE_HIDDEN_P 64

View File

@ -64,7 +64,8 @@ typedef struct bKinematicConstraint{
Object *tar;
float tolerance; /* Acceptable distance from target */
short iterations; /* Maximum number of iterations to try */
short flag; /* Like IK to Tip */
short flag; /* Like CONSTRAINT_IK_TIP */
int rootbone, pad; /* index to rootbone, if zero go all the way to mother bone */
char subtarget[32]; /* String to specify sub-object target */
float weight; /* Weight of goal in IK tree */
@ -215,7 +216,6 @@ typedef struct bStretchToConstraint{
/* bKinematicConstraint->flag */
#define CONSTRAINT_IK_TIP 1
#define CONSTRAINT_IK_ROT 2
#define CONSTRAINT_IK_TREE 4
#endif

View File

@ -1593,14 +1593,14 @@ static PyObject *Bone_hasIK( BPy_Bone * self )
{
if( !self->bone ) { //test to see if linked to armature
//use python vars
if( self->flag & BONE_IK_TOPARENT ) {
if( self->flag & BONE_CONNECTED ) {
return EXPP_incr_ret_True();
} else {
return EXPP_incr_ret_False();
}
} else {
//use bone datastruct
if( self->bone->flag & BONE_IK_TOPARENT ) {
if( self->bone->flag & BONE_CONNECTED ) {
return EXPP_incr_ret_True();
} else {
return EXPP_incr_ret_False();

View File

@ -2071,7 +2071,7 @@ static void attach_bone_to_parent_cb(void *bonev, void *arg2_unused)
{
EditBone *ebone= bonev;
if (ebone->parent && (ebone->flag & BONE_IK_TOPARENT)) {
if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
/* Attach this bone to its parent */
VECCOPY(ebone->head, ebone->parent->tail);
}
@ -2081,7 +2081,7 @@ static void parnr_to_editbone(EditBone *bone)
{
if (bone->parNr == -1){
bone->parent = NULL;
bone->flag &= ~BONE_IK_TOPARENT;
bone->flag &= ~BONE_CONNECTED;
}
else{
bone->parent = BLI_findlink(&G.edbo, bone->parNr);
@ -2255,9 +2255,9 @@ static void editing_panel_armature_bones(Object *ob, bArmature *arm)
MEM_freeN(boneString);
/* IK to parent flag */
/* Connect to parent flag */
if (curBone->parent){
but=uiDefButBitI(block, TOG, BONE_IK_TOPARENT, B_ARM_RECALCDATA, "IK", bx+300,by,32,18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "IK link to parent");
but=uiDefButBitI(block, TOG, BONE_CONNECTED, B_ARM_RECALCDATA, "Con", bx+300,by,32,18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Connect this Bone to Parent");
uiButSetFunc(but, attach_bone_to_parent_cb, curBone, NULL);
}
@ -2337,7 +2337,7 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm)
zerolimit = 1;
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, BONE_IK_NO_XDOF, B_ARM_RECALCDATA, "No X DoF", bx-10,by-60,114,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable X DoF for IK");
uiDefButBitS(block, TOG, BONE_IK_NO_XDOF, B_ARM_RECALCDATA, "Lock X Rot", bx-10,by-60,114,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable X DoF for IK");
if ((pchan->ikflag & BONE_IK_NO_XDOF)==0) {
uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff X:", bx-10, by-80, 114, 19, &pchan->stiffness[0], 0.0, 0.99, 1.0, 0.0, "Resistance to bending for X axis");
uiDefButBitS(block, TOG, BONE_IK_XLIMIT, B_ARM_RECALCDATA, "Limit X", bx-10,by-100,114,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over X axis");
@ -2351,7 +2351,7 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm)
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, BONE_IK_NO_YDOF, B_ARM_RECALCDATA, "No Y DoF", bx+104,by-60,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Y DoF for IK");
uiDefButBitS(block, TOG, BONE_IK_NO_YDOF, B_ARM_RECALCDATA, "Lock Y Rot", bx+104,by-60,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Y DoF for IK");
if ((pchan->ikflag & BONE_IK_NO_YDOF)==0) {
uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff Y:", bx+104, by-80, 114, 19, &pchan->stiffness[1], 0.0, 0.99, 1.0, 0.0, "Resistance to bending for Y axis");
uiDefButBitS(block, TOG, BONE_IK_YLIMIT, B_ARM_RECALCDATA, "Limit Y", bx+104,by-100,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over Y axis");
@ -2365,7 +2365,7 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm)
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, BONE_IK_NO_ZDOF, B_ARM_RECALCDATA, "No Z DoF", bx+217,by-60,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Z DoF for IK");
uiDefButBitS(block, TOG, BONE_IK_NO_ZDOF, B_ARM_RECALCDATA, "Lock Z Rot", bx+217,by-60,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Z DoF for IK");
if ((pchan->ikflag & BONE_IK_NO_ZDOF)==0) {
uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff Z:", bx+217, by-80, 114, 19, &pchan->stiffness[2], 0.0, 0.99, 1.0, 0.0, "Resistance to bending for Z axis");
uiDefButBitS(block, TOG, BONE_IK_ZLIMIT, B_ARM_RECALCDATA, "Limit Z", bx+217,by-100,113,19, &pchan->flag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over Z axis");
@ -3343,6 +3343,7 @@ void editing_panels()
}
else if(ob->flag & OB_POSEMODE) {
editing_panel_pose_bones(ob, arm);
object_panel_constraint("Editing");
}
break;
}

View File

@ -423,7 +423,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
/* rounded header */
rb_col= (con->flag & CONSTRAINT_ACTIVE)?10:-10;
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-1, width+30, 22, NULL, 5.0, 0.0,
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-1, width+40, 22, NULL, 5.0, 0.0,
(con->flag & CONSTRAINT_EXPAND)?3:15 , rb_col-20, "");
/* open/close */
@ -495,7 +495,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
bArmature *arm;
height = 88;
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
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, "");
@ -533,7 +533,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
bArmature *arm;
height = 66;
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
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, "");
@ -563,7 +563,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
bArmature *arm;
height = 46;
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
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, "");
@ -586,33 +586,32 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
bArmature *arm;
height = 108;
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
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, "");
/* Draw target parameters */
uiDefButBitS(block, TOG, CONSTRAINT_IK_ROT, B_CONSTRAINT_TEST, "Rot", *xco, *yco-24,60,19, &data->flag, 0, 0, 0, 0, "Chain follows rotation of target");
uiBlockBeginAlign(block);
uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object");
uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 19, &data->tar, "Target Object");
arm = get_armature(data->tar);
if (arm)
but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,19, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
else
strcpy (data->subtarget, "");
uiBlockEndAlign(block);
uiDefButBitS(block, TOG, CONSTRAINT_IK_TIP, B_CONSTRAINT_TEST, "Use Tip", *xco+((width/2)-117), *yco-42, 80, 18, &data->flag, 0, 0, 0, 0, "Include Bone's tip als last element in Chain");
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, CONSTRAINT_IK_TIP, B_CONSTRAINT_TEST, "Use Tip", *xco, *yco-64, 142, 19, &data->flag, 0, 0, 0, 0, "Include Bone's tip als last element in Chain");
uiDefButI(block, NUM, B_CONSTRAINT_TEST, "ChainLen:", *xco+142, *yco-64,143,19, &data->rootbone, 0, 255, 0, 0, "If not zero, the amount of bones in this chain");
uiBlockBeginAlign(block);
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Tolerance:", *xco+((width/2)-117), *yco-64, 120, 18, &data->tolerance, 0.0001f, 1.0, 0.0, 0.0, "Maximum distance to target after solving");
uiDefButS(block, NUM, B_CONSTRAINT_TEST, "Iterations:", *xco+((width/2)+3), *yco-64, 120, 18, &data->iterations, 1, 10000, 0.0, 0.0, "Maximum number of solving iterations");
uiBlockEndAlign(block);
uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "PosW ", *xco, *yco-86, 142, 19, &data->weight, 0.01, 1.0, 2, 2, "For Tree-IK: weight of position control for this target");
uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "RotW ", *xco+142, *yco-86, 143, 19, &data->orientweight, 0.01, 1.0, 2, 2, "For Tree-IK: Weight of orientation control for this target");
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Tolerance:", *xco, *yco-106, 142, 19, &data->tolerance, 0.0001f, 1.0, 0, 0, "Maximum distance to target after solving");
uiDefButS(block, NUM, B_CONSTRAINT_TEST, "Iterations:", *xco+142, *yco-106, 143, 19, &data->iterations, 1, 10000, 0, 0, "Maximum number of solving iterations");
uiDefButBitS(block, TOG, CONSTRAINT_IK_TREE, B_CONSTRAINT_TEST, "Tree IK", *xco+((width/2)-117), *yco-86,120,18, &data->flag, 0, 0, 0, 0, "IK chain becomes tree, when it shares Root with other Chains");
uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "Weight ", *xco+((width/2)+3), *yco-86, 120, 18, &data->weight, 0.0, 1.0, 0.0, 0.0, "Weight of position control for this target");
uiDefButBitS(block, TOG, CONSTRAINT_IK_ROT, B_CONSTRAINT_TEST, "Orientation", *xco+((width/2)-117), *yco-108,120,18, &data->flag, 0, 0, 0, 0, "Follow orientation of target");
uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "Weight ", *xco+((width/2)+3), *yco-108, 120, 18, &data->orientweight, 0.0, 1.0, 0.0, 0.0, "Weight of orientation control for this target");
}
break;
case CONSTRAINT_TYPE_TRACKTO:
@ -621,7 +620,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
bArmature *arm;
height = 66;
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
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, "");
@ -662,7 +661,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
bLockTrackConstraint *data = con->data;
bArmature *arm;
height = 66;
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
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, "");
@ -703,7 +702,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
bFollowPathConstraint *data = con->data;
height = 66;
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
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, "");
@ -742,7 +741,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
bArmature *arm;
height = 105;
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
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, "");
@ -786,7 +785,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
case CONSTRAINT_TYPE_NULL:
{
height = 17;
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
}
break;
@ -973,7 +972,7 @@ void do_constraintbuts(unsigned short event)
allqueue (REDRAWBUTSOBJECT, 0);
}
static void object_panel_constraint(void)
void object_panel_constraint(char *context)
{
uiBlock *block;
Object *ob= OBACT;
@ -983,7 +982,7 @@ static void object_panel_constraint(void)
char str[64];
block= uiNewBlock(&curarea->uiblocks, "object_panel_constraint", UI_EMBOSS, UI_HELV, curarea->win);
if(uiNewPanel(curarea, block, "Constraints", "Object", 640, 0, 318, 204)==0) return;
if(uiNewPanel(curarea, block, "Constraints", context, 640, 0, 318, 204)==0) return;
/* this is a variable height panel, newpanel doesnt force new size on existing panels */
/* so first we make it default height */
@ -1758,7 +1757,7 @@ void object_panels()
object_panel_anim(ob);
object_panel_draw(ob);
object_panel_constraint();
object_panel_constraint("Object");
if(ob->type==OB_MESH) {
object_panel_effects(ob);
}

View File

@ -333,8 +333,8 @@ static void draw_bone_solid_octahedral(void)
static void draw_bone_points(int dt, int armflag, unsigned int boneflag, int id)
{
/* Draw root point if we have no IK parent */
if (!(boneflag & BONE_IK_TOPARENT)){
/* Draw root point if we are not connected */
if (!(boneflag & BONE_CONNECTED)){
if (id != -1)
glLoadName (id | BONESEL_ROOT);
@ -413,7 +413,7 @@ static void draw_sphere_bone_dist(float smat[][4], float imat[][4], int boneflag
length= ebone->length;
tail= ebone->rad_tail;
dist= ebone->dist;
if (ebone->parent && (ebone->flag & BONE_IK_TOPARENT))
if (ebone->parent && (ebone->flag & BONE_CONNECTED))
head= ebone->parent->rad_tail;
else
head= ebone->rad_head;
@ -424,7 +424,7 @@ static void draw_sphere_bone_dist(float smat[][4], float imat[][4], int boneflag
length= pchan->bone->length;
tail= pchan->bone->rad_tail;
dist= pchan->bone->dist;
if (pchan->parent && (pchan->bone->flag & BONE_IK_TOPARENT))
if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED))
head= pchan->parent->bone->rad_tail;
else
head= pchan->bone->rad_head;
@ -522,7 +522,7 @@ static void draw_sphere_bone_wire(float smat[][4], float imat[][4], int armflag,
length= ebone->length;
tail= ebone->rad_tail;
if (ebone->parent && (boneflag & BONE_IK_TOPARENT))
if (ebone->parent && (boneflag & BONE_CONNECTED))
head= ebone->parent->rad_tail;
else
head= ebone->rad_head;
@ -532,7 +532,7 @@ static void draw_sphere_bone_wire(float smat[][4], float imat[][4], int armflag,
else {
length= pchan->bone->length;
tail= pchan->bone->rad_tail;
if (pchan->parent && (boneflag & BONE_IK_TOPARENT))
if (pchan->parent && (boneflag & BONE_CONNECTED))
head= pchan->parent->bone->rad_tail;
else
head= pchan->bone->rad_head;
@ -552,8 +552,8 @@ static void draw_sphere_bone_wire(float smat[][4], float imat[][4], int armflag,
else BIF_ThemeColor(TH_WIRE);
}
/* Draw root point if we have no IK parent */
if (!(boneflag & BONE_IK_TOPARENT)){
/* Draw root point if we are not connected */
if (!(boneflag & BONE_CONNECTED)){
if (id != -1)
glLoadName (id | BONESEL_ROOT);
@ -636,7 +636,7 @@ static void draw_sphere_bone(int dt, int armflag, int boneflag, int constflag, u
if(ebone) {
length= ebone->length;
tail= ebone->rad_tail;
if (ebone->parent && (boneflag & BONE_IK_TOPARENT))
if (ebone->parent && (boneflag & BONE_CONNECTED))
head= ebone->parent->rad_tail;
else
head= ebone->rad_head;
@ -644,7 +644,7 @@ static void draw_sphere_bone(int dt, int armflag, int boneflag, int constflag, u
else {
length= pchan->bone->length;
tail= pchan->bone->rad_tail;
if (pchan->parent && (boneflag & BONE_IK_TOPARENT))
if (pchan->parent && (boneflag & BONE_CONNECTED))
head= pchan->parent->bone->rad_tail;
else
head= pchan->bone->rad_head;
@ -679,8 +679,8 @@ static void draw_sphere_bone(int dt, int armflag, int boneflag, int constflag, u
else if(dt==OB_SOLID)
BIF_ThemeColorShade(TH_BONE_SOLID, -30);
/* Draw root point if we have no IK parent */
if (!(boneflag & BONE_IK_TOPARENT)){
/* Draw root point if we are not connected */
if (!(boneflag & BONE_CONNECTED)){
if (id != -1)
glLoadName (id | BONESEL_ROOT);
gluSphere( qobj, head, 16, 10);
@ -788,8 +788,8 @@ static void draw_line_bone(int armflag, int boneflag, int constflag, unsigned in
BIF_ThemeColor(TH_WIRE);
}
/* Draw root point if we have no IK parent */
if (!(boneflag & BONE_IK_TOPARENT)){
/* Draw root point if we are not connected */
if (!(boneflag & BONE_CONNECTED)){
if (G.f & G_PICKSEL) { // no bitmap in selection mode, crashes 3d cards...
glLoadName (id | BONESEL_ROOT);
glBegin(GL_POINTS);
@ -839,8 +839,8 @@ static void draw_line_bone(int armflag, int boneflag, int constflag, unsigned in
glLineWidth(2.0);
/* Draw root point if we have no IK parent */
if (!(boneflag & BONE_IK_TOPARENT)){
/* Draw root point if we are not connected */
if (!(boneflag & BONE_CONNECTED)){
if ((G.f & G_PICKSEL)==0) { // no bitmap in selection mode, crashes 3d cards...
if(armflag & ARM_EDITMODE) {
if (boneflag & BONE_ROOTSEL) BIF_ThemeColor(TH_VERTEX_SELECT);
@ -1064,6 +1064,43 @@ static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned
}
}
static void pchan_draw_IK_root_lines(bPoseChannel *pchan)
{
bConstraint *con;
bPoseChannel *parchan;
for(con= pchan->constraints.first; con; con= con->next) {
if(con->type == CONSTRAINT_TYPE_KINEMATIC) {
bKinematicConstraint *data = (bKinematicConstraint*)con->data;
int segcount= 0;
setlinestyle(3);
glBegin(GL_LINES);
/* exclude tip from chain? */
if(!(data->flag & CONSTRAINT_IK_TIP))
parchan= pchan->parent;
else
parchan= pchan;
glVertex3fv(parchan->pose_tail);
/* Find the chain's root */
while (parchan->parent){
segcount++;
if(segcount==data->rootbone || segcount>255) break; // 255 is weak
parchan= parchan->parent;
}
if(parchan)
glVertex3fv(parchan->pose_head);
glEnd();
setlinestyle(0);
}
}
}
/* assumes object is Armature with pose */
static void draw_pose_channels(Base *base, int dt)
{
@ -1127,7 +1164,7 @@ static void draw_pose_channels(Base *base, int dt)
/* catch exception for bone with hidden parent */
flag= bone->flag;
if(bone->parent && (bone->parent->flag & BONE_HIDDEN_P))
flag &= ~BONE_IK_TOPARENT;
flag &= ~BONE_CONNECTED;
if(arm->drawtype==ARM_ENVELOPE)
draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
@ -1161,19 +1198,31 @@ static void draw_pose_channels(Base *base, int dt)
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
bone= pchan->bone;
if(bone && !(bone->flag & BONE_HIDDEN_P)) {
// Draw a line from our root to the parent's tip
if (do_dashed && bone->parent && !(bone->flag & BONE_IK_TOPARENT) ){
if (arm->flag & ARM_POSEMODE) {
glLoadName (index & 0xFFFF); // object tag, for bordersel optim
BIF_ThemeColor(TH_WIRE);
if (do_dashed && bone->parent) {
// Draw a line from our root to the parent's tip
if(!(bone->flag & BONE_CONNECTED) ){
if (arm->flag & ARM_POSEMODE) {
glLoadName (index & 0xFFFF); // object tag, for bordersel optim
BIF_ThemeColor(TH_WIRE);
}
setlinestyle(3);
glBegin(GL_LINES);
glVertex3fv(pchan->pose_head);
glVertex3fv(pchan->parent->pose_tail);
glEnd();
setlinestyle(0);
}
// Draw a line to IK root bone
if(arm->flag & ARM_POSEMODE) {
if(pchan->constflag & PCHAN_HAS_IK) {
if(bone->flag & BONE_SELECTED) {
glLoadName (index & 0xFFFF);
glColor3ub(200, 200, 50); // add theme!
pchan_draw_IK_root_lines(pchan);
}
}
}
setlinestyle(3);
glBegin(GL_LINES);
glVertex3fv(pchan->pose_head);
glVertex3fv(pchan->parent->pose_tail);
glEnd();
setlinestyle(0);
}
if(arm->drawtype!=ARM_ENVELOPE) {
@ -1184,7 +1233,7 @@ static void draw_pose_channels(Base *base, int dt)
/* catch exception for bone with hidden parent */
flag= bone->flag;
if(bone->parent && (bone->parent->flag & BONE_HIDDEN_P))
flag &= ~BONE_IK_TOPARENT;
flag &= ~BONE_CONNECTED;
/* extra draw service for pose mode */
constflag= pchan->constflag;
@ -1321,7 +1370,7 @@ static void draw_ebones(Object *ob, int dt)
/* catch exception for bone with hidden parent */
flag= eBone->flag;
if(eBone->parent && (eBone->parent->flag & BONE_HIDDEN_A))
flag &= ~BONE_IK_TOPARENT;
flag &= ~BONE_CONNECTED;
if(arm->drawtype==ARM_ENVELOPE)
draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
@ -1338,6 +1387,7 @@ static void draw_ebones(Object *ob, int dt)
/* if wire over solid, set offset */
index= -1;
glLoadName(-1);
if(arm->drawtype==ARM_LINE) {
if(G.f & G_PICKSEL)
index= 0;
@ -1353,7 +1403,7 @@ static void draw_ebones(Object *ob, int dt)
/* catch exception for bone with hidden parent */
flag= eBone->flag;
if(eBone->parent && (eBone->parent->flag & BONE_HIDDEN_A))
flag &= ~BONE_IK_TOPARENT;
flag &= ~BONE_CONNECTED;
if(arm->drawtype==ARM_ENVELOPE) {
if(dt<OB_SOLID)

View File

@ -1669,13 +1669,13 @@ void do_viewbuts(unsigned short event)
if (ebone) {
ebone->roll= M_PI*ob_eul[0]/180.0;
// Update our parent
if (ebone->parent && ebone->flag & BONE_IK_TOPARENT){
if (ebone->parent && ebone->flag & BONE_CONNECTED){
VECCOPY (ebone->parent->tail, ebone->head);
}
// Update our children if necessary
for (child = G.edbo.first; child; child=child->next){
if (child->parent == ebone && (child->flag & BONE_IK_TOPARENT)){
if (child->parent == ebone && (child->flag & BONE_CONNECTED)){
VECCOPY (child->head, ebone->tail);
}
}
@ -1687,13 +1687,13 @@ void do_viewbuts(unsigned short event)
eboflip->tail[0]= -ebone->tail[0];
// Update our parent
if (eboflip->parent && eboflip->flag & BONE_IK_TOPARENT){
if (eboflip->parent && eboflip->flag & BONE_CONNECTED){
VECCOPY (eboflip->parent->tail, eboflip->head);
}
// Update our children if necessary
for (child = G.edbo.first; child; child=child->next){
if (child->parent == eboflip && (child->flag & BONE_IK_TOPARENT)){
if (child->parent == eboflip && (child->flag & BONE_CONNECTED)){
VECCOPY (child->head, eboflip->tail);
}
}

View File

@ -589,8 +589,8 @@ void countall()
for (ebo=G.edbo.first;ebo;ebo=ebo->next){
G.totbone++;
/* Sync selection to parent for ik children */
if ((ebo->flag & BONE_IK_TOPARENT) && ebo->parent){
/* Sync selection to parent for connected children */
if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
G.totvert--;
if (ebo->parent->flag & BONE_TIPSEL)
ebo->flag |= BONE_ROOTSEL;
@ -610,8 +610,8 @@ void countall()
if(ebo->flag & BONE_SELECTED) G.totbonesel++;
// If this is an IK child and it's parent is being moved, remove our root
if ((ebo->flag & BONE_IK_TOPARENT)&& (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL)){
// If this is a connected child and it's parent is being moved, remove our root
if ((ebo->flag & BONE_CONNECTED)&& (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL)){
G.totvertsel--;
}
@ -752,7 +752,7 @@ static void special_transvert_update(void)
/* Ensure all bones are correctly adjusted */
for (ebo=G.edbo.first; ebo; ebo=ebo->next){
if ((ebo->flag & BONE_IK_TOPARENT) && ebo->parent){
if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
/* If this bone has a parent tip that has been moved */
if (ebo->parent->flag & BONE_TIPSEL){
VECCOPY (ebo->head, ebo->parent->tail);
@ -880,9 +880,9 @@ static void make_trans_verts(float *min, float *max, int mode)
tottrans++;
}
/* Only add the root if there is no selected IK parent */
/* Only add the root if there is no connection */
if (ebo->flag & BONE_ROOTSEL){
if (!(ebo->parent && (ebo->flag & BONE_IK_TOPARENT) && ebo->parent->flag & BONE_TIPSEL)){
if (!(ebo->parent && (ebo->flag & BONE_CONNECTED) && ebo->parent->flag & BONE_TIPSEL)){
VECCOPY (tv->oldloc, ebo->head);
tv->loc= ebo->head;
tv->nor= NULL;

View File

@ -132,7 +132,7 @@ static void make_boneList(ListBase* list, ListBase *bones, EditBone *parent)
/* fix selection flags */
if(eBone->flag & BONE_SELECTED) {
eBone->flag |= BONE_TIPSEL;
if(eBone->parent && (eBone->flag & BONE_IK_TOPARENT))
if(eBone->parent && (eBone->flag & BONE_CONNECTED))
eBone->parent->flag |= BONE_TIPSEL;
else
eBone->flag |= BONE_ROOTSEL;
@ -579,7 +579,7 @@ static void selectconnected_posebonechildren (Object *ob, Bone *bone)
{
Bone *curBone;
if (!(bone->flag & BONE_IK_TOPARENT))
if (!(bone->flag & BONE_CONNECTED))
return;
select_actionchannel_by_name (ob->action, bone->name, !(G.qual & LR_SHIFTKEY));
@ -618,7 +618,7 @@ void selectconnected_posearmature(void)
else
curBone->flag |= BONE_SELECTED;
if (curBone->flag & BONE_IK_TOPARENT)
if (curBone->flag & BONE_CONNECTED)
next=curBone->parent;
else
next=NULL;
@ -701,7 +701,7 @@ void selectconnected_armature(void)
curBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
}
if (curBone->flag & BONE_IK_TOPARENT)
if (curBone->flag & BONE_CONNECTED)
next=curBone->parent;
else
next=NULL;
@ -712,7 +712,7 @@ void selectconnected_armature(void)
for (curBone=G.edbo.first; curBone; curBone=next){
next = curBone->next;
if (curBone->parent == bone){
if (curBone->flag & BONE_IK_TOPARENT){
if (curBone->flag & BONE_CONNECTED){
if (G.qual & LR_SHIFTKEY)
curBone->flag &= ~(BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
else
@ -833,7 +833,7 @@ static void delete_bone(EditBone* exBone)
for (curBone=G.edbo.first;curBone;curBone=curBone->next){
if (curBone->parent==exBone){
curBone->parent=exBone->parent;
curBone->flag &= ~BONE_IK_TOPARENT;
curBone->flag &= ~BONE_CONNECTED;
}
}
@ -907,12 +907,12 @@ void mouse_armature(void)
deselectall_armature(0);
}
/* by definition the non-root non-IK bones have no root point drawn,
/* by definition the non-root non-connected bones have no root point drawn,
so a root selection needs to be delivered to the parent tip,
countall() (bad location) flushes these flags */
if(selmask & BONE_SELECTED) {
if(nearBone->parent && (nearBone->flag & BONE_IK_TOPARENT)) {
if(nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
/* click in a chain */
if(G.qual & LR_SHIFTKEY) {
/* hold shift inverts this bone's selection */
@ -1280,7 +1280,7 @@ void addvert_armature(void)
VECCOPY(newbone->head, ebone->tail);
newbone->parent= ebone;
newbone->flag |= BONE_IK_TOPARENT;
newbone->flag |= BONE_CONNECTED;
}
curs= give_cursor();
@ -1368,7 +1368,7 @@ void adduplicate_armature(void)
*/
else {
eBone->parent=(EditBone*) curBone->parent;
eBone->flag &= ~BONE_IK_TOPARENT;
eBone->flag &= ~BONE_CONNECTED;
}
/* Lets try to fix any constraint subtargets that might
@ -1473,10 +1473,20 @@ void make_bone_parent(void)
}
}
}
if(selbone==NULL) error("Need one active and one selected bone");
if(selbone==NULL) {
/* we make sure bone is connected */
if(val==1 && actbone->parent) {
actbone->flag |= BONE_CONNECTED;
VECCOPY(actbone->head, actbone->parent->tail);
countall(); // checks selection
allqueue(REDRAWVIEW3D, 0);
BIF_undo_push("Connect to Parent");
}
else error("Need one active and one selected bone");
}
else {
/* if selbone had a parent we clear parent tip */
if(selbone->parent && (selbone->flag & BONE_IK_TOPARENT))
if(selbone->parent && (selbone->flag & BONE_CONNECTED))
selbone->parent->flag &= ~(BONE_TIPSEL);
selbone->parent= actbone;
@ -1485,12 +1495,12 @@ void make_bone_parent(void)
for(ebone= actbone->parent; ebone; ebone= ebone->parent) {
if(ebone->parent==selbone) {
ebone->parent= NULL;
ebone->flag &= ~BONE_IK_TOPARENT;
ebone->flag &= ~BONE_CONNECTED;
}
}
if(val==1) { // connected
selbone->flag |= BONE_IK_TOPARENT;
selbone->flag |= BONE_CONNECTED;
VecSubf(offset, actbone->tail, selbone->head);
VECCOPY(selbone->head, actbone->tail);
@ -1509,16 +1519,16 @@ void make_bone_parent(void)
}
}
else {
selbone->flag &= ~BONE_IK_TOPARENT;
selbone->flag &= ~BONE_CONNECTED;
}
countall(); // checks selection
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
allqueue(REDRAWOOPS, 0);
BIF_undo_push("Make Parent");
}
}
return;
}
void clear_bone_parent(void)
@ -1526,7 +1536,7 @@ void clear_bone_parent(void)
EditBone *ebone;
short val;
val= pupmenu("Clear Parent%t|Clear Parent%x1|Disconnect IK%x2");
val= pupmenu("Clear Parent%t|Clear Parent%x1|Disconnect Bone%x2");
if(val<1) return;
for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
@ -1536,8 +1546,7 @@ void clear_bone_parent(void)
ebone->parent->flag &= ~(BONE_TIPSEL);
if(val==1) ebone->parent= NULL;
ebone->flag &= ~BONE_IK_TOPARENT;
ebone->flag &= ~BONE_CONNECTED;
}
}
}
@ -1545,6 +1554,7 @@ void clear_bone_parent(void)
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSEDIT, 0);
allqueue(REDRAWOOPS, 0);
BIF_undo_push("Clear Parent");
}
@ -1600,7 +1610,7 @@ void extrude_armature(int forked)
/* since we allow root extrude too, we have to make sure selection is OK */
for (ebone = G.edbo.first; ebone; ebone=ebone->next){
if(ebone->flag & BONE_ROOTSEL) {
if(ebone->parent && (ebone->flag & BONE_IK_TOPARENT)) {
if(ebone->parent && (ebone->flag & BONE_CONNECTED)) {
if(ebone->parent->flag & BONE_TIPSEL)
ebone->flag &= ~BONE_ROOTSEL;
}
@ -1674,7 +1684,7 @@ void extrude_armature(int forked)
newbone->segments= 1;
newbone->boneclass= ebone->boneclass;
newbone->flag |= BONE_IK_TOPARENT;
if(newbone->parent) newbone->flag |= BONE_CONNECTED;
strcpy (newbone->name, ebone->name);
@ -1934,14 +1944,14 @@ int ik_chain_looper(Object *ob, Bone *bone, void *data,
for (curBone = bone; curBone; curBone=curBone->parent) {
if (!curBone->parent)
break;
else if (!(curBone->flag & BONE_IK_TOPARENT))
else if (!(curBone->flag & BONE_CONNECTED))
break;
count += bone_func(ob, curBone->parent, data);
}
/* The children */
for (curBone = bone->childbase.first; curBone; curBone=curBone->next){
if (curBone->flag & BONE_IK_TOPARENT) {
if (curBone->flag & BONE_CONNECTED) {
count += bone_func(ob, curBone, data);
}
}

View File

@ -116,22 +116,20 @@ ListBase *get_active_constraint_channels (Object *ob, int forcevalid)
/* if object in posemode, active bone constraints, else object constraints */
ListBase *get_active_constraints(Object *ob)
{
ListBase *list;
if (!ob)
return NULL;
list = &ob->constraints;
if (ob->flag & OB_POSEMODE) {
bPoseChannel *pchan;
pchan = get_active_posechannel(ob);
if (pchan)
list = &pchan->constraints;
return &pchan->constraints;
}
else
return &ob->constraints;
return list;
return NULL;
}
/* single constraint */

View File

@ -1294,7 +1294,7 @@ static int tree_element_active_ebone(TreeElement *te, TreeStoreElem *tselem, int
ebone->flag |= BONE_SELECTED|BONE_ROOTSEL|BONE_TIPSEL|BONE_ACTIVE;
// flush to parent?
if(ebone->parent && (ebone->flag & BONE_IK_TOPARENT)) ebone->parent->flag |= BONE_TIPSEL;
if(ebone->parent && (ebone->flag & BONE_CONNECTED)) ebone->parent->flag |= BONE_TIPSEL;
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWOOPS, 0);

View File

@ -261,14 +261,21 @@ void pose_add_IK(void)
bPoseChannel *pchan= pchanact;
while(pchan) {
if(pchan==pchansel) break;
if(pchan->bone->flag & BONE_IK_TOPARENT)
pchan= pchan->parent;
else pchan= NULL;
pchan= pchan->parent;
}
if(pchan) {
error("IK target should not be in the IK chain itself");
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);

View File

@ -382,8 +382,8 @@ void count_bone_select(TransInfo *t, ListBase *lb, int do_it)
do_next= do_it;
if(do_it) {
if (bone->flag & BONE_SELECTED) {
/* We don't let IK children get "grabbed" */
if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_IK_TOPARENT)==0 ) {
/* We don't let connected children get "grabbed" */
if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_CONNECTED)==0 ) {
bone->flag |= BONE_TRANSFORM;
t->total++;
do_next= 0; // no transform on children if one parent bone is selected
@ -402,8 +402,8 @@ static int add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tra
if(bone) {
if (bone->flag & BONE_TRANSFORM) {
/* We don't let IK children get "grabbed" */
if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_IK_TOPARENT)==0 ) {
/* We don't let connected children get "grabbed" */
if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_CONNECTED)==0 ) {
VECCOPY(vec, pchan->pose_mat[3]);
VECCOPY(td->center, vec);

View File

@ -183,7 +183,7 @@ void recalcData(TransInfo *t)
/* Ensure all bones are correctly adjusted */
for (ebo=G.edbo.first; ebo; ebo=ebo->next){
if ((ebo->flag & BONE_IK_TOPARENT) && ebo->parent){
if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
/* If this bone has a parent tip that has been moved */
if (ebo->parent->flag & BONE_TIPSEL){
VECCOPY (ebo->head, ebo->parent->tail);

View File

@ -219,8 +219,8 @@ int calc_manipulator_stats(ScrArea *sa)
EditBone *ebo;
for (ebo=G.edbo.first;ebo;ebo=ebo->next){
// If this is an IK child and it's parent is being moved, don't count as selected
if ((ebo->flag & BONE_IK_TOPARENT)&& (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL));
// If this is a connected child and it's parent is being moved, don't count as selected
if ((ebo->flag & BONE_CONNECTED)&& (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL));
else {
if (ebo->flag & BONE_TIPSEL) {
calc_tw_center(ebo->tail);