diff --git a/release/scripts/ui/buttons_object_constraint.py b/release/scripts/ui/buttons_object_constraint.py index 6be166e8af0..63fe27f2e4b 100644 --- a/release/scripts/ui/buttons_object_constraint.py +++ b/release/scripts/ui/buttons_object_constraint.py @@ -50,6 +50,7 @@ class ConstraintButtonsPanel(bpy.types.Panel): layout.item_pointerR(con, "subtarget", con.target, "vertex_groups", text="Vertex Group") def ik_template(self, layout, con): + # only used for iTaSC layout.itemR(con, "pole_target") if con.pole_target and con.pole_target.type == 'ARMATURE': @@ -60,14 +61,14 @@ class ConstraintButtonsPanel(bpy.types.Panel): row.itemL() row.itemR(con, "pole_angle") - split = layout.split() + split = layout.split(percentage=0.33) col = split.column() col.itemR(con, "tail") col.itemR(con, "stretch") col = split.column() - col.itemR(con, "iterations") col.itemR(con, "chain_length") + col.itemR(con, "targetless") def CHILD_OF(self, context, layout, con): self.target_template(layout, con) @@ -115,24 +116,74 @@ class ConstraintButtonsPanel(bpy.types.Panel): layout.itemR(con, "ik_type") getattr(self, "IK_"+con.ik_type)(context, layout, con) else: - self.IK_COPY_POSE(context, layout, con) + # Legacy IK constraint + self.target_template(layout, con) + layout.itemR(con, "pole_target") + + if con.pole_target and con.pole_target.type == 'ARMATURE': + layout.item_pointerR(con, "pole_subtarget", con.pole_target.data, "bones", text="Bone") + + if con.pole_target: + row = layout.row() + row.itemL() + row.itemR(con, "pole_angle") + + split = layout.split() + col = split.column() + col.itemR(con, "tail") + col.itemR(con, "stretch") + + col = split.column() + col.itemR(con, "iterations") + col.itemR(con, "chain_length") + + split = layout.split() + col = split.column() + col.itemL() + col.itemR(con, "targetless") + col.itemR(con, "rotation") + + col = split.column() + col.itemL(text="Weight:") + col.itemR(con, "weight", text="Position", slider=True) + sub = col.column() + sub.active = con.rotation + sub.itemR(con, "orient_weight", text="Rotation", slider=True) def IK_COPY_POSE(self, context, layout, con): self.target_template(layout, con) self.ik_template(layout, con) - - split = layout.split() - col = split.column() - col.itemL() - col.itemR(con, "targetless") - col.itemR(con, "rotation") - - col = split.column() - col.itemL(text="Weight:") - col.itemR(con, "weight", text="Position", slider=True) - sub = col.column() - sub.active = con.rotation - sub.itemR(con, "orient_weight", text="Rotation", slider=True) + + row = layout.row() + row.itemL(text="Axis Ref:") + row.itemR(con, "axis_reference", expand=True) + split = layout.split(percentage=0.33) + split.row().itemR(con, "position") + row = split.row() + row.itemR(con, "weight", text="Weight", slider=True) + row.active = con.position + split = layout.split(percentage=0.33) + row = split.row() + row.itemL(text="Lock:") + row = split.row() + row.itemR(con, "pos_lock_x", text="X") + row.itemR(con, "pos_lock_y", text="Y") + row.itemR(con, "pos_lock_z", text="Z") + split.active = con.position + + split = layout.split(percentage=0.33) + split.row().itemR(con, "rotation") + row = split.row() + row.itemR(con, "orient_weight", text="Weight", slider=True) + row.active = con.rotation + split = layout.split(percentage=0.33) + row = split.row() + row.itemL(text="Lock:") + row = split.row() + row.itemR(con, "rot_lock_x", text="X") + row.itemR(con, "rot_lock_y", text="Y") + row.itemR(con, "rot_lock_z", text="Z") + split.active = con.rotation def IK_DISTANCE(self, context, layout, con): self.target_template(layout, con) @@ -610,20 +661,13 @@ class BONE_PT_inverse_kinematics(ConstraintButtonsPanel): split.itemL() if ob.pose.ik_solver == "ITASC": - layout.itemL(text="Joint constraint:") - split = layout.split(percentage=0.3) - row = split.row() - row.itemR(pchan, "ik_rot_control", text="Rotation") - row = split.row() + row = layout.row() + row.itemR(pchan, "ik_rot_control", text="Control Rotation") row.itemR(pchan, "ik_rot_weight", text="Weight", slider=True) - row.active = pchan.ik_rot_control # not supported yet - #split = layout.split(percentage=0.3) - #row = split.row() - #row.itemR(pchan, "ik_lin_control", text="Size") - #row = split.row() + #row = layout.row() + #row.itemR(pchan, "ik_lin_control", text="Joint Size") #row.itemR(pchan, "ik_lin_weight", text="Weight", slider=True) - #row.active = pchan.ik_lin_control class BONE_PT_iksolver_itasc(ConstraintButtonsPanel): __label__ = "iTaSC parameters" diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index 7f4c1967207..b6fceabdb46 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -1417,10 +1417,22 @@ static IK_Scene* convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan) switch (condata->type) { case CONSTRAINT_IK_COPYPOSE: controltype = 0; - if ((condata->flag & CONSTRAINT_IK_ROT) && (condata->orientweight != 0.0)) - controltype |= iTaSC::CopyPose::CTL_ROTATION; - if ((condata->weight != 0.0)) - controltype |= iTaSC::CopyPose::CTL_POSITION; + if (condata->flag & CONSTRAINT_IK_ROT) { + if (!(condata->flag & CONSTRAINT_IK_NO_ROT_X)) + controltype |= iTaSC::CopyPose::CTL_ROTATIONX; + if (!(condata->flag & CONSTRAINT_IK_NO_ROT_Y)) + controltype |= iTaSC::CopyPose::CTL_ROTATIONY; + if (!(condata->flag & CONSTRAINT_IK_NO_ROT_Z)) + controltype |= iTaSC::CopyPose::CTL_ROTATIONZ; + } + if (condata->flag & CONSTRAINT_IK_POS) { + if (!(condata->flag & CONSTRAINT_IK_NO_POS_X)) + controltype |= iTaSC::CopyPose::CTL_POSITIONX; + if (!(condata->flag & CONSTRAINT_IK_NO_POS_Y)) + controltype |= iTaSC::CopyPose::CTL_POSITIONY; + if (!(condata->flag & CONSTRAINT_IK_NO_POS_Z)) + controltype |= iTaSC::CopyPose::CTL_POSITIONZ; + } if (controltype) { iktarget->constraint = new iTaSC::CopyPose(controltype, controltype, bonelen); // set the gain @@ -1432,7 +1444,10 @@ static IK_Scene* convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan) iktarget->errorCallback = copypose_error; iktarget->controlType = controltype; // add the constraint - ret = scene->addConstraintSet(iktarget->constraintName, iktarget->constraint, armname, iktarget->targetName, ikscene->channels[iktarget->channel].tail); + if (condata->flag & CONSTRAINT_IK_TARGETAXIS) + ret = scene->addConstraintSet(iktarget->constraintName, iktarget->constraint, iktarget->targetName, armname, "", ikscene->channels[iktarget->channel].tail); + else + ret = scene->addConstraintSet(iktarget->constraintName, iktarget->constraint, armname, iktarget->targetName, ikscene->channels[iktarget->channel].tail); } break; case CONSTRAINT_IK_DISTANCE: diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index fccec7a556f..7232042c876 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -502,6 +502,16 @@ typedef enum B_CONSTRAINTCHANNEL_FLAG { #define CONSTRAINT_IK_POS 32 #define CONSTRAINT_IK_SETANGLE 64 #define CONSTRAINT_IK_GETANGLE 128 + /* limit axis */ +#define CONSTRAINT_IK_NO_POS_X 256 +#define CONSTRAINT_IK_NO_POS_Y 512 +#define CONSTRAINT_IK_NO_POS_Z 1024 +#define CONSTRAINT_IK_NO_ROT_X 2048 +#define CONSTRAINT_IK_NO_ROT_Y 4096 +#define CONSTRAINT_IK_NO_ROT_Z 8192 + /* axis relative to target */ +#define CONSTRAINT_IK_TARGETAXIS 16384 + /* MinMax (floor) flags */ #define MINMAX_STICKY 0x01 diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 325318ba34a..395633f5240 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -87,6 +87,12 @@ EnumPropertyItem constraint_ik_type_items[] ={ {0, NULL, 0, NULL, NULL}, }; +EnumPropertyItem constraint_ik_axisref_items[] ={ + {0, "BONE", 0, "Bone", ""}, + {CONSTRAINT_IK_TARGETAXIS, "TARGET", 0, "Target", ""}, + {0, NULL, 0, NULL, NULL}, +}; + #ifdef RNA_RUNTIME #include "BKE_action.h" @@ -497,11 +503,52 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Use Tail", "Include bone's tail as last element in chain."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); + prop= RNA_def_property(srna, "axis_reference", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, constraint_ik_axisref_items); + RNA_def_property_ui_text(prop, "Axis Reference", "Constraint axis Lock options relative to Bone or Target reference"); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); + + prop= RNA_def_property(srna, "position", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_IK_POS); + RNA_def_property_ui_text(prop, "Position", "Chain follows position of target."); + RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); + + prop= RNA_def_property(srna, "pos_lock_x", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_IK_NO_POS_X); + RNA_def_property_ui_text(prop, "Lock X Pos", "Constraint position along X axis"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Constraint_dependency_update"); + + prop= RNA_def_property(srna, "pos_lock_y", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_IK_NO_POS_Y); + RNA_def_property_ui_text(prop, "Lock Y Pos", "Constraint position along Y axis"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Constraint_dependency_update"); + + prop= RNA_def_property(srna, "pos_lock_z", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_IK_NO_POS_Z); + RNA_def_property_ui_text(prop, "Lock Z Pos", "Constraint position along Z axis"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Constraint_dependency_update"); + prop= RNA_def_property(srna, "rotation", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_IK_ROT); RNA_def_property_ui_text(prop, "Rotation", "Chain follows rotation of target."); RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update"); + prop= RNA_def_property(srna, "rot_lock_x", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_IK_NO_ROT_X); + RNA_def_property_ui_text(prop, "Lock X Rot", "Constraint rotation along X axis"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Constraint_dependency_update"); + + prop= RNA_def_property(srna, "rot_lock_y", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_IK_NO_ROT_Y); + RNA_def_property_ui_text(prop, "Lock Y Rot", "Constraint rotation along Y axis"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Constraint_dependency_update"); + + prop= RNA_def_property(srna, "rot_lock_z", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_IK_NO_ROT_Z); + RNA_def_property_ui_text(prop, "Lock Z Rot", "Constraint rotation along Z axis"); + RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Constraint_dependency_update"); + prop= RNA_def_property(srna, "targetless", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_IK_AUTO); RNA_def_property_ui_text(prop, "Targetless", "Use targetless IK.");