diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 720ed0513ed..155d5a7d21c 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1573,21 +1573,16 @@ static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip) /* find IK constraint, and validate it */ for(con= pchan_tip->constraints.first; con; con= con->next) { - if(con->type==CONSTRAINT_TYPE_KINEMATIC) break; + if(con->type==CONSTRAINT_TYPE_KINEMATIC) { + data=(bKinematicConstraint*)con->data; + if (data->flag & CONSTRAINT_IK_AUTO) break; + if (data->tar==NULL) continue; + if (data->tar->type==OB_ARMATURE && data->subtarget[0]==0) continue; + if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0)) break; + } } if(con==NULL) return; - data=(bKinematicConstraint*)con->data; - - /* two types of targets */ - if(data->flag & CONSTRAINT_IK_AUTO); - else { - if(con->flag & CONSTRAINT_DISABLE) return; /* checked in editconstraint.c */ - if(con->enforce == 0.0f) return; - 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; diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index fa5b5a75941..ecfb7dc7a90 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -463,7 +463,9 @@ typedef enum B_CONSTRAINTCHANNEL_FLAG { /* bKinematicConstraint->flag */ #define CONSTRAINT_IK_TIP 1 #define CONSTRAINT_IK_ROT 2 + /* targetless */ #define CONSTRAINT_IK_AUTO 4 + /* autoik */ #define CONSTRAINT_IK_TEMP 8 #define CONSTRAINT_IK_STRETCH 16 #define CONSTRAINT_IK_POS 32 diff --git a/source/blender/src/drawarmature.c b/source/blender/src/drawarmature.c index c37eaf7986c..f050a730380 100644 --- a/source/blender/src/drawarmature.c +++ b/source/blender/src/drawarmature.c @@ -1301,7 +1301,7 @@ static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp) bPoseChannel *parchan; for (con= pchan->constraints.first; con; con= con->next) { - if (con->type == CONSTRAINT_TYPE_KINEMATIC) { + if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) { bKinematicConstraint *data = (bKinematicConstraint*)con->data; int segcount= 0; @@ -2573,3 +2573,4 @@ int draw_armature(Base *base, int dt, int flag) /* *************** END Armature drawing ******************* */ + diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index 19fb8dc2ecd..0f624d979d5 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -213,6 +213,8 @@ int pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan) bConstraint *con; Bone *bone; + /* No need to check if constraint is active (has influence), + * since all constraints with CONSTRAINT_IK_AUTO are active */ for(con= pchan->constraints.first; con; con= con->next) { if(con->type==CONSTRAINT_TYPE_KINEMATIC) { bKinematicConstraint *data= con->data; @@ -1733,3 +1735,4 @@ void pose_flipquats(void) autokeyframe_pose_cb_func(ob, TFM_ROTATION, 0); } + diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 7a2ca3f088b..70dcb58b87c 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -397,7 +397,7 @@ static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan) bConstraint *con= pchan->constraints.first; for(;con; con= con->next) { - if(con->type==CONSTRAINT_TYPE_KINEMATIC) { + if(con->type==CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) { bKinematicConstraint *data= con->data; if(data->tar==NULL) @@ -505,12 +505,17 @@ static short apply_targetless_ik(Object *ob) Mat3ToQuat(rmat3, parchan->quat); /* for size, remove rotation */ - QuatToMat3(parchan->quat, qmat); - Mat3Inv(imat, qmat); - Mat3MulMat3(smat, rmat3, imat); - Mat3ToSize(smat, parchan->size); + /* causes problems with some constraints (so apply only if needed) */ + if (data->flag & CONSTRAINT_IK_STRETCH) { + QuatToMat3(parchan->quat, qmat); + Mat3Inv(imat, qmat); + Mat3MulMat3(smat, rmat3, imat); + Mat3ToSize(smat, parchan->size); + } - VECCOPY(parchan->loc, rmat[3]); + /* causes problems with some constraints (e.g. childof), so disable this */ + /* as it is IK shouldn't affect location directly */ + /* VECCOPY(parchan->loc, rmat[3]); */ } } @@ -711,7 +716,7 @@ static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen) /* check if pchan has ik-constraint */ for (con= pchan->constraints.first; con; con= con->next) { - if (con->type == CONSTRAINT_TYPE_KINEMATIC) { + if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) { bKinematicConstraint *data= con->data; /* only accept if a temporary one (for auto-ik) */ @@ -763,6 +768,7 @@ static void pose_grab_with_ik_clear(Object *ob) /* clear all temporary lock flags */ pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP); + pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* remove all temporary IK-constraints added */ for (con= pchan->constraints.first; con; con= con->next) { if (con->type==CONSTRAINT_TYPE_KINEMATIC) { @@ -771,9 +777,11 @@ static void pose_grab_with_ik_clear(Object *ob) BLI_remlink(&pchan->constraints, con); MEM_freeN(con->data); MEM_freeN(con); - pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET); - break; + continue; } + pchan->constflag |= PCHAN_HAS_IK; + if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0)) + pchan->constflag |= PCHAN_HAS_TARGET; } } } @@ -784,6 +792,7 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan) { bKinematicConstraint *data; bConstraint *con; + bConstraint *targetless = 0; /* Sanity check */ if (pchan == NULL) @@ -791,23 +800,31 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan) /* Rule: not if there's already an IK on this channel */ for (con= pchan->constraints.first; con; con= con->next) { - if (con->type==CONSTRAINT_TYPE_KINEMATIC) - break; - } - - if (con) { - /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */ - data= has_targetless_ik(pchan); - if (data) - data->flag |= CONSTRAINT_IK_AUTO; - return 0; + if (con->type==CONSTRAINT_TYPE_KINEMATIC) { + bKinematicConstraint *data= con->data; + if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0)) { + targetless = con; + /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */ + if (con->enforce!=0.0) { + targetless->flag |= CONSTRAINT_IK_AUTO; + return 0; + } + } + if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0)) + return 0; + } } con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC); BLI_addtail(&pchan->constraints, con); pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */ data= con->data; - data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO; + if (targetless) { /* if exists use values from last targetless IK-constraint as base */ + *data = *((bKinematicConstraint*)targetless->data); + } + else + data->flag= CONSTRAINT_IK_TIP; + data->flag |= CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO; VECCOPY(data->grabtarget, pchan->pose_tail); data->rootbone= 1; @@ -4279,3 +4296,4 @@ void createTransData(TransInfo *t) +