Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2007-10-24 18:58:31 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2007-10-24 18:58:31 +0400
commit30be716fc8e0ada286a94a53bf64dc5d16402c24 (patch)
tree6d5bbd71a1eea495afabfe7b93e8556b50dbab58 /source
parent79224961836db454b454f20479a76b83e3eed3bc (diff)
Pole Target for IK
================== This adds an extra target to the IK solver constraint to define the roll of the IK chain. http://www.blender.org/development/current-projects/changes-since-244/inverse-kinematics/ Also fixes a crashes using ctrl+I to set an IK constraint on a bone due to the recent constraints refactor.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_constraint.h3
-rw-r--r--source/blender/blenkernel/intern/armature.c43
-rw-r--r--source/blender/blenkernel/intern/constraint.c90
-rw-r--r--source/blender/blenloader/intern/readfile.c2
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h7
-rw-r--r--source/blender/src/buttons_object.c107
-rw-r--r--source/blender/src/editconstraint.c20
-rw-r--r--source/blender/src/editobject.c2
8 files changed, 187 insertions, 87 deletions
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 40fd8c5ed18..aa8e9cf18f8 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -126,14 +126,13 @@ void copy_constraint_channels(struct ListBase *dst, struct ListBase *src);
void clone_constraint_channels(struct ListBase *dst, struct ListBase *src);
void free_constraint_channels(struct ListBase *chanbase);
-
/* Constraint Evaluation function prototypes */
struct bConstraintOb *constraints_make_evalob(struct Object *ob, void *subdata, short datatype);
void constraints_clear_evalob(struct bConstraintOb *cob);
void constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, float mat[][4], short from, short to);
-void get_constraint_target_matrix(struct bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float ctime);
+void get_constraint_target_matrix(struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[][4], float ctime);
void solve_constraints(struct ListBase *conlist, struct bConstraintOb *cob, float ctime);
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 09a7b2a8dcc..38a6a05017c 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -1512,7 +1512,7 @@ static void execute_posetree(Object *ob, PoseTree *tree)
IK_Segment *seg, *parent, **iktree, *iktarget;
IK_Solver *solver;
PoseTarget *target;
- bKinematicConstraint *data;
+ bKinematicConstraint *data, *poleangledata=NULL;
Bone *bone;
if (tree->totchannel == 0)
@@ -1624,12 +1624,15 @@ static void execute_posetree(Object *ob, PoseTree *tree)
Mat4Invert (goalinv, imat);
for (target=tree->targets.first; target; target=target->next) {
+ float polepos[3];
+ int poleconstrain= 0;
+
data= (bKinematicConstraint*)target->con->data;
/* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though
* strictly speaking, it is a posechannel)
*/
- get_constraint_target_matrix(target->con, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
+ get_constraint_target_matrix(target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
/* and set and transform goal */
Mat4MulMat4(goal, rootmat, goalinv);
@@ -1637,6 +1640,26 @@ static void execute_posetree(Object *ob, PoseTree *tree)
VECCOPY(goalpos, goal[3]);
Mat3CpyMat4(goalrot, goal);
+ /* same for pole vector target */
+ if(data->poletar) {
+ get_constraint_target_matrix(target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
+
+ if(data->flag & CONSTRAINT_IK_SETANGLE) {
+ /* don't solve IK when we are setting the pole angle */
+ break;
+ }
+ else {
+ Mat4MulMat4(goal, rootmat, goalinv);
+ VECCOPY(polepos, goal[3]);
+ poleconstrain= 1;
+
+ if(data->flag & CONSTRAINT_IK_GETANGLE) {
+ poleangledata= data;
+ data->flag &= ~CONSTRAINT_IK_GETANGLE;
+ }
+ }
+ }
+
/* do we need blending? */
if (target->con->enforce!=1.0) {
float q1[4], q2[4], q[4];
@@ -1664,14 +1687,24 @@ static void execute_posetree(Object *ob, PoseTree *tree)
iktarget= iktree[target->tip];
- if(data->weight != 0.0)
+ if(data->weight != 0.0) {
+ if(poleconstrain)
+ IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos,
+ polepos, data->poleangle*M_PI/180, (poleangledata == data));
IK_SolverAddGoal(solver, iktarget, goalpos, data->weight);
- if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0) && (data->flag & CONSTRAINT_IK_AUTO)==0)
- IK_SolverAddGoalOrientation(solver, iktarget, goalrot, data->orientweight);
+ }
+ if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0))
+ if((data->flag & CONSTRAINT_IK_AUTO)==0)
+ IK_SolverAddGoalOrientation(solver, iktarget, goalrot,
+ data->orientweight);
}
/* solve */
IK_Solve(solver, 0.0f, tree->iterations);
+
+ if(poleangledata)
+ poleangledata->poleangle= IK_SolverGetPoleAngle(solver)*180/M_PI;
+
IK_FreeSolver(solver);
/* gather basis changes */
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 9dce9c3a611..a8305a7dec1 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -804,12 +804,12 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain
* (Hopefully all compilers will be happy with the lines with just a space on them. Those are
* really just to help this code easier to read)
*/
-#define SINGLETARGET_GET_TARS(con, data, ct, list) \
+#define SINGLETARGET_GET_TARS(con, datatar, datasubtarget, ct, list) \
{ \
ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \
\
- ct->tar= data->tar; \
- strcpy(ct->subtarget, data->subtarget); \
+ ct->tar= datatar; \
+ strcpy(ct->subtarget, datasubtarget); \
ct->space= con->tarspace; \
ct->flag= CONSTRAINT_TAR_TEMP; \
\
@@ -827,11 +827,11 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain
* (Hopefully all compilers will be happy with the lines with just a space on them. Those are
* really just to help this code easier to read)
*/
-#define SINGLETARGETNS_GET_TARS(con, data, ct, list) \
+#define SINGLETARGETNS_GET_TARS(con, datatar, ct, list) \
{ \
ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \
\
- ct->tar= data->tar; \
+ ct->tar= datatar; \
ct->space= con->tarspace; \
ct->flag= CONSTRAINT_TAR_TEMP; \
\
@@ -845,16 +845,16 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain
* (Hopefully all compilers will be happy with the lines with just a space on them. Those are
* really just to help this code easier to read)
*/
-#define SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy) \
+#define SINGLETARGET_FLUSH_TARS(con, datatar, datasubtarget, ct, list, nocopy) \
{ \
if (ct) { \
if (nocopy == 0) { \
- data->tar= ct->tar; \
- strcpy(data->subtarget, ct->subtarget); \
+ datatar= ct->tar; \
+ strcpy(datasubtarget, ct->subtarget); \
con->tarspace= ct->space; \
} \
\
- BLI_freelistN(list); \
+ BLI_freelinkN(list, ct); \
} \
}
@@ -863,15 +863,15 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain
* (Hopefully all compilers will be happy with the lines with just a space on them. Those are
* really just to help this code easier to read)
*/
-#define SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy) \
+#define SINGLETARGETNS_FLUSH_TARS(con, datatar, ct, list, nocopy) \
{ \
if (ct) { \
if (nocopy == 0) { \
- data->tar= ct->tar; \
+ datatar= ct->tar; \
con->tarspace= ct->space; \
} \
\
- BLI_freelistN(list); \
+ BLI_freelinkN(list, ct); \
} \
}
@@ -894,7 +894,7 @@ static void childof_get_tars (bConstraint *con, ListBase *list)
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints */
- SINGLETARGET_GET_TARS(con, data, ct, list)
+ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
}
}
@@ -905,7 +905,7 @@ static void childof_flush_tars (bConstraint *con, ListBase *list, short nocopy)
bConstraintTarget *ct= list->first;
/* the following macro is used for all standard single-target constraints */
- SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
}
}
@@ -992,7 +992,7 @@ static void trackto_get_tars (bConstraint *con, ListBase *list)
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints */
- SINGLETARGET_GET_TARS(con, data, ct, list)
+ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
}
}
@@ -1003,7 +1003,7 @@ static void trackto_flush_tars (bConstraint *con, ListBase *list, short nocopy)
bConstraintTarget *ct= list->first;
/* the following macro is used for all standard single-target constraints */
- SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
}
}
@@ -1169,7 +1169,8 @@ static void kinematic_get_tars (bConstraint *con, ListBase *list)
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints */
- SINGLETARGET_GET_TARS(con, data, ct, list)
+ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
+ SINGLETARGET_GET_TARS(con, data->poletar, data->polesubtarget, ct, list)
}
}
@@ -1180,7 +1181,9 @@ static void kinematic_flush_tars (bConstraint *con, ListBase *list, short nocopy
bConstraintTarget *ct= list->first;
/* the following macro is used for all standard single-target constraints */
- SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
+ ct= ct->next;
+ SINGLETARGET_FLUSH_TARS(con, data->poletar, data->polesubtarget, ct, list, nocopy)
}
}
@@ -1245,7 +1248,7 @@ static void followpath_get_tars (bConstraint *con, ListBase *list)
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints without subtargets */
- SINGLETARGETNS_GET_TARS(con, data, ct, list)
+ SINGLETARGETNS_GET_TARS(con, data->tar, ct, list)
}
}
@@ -1256,7 +1259,7 @@ static void followpath_flush_tars (bConstraint *con, ListBase *list, short nocop
bConstraintTarget *ct= list->first;
/* the following macro is used for all standard single-target constraints */
- SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy)
+ SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, nocopy)
}
}
@@ -1283,7 +1286,7 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
if (cu->path && cu->path->data) {
curvetime= bsystem_time(ct->tar, (float)ctime, 0.0) - data->offset;
-
+
if (calc_ipo_spec(cu->ipo, CU_SPEED, &curvetime)==0) {
curvetime /= cu->pathlen;
CLAMP(curvetime, 0.0, 1.0);
@@ -1546,7 +1549,7 @@ static void loclike_get_tars (bConstraint *con, ListBase *list)
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints */
- SINGLETARGET_GET_TARS(con, data, ct, list)
+ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
}
}
@@ -1557,7 +1560,7 @@ static void loclike_flush_tars (bConstraint *con, ListBase *list, short nocopy)
bConstraintTarget *ct= list->first;
/* the following macro is used for all standard single-target constraints */
- SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
}
}
@@ -1661,7 +1664,7 @@ static void rotlike_get_tars (bConstraint *con, ListBase *list)
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints */
- SINGLETARGET_GET_TARS(con, data, ct, list)
+ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
}
}
@@ -1672,7 +1675,7 @@ static void rotlike_flush_tars (bConstraint *con, ListBase *list, short nocopy)
bConstraintTarget *ct= list->first;
/* the following macro is used for all standard single-target constraints */
- SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
}
}
@@ -1749,7 +1752,7 @@ static void sizelike_get_tars (bConstraint *con, ListBase *list)
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints */
- SINGLETARGET_GET_TARS(con, data, ct, list)
+ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
}
}
@@ -1760,7 +1763,7 @@ static void sizelike_flush_tars (bConstraint *con, ListBase *list, short nocopy)
bConstraintTarget *ct= list->first;
/* the following macro is used for all standard single-target constraints */
- SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
}
}
@@ -1928,7 +1931,7 @@ static void actcon_get_tars (bConstraint *con, ListBase *list)
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints */
- SINGLETARGET_GET_TARS(con, data, ct, list)
+ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
}
}
@@ -1939,7 +1942,7 @@ static void actcon_flush_tars (bConstraint *con, ListBase *list, short nocopy)
bConstraintTarget *ct= list->first;
/* the following macro is used for all standard single-target constraints */
- SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
}
}
@@ -2068,7 +2071,7 @@ static void locktrack_get_tars (bConstraint *con, ListBase *list)
bConstraintTarget *ct;
/* the following macro is used for all standard single-target constraints */
- SINGLETARGET_GET_TARS(con, data, ct, list)
+ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
}
}
@@ -2079,7 +2082,7 @@ static void locktrack_flush_tars (bConstraint *con, ListBase *list, short nocopy
bConstraintTarget *ct= list->first;
/* the following macro is used for all standard single-target constraints */
- SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
}
}
@@ -2419,7 +2422,7 @@ static void stretchto_get_tars (bConstraint *con, ListBase *list)
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints */
- SINGLETARGET_GET_TARS(con, data, ct, list)
+ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
}
}
@@ -2430,7 +2433,7 @@ static void stretchto_flush_tars (bConstraint *con, ListBase *list, short nocopy
bConstraintTarget *ct= list->first;
/* the following macro is used for all standard single-target constraints */
- SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
}
}
@@ -2595,7 +2598,7 @@ static void minmax_get_tars (bConstraint *con, ListBase *list)
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints */
- SINGLETARGET_GET_TARS(con, data, ct, list)
+ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
}
}
@@ -2606,7 +2609,7 @@ static void minmax_flush_tars (bConstraint *con, ListBase *list, short nocopy)
bConstraintTarget *ct= list->first;
/* the following macro is used for all standard single-target constraints */
- SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
}
}
@@ -2725,7 +2728,7 @@ static void rbj_get_tars (bConstraint *con, ListBase *list)
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints without subtargets */
- SINGLETARGETNS_GET_TARS(con, data, ct, list)
+ SINGLETARGETNS_GET_TARS(con, data->tar, ct, list)
}
}
@@ -2736,7 +2739,7 @@ static void rbj_flush_tars (bConstraint *con, ListBase *list, short nocopy)
bConstraintTarget *ct= list->first;
/* the following macro is used for all standard single-target constraints */
- SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy)
+ SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, nocopy)
}
}
@@ -2764,7 +2767,7 @@ static void clampto_get_tars (bConstraint *con, ListBase *list)
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints without subtargets */
- SINGLETARGETNS_GET_TARS(con, data, ct, list)
+ SINGLETARGETNS_GET_TARS(con, data->tar, ct, list)
}
}
@@ -2775,7 +2778,7 @@ static void clampto_flush_tars (bConstraint *con, ListBase *list, short nocopy)
bConstraintTarget *ct= list->first;
/* the following macro is used for all standard single-target constraints */
- SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy)
+ SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, nocopy)
}
}
@@ -2937,7 +2940,7 @@ static void transform_get_tars (bConstraint *con, ListBase *list)
bConstraintTarget *ct;
/* standard target-getting macro for single-target constraints */
- SINGLETARGET_GET_TARS(con, data, ct, list)
+ SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list)
}
}
@@ -2948,7 +2951,7 @@ static void transform_flush_tars (bConstraint *con, ListBase *list, short nocopy
bConstraintTarget *ct= list->first;
/* the following macro is used for all standard single-target constraints */
- SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy)
}
}
@@ -3225,7 +3228,7 @@ void copy_constraints (ListBase *dst, ListBase *src)
* None of the actual calculations of the matricies should be done here! Also, this function is
* not to be used by any new constraints, particularly any that have multiple targets.
*/
-void get_constraint_target_matrix (bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float ctime)
+void get_constraint_target_matrix (bConstraint *con, int n, short ownertype, void *ownerdata, float mat[][4], float ctime)
{
bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
ListBase targets = {NULL, NULL};
@@ -3272,6 +3275,9 @@ void get_constraint_target_matrix (bConstraint *con, short ownertype, void *owne
/* only calculate the target matrix on the first target */
ct= (bConstraintTarget *)targets.first;
+ while(ct && n-- > 0)
+ ct= ct->next;
+
if (ct) {
if (cti->get_target_matrix)
cti->get_target_matrix(con, cob, ct, ctime);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index e1d538a54da..2293fbef0b5 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1664,6 +1664,7 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
bKinematicConstraint *data;
data = ((bKinematicConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
+ data->poletar = newlibadr(fd, id->lib, data->poletar);
}
break;
case CONSTRAINT_TYPE_TRACKTO:
@@ -7289,6 +7290,7 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
{
bKinematicConstraint *data = (bKinematicConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
+ expand_doit(fd, mainvar, data->poletar);
}
break;
case CONSTRAINT_TYPE_TRACKTO:
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index e06063a11a1..431ef56e1c4 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -125,10 +125,13 @@ typedef struct bKinematicConstraint {
int rootbone; /* index to rootbone, if zero go all the way to mother bone */
char subtarget[32]; /* String to specify sub-object target */
+ Object *poletar; /* Pole vector target */
+ char polesubtarget[32]; /* Pole vector sub-object target */
+ float poleangle; /* Pole vector rest angle */
+
float weight; /* Weight of goal in IK tree */
float orientweight; /* Amount of rotation a target applies on chain */
float grabtarget[3]; /* for target-less IK */
- int pad;
} bKinematicConstraint;
/* Track To Constraint */
@@ -439,6 +442,8 @@ typedef enum B_CONSTRAINTCHANNEL_FLAG {
#define CONSTRAINT_IK_TEMP 8
#define CONSTRAINT_IK_STRETCH 16
#define CONSTRAINT_IK_POS 32
+#define CONSTRAINT_IK_SETANGLE 64
+#define CONSTRAINT_IK_GETANGLE 128
/* MinMax (floor) flags */
#define MINMAX_STICKY 0x01
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index 94a40a7ebb6..35db9294af1 100644
--- a/source/blender/src/buttons_object.c
+++ b/source/blender/src/buttons_object.c
@@ -410,6 +410,24 @@ void autocomplete_vgroup(char *str, void *arg_v)
}
}
+/* pole angle callback */
+void con_kinematic_set_pole_angle(void *ob_v, void *con_v)
+{
+ bConstraint *con= con_v;
+ bKinematicConstraint *data = con->data;
+
+ if(data->poletar) {
+ if(data->flag & CONSTRAINT_IK_SETANGLE) {
+ data->flag |= CONSTRAINT_IK_GETANGLE;
+ data->flag &= ~CONSTRAINT_IK_SETANGLE;
+ }
+ else {
+ data->flag &= ~CONSTRAINT_IK_GETANGLE;
+ data->flag |= CONSTRAINT_IK_SETANGLE;
+ }
+ }
+}
+
/* some commonly used macros in the constraints drawing code */
#define is_armature_target(target) (target && target->type==OB_ARMATURE)
#define is_armature_owner(ob) ((ob->type == OB_ARMATURE) && (ob->flag & OB_POSEMODE))
@@ -878,47 +896,76 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
{
bKinematicConstraint *data = con->data;
- height = 111;
+ height = 146;
+ if(data->poletar)
+ height += 30;
+
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, "");
+ /* IK Target */
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco, *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, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 19, &data->tar, "Target Object");
-
- if (is_armature_target(data->tar)) {
- but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,19, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
- uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar);
- }
- else if (is_geom_target(data->tar)) {
- but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
- uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
- }
- else {
- strcpy(data->subtarget, "");
- }
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco, *yco-44, 137, 19, &data->tar, "Target Object");
+
+ if (is_armature_target(data->tar)) {
+ but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco, *yco-62,137,19, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
+ uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar);
+ }
+ else if (is_geom_target(data->tar)) {
+ but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco, *yco-62,137,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
+ }
+ else {
+ strcpy (data->subtarget, "");
+ }
+
uiBlockEndAlign(block);
-
+
+ /* Settings */
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, CONSTRAINT_IK_TIP, B_CONSTRAINT_TEST, "Use Tail", *xco, *yco-64, 137, 19, &data->flag, 0, 0, 0, 0, "Include Bone's tail as last element in Chain");
- uiDefButI(block, NUM, B_CONSTRAINT_TEST, "ChainLen:", *xco, *yco-84,137,19, &data->rootbone, 0, 255, 0, 0, "If not zero, the amount of bones in this chain");
- uiBlockEndAlign(block);
-
+ uiDefButBitS(block, TOG, CONSTRAINT_IK_TIP, B_CONSTRAINT_TEST, "Use Tail", *xco, *yco-92, 137, 19, &data->flag, 0, 0, 0, 0, "Include Bone's tail als last element in Chain");
+ uiDefButI(block, NUM, B_CONSTRAINT_TEST, "ChainLen:", *xco, *yco-112,137,19, &data->rootbone, 0, 255, 0, 0, "If not zero, the amount of bones in this chain");
+
uiBlockBeginAlign(block);
- uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "PosW ", *xco+147, *yco-64, 137, 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+147, *yco-84, 137, 19, &data->orientweight, 0.01, 1.0, 2, 2, "For Tree-IK: Weight of orientation control for this target");
- uiBlockEndAlign(block);
-
+ uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "PosW ", *xco+147, *yco-92, 137, 19, &data->weight, 0.01, 1.0, 2, 2, "For Tree-IK: weight of position control for this target");
+ uiDefButBitS(block, TOG, CONSTRAINT_IK_ROT, B_CONSTRAINT_TEST, "Rot", *xco+147, *yco-112, 40,19, &data->flag, 0, 0, 0, 0, "Chain follows rotation of target");
+ uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "W ", *xco+187, *yco-112, 97, 19, &data->orientweight, 0.01, 1.0, 2, 2, "For Tree-IK: Weight of orientation control for this target");
+
uiBlockBeginAlign(block);
- uiDefButS(block, NUM, B_CONSTRAINT_TEST, "Iterations:", *xco, *yco-109, 137, 19, &data->iterations, 1, 10000, 0, 0, "Maximum number of solving iterations");
- uiBlockEndAlign(block);
-
+
+ uiDefButBitS(block, TOG, CONSTRAINT_IK_STRETCH, B_CONSTRAINT_TEST, "Stretch", *xco, *yco-137,137,19, &data->flag, 0, 0, 0, 0, "Enable IK stretching");
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, CONSTRAINT_IK_STRETCH, B_CONSTRAINT_TEST, "Stretch", *xco+147, *yco-109,137,19, &data->flag, 0, 0, 0, 0, "Enable IK stretching");
+ uiDefButS(block, NUM, B_CONSTRAINT_TEST, "Iterations:", *xco+147, *yco-137, 137, 19, &data->iterations, 1, 10000, 0, 0, "Maximum number of solving iterations");
uiBlockEndAlign(block);
+
+ /* Pole Vector */
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Pole Target:", *xco+147, *yco-24, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+
+ uiBlockBeginAlign(block);
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+147, *yco-44, 137, 19, &data->poletar, "Pole Target Object");
+ if (is_armature_target(data->poletar)) {
+ but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+147, *yco-62,137,19, &data->polesubtarget, 0, 24, 0, 0, "Pole Subtarget Bone");
+ uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->poletar);
+ }
+ else if (is_geom_target(data->poletar)) {
+ but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+147, *yco-62,137,18, &data->polesubtarget, 0, 24, 0, 0, "Name of Vertex Group defining pole 'target' points");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->poletar);
+ }
+ else {
+ strcpy (data->polesubtarget, "");
+ }
+
+ if(data->poletar) {
+ uiBlockBeginAlign(block);
+#if 0
+ but = uiDefBut(block, BUT, B_CONSTRAINT_TEST, (data->flag & CONSTRAINT_IK_SETANGLE)? "Set Pole Offset": "Clear Pole Offset", *xco, *yco-167, 137, 19, 0, 0.0, 1.0, 0.0, 0.0, "Set the pole rotation offset from the current pose");
+ uiButSetFunc(but, con_kinematic_set_pole_angle, ob, con);
+ if(!(data->flag & CONSTRAINT_IK_SETANGLE))
+#endif
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Pole Offset ", *xco, *yco-167, 137, 19, &data->poleangle, -180.0, 180.0, 0, 0, "Pole rotation offset");
+ }
}
break;
case CONSTRAINT_TYPE_TRACKTO:
diff --git a/source/blender/src/editconstraint.c b/source/blender/src/editconstraint.c
index 0360c4add18..e0588b4c2a0 100644
--- a/source/blender/src/editconstraint.c
+++ b/source/blender/src/editconstraint.c
@@ -417,18 +417,26 @@ static void test_constraints (Object *owner, const char substring[])
case CONSTRAINT_TYPE_KINEMATIC:
{
bKinematicConstraint *data = curcon->data;
+
if (!exist_object(data->tar)) {
data->tar = NULL;
curcon->flag |= CONSTRAINT_DISABLE;
- break;
}
-
- if ( (data->tar == owner) &&
+ else if ( (data->tar == owner) &&
(!get_named_bone(get_armature(owner),
data->subtarget))) {
curcon->flag |= CONSTRAINT_DISABLE;
- break;
}
+
+ if (data->poletar && !exist_object(data->poletar)) {
+ data->poletar = NULL;
+ }
+ else if ( (data->poletar == owner) &&
+ (!get_named_bone(get_armature(owner),
+ data->polesubtarget))) {
+ curcon->flag |= CONSTRAINT_DISABLE;
+ }
+
}
break;
case CONSTRAINT_TYPE_TRACKTO:
@@ -816,7 +824,7 @@ void add_constraint(int only_IK)
set_constraint_nth_target(con, ob, pchansel->name, 0);
}
else if(obsel) {
- set_constraint_nth_target(con, obsel, NULL, 0);
+ set_constraint_nth_target(con, obsel, "", 0);
}
else if (ELEM4(nr, 11, 13, 14, 15)==0) { /* add new empty as target */
Base *base= BASACT, *newbase;
@@ -838,7 +846,7 @@ void add_constraint(int only_IK)
else
VECCOPY(obt->loc, ob->obmat[3]);
- set_constraint_nth_target(con, obt, NULL, 0);
+ set_constraint_nth_target(con, obt, "", 0);
/* restore, add_object sets active */
BASACT= base;
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index 1c9cf15bc7e..997593b30b1 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -1416,7 +1416,7 @@ void make_parent(void)
add_constraint_to_object(con, base->object);
- get_constraint_target_matrix(con, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, G.scene->r.cfra - base->object->sf);
+ get_constraint_target_matrix(con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, G.scene->r.cfra - base->object->sf);
VecSubf(vec, base->object->obmat[3], cmat[3]);
base->object->loc[0] = vec[0];