diff options
21 files changed, 301 insertions, 206 deletions
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 03e9e5953c4..9ef64de4d0d 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -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; } diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 0699ed14858..827b3963a00 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -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); } } } diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index c0cfc4afc82..76364d6a085 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -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; } } } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 7434ed3a3ab..1434e980ec0 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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); } } diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index 98427c3b765..e06b3591802 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -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); diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index edc78a90260..91dbb0758ba 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -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 }; diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index cb790b816cb..947a3631932 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -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 diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 9f05532ac60..70e1bc3f3bc 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -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 diff --git a/source/blender/python/api2_2x/Bone.c b/source/blender/python/api2_2x/Bone.c index 59fa42c6139..8d66b08265a 100644 --- a/source/blender/python/api2_2x/Bone.c +++ b/source/blender/python/api2_2x/Bone.c @@ -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(); diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 077e3bec1ae..0ffe38adf9c 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -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; } diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index d514f225b75..6b8d5d7e5f7 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -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); - 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); + 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"); - 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"); + uiBlockBeginAlign(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_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); } diff --git a/source/blender/src/drawarmature.c b/source/blender/src/drawarmature.c index a2dbca90446..c6508b50c2a 100644 --- a/source/blender/src/drawarmature.c +++ b/source/blender/src/drawarmature.c @@ -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) diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 7f293e5f07b..12546ca0366 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -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); } } diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c index 636dbf2d568..8bb6101f64a 100644 --- a/source/blender/src/edit.c +++ b/source/blender/src/edit.c @@ -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; diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 78e72a4783c..7546158d887 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -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); } } diff --git a/source/blender/src/editconstraint.c b/source/blender/src/editconstraint.c index 142587776c5..e6dbd21c990 100644 --- a/source/blender/src/editconstraint.c +++ b/source/blender/src/editconstraint.c @@ -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 */ diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c index 03b833de47a..6d36be20ea6 100644 --- a/source/blender/src/outliner.c +++ b/source/blender/src/outliner.c @@ -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); diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index 588bf70a4e5..9fa316a2a48 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -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); diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 1d4b1ab3ed2..64c5eaf885d 100755 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -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); diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index ca9a65f4485..93854d5cdc9 100755 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -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); diff --git a/source/blender/src/transform_manipulator.c b/source/blender/src/transform_manipulator.c index c71abf15134..daedcc370ff 100644 --- a/source/blender/src/transform_manipulator.c +++ b/source/blender/src/transform_manipulator.c @@ -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); |