diff --git a/source/blender/blenkernel/intern/action.cc b/source/blender/blenkernel/intern/action.cc index c9003bf9fb1..51612a17572 100644 --- a/source/blender/blenkernel/intern/action.cc +++ b/source/blender/blenkernel/intern/action.cc @@ -1187,11 +1187,12 @@ void BKE_pose_update_constraint_flags(bPose *pose) pchan->constflag |= PCHAN_HAS_NO_TARGET; } + bPoseChannel *chain_tip = (data->flag & CONSTRAINT_IK_TIP) ? pchan : pchan->parent; + /* negative rootbone = recalc rootbone index. used in do_versions */ if (data->rootbone < 0) { data->rootbone = 0; - bPoseChannel *chain_tip = (data->flag & CONSTRAINT_IK_TIP) ? pchan : pchan->parent; bPoseChannel *parchan = chain_tip; while (parchan) { data->rootbone++; @@ -1201,6 +1202,16 @@ void BKE_pose_update_constraint_flags(bPose *pose) parchan = parchan->parent; } } + + /* Mark the pose bones in the IK chain as influenced by it. */ + { + bPoseChannel *chain_bone = chain_tip; + for (short index = 0; chain_bone && (data->rootbone == 0 || index < data->rootbone); + index++) { + chain_bone->constflag |= PCHAN_INFLUENCED_BY_IK; + chain_bone = chain_bone->parent; + } + } break; } diff --git a/source/blender/blenkernel/intern/armature_update.cc b/source/blender/blenkernel/intern/armature_update.cc index 161f6907ce5..29e3595d431 100644 --- a/source/blender/blenkernel/intern/armature_update.cc +++ b/source/blender/blenkernel/intern/armature_update.cc @@ -942,6 +942,7 @@ static void pose_channel_flush_to_orig_if_needed(Depsgraph *depsgraph, copy_v3_v3(pchan_orig->pose_head, pchan->pose_mat[3]); copy_m4_m4(pchan_orig->constinv, pchan->constinv); copy_v3_v3(pchan_orig->pose_tail, pchan->pose_tail); + pchan_orig->constflag = pchan->constflag; } void BKE_pose_bone_done(Depsgraph *depsgraph, Object *object, int pchan_index) diff --git a/source/blender/draw/engines/overlay/overlay_armature.cc b/source/blender/draw/engines/overlay/overlay_armature.cc index 176a655adfe..0e03c6eb769 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.cc +++ b/source/blender/draw/engines/overlay/overlay_armature.cc @@ -1201,7 +1201,11 @@ static void get_pchan_color_constraint(const ThemeWireColor *bcolor, float r_color[4]) { const ePchan_ConstFlag constflag = bone.constflag(); - if (constflag == 0 || (bcolor && (bcolor->flag & TH_WIRECOLOR_CONSTCOLS) == 0)) { + /* Not all flags should result in a different bone color. */ + const ePchan_ConstFlag flags_to_color = PCHAN_HAS_NO_TARGET | PCHAN_HAS_IK | PCHAN_HAS_SPLINEIK | + PCHAN_HAS_CONST; + if ((constflag & flags_to_color) == 0 || + (bcolor && (bcolor->flag & TH_WIRECOLOR_CONSTCOLS) == 0)) { get_pchan_color_solid(bcolor, r_color); return; } diff --git a/source/blender/editors/animation/keyframing.cc b/source/blender/editors/animation/keyframing.cc index aa15c73dec0..f362e03162e 100644 --- a/source/blender/editors/animation/keyframing.cc +++ b/source/blender/editors/animation/keyframing.cc @@ -887,6 +887,13 @@ static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop) /* Pose Channel */ bPoseChannel *pchan = static_cast(ptr->data); + if (pchan->constflag & (PCHAN_HAS_IK | PCHAN_INFLUENCED_BY_IK)) { + /* Spline IK cannot generally be keyed visually, because (at least with the default + * constraint settings) it requires non-uniform scaling that causes shearing in child bones, + * which cannot be represented by the bone's loc/rot/scale properties. */ + return true; + } + con = static_cast(pchan->constraints.first); has_parent = (pchan->parent != nullptr); } diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 0cf5cb5846b..7de6c3bfd71 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -395,7 +395,9 @@ typedef enum ePchan_ConstFlag { PCHAN_HAS_NO_TARGET = (1 << 3), /* Has (spline) IK constraint but no target is set. */ /* PCHAN_HAS_STRIDE = (1 << 4), */ /* UNUSED */ PCHAN_HAS_SPLINEIK = (1 << 5), /* Has Spline IK constraint. */ + PCHAN_INFLUENCED_BY_IK = (1 << 6), /* Is part of a (non-spline) IK chain. */ } ePchan_ConstFlag; +ENUM_OPERATORS(ePchan_ConstFlag, PCHAN_INFLUENCED_BY_IK); /* PoseChannel->ikflag */ typedef enum ePchan_IkFlag {