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
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_constraint.h53
-rw-r--r--source/blender/blenkernel/BKE_object.h1
-rw-r--r--source/blender/blenkernel/bad_level_call_stubs/stubs.c2
-rw-r--r--source/blender/blenkernel/intern/action.c8
-rw-r--r--source/blender/blenkernel/intern/armature.c272
-rw-r--r--source/blender/blenkernel/intern/constraint.c1436
-rw-r--r--source/blender/blenkernel/intern/object.c138
-rw-r--r--source/blender/blenlib/BLI_arithb.h2
-rw-r--r--source/blender/blenlib/intern/arithb.c107
-rw-r--r--source/blender/blenloader/intern/readfile.c155
-rw-r--r--source/blender/blenloader/intern/writefile.c6
-rw-r--r--source/blender/makesdna/DNA_action_types.h1
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h170
-rw-r--r--source/blender/makesdna/DNA_object_types.h3
-rw-r--r--source/blender/python/BPY_extern.h2
-rw-r--r--source/blender/python/BPY_interface.c6
-rw-r--r--source/blender/python/api2_2x/Constraint.c192
-rw-r--r--source/blender/src/buttons_object.c457
-rw-r--r--source/blender/src/drawobject.c4
-rw-r--r--source/blender/src/editconstraint.c73
-rw-r--r--source/blender/src/editobject.c6
-rwxr-xr-xsource/blender/src/transform_conversions.c46
23 files changed, 1721 insertions, 1421 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 4b9e10651cf..e175725a6ae 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -44,7 +44,7 @@ struct ListBase;
struct MemFile;
#define BLENDER_VERSION 244
-#define BLENDER_SUBVERSION 2
+#define BLENDER_SUBVERSION 3
#define BLENDER_MINVERSION 240
#define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 2bec643d5b0..6a11159645c 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -33,43 +33,66 @@
#ifndef BKE_CONSTRAINT_H
#define BKE_CONSTRAINT_H
+
struct bConstraint;
-struct Object;
struct ListBase;
+struct Object;
struct bConstraintChannel;
+struct bPoseChannel;
struct bAction;
struct bArmature;
-/* Function prototypes */
+/* ---------------------------------------------------------------------------- */
+
+/* Constraint target/owner types */
+#define TARGET_OBJECT 1 /* string is "" */
+#define TARGET_BONE 2 /* string is bone-name */
+#define TARGET_VERT 3 /* string is vertex-group name */
+#define TARGET_CV 4 /* string is vertex-group name - is not available until curves get vgroups */
+
+/* ---------------------------------------------------------------------------- */
+
+/* special struct for use in constraint evaluation */
+typedef struct bConstraintOb {
+ struct Object *ob; /* if pchan, then armature that it comes from, otherwise constraint owner */
+ struct bPoseChannel *pchan; /* pose channel that owns the constraints being evaluated */
+
+ float matrix[4][4]; /* matrix where constraints are accumulated + solved */
+ float startmat[4][4]; /* original matrix (before constraint solving) */
+
+ short type; /* type of owner */
+} bConstraintOb;
+
+/* ---------------------------------------------------------------------------- */
+
+/* Constraint function prototypes */
void unique_constraint_name (struct bConstraint *con, struct ListBase *list);
void *new_constraint_data (short type);
-void evaluate_constraint (struct bConstraint *constraint, struct Object *ob, short ownertype, void *ownerdata, float targetmat[][4]);
void free_constraints (struct ListBase *conlist);
void copy_constraints (struct ListBase *dst, struct ListBase *src);
-void copy_constraint_channels (ListBase *dst, ListBase *src);
-void clone_constraint_channels (struct ListBase *dst, struct ListBase *src);
void relink_constraints (struct ListBase *list);
void free_constraint_data (struct bConstraint *con);
-/* channels */
+/* Constraint Channel function prototypes */
struct bConstraintChannel *get_constraint_channel (ListBase *list, const char *name);
struct bConstraintChannel *verify_constraint_channel (ListBase *list, const char *name);
+void do_constraint_channels (struct ListBase *conbase, struct ListBase *chanbase, float ctime);
+void copy_constraint_channels (ListBase *dst, ListBase *src);
+void clone_constraint_channels (struct ListBase *dst, struct ListBase *src);
void free_constraint_channels (ListBase *chanbase);
-/* Gemeric functions */
-void do_constraint_channels (struct ListBase *conbase, struct ListBase *chanbase, float ctime);
-short get_constraint_target_matrix (struct bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float size[3], float time);
+/* Target function prototypes */
char constraint_has_target (struct bConstraint *con);
struct Object *get_constraint_target(struct bConstraint *con, char **subtarget);
void set_constraint_target(struct bConstraint *con, struct Object *ob, char *subtarget);
+/* Constraint Evaluation function prototypes */
+struct bConstraintOb *constraints_make_evalob (struct Object *ob, void *subdata, short datatype);
+void constraints_clear_evalob(struct bConstraintOb *cob);
+
+short get_constraint_target_matrix (struct bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float time);
+void solve_constraints (struct ListBase *conlist, struct bConstraintOb *cob, float ctime);
-/* Constraint target/owner types */
-#define TARGET_OBJECT 1 // string is ""
-#define TARGET_BONE 2 // string is bone-name
-#define TARGET_VERT 3 // string is "VE:#"
-#define TARGET_FACE 4 // string is "FA:#"
-#define TARGET_CV 5 // string is "CV:#"
#endif
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 52d529ea32d..e38446e0d46 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -104,7 +104,6 @@ void object_boundbox_flag(struct Object *ob, int flag, int set);
void minmax_object(struct Object *ob, float *min, float *max);
void minmax_object_duplis(struct Object *ob, float *min, float *max);
void solve_tracking (struct Object *ob, float targetmat[][4]);
-void solve_constraints (struct Object *ob, short obtype, void *obdata, float ctime);
void object_handle_update(struct Object *ob);
diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
index e76c53fc72c..340ac1ed693 100644
--- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c
+++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
@@ -126,7 +126,7 @@ int BPY_button_eval(char *expr, double *value)
}
/* constraint.c */
-void BPY_pyconstraint_eval(struct bPythonConstraint *con, float obmat[][4], short ownertype, void *ownerdata, float targetmat[][4])
+void BPY_pyconstraint_eval(struct bPythonConstraint *con, float ownermat[][4], float targetmat[][4])
{
}
int BPY_pyconstraint_targets(struct bPythonConstraint *con, float targetmat[][4])
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index aa9d3d30f98..bb0953cc1cc 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -225,12 +225,12 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name)
{
bPoseChannel *chan;
- if (!pose){
+ if (!pose) {
return NULL;
}
/* See if this channel exists */
- for (chan=pose->chanbase.first; chan; chan=chan->next){
+ for (chan=pose->chanbase.first; chan; chan=chan->next) {
if (!strcmp (name, chan->name))
return chan;
}
@@ -239,7 +239,7 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name)
chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel");
strncpy (chan->name, name, 31);
- /* init vars to prevent mat errors */
+ /* init vars to prevent math errors */
chan->quat[0] = 1.0F;
chan->size[0] = chan->size[1] = chan->size[2] = 1.0F;
@@ -247,6 +247,8 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name)
chan->limitmax[0]= chan->limitmax[1]= chan->limitmax[2]= 180.0f;
chan->stiffness[0]= chan->stiffness[1]= chan->stiffness[2]= 0.0f;
+ Mat4One(chan->constinv);
+
BLI_addtail (&pose->chanbase, chan);
return chan;
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 669724bd250..b320a7e0106 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -1321,7 +1321,7 @@ static void execute_posetree(Object *ob, PoseTree *tree)
float goalrot[3][3], goalpos[3];
float rootmat[4][4], imat[4][4];
float goal[4][4], goalinv[4][4];
- float size[3], irest_basis[3][3], full_basis[3][3];
+ float irest_basis[3][3], full_basis[3][3];
float end_pose[4][4], world_pose[4][4];
float length, basis[3][3], rest_basis[3][3], start[3], *ikstretch=NULL;
int a, flag, hasstretch=0;
@@ -1444,7 +1444,7 @@ static void execute_posetree(Object *ob, PoseTree *tree)
data= (bKinematicConstraint*)target->con->data;
/* 1.0=ctime, we pass on object for auto-ik */
- get_constraint_target_matrix(target->con, TARGET_BONE, ob, rootmat, size, 1.0);
+ get_constraint_target_matrix(target->con, TARGET_BONE, ob, rootmat, 1.0);
/* and set and transform goal */
Mat4MulMat4(goal, rootmat, goalinv);
@@ -1603,211 +1603,7 @@ static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[][3]) // nr = t
pchan->flag |= POSE_DONE;
}
-static void do_local_constraint(bPoseChannel *pchan, bConstraint *con)
-{
- switch(con->type) {
- case CONSTRAINT_TYPE_LOCLIKE:
- {
- bLocateLikeConstraint *data= con->data;
- float fac= con->enforce;
-
- if(data->tar && data->subtarget[0]) {
- bPoseChannel *pchant= get_pose_channel(data->tar->pose, data->subtarget);
- if(pchant) {
- float loc[3];
-
- /* copy location of tip of bone? */
- if (data->flag & LOCLIKE_TIP) {
- float mat[4][4], tmat[4][4];
-
- Mat4One(tmat);
- VECCOPY(tmat[3], pchant->pose_tail);
-
- armature_mat_pose_to_delta(mat, tmat, pchant->bone->arm_mat);
- VECCOPY(loc, mat[3]);
- }
- else
- VECCOPY(loc, pchant->loc);
-
- /* do offsets? */
- if (data->flag & LOCLIKE_OFFSET)
- VecAddf(loc, loc, pchan->loc);
-
- if (data->flag & LOCLIKE_X)
- pchan->loc[0]= FloatLerpf(loc[0], pchan->loc[0], fac);
- if (data->flag & LOCLIKE_Y)
- pchan->loc[1]= FloatLerpf(loc[1], pchan->loc[1], fac);
- if (data->flag & LOCLIKE_Z)
- pchan->loc[2]= FloatLerpf(loc[2], pchan->loc[2], fac);
- if (data->flag & LOCLIKE_X_INVERT)
- pchan->loc[0]= FloatLerpf(pchant->loc[0], pchan->loc[0], -fac);
- if (data->flag & LOCLIKE_Y_INVERT)
- pchan->loc[1]= FloatLerpf(pchant->loc[1], pchan->loc[1], -fac);
- if (data->flag & LOCLIKE_Z_INVERT)
- pchan->loc[2]= FloatLerpf(pchant->loc[2], pchan->loc[2], -fac);
- }
- }
- }
- break;
- case CONSTRAINT_TYPE_ROTLIKE:
- {
- bRotateLikeConstraint *data= con->data;
- if(data->tar && data->subtarget[0]) {
- bPoseChannel *pchant= get_pose_channel(data->tar->pose, data->subtarget);
- if(pchant) {
- if(data->flag != (ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z)) {
- float eul[3], eult[3], euln[3];
- float fac= con->enforce;
-
- QuatToEul(pchan->quat, eul);
- QuatToEul(pchant->quat, eult);
- VECCOPY(euln, eul);
-
- if(data->flag & ROTLIKE_X) euln[0]= FloatLerpf(eult[0], eul[0], fac);
- if(data->flag & ROTLIKE_Y) euln[1]= FloatLerpf(eult[1], eul[1], fac);
- if(data->flag & ROTLIKE_Z) euln[2]= FloatLerpf(eult[2], eul[2], fac);
- if(data->flag & ROTLIKE_X_INVERT) euln[0]= FloatLerpf(eult[0], eul[0], -fac);
- if(data->flag & ROTLIKE_Y_INVERT) euln[1]= FloatLerpf(eult[1], eul[1], -fac);
- if(data->flag & ROTLIKE_Z_INVERT) euln[2]= FloatLerpf(eult[2], eul[2], -fac);
-
- compatible_eul(eul, euln);
- EulToQuat(euln, pchan->quat);
- }
- else {
- QuatInterpol(pchan->quat, pchan->quat, pchant->quat, con->enforce);
- }
- }
- }
- }
- break;
- case CONSTRAINT_TYPE_SIZELIKE:
- {
- bSizeLikeConstraint *data= con->data;
- float fac= con->enforce;
-
- if(data->tar && data->subtarget[0]) {
- bPoseChannel *pchant= get_pose_channel(data->tar->pose, data->subtarget);
- if(pchant) {
- if (data->flag & SIZELIKE_X)
- pchan->size[0]= FloatLerpf(pchant->size[0], pchan->size[0], fac);
- if (data->flag & SIZELIKE_Y)
- pchan->size[1]= FloatLerpf(pchant->size[1], pchan->size[1], fac);
- if (data->flag & SIZELIKE_Z)
- pchan->size[2]= FloatLerpf(pchant->size[2], pchan->size[2], fac);
- }
- }
- }
- break;
- case CONSTRAINT_TYPE_LOCLIMIT:
- {
- bLocLimitConstraint *data= con->data;
- float fac= con->enforce;
-
- if (data->flag & LIMIT_XMIN) {
- if(pchan->loc[0] < data->xmin)
- pchan->loc[0] = FloatLerpf(data->xmin, pchan->loc[0], fac);
- }
- if (data->flag & LIMIT_XMAX) {
- if (pchan->loc[0] > data->xmax)
- pchan->loc[0] = FloatLerpf(data->xmax, pchan->loc[0], fac);
- }
- if (data->flag & LIMIT_YMIN) {
- if(pchan->loc[1] < data->ymin)
- pchan->loc[1] = FloatLerpf(data->ymin, pchan->loc[1], fac);
- }
- if (data->flag & LIMIT_YMAX) {
- if (pchan->loc[1] > data->ymax)
- pchan->loc[1] = FloatLerpf(data->ymax, pchan->loc[1], fac);
- }
- if (data->flag & LIMIT_ZMIN) {
- if(pchan->loc[2] < data->zmin)
- pchan->loc[2] = FloatLerpf(data->zmin, pchan->loc[2], fac);
- }
- if (data->flag & LIMIT_ZMAX) {
- if (pchan->loc[2] > data->zmax)
- pchan->loc[2] = FloatLerpf(data->zmax, pchan->loc[2], fac);
- }
- }
- break;
- case CONSTRAINT_TYPE_ROTLIMIT:
- {
- bRotLimitConstraint *data = con->data;
- float eul[3];
- float fac= con->enforce;
-
- QuatToEul(pchan->quat, eul);
-
- /* eulers: radians to degrees! */
- eul[0] = (eul[0] / (2*M_PI) * 360);
- eul[1] = (eul[1] / (2*M_PI) * 360);
- eul[2] = (eul[2] / (2*M_PI) * 360);
-
- /* limiting of euler values... */
- if (data->flag & LIMIT_XROT) {
- if (eul[0] < data->xmin)
- eul[0] = FloatLerpf(data->xmin, eul[0], fac);
-
- if (eul[0] > data->xmax)
- eul[0] = FloatLerpf(data->xmax, eul[0], fac);
- }
- if (data->flag & LIMIT_YROT) {
- if (eul[1] < data->ymin)
- eul[1] = FloatLerpf(data->ymin, eul[1], fac);
-
- if (eul[1] > data->ymax)
- eul[1] = FloatLerpf(data->ymax, eul[1], fac);
- }
- if (data->flag & LIMIT_ZROT) {
- if (eul[2] < data->zmin)
- eul[2] = FloatLerpf(data->zmin, eul[2], fac);
-
- if (eul[2] > data->zmax)
- eul[2] = FloatLerpf(data->zmax, eul[2], fac);
- }
-
- /* eulers: degrees to radians ! */
- eul[0] = (eul[0] / 360 * (2*M_PI));
- eul[1] = (eul[1] / 360 * (2*M_PI));
- eul[2] = (eul[2] / 360 * (2*M_PI));
-
- /* convert back */
- EulToQuat(eul, pchan->quat);
- }
- break;
- case CONSTRAINT_TYPE_SIZELIMIT:
- {
- bSizeLimitConstraint *data= con->data;
- float fac= con->enforce;
-
- if (data->flag & LIMIT_XMIN) {
- if(pchan->size[0] < data->xmin)
- pchan->size[0] = FloatLerpf(data->xmin, pchan->size[0], fac);
- }
- if (data->flag & LIMIT_XMAX) {
- if (pchan->size[0] > data->xmax)
- pchan->size[0] = FloatLerpf(data->xmax, pchan->size[0], fac);
- }
- if (data->flag & LIMIT_YMIN) {
- if(pchan->size[1] < data->ymin)
- pchan->size[1] = FloatLerpf(data->ymin, pchan->size[1], fac);
- }
- if (data->flag & LIMIT_YMAX) {
- if (pchan->size[1] > data->ymax)
- pchan->size[1] = FloatLerpf(data->ymax, pchan->size[1], fac);
- }
- if (data->flag & LIMIT_ZMIN) {
- if(pchan->size[2] < data->zmin)
- pchan->size[2] = FloatLerpf(data->zmin, pchan->size[2], fac);
- }
- if (data->flag & LIMIT_ZMAX) {
- if (pchan->size[2] > data->zmax)
- pchan->size[2] = FloatLerpf(data->zmax, pchan->size[2], fac);
- }
- }
- break;
- }
-}
-
+/* NLA strip modifiers */
static void do_strip_modifiers(Object *armob, Bone *bone, bPoseChannel *pchan)
{
bActionModifier *amod;
@@ -1906,32 +1702,16 @@ static void where_is_pose_bone(Object *ob, bPoseChannel *pchan, float ctime)
{
Bone *bone, *parbone;
bPoseChannel *parchan;
- float vec[3], quat[4];
- int did_local= 0; /* copying quaternion should be limited, chan_calc_mat() normalizes quat */
+ float vec[3];
/* set up variables for quicker access below */
bone= pchan->bone;
parbone= bone->parent;
parchan= pchan->parent;
-
- /* Do local constraints, these only work on the channel data (loc rot size) */
- QUATCOPY(quat, pchan->quat);
- if(pchan->constraints.first) {
- bConstraint *con;
- for(con=pchan->constraints.first; con; con= con->next) {
- if(con->flag & CONSTRAINT_LOCAL) {
- do_local_constraint(pchan, con);
- did_local= 1;
- }
- }
- }
/* this gives a chan_mat with actions (ipos) results */
chan_calc_mat(pchan);
- if(did_local)
- QUATCOPY(pchan->quat, quat); /* local constraint hack. bad! */
-
/* construct the posemat based on PoseChannels, that we do before applying constraints */
/* pose_mat(b)= pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * chan_mat(b) */
@@ -1970,44 +1750,33 @@ static void where_is_pose_bone(Object *ob, bPoseChannel *pchan, float ctime)
VecAddf(pchan->pose_mat[3], pchan->pose_mat[3], ob->pose->cyclic_offset);
}
+ /* do NLA strip modifiers - i.e. curve follow */
do_strip_modifiers(ob, bone, pchan);
/* Do constraints */
- if(pchan->constraints.first) {
- static Object conOb;
- static int initialized= 0;
+ if (pchan->constraints.first) {
+ bConstraintOb *cob;
+ /* make a copy of location of PoseChannel for later */
VECCOPY(vec, pchan->pose_mat[3]);
- /* Build a workob to pass the bone to the constraint solver */
- if(initialized==0) {
- memset(&conOb, 0, sizeof(Object));
- initialized= 1;
- }
- conOb.size[0]= conOb.size[1]= conOb.size[2]= 1.0;
- conOb.data = ob->data;
- conOb.type = ob->type;
- conOb.parent = ob; // ik solver retrieves the armature that way !?!?!?!
- conOb.pose= ob->pose; // needed for retrieving pchan
- conOb.trackflag = ob->trackflag;
- conOb.upflag = ob->upflag;
-
- /* Collect the constraints from the pose (listbase copy) */
- conOb.constraints = pchan->constraints;
+ /* prepare PoseChannel for Constraint solving
+ * - makes a copy of matrix, and creates temporary struct to use
+ */
+ cob= constraints_make_evalob(ob, pchan, TARGET_BONE);
- /* conOb.obmat takes bone to worldspace */
- Mat4MulMat4 (conOb.obmat, pchan->pose_mat, ob->obmat);
+ /* Solve PoseChannel's Constraints */
+ solve_constraints(&pchan->constraints, cob, ctime); // ctime doesnt alter objects
- /* Solve */
- solve_constraints (&conOb, TARGET_BONE, (void*)pchan, ctime); // ctime doesnt alter objects
-
- /* Take out of worldspace */
- Mat4MulMat4 (pchan->pose_mat, conOb.obmat, ob->imat);
+ /* cleanup after Constraint Solving
+ * - applies matrix back to pchan, and frees temporary struct used
+ */
+ constraints_clear_evalob(cob);
/* prevent constraints breaking a chain */
- if(pchan->bone->flag & BONE_CONNECTED)
+ if(pchan->bone->flag & BONE_CONNECTED) {
VECCOPY(pchan->pose_mat[3], vec);
-
+ }
}
/* calculate head */
@@ -2016,7 +1785,6 @@ static void where_is_pose_bone(Object *ob, bPoseChannel *pchan, float ctime)
VECCOPY(vec, pchan->pose_mat[1]);
VecMulf(vec, bone->length);
VecAddf(pchan->pose_tail, pchan->pose_head, vec);
-
}
/* This only reads anim data from channels, and writes to channels */
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 25b8c9ac171..5613ff80c9f 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -25,7 +25,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): 2007, Joshua Leung, major recode
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
@@ -72,7 +72,6 @@
#define M_PI 3.14159265358979323846
#endif
-/* Local function prototypes */
/* ********************* Data level ****************** */
@@ -165,22 +164,21 @@ void copy_constraints (ListBase *dst, ListBase *src)
bConstraint *con, *srccon;
dst->first= dst->last= NULL;
-
duplicatelist (dst, src);
for (con = dst->first, srccon=src->first; con; srccon=srccon->next, con=con->next) {
con->data = MEM_dupallocN (con->data);
+
+ /* only do specific constraints if required */
if (con->type == CONSTRAINT_TYPE_PYTHON) {
- bPythonConstraint *pycon = (bPythonConstraint*) con->data;
- bPythonConstraint *opycon = (bPythonConstraint*) srccon->data;
-
+ bPythonConstraint *pycon = (bPythonConstraint *)con->data;
+ bPythonConstraint *opycon = (bPythonConstraint *)srccon->data;
+
pycon->prop = IDP_CopyProperty(opycon->prop);
}
- /* removed a whole lot of useless code here (ton) */
}
}
-
/* **************** Editor Functions **************** */
char constraint_has_target (bConstraint *con)
@@ -189,103 +187,97 @@ char constraint_has_target (bConstraint *con)
case CONSTRAINT_TYPE_PYTHON:
{
bPythonConstraint *data = con->data;
- if (data->tar)
- return 1;
+ if (data->tar) return 1;
}
break;
case CONSTRAINT_TYPE_TRACKTO:
{
bTrackToConstraint *data = con->data;
- if (data->tar)
- return 1;
+ if (data->tar) return 1;
}
break;
case CONSTRAINT_TYPE_KINEMATIC:
{
bKinematicConstraint *data = con->data;
- if (data->tar)
- return 1;
+ if (data->tar) return 1;
}
break;
case CONSTRAINT_TYPE_FOLLOWPATH:
{
bFollowPathConstraint *data = con->data;
- if (data->tar)
- return 1;
+ if (data->tar) return 1;
}
break;
case CONSTRAINT_TYPE_ROTLIKE:
{
bRotateLikeConstraint *data = con->data;
- if (data->tar)
- return 1;
+ if (data->tar) return 1;
}
break;
case CONSTRAINT_TYPE_LOCLIKE:
{
bLocateLikeConstraint *data = con->data;
- if (data->tar)
- return 1;
+ if (data->tar) return 1;
}
break;
case CONSTRAINT_TYPE_SIZELIKE:
{
bSizeLikeConstraint *data = con->data;
- if (data->tar)
- return 1;
+ if (data->tar) return 1;
}
break;
case CONSTRAINT_TYPE_MINMAX:
{
bMinMaxConstraint *data = con->data;
- if (data->tar)
- return 1;
+ if (data->tar) return 1;
}
break;
case CONSTRAINT_TYPE_ACTION:
{
bActionConstraint *data = con->data;
- if (data->tar)
- return 1;
+ if (data->tar) return 1;
}
break;
case CONSTRAINT_TYPE_LOCKTRACK:
{
bLockTrackConstraint *data = con->data;
- if (data->tar)
- return 1;
+ if (data->tar) return 1;
}
case CONSTRAINT_TYPE_STRETCHTO:
{
bStretchToConstraint *data = con->data;
- if (data->tar)
- return 1;
+ if (data->tar) return 1;
}
break;
case CONSTRAINT_TYPE_RIGIDBODYJOINT:
{
bRigidBodyJointConstraint *data = con->data;
- if (data->tar)
- return 1;
+ if (data->tar) return 1;
}
break;
case CONSTRAINT_TYPE_CLAMPTO:
{
bClampToConstraint *data = con->data;
- if (data->tar)
- return 1;
+ if (data->tar) return 1;
}
break;
+ case CONSTRAINT_TYPE_CHILDOF:
+ {
+ bChildOfConstraint *data = con->data;
+ if (data->tar) return 1;
+ }
+ break;
}
- // Unknown types or CONSTRAINT_TYPE_NULL or no target
+
+ /* Unknown types or CONSTRAINT_TYPE_NULL or no target */
return 0;
}
Object *get_constraint_target(bConstraint *con, char **subtarget)
{
/* If the target for this constraint is target, return a pointer
- * to the name for this constraints subtarget ... NULL otherwise
- */
+ * to the name for this constraints subtarget ... NULL otherwise
+ */
switch (con->type) {
case CONSTRAINT_TYPE_PYTHON:
{
@@ -361,7 +353,7 @@ Object *get_constraint_target(bConstraint *con, char **subtarget)
{
bStretchToConstraint *data = con->data;
*subtarget= data->subtarget;
- return (data->tar);
+ return data->tar;
}
break;
case CONSTRAINT_TYPE_RIGIDBODYJOINT:
@@ -378,6 +370,13 @@ Object *get_constraint_target(bConstraint *con, char **subtarget)
return data->tar;
}
break;
+ case CONSTRAINT_TYPE_CHILDOF:
+ {
+ bChildOfConstraint *data = con->data;
+ *subtarget= data->subtarget;
+ return data->tar;
+ }
+ break;
default:
*subtarget= NULL;
break;
@@ -388,63 +387,62 @@ Object *get_constraint_target(bConstraint *con, char **subtarget)
void set_constraint_target(bConstraint *con, Object *ob, char *subtarget)
{
- /* Set the target for this constraint */
+ /* Set the target for this constraint */
switch (con->type) {
-
case CONSTRAINT_TYPE_PYTHON:
{
bPythonConstraint *data = con->data;
data->tar= ob;
- if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
+ if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
}
break;
case CONSTRAINT_TYPE_ACTION:
{
bActionConstraint *data = con->data;
data->tar= ob;
- if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
+ if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
}
break;
case CONSTRAINT_TYPE_LOCLIKE:
{
bLocateLikeConstraint *data = con->data;
data->tar= ob;
- if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
+ if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
}
break;
case CONSTRAINT_TYPE_ROTLIKE:
{
bRotateLikeConstraint *data = con->data;
data->tar= ob;
- if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
+ if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
}
break;
case CONSTRAINT_TYPE_SIZELIKE:
{
bSizeLikeConstraint *data = con->data;
data->tar= ob;
- if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
+ if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
}
break;
case CONSTRAINT_TYPE_KINEMATIC:
{
bKinematicConstraint *data = con->data;
data->tar= ob;
- if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
+ if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
}
break;
case CONSTRAINT_TYPE_TRACKTO:
{
bTrackToConstraint *data = con->data;
data->tar= ob;
- if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
+ if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
}
break;
case CONSTRAINT_TYPE_LOCKTRACK:
{
bLockTrackConstraint *data = con->data;
data->tar= ob;
- if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
+ if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
}
break;
case CONSTRAINT_TYPE_FOLLOWPATH:
@@ -457,7 +455,7 @@ void set_constraint_target(bConstraint *con, Object *ob, char *subtarget)
{
bStretchToConstraint *data = con->data;
data->tar= ob;
- if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
+ if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
}
break;
case CONSTRAINT_TYPE_RIGIDBODYJOINT:
@@ -470,7 +468,7 @@ void set_constraint_target(bConstraint *con, Object *ob, char *subtarget)
{
bMinMaxConstraint *data = (bMinMaxConstraint*)con->data;
data->tar= ob;
- if(subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
+ if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
}
break;
case CONSTRAINT_TYPE_CLAMPTO:
@@ -479,26 +477,32 @@ void set_constraint_target(bConstraint *con, Object *ob, char *subtarget)
data->tar= ob;
}
break;
+ case CONSTRAINT_TYPE_CHILDOF:
+ {
+ bChildOfConstraint *data = con->data;
+ data->tar= ob;
+ if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
+ }
+ break;
}
}
void unique_constraint_name (bConstraint *con, ListBase *list)
{
- char tempname[64];
- int number;
- char *dot;
- int exists = 0;
bConstraint *curcon;
+ char tempname[64];
+ int number = 1, exists = 0;
+ char *dot;
/* See if we are given an empty string */
if (con->name[0] == '\0') {
/* give it default name first */
- strcpy (con->name, "Const");
+ strcpy(con->name, "Const");
}
/* See if we even need to do this */
for (curcon = list->first; curcon; curcon=curcon->next) {
- if (curcon!=con){
+ if (curcon != con) {
if (!strcmp(curcon->name, con->name)) {
exists = 1;
break;
@@ -514,20 +518,20 @@ void unique_constraint_name (bConstraint *con, ListBase *list)
if (dot)
*dot=0;
- for (number = 1; number <=999; number++) {
- sprintf (tempname, "%s.%03d", con->name, number);
+ for (number = 1; number <= 999; number++) {
+ sprintf(tempname, "%s.%03d", con->name, number);
exists = 0;
for (curcon=list->first; curcon; curcon=curcon->next) {
if (con!=curcon) {
- if (!strcmp (curcon->name, tempname)) {
+ if (!strcmp(curcon->name, tempname)) {
exists = 1;
break;
}
}
}
if (!exists) {
- strcpy (con->name, tempname);
+ strcpy(con->name, tempname);
return;
}
}
@@ -590,7 +594,7 @@ void *new_constraint_data (short type)
case CONSTRAINT_TYPE_LOCLIKE:
{
bLocateLikeConstraint *data;
- data = MEM_callocN(sizeof(bLocateLikeConstraint), "loclikeConstraint");
+ data = MEM_callocN(sizeof(bLocateLikeConstraint), "LocLikeConstraint");
data->flag = LOCLIKE_X|LOCLIKE_Y|LOCLIKE_Z;
result = data;
}
@@ -598,7 +602,7 @@ void *new_constraint_data (short type)
case CONSTRAINT_TYPE_ROTLIKE:
{
bRotateLikeConstraint *data;
- data = MEM_callocN(sizeof(bRotateLikeConstraint), "rotlikeConstraint");
+ data = MEM_callocN(sizeof(bRotateLikeConstraint), "RotLikeConstraint");
data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z;
result = data;
}
@@ -606,7 +610,7 @@ void *new_constraint_data (short type)
case CONSTRAINT_TYPE_SIZELIKE:
{
bSizeLikeConstraint *data;
- data = MEM_callocN(sizeof(bLocateLikeConstraint), "sizelikeConstraint");
+ data = MEM_callocN(sizeof(bLocateLikeConstraint), "SizeLikeConstraint");
data->flag = SIZELIKE_X|SIZELIKE_Y|SIZELIKE_Z;
result = data;
}
@@ -614,8 +618,10 @@ void *new_constraint_data (short type)
case CONSTRAINT_TYPE_ACTION:
{
bActionConstraint *data;
- data = MEM_callocN(sizeof(bActionConstraint), "actionConstraint");
- data->local= 1;
+ data = MEM_callocN(sizeof(bActionConstraint), "ActionConstraint");
+
+ /* set type to 20 (Loc X), as 0 is Rot X for backwards compatability */
+ data->type = 20;
result = data;
}
@@ -624,10 +630,10 @@ void *new_constraint_data (short type)
{
bLockTrackConstraint *data;
data = MEM_callocN(sizeof(bLockTrackConstraint), "locktrackConstraint");
-
+
data->trackflag = TRACK_Y;
data->lockflag = LOCK_Z;
-
+
result = data;
}
break;
@@ -680,32 +686,11 @@ void *new_constraint_data (short type)
case CONSTRAINT_TYPE_RIGIDBODYJOINT:
{
bRigidBodyJointConstraint *data;
- int i;
- Base *base_iter;
-
data = MEM_callocN(sizeof(bRigidBodyJointConstraint), "RigidBodyToConstraint");
- base_iter = G.scene->base.first;
- while( base_iter && !data->tar ) {
- if( ( ( base_iter->flag & SELECT ) &&
-// ( base_iter->lay & G.vd->lay ) ) &&
- ( base_iter != G.scene->basact ) )
- )
- data->tar=base_iter->object;
- base_iter = base_iter->next;
- }
+
+ // removed code which set target of this constraint
data->type=1;
- data->pivX=0.0;
- data->pivY=0.0;
- data->pivZ=0.0;
- data->axX=0.0;
- data->axY=0.0;
- data->axZ=0.0;
- for (i=0;i<6;i++)
- {
- data->minLimit[i]=0.0;
- data->maxLimit[i]=0.0;
- }
- data->extraFz=0.0;
+
result = data;
}
break;
@@ -716,6 +701,19 @@ void *new_constraint_data (short type)
result = data;
}
break;
+ case CONSTRAINT_TYPE_CHILDOF:
+ {
+ bChildOfConstraint *data;
+ data = MEM_callocN(sizeof(bChildOfConstraint), "ChildOfConstraint");
+
+ data->flag = (CHILDOF_LOCX | CHILDOF_LOCY | CHILDOF_LOCZ |
+ CHILDOF_ROTX |CHILDOF_ROTY | CHILDOF_ROTZ |
+ CHILDOF_SIZEX | CHILDOF_SIZEY | CHILDOF_SIZEZ);
+ Mat4One(data->invmat);
+
+ result = data;
+ }
+ break;
default:
result = NULL;
@@ -755,55 +753,334 @@ bConstraintChannel *verify_constraint_channel (ListBase *list, const char *name)
/* ***************** Evaluating ********************* */
-/* does ipos only */
+/* package an object/bone for use in constraint evaluation */
+/* This function MEM_calloc's a bConstraintOb struct, that will need to be freed after evaluation */
+bConstraintOb *constraints_make_evalob (Object *ob, void *subdata, short datatype)
+{
+ bConstraintOb *cob;
+
+ /* create regardless of whether we have any data! */
+ cob= MEM_callocN(sizeof(bConstraintOb), "bConstraintOb");
+
+ /* based on type of available data */
+ switch (datatype) {
+ case TARGET_OBJECT:
+ {
+ /* disregard subdata... calloc should set other values right */
+ if (ob) {
+ cob->ob = ob;
+ cob->type = datatype;
+ Mat4CpyMat4(cob->matrix, ob->obmat);
+ Mat4CpyMat4(cob->startmat, ob->obmat);
+ }
+ else
+ Mat4One(cob->matrix);
+ }
+ break;
+ case TARGET_BONE:
+ {
+ /* only set if we have valid bone, otherwise default */
+ if (ob && subdata) {
+ cob->ob = ob;
+ cob->pchan = (bPoseChannel *)subdata;
+ cob->type = datatype;
+
+ /* matrix in world-space */
+ Mat4MulMat4 (cob->matrix, cob->pchan->pose_mat, ob->obmat);
+ Mat4CpyMat4(cob->startmat, cob->matrix);
+ }
+ else
+ Mat4One(cob->matrix);
+ Mat4CpyMat4(cob->startmat, cob->matrix);
+ }
+ break;
+
+ default: // other types not yet handled
+ Mat4One(cob->matrix);
+ break;
+ }
+
+ return cob;
+}
+
+/* cleanup after constraint evaluation */
+void constraints_clear_evalob (bConstraintOb *cob)
+{
+ float delta[4][4], imat[4][4];
+
+ /* prevent crashes */
+ if (cob == NULL)
+ return;
+
+ /* calculate delta of constraints evaluation */
+ Mat4Invert(imat, cob->startmat);
+ Mat4MulMat4(delta, cob->matrix, imat);
+
+ /* copy matrices back to source */
+ switch (cob->type) {
+ case TARGET_OBJECT:
+ {
+ /* copy new ob-matrix back to owner */
+ Mat4CpyMat4(cob->ob->obmat, cob->matrix);
+
+ /* copy inverse of delta back to owner */
+ Mat4Invert(cob->ob->constinv, delta);
+ }
+ break;
+ case TARGET_BONE:
+ {
+ /* copy new pose-matrix back to owner */
+ Mat4MulMat4(cob->pchan->pose_mat, cob->matrix, cob->ob->imat);
+
+ /* copy inverse of delta back to owner */
+ Mat4Invert(cob->pchan->constinv, delta);
+ }
+ break;
+ }
+
+ /* free tempolary struct */
+ MEM_freeN(cob);
+}
+
+/* -------------------------------- Constraint Channels ---------------------------- */
+
+/* does IPO's of constraint channels only */
void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime)
{
bConstraint *con;
bConstraintChannel *chan;
- IpoCurve *icu=NULL;
+ IpoCurve *icu= NULL;
+ /* for each Constraint, calculate its Influence from the corresponding ConstraintChannel */
for (con=conbase->first; con; con=con->next) {
chan = get_constraint_channel(chanbase, con->name);
- if (chan && chan->ipo){
+ if (chan && chan->ipo) {
calc_ipo(chan->ipo, ctime);
- for (icu=chan->ipo->curve.first; icu; icu=icu->next){
- switch (icu->adrcode){
- case CO_ENFORCE:
- con->enforce = icu->curval;
- if (con->enforce<0.0f) con->enforce= 0.0f;
- else if (con->enforce>1.0f) con->enforce= 1.0f;
- break;
+ for (icu=chan->ipo->curve.first; icu; icu=icu->next) {
+ switch (icu->adrcode) {
+ case CO_ENFORCE:
+ {
+ con->enforce = icu->curval;
+ if (con->enforce<0.0f) con->enforce= 0.0f;
+ else if (con->enforce>1.0f) con->enforce= 1.0f;
+ }
+ break;
}
}
}
}
}
-static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], float size[3])
+/* ------------------------------- Space-Conversion API ---------------------------- */
+
+/* This function is responsible for the correct transformations/conversions
+ * of a matrix from one space to another for constraint evaluation.
+ * For now, this is only implemented for Objects and PoseChannels.
+ */
+static void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4], short from, short to)
{
+ float tempmat[4][4];
+ float diff_mat[4][4];
+ float imat[4][4];
+
+ /* prevent crashes in these unlikely events */
+ if (ob==NULL || mat==NULL) return;
+ /* optimise trick - check if need to do anything */
+ if (from == to) return;
+
+ /* are we dealing with pose-channels or objects */
+ if (pchan) {
+ /* pose channels */
+ switch (from) {
+ case CONSTRAINT_SPACE_WORLD: /* ---------- FROM WORLDSPACE ---------- */
+ {
+ /* world to pose */
+ if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_LOCAL || to==CONSTRAINT_SPACE_PARLOCAL) {
+ Mat4Invert(imat, ob->obmat);
+ Mat4CpyMat4(tempmat, mat);
+ Mat4MulMat4(mat, tempmat, imat);
+ }
+ /* pose to local */
+ if (to == CONSTRAINT_SPACE_LOCAL) {
+ /* call self with slightly different values */
+ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+ }
+ /* pose to local + parent */
+ else if (to == CONSTRAINT_SPACE_PARLOCAL) {
+ /* call self with slightly different values */
+ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+ }
+ }
+ break;
+ case CONSTRAINT_SPACE_POSE: /* ---------- FROM POSESPACE ---------- */
+ {
+ /* pose to world */
+ if (to == CONSTRAINT_SPACE_WORLD) {
+ Mat4CpyMat4(tempmat, mat);
+ Mat4MulMat4(mat, tempmat, ob->obmat);
+ }
+ /* pose to local */
+ else if (to == CONSTRAINT_SPACE_LOCAL) {
+ if (pchan->bone) {
+ if (pchan->parent && pchan->parent->bone) {
+ float offs_bone[4][4];
+
+ /* construct offs_bone the same way it is done in armature.c */
+ Mat4CpyMat3(offs_bone, pchan->bone->bone_mat);
+ VECCOPY(offs_bone[3], pchan->bone->head);
+ offs_bone[3][1]+= pchan->parent->bone->length;
+
+ if (pchan->bone->flag & BONE_HINGE) {
+ /* pose_mat = par_pose-space_location * chan_mat */
+ float tmat[4][4];
+
+ /* the rotation of the parent restposition */
+ Mat4CpyMat4(tmat, pchan->parent->bone->arm_mat);
+
+ /* the location of actual parent transform */
+ VECCOPY(tmat[3], offs_bone[3]);
+ offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
+ Mat4MulVecfl(pchan->parent->pose_mat, tmat[3]);
+
+ Mat4MulMat4(diff_mat, offs_bone, tmat);
+ Mat4Invert(imat, diff_mat);
+ }
+ else {
+ /* pose_mat = par_pose_mat * bone_mat * chan_mat */
+ Mat4MulMat4(diff_mat, pchan->parent->pose_mat, offs_bone);
+ Mat4Invert(imat, diff_mat);
+ }
+ }
+ else {
+ /* pose_mat = chan_mat * arm_mat */
+ Mat4Invert(imat, pchan->bone->arm_mat);
+ }
+
+ Mat4CpyMat4(tempmat, mat);
+ Mat4MulMat4(mat, tempmat, imat);
+ }
+ }
+ /* pose to local with parent */
+ else if (to == CONSTRAINT_SPACE_PARLOCAL) {
+ if (pchan->bone) {
+ Mat4Invert(imat, pchan->bone->arm_mat);
+ Mat4CpyMat4(tempmat, mat);
+ Mat4MulMat4(mat, tempmat, imat);
+ }
+ }
+ }
+ break;
+ case CONSTRAINT_SPACE_LOCAL: /* ------------ FROM LOCALSPACE --------- */
+ {
+ /* local to pose */
+ if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_WORLD) {
+ /* do inverse procedure that was done for pose to local */
+ if (pchan->bone) {
+ /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */
+ if (pchan->parent) {
+ float offs_bone[4][4];
+
+ /* construct offs_bone the same way it is done in armature.c */
+ Mat4CpyMat3(offs_bone, pchan->bone->bone_mat);
+ VECCOPY(offs_bone[3], pchan->bone->head);
+ offs_bone[3][1]+= pchan->parent->bone->length;
+
+ Mat4MulMat4(diff_mat, offs_bone, pchan->parent->pose_mat);
+ Mat4CpyMat4(tempmat, mat);
+ Mat4MulMat4(mat, tempmat, diff_mat);
+ }
+ else {
+ Mat4CpyMat4(diff_mat, pchan->bone->arm_mat);
+
+ Mat4CpyMat4(tempmat, mat);
+ Mat4MulMat4(mat, tempmat, diff_mat);
+ }
+ }
+ }
+ /* local to world */
+ if (to == CONSTRAINT_SPACE_WORLD) {
+ /* call self with slightly different values */
+ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+ }
+ }
+ break;
+ case CONSTRAINT_SPACE_PARLOCAL: /* -------------- FROM LOCAL WITH PARENT ---------- */
+ {
+ /* local to pose */
+ if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_WORLD) {
+ if (pchan->bone) {
+ Mat4CpyMat4(diff_mat, pchan->bone->arm_mat);
+ Mat4CpyMat4(tempmat, mat);
+ Mat4MulMat4(mat, diff_mat, tempmat);
+ }
+ }
+ /* local to world */
+ if (to == CONSTRAINT_SPACE_WORLD) {
+ /* call self with slightly different values */
+ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to);
+ }
+ }
+ break;
+ }
+ }
+ else {
+ /* objects */
+ if (from==CONSTRAINT_SPACE_WORLD && to==CONSTRAINT_SPACE_LOCAL) {
+ /* check if object has a parent - otherwise this won't work */
+ if (ob->parent) {
+ /* 'subtract' parent's effects from owner */
+ Mat4MulMat4(diff_mat, ob->parentinv, ob->parent->obmat);
+ Mat4Invert(imat, diff_mat);
+ Mat4CpyMat4(tempmat, mat);
+ Mat4MulMat4(mat, tempmat, imat);
+ }
+ }
+ else if (from==CONSTRAINT_SPACE_LOCAL && to==CONSTRAINT_SPACE_WORLD) {
+ /* check that object has a parent - otherwise this won't work */
+ if (ob->parent) {
+ /* 'add' parent's effect back to owner */
+ Mat4CpyMat4(tempmat, mat);
+ Mat4MulMat4(diff_mat, ob->parentinv, ob->parent->obmat);
+ Mat4MulMat4(mat, tempmat, diff_mat);
+ }
+ }
+ }
+}
+
+/* ------------------------------- Target ---------------------------- */
+/* generic function to get the appropriate matrix for most target cases */
+/* The cases where the target can be object data have not been implemented */
+// TODO: add 'space' handling stuff here!
+static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], short from, short to)
+{
/* Case OBJECT */
if (!strlen(substring)) {
- Mat4CpyMat4 (mat, ob->obmat);
- VECCOPY (size, ob->size); // whats this for, hack! (ton)
+ Mat4CpyMat4(mat, ob->obmat);
+ constraint_mat_convertspace(ob, NULL, mat, from, to);
+ }
+ /* Case VERTEXGROUP */
+ else if (ELEM(ob->type, OB_MESH, OB_LATTICE)) {
+ /* devise a matrix from the data in the vertexgroup */
+ /* TODO: will be handled in other files */
}
/* Case BONE */
else {
bPoseChannel *pchan;
- float bsize[3]={1, 1, 1};
-
+
pchan = get_pose_channel(ob->pose, substring);
- if (pchan){
- /**
- * Multiply the objectspace bonematrix by the skeletons's global
- * transform to obtain the worldspace transformation of the target
+ if (pchan) {
+ /* Multiply the PoseSpace accumulation/final matrix for this
+ * PoseChannel by the Armature Object's Matrix to get a worldspace
+ * matrix.
*/
- Mat4MulMat4 (mat, pchan->pose_mat, ob->obmat);
+ Mat4MulMat4(mat, pchan->pose_mat, ob->obmat);
}
else
- Mat4CpyMat4 (mat, ob->obmat);
-
- VECCOPY(size, bsize); // whats this for, hack! (ton)
+ Mat4CpyMat4(mat, ob->obmat);
+
+ /* convert matrix space as required */
+ constraint_mat_convertspace(ob, pchan, mat, from, to);
}
}
@@ -826,7 +1103,7 @@ static void vectomat(float *vec, float *target_up, short axis, short upflag, sho
float right[3];
float neg = -1;
int right_index;
-
+
VecCopyf(n, vec);
if(Normalize(n) == 0.0) {
n[0] = 0.0;
@@ -883,7 +1160,7 @@ static void vectomat(float *vec, float *target_up, short axis, short upflag, sho
m[axis][1] = n[1];
m[axis][2] = n[2];
}
-
+ /* identity matrix - don't do anything if the two axes are the same */
else {
m[0][0]= m[1][1]= m[2][2]= 1.0;
m[0][1]= m[0][2]= m[0][3]= 0.0;
@@ -895,9 +1172,9 @@ static void vectomat(float *vec, float *target_up, short axis, short upflag, sho
/* called during solve_constraints */
/* also for make_parent, to find correct inverse of "follow path" */
-/* warning, ownerdata is void... is not Bone anymore, but PoseChannel or Object */
+/* warning: ownerdata is PoseChannel or Object */
/* ctime is global time, uncorrected for local bsystem_time */
-short get_constraint_target_matrix (bConstraint *con, short ownertype, void* ownerdata, float mat[][4], float size[3], float ctime)
+short get_constraint_target_matrix (bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float ctime)
{
short valid=0;
@@ -914,87 +1191,64 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
bActionConstraint *data = (bActionConstraint*)con->data;
bPose *pose;
bPoseChannel *pchan, *tchan;
- float tempmat3[3][3];
- float eul[3];
- float s,t;
+ float tempmat[4][4], vec[3];
+ float s, t;
+ short axis;
- Mat4One(mat); // return mat
+ /* initialise return matrix */
+ Mat4One(mat);
+ /* only continue if there is a target */
if (data->tar==NULL) return 0;
- /* need proper check for bone... */
- if (data->subtarget[0]) {
- pchan = get_pose_channel(data->tar->pose, data->subtarget);
- if (pchan) {
- float arm_mat[3][3], pose_mat[3][3]; /* arm mat should be bone mat! bug... */
-
- Mat3CpyMat4(arm_mat, pchan->bone->arm_mat);
- Mat3CpyMat4(pose_mat, pchan->pose_mat);
-
- /* new; true local rotation constraint */
- if(data->local) {
- float diff_mat[3][3], par_mat[3][3], ipar_mat[3][3];
- /* we need the local rotation = current rotation - (parent rotation + restpos) */
-
- if (pchan->parent) {
- Mat3CpyMat4(par_mat, pchan->parent->pose_mat);
- Mat3MulMat3(diff_mat, par_mat, arm_mat);
-
- Mat3Inv(ipar_mat, diff_mat);
- }
- else {
- Mat3Inv(ipar_mat, arm_mat);
- }
-
- Mat3MulMat3(tempmat3, ipar_mat, pose_mat);
- }
- else { /* we use the deform mat, for backwards compatibility */
- float imat[3][3];
-
- Mat3Inv(imat, arm_mat);
- Mat3MulMat3(tempmat3, pose_mat, imat);
- }
- }
- else Mat3One(tempmat3);
+ /* get the transform matrix of the target */
+ constraint_target_to_mat4(data->tar, data->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, con->tarspace); // FIXME: change these spaces
+
+ /* determine where in transform range target is */
+ /* data->type is mapped as follows for backwards compatability:
+ * 00,01,02 - rotation (it used to be like this)
+ * 10,11,12 - scaling
+ * 20,21,22 - location
+ */
+ if (data->type < 10) {
+ /* extract rotation (is in whatever space target should be in) */
+ Mat4ToEul(tempmat, vec);
+ vec[0] *= (float)(180.0/M_PI);
+ vec[1] *= (float)(180.0/M_PI);
+ vec[2] *= (float)(180.0/M_PI);
+ axis= data->type;
+ }
+ else if (data->type < 20) {
+ /* extract scaling (is in whatever space target should be in) */
+ Mat4ToSize(tempmat, vec);
+ axis= data->type - 10;
}
else {
- float ans[4][4];
-
- constraint_target_to_mat4(data->tar, data->subtarget, ans, size);
- /* extract rotation, is in global world coordinates */
- Mat3CpyMat4(tempmat3, ans);
+ /* extract location */
+ VECCOPY(vec, tempmat[3]);
+ axis= data->type - 20;
}
- Mat3ToEul(tempmat3, eul);
- eul[0] *= (float)(180.0/M_PI);
- eul[1] *= (float)(180.0/M_PI);
- eul[2] *= (float)(180.0/M_PI);
-
/* Target defines the animation */
- s = (eul[data->type]-data->min)/(data->max-data->min);
- if (s<0)
- s=0;
- if (s>1)
- s=1;
-
+ s = (vec[axis]-data->min) / (data->max-data->min);
+ CLAMP(s, 0, 1);
t = ( s * (data->end-data->start)) + data->start;
-
+
/* Get the appropriate information from the action, we make temp pose */
pose = MEM_callocN(sizeof(bPose), "pose");
pchan = ownerdata;
tchan= verify_pose_channel(pose, pchan->name);
- extract_pose_from_action (pose, data->act, t);
+ extract_pose_from_action(pose, data->act, t);
chan_calc_mat(tchan);
Mat4CpyMat4(mat, tchan->chan_mat);
-
+
/* Clean up */
free_pose_channels(pose);
MEM_freeN(pose);
}
-
}
break;
case CONSTRAINT_TYPE_LOCLIKE:
@@ -1006,77 +1260,80 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
if (strlen(data->subtarget)) {
bPoseChannel *pchan;
float tmat[4][4];
- float bsize[3]={1, 1, 1};
pchan = get_pose_channel(ob->pose, data->subtarget);
if (pchan) {
Mat4CpyMat4(tmat, pchan->pose_mat);
- if (data->flag & LOCLIKE_TIP)
+ if (data->flag & LOCLIKE_TIP) {
VECCOPY(tmat[3], pchan->pose_tail);
+ }
- Mat4MulMat4 (mat, tmat, ob->obmat);
+ Mat4MulMat4(mat, tmat, ob->obmat);
}
else
- Mat4CpyMat4 (mat, ob->obmat);
-
- VECCOPY(size, bsize); // what's this hack for?
+ Mat4CpyMat4(mat, ob->obmat);
+
+ /* convert matrix space as required */
+ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
}
else {
- Mat4CpyMat4 (mat, ob->obmat);
- VECCOPY(size, data->tar->size); // what's this hack for?
+ Mat4CpyMat4(mat, ob->obmat);
+
+ /* convert matrix space as required */
+ constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
}
valid=1;
}
else
- Mat4One (mat);
+ Mat4One(mat);
}
break;
- case CONSTRAINT_TYPE_MINMAX:
+ case CONSTRAINT_TYPE_ROTLIKE:
{
- bMinMaxConstraint *data = (bMinMaxConstraint*)con->data;
-
+ bRotateLikeConstraint *data;
+ data = (bRotateLikeConstraint*)con->data;
+
if (data->tar) {
- constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
valid=1;
}
else
- Mat4One (mat);
+ Mat4One(mat);
}
break;
- case CONSTRAINT_TYPE_ROTLIKE:
+ case CONSTRAINT_TYPE_SIZELIKE:
{
- bRotateLikeConstraint *data;
- data = (bRotateLikeConstraint*)con->data;
-
+ bSizeLikeConstraint *data;
+ data = (bSizeLikeConstraint*)con->data;
+
if (data->tar) {
- constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
valid=1;
}
else
- Mat4One (mat);
+ Mat4One(mat);
}
break;
- case CONSTRAINT_TYPE_SIZELIKE:
+ case CONSTRAINT_TYPE_MINMAX:
{
- bSizeLikeConstraint *data;
- data = (bSizeLikeConstraint*)con->data;
-
+ bMinMaxConstraint *data = (bMinMaxConstraint*)con->data;
+
if (data->tar) {
- constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
valid=1;
}
else
- Mat4One (mat);
+ Mat4One(mat);
}
break;
case CONSTRAINT_TYPE_TRACKTO:
{
bTrackToConstraint *data;
data = (bTrackToConstraint*)con->data;
-
+
if (data->tar) {
- constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
valid=1;
}
else
@@ -1087,13 +1344,13 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
{
bKinematicConstraint *data;
data = (bKinematicConstraint*)con->data;
-
+
if (data->tar) {
- constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
valid=1;
}
else if (data->flag & CONSTRAINT_IK_AUTO) {
- Object *ob= ownerdata;
+ Object *ob= (Object *)ownerdata;
if (ob==NULL)
Mat4One(mat);
@@ -1107,46 +1364,46 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
}
}
else
- Mat4One (mat);
+ Mat4One(mat);
}
break;
case CONSTRAINT_TYPE_LOCKTRACK:
{
bLockTrackConstraint *data;
data = (bLockTrackConstraint*)con->data;
-
+
if (data->tar) {
- constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
valid=1;
}
else
- Mat4One (mat);
+ Mat4One(mat);
}
break;
case CONSTRAINT_TYPE_FOLLOWPATH:
{
bFollowPathConstraint *data;
data = (bFollowPathConstraint*)con->data;
-
+
if (data->tar) {
Curve *cu;
- float q[4], vec[4], dir[3], *quat, x1, totmat[4][4];
+ float q[4], vec[4], dir[3], *quat, x1;
+ float totmat[4][4];
float curvetime;
-
- Mat4One (totmat);
- Mat4One (mat);
-
+
+ Mat4One(totmat);
+ Mat4One(mat);
+
cu= data->tar->data;
-
- /* note; when creating constraints that follow path, the curve gets the CU_PATH set now,
+
+ /* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
currently for paths to work it needs to go through the bevlist/displist system (ton) */
if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
makeDispListCurveTypes(data->tar, 0);
if (cu->path && cu->path->data) {
-
curvetime= bsystem_time(data->tar, data->tar->parent, (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);
@@ -1167,27 +1424,27 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
QuatToMat4(quat, totmat);
}
VECCOPY(totmat[3], vec);
-
+
Mat4MulSerie(mat, data->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
}
}
valid=1;
}
else
- Mat4One (mat);
+ Mat4One(mat);
}
break;
case CONSTRAINT_TYPE_STRETCHTO:
{
bStretchToConstraint *data;
data = (bStretchToConstraint*)con->data;
-
+
if (data->tar) {
- constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
valid = 1;
}
else
- Mat4One (mat);
+ Mat4One(mat);
}
break;
case CONSTRAINT_TYPE_PYTHON:
@@ -1207,11 +1464,11 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
/* if the script doesn't set the target matrix for any reason, fall back to standard methods */
if (BPY_pyconstraint_targets(data, mat) < 1) {
if (data->tar) {
- constraint_target_to_mat4(data->tar, data->subtarget, mat, size);
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
valid = 1;
}
else
- Mat4One (mat);
+ Mat4One(mat);
}
}
break;
@@ -1219,18 +1476,33 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
{
bClampToConstraint *data;
data = (bClampToConstraint*)con->data;
-
+
if (data->tar) {
Curve *cu= data->tar->data;
/* note; when creating constraints that follow path, the curve gets the CU_PATH set now,
currently for paths to work it needs to go through the bevlist/displist system (ton) */
- if(cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
+ if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
makeDispListCurveTypes(data->tar, 0);
+
+ valid = 1;
}
- Mat4One (mat);
+ Mat4One(mat);
+ }
+ break;
+ case CONSTRAINT_TYPE_CHILDOF:
+ {
+ bChildOfConstraint *data;
+ data= (bChildOfConstraint *)con->data;
+
+ if (data->tar) {
+ constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
+ valid = 1;
+ }
+ else
+ Mat4One(mat);
}
break;
@@ -1242,19 +1514,16 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
return valid;
}
-/* only called during solve_constraints */
-/* bone constraints create a fake object to work on, then ob is a workob */
-/* if ownerdata is set, it's the posechannel */
-void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, void *ownerdata, float targetmat[][4])
+/* ---------------------------------------------- Constraint Evaluation ------------------------------------------------- */
+
+/* This is only called during solve_constraints to solve a particular constraint.
+ * It works on ownermat, and uses targetmat to help accomplish its tasks.
+ */
+static void evaluate_constraint (bConstraint *constraint, float ownermat[][4], float targetmat[][4])
{
- float M_oldmat[4][4];
- float M_identity[4][4];
-
- if (!constraint || !ob)
+ if (constraint == NULL || constraint->data == NULL)
return;
-
- Mat4One (M_identity);
-
+
switch (constraint->type) {
case CONSTRAINT_TYPE_NULL:
case CONSTRAINT_TYPE_KINEMATIC: /* removed */
@@ -1263,8 +1532,8 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
{
bPythonConstraint *data;
- data= constraint->data;
- BPY_pyconstraint_eval(data, ob->obmat, ownertype, ownerdata, targetmat);
+ data = constraint->data;
+ BPY_pyconstraint_eval(data, ownermat, targetmat);
}
break;
case CONSTRAINT_TYPE_ACTION:
@@ -1273,9 +1542,9 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
float temp[4][4];
data = constraint->data;
- Mat4CpyMat4 (temp, ob->obmat);
+ Mat4CpyMat4(temp, ownermat);
- Mat4MulMat4(ob->obmat, targetmat, temp);
+ Mat4MulMat4(ownermat, targetmat, temp);
}
break;
case CONSTRAINT_TYPE_LOCLIKE:
@@ -1286,25 +1555,25 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
data = constraint->data;
if (data->flag & LOCLIKE_OFFSET)
- VECCOPY(offset, ob->obmat[3]);
+ VECCOPY(offset, ownermat[3]);
if (data->flag & LOCLIKE_X) {
- ob->obmat[3][0] = targetmat[3][0];
+ ownermat[3][0] = targetmat[3][0];
- if(data->flag & LOCLIKE_X_INVERT) ob->obmat[3][0] *= -1;
- ob->obmat[3][0] += offset[0];
+ if(data->flag & LOCLIKE_X_INVERT) ownermat[3][0] *= -1;
+ ownermat[3][0] += offset[0];
}
if (data->flag & LOCLIKE_Y) {
- ob->obmat[3][1] = targetmat[3][1];
+ ownermat[3][1] = targetmat[3][1];
- if(data->flag & LOCLIKE_Y_INVERT) ob->obmat[3][1] *= -1;
- ob->obmat[3][1] += offset[1];
+ if(data->flag & LOCLIKE_Y_INVERT) ownermat[3][1] *= -1;
+ ownermat[3][1] += offset[1];
}
if (data->flag & LOCLIKE_Z) {
- ob->obmat[3][2] = targetmat[3][2];
+ ownermat[3][2] = targetmat[3][2];
- if(data->flag & LOCLIKE_Z_INVERT) ob->obmat[3][2] *= -1;
- ob->obmat[3][2] += offset[2];
+ if(data->flag & LOCLIKE_Z_INVERT) ownermat[3][2] *= -1;
+ ownermat[3][2] += offset[2];
}
}
break;
@@ -1314,36 +1583,52 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
float loc[3];
float eul[3], obeul[3];
float size[3];
+ short changed= 0;
data = constraint->data;
- VECCOPY(loc, ob->obmat[3]);
- Mat4ToSize(ob->obmat, size);
+ VECCOPY(loc, ownermat[3]);
+ Mat4ToSize(ownermat, size);
Mat4ToEul(targetmat, eul);
- Mat4ToEul(ob->obmat, obeul);
-
- if(data->flag != (ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z)) {
- if(!(data->flag & ROTLIKE_X)) {
- eul[0]= obeul[0];
- }
- if(!(data->flag & ROTLIKE_Y)) {
- eul[1]= obeul[1];
- }
- if(!(data->flag & ROTLIKE_Z)) {
- eul[2]= obeul[2];
- }
- compatible_eul(eul, obeul);
+ Mat4ToEul(ownermat, obeul);
+
+ if ((data->flag & ROTLIKE_X)==0) {
+ eul[0] = obeul[0];
+ changed = 1;
+ }
+ else if (data->flag & ROTLIKE_X_INVERT) {
+ eul[0] *= -1;
+ changed = 1;
+ }
+ if ((data->flag & ROTLIKE_Y)==0) {
+ eul[1] = obeul[1];
+ changed = 1;
+ }
+ else if (data->flag & ROTLIKE_Y_INVERT) {
+ eul[1] *= -1;
+ changed = 1;
+ }
+ if ((data->flag & ROTLIKE_Z)==0) {
+ eul[2] = obeul[2];
+ changed = 1;
+ }
+ else if (data->flag & ROTLIKE_Z_INVERT) {
+ eul[2] *= -1;
+ changed = 1;
}
- if((data->flag & ROTLIKE_X) && (data->flag & ROTLIKE_X_INVERT))
- eul[0]*= -1;
- if((data->flag & ROTLIKE_Y) && (data->flag & ROTLIKE_Y_INVERT))
- eul[1]*= -1;
- if((data->flag & ROTLIKE_Z) && (data->flag & ROTLIKE_Z_INVERT))
- eul[2]*= -1;
- LocEulSizeToMat4(ob->obmat, loc, eul, size);
+ if (changed) {
+ compatible_eul(eul, obeul);
+ LocEulSizeToMat4(ownermat, loc, eul, size);
+ }
+ else {
+ float quat[4];
+
+ Mat4ToQuat(targetmat, quat);
+ LocQuatSizeToMat4(ownermat, loc, quat, size);
+ }
}
break;
case CONSTRAINT_TYPE_SIZELIKE:
@@ -1354,36 +1639,36 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
data = constraint->data;
Mat4ToSize(targetmat, size);
- Mat4ToSize(ob->obmat, obsize);
+ Mat4ToSize(ownermat, obsize);
- if (data->flag & SIZELIKE_X && obsize[0] != 0)
- VecMulf(ob->obmat[0], size[0] / obsize[0]);
- if (data->flag & SIZELIKE_Y && obsize[1] != 0)
- VecMulf(ob->obmat[1], size[1] / obsize[1]);
- if (data->flag & SIZELIKE_Z && obsize[2] != 0)
- VecMulf(ob->obmat[2], size[2] / obsize[2]);
+ if ((data->flag & SIZELIKE_X) && obsize[0] != 0)
+ VecMulf(ownermat[0], size[0] / obsize[0]);
+ if ((data->flag & SIZELIKE_Y) && obsize[1] != 0)
+ VecMulf(ownermat[1], size[1] / obsize[1]);
+ if ((data->flag & SIZELIKE_Z) && obsize[2] != 0)
+ VecMulf(ownermat[2], size[2] / obsize[2]);
}
break;
case CONSTRAINT_TYPE_MINMAX:
{
bMinMaxConstraint *data;
+ float obmat[4][4], imat[4][4], tarmat[4][4], tmat[4][4];
float val1, val2;
int index;
- float obmat[4][4],imat[4][4],tarmat[4][4],tmat[4][4];
-
+
data = constraint->data;
- Mat4CpyMat4(obmat,ob->obmat);
- Mat4CpyMat4(tarmat,targetmat);
+ Mat4CpyMat4(obmat, ownermat);
+ Mat4CpyMat4(tarmat, targetmat);
if (data->flag & MINMAX_USEROT) {
/* take rotation of target into account by doing the transaction in target's localspace */
- Mat4Invert(imat,tarmat);
- Mat4MulMat4(tmat,obmat,imat);
- Mat4CpyMat4(obmat,tmat);
+ Mat4Invert(imat, tarmat);
+ Mat4MulMat4(tmat, obmat, imat);
+ Mat4CpyMat4(obmat, tmat);
Mat4One(tarmat);
}
-
+
switch (data->minmaxflag) {
case TRACK_Z:
val1 = tarmat[3][2];
@@ -1432,11 +1717,11 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
}
if (data->flag & MINMAX_USEROT) {
/* get out of localspace */
- Mat4MulMat4(tmat,obmat,targetmat);
- Mat4CpyMat4(ob->obmat,tmat);
+ Mat4MulMat4(tmat, obmat, targetmat);
+ Mat4CpyMat4(ownermat, tmat);
}
else {
- VECCOPY(ob->obmat[3],obmat[3]);
+ VECCOPY(ownermat[3], obmat[3]);
}
}
else {
@@ -1447,8 +1732,7 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
case CONSTRAINT_TYPE_TRACKTO:
{
bTrackToConstraint *data;
- float size[3];
- float vec[3];
+ float size[3], vec[3];
float totmat[3][3];
float tmat[4][4];
@@ -1456,29 +1740,26 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
if (data->tar) {
/* Get size property, since ob->size is only the object's own relative size, not its global one */
- Mat4ToSize (ob->obmat, size);
-
- Mat4CpyMat4 (M_oldmat, ob->obmat);
+ Mat4ToSize (ownermat, size);
/* Clear the object's rotation */
- ob->obmat[0][0]=size[0];
- ob->obmat[0][1]=0;
- ob->obmat[0][2]=0;
- ob->obmat[1][0]=0;
- ob->obmat[1][1]=size[1];
- ob->obmat[1][2]=0;
- ob->obmat[2][0]=0;
- ob->obmat[2][1]=0;
- ob->obmat[2][2]=size[2];
+ ownermat[0][0]=size[0];
+ ownermat[0][1]=0;
+ ownermat[0][2]=0;
+ ownermat[1][0]=0;
+ ownermat[1][1]=size[1];
+ ownermat[1][2]=0;
+ ownermat[2][0]=0;
+ ownermat[2][1]=0;
+ ownermat[2][2]=size[2];
- VecSubf(vec, ob->obmat[3], targetmat[3]);
- vectomat(vec, targetmat[2],
+ VecSubf(vec, ownermat[3], targetmat[3]);
+ vectomat(vec, ownermat[2],
(short)data->reserved1, (short)data->reserved2,
data->flags, totmat);
- Mat4CpyMat4(tmat, ob->obmat);
-
- Mat4MulMat34(ob->obmat, totmat, tmat);
+ Mat4CpyMat4(tmat, ownermat);
+ Mat4MulMat34(ownermat, totmat, tmat);
}
}
break;
@@ -1495,10 +1776,8 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
data = constraint->data;
if (data->tar) {
- Mat4CpyMat4 (M_oldmat, ob->obmat);
-
/* Vector object -> target */
- VecSubf(vec, targetmat[3], ob->obmat[3]);
+ VecSubf(vec, targetmat[3], ownermat[3]);
switch (data->lockflag){
case LOCK_X: /* LOCK X */
{
@@ -1506,74 +1785,70 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
case TRACK_Y: /* LOCK X TRACK Y */
{
/* Projection of Vector on the plane */
- Projf(vec2, vec, ob->obmat[0]);
+ Projf(vec2, vec, ownermat[0]);
VecSubf(totmat[1], vec, vec2);
Normalize(totmat[1]);
- /* the x axis is fixed*/
- totmat[0][0] = ob->obmat[0][0];
- totmat[0][1] = ob->obmat[0][1];
- totmat[0][2] = ob->obmat[0][2];
+ /* the x axis is fixed */
+ totmat[0][0] = ownermat[0][0];
+ totmat[0][1] = ownermat[0][1];
+ totmat[0][2] = ownermat[0][2];
Normalize(totmat[0]);
- /* the z axis gets mapped onto
- a third orthogonal vector */
+ /* the z axis gets mapped onto a third orthogonal vector */
Crossf(totmat[2], totmat[0], totmat[1]);
}
break;
case TRACK_Z: /* LOCK X TRACK Z */
{
/* Projection of Vector on the plane */
- Projf(vec2, vec, ob->obmat[0]);
+ Projf(vec2, vec, ownermat[0]);
VecSubf(totmat[2], vec, vec2);
Normalize(totmat[2]);
- /* the x axis is fixed*/
- totmat[0][0] = ob->obmat[0][0];
- totmat[0][1] = ob->obmat[0][1];
- totmat[0][2] = ob->obmat[0][2];
+ /* the x axis is fixed */
+ totmat[0][0] = ownermat[0][0];
+ totmat[0][1] = ownermat[0][1];
+ totmat[0][2] = ownermat[0][2];
Normalize(totmat[0]);
- /* the z axis gets mapped onto
- a third orthogonal vector */
+ /* the z axis gets mapped onto a third orthogonal vector */
Crossf(totmat[1], totmat[2], totmat[0]);
}
break;
case TRACK_nY: /* LOCK X TRACK -Y */
{
/* Projection of Vector on the plane */
- Projf(vec2, vec, ob->obmat[0]);
+ Projf(vec2, vec, ownermat[0]);
VecSubf(totmat[1], vec, vec2);
Normalize(totmat[1]);
VecMulf(totmat[1],-1);
- /* the x axis is fixed*/
- totmat[0][0] = ob->obmat[0][0];
- totmat[0][1] = ob->obmat[0][1];
- totmat[0][2] = ob->obmat[0][2];
+ /* the x axis is fixed */
+ totmat[0][0] = ownermat[0][0];
+ totmat[0][1] = ownermat[0][1];
+ totmat[0][2] = ownermat[0][2];
Normalize(totmat[0]);
- /* the z axis gets mapped onto
- a third orthogonal vector */
+ /* the z axis gets mapped onto a third orthogonal vector */
Crossf(totmat[2], totmat[0], totmat[1]);
}
break;
case TRACK_nZ: /* LOCK X TRACK -Z */
{
/* Projection of Vector on the plane */
- Projf(vec2, vec, ob->obmat[0]);
+ Projf(vec2, vec, ownermat[0]);
VecSubf(totmat[2], vec, vec2);
Normalize(totmat[2]);
VecMulf(totmat[2],-1);
- /* the x axis is fixed*/
- totmat[0][0] = ob->obmat[0][0];
- totmat[0][1] = ob->obmat[0][1];
- totmat[0][2] = ob->obmat[0][2];
+ /* the x axis is fixed */
+ totmat[0][0] = ownermat[0][0];
+ totmat[0][1] = ownermat[0][1];
+ totmat[0][2] = ownermat[0][2];
Normalize(totmat[0]);
- /* the z axis gets mapped onto
- a third orthogonal vector */
+ /* the z axis gets mapped onto a third orthogonal vector */
Crossf(totmat[1], totmat[2], totmat[0]);
}
break;
@@ -1593,74 +1868,70 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
case TRACK_X: /* LOCK Y TRACK X */
{
/* Projection of Vector on the plane */
- Projf(vec2, vec, ob->obmat[1]);
+ Projf(vec2, vec, ownermat[1]);
VecSubf(totmat[0], vec, vec2);
Normalize(totmat[0]);
- /* the y axis is fixed*/
- totmat[1][0] = ob->obmat[1][0];
- totmat[1][1] = ob->obmat[1][1];
- totmat[1][2] = ob->obmat[1][2];
+ /* the y axis is fixed */
+ totmat[1][0] = ownermat[1][0];
+ totmat[1][1] = ownermat[1][1];
+ totmat[1][2] = ownermat[1][2];
Normalize(totmat[1]);
- /* the z axis gets mapped onto
- a third orthogonal vector */
+ /* the z axis gets mapped onto a third orthogonal vector */
Crossf(totmat[2], totmat[0], totmat[1]);
}
break;
case TRACK_Z: /* LOCK Y TRACK Z */
{
/* Projection of Vector on the plane */
- Projf(vec2, vec, ob->obmat[1]);
+ Projf(vec2, vec, ownermat[1]);
VecSubf(totmat[2], vec, vec2);
Normalize(totmat[2]);
- /* the y axis is fixed*/
- totmat[1][0] = ob->obmat[1][0];
- totmat[1][1] = ob->obmat[1][1];
- totmat[1][2] = ob->obmat[1][2];
+ /* the y axis is fixed */
+ totmat[1][0] = ownermat[1][0];
+ totmat[1][1] = ownermat[1][1];
+ totmat[1][2] = ownermat[1][2];
Normalize(totmat[1]);
- /* the z axis gets mapped onto
- a third orthogonal vector */
+ /* the z axis gets mapped onto a third orthogonal vector */
Crossf(totmat[0], totmat[1], totmat[2]);
}
break;
case TRACK_nX: /* LOCK Y TRACK -X */
{
/* Projection of Vector on the plane */
- Projf(vec2, vec, ob->obmat[1]);
+ Projf(vec2, vec, ownermat[1]);
VecSubf(totmat[0], vec, vec2);
Normalize(totmat[0]);
VecMulf(totmat[0],-1);
- /* the y axis is fixed*/
- totmat[1][0] = ob->obmat[1][0];
- totmat[1][1] = ob->obmat[1][1];
- totmat[1][2] = ob->obmat[1][2];
+ /* the y axis is fixed */
+ totmat[1][0] = ownermat[1][0];
+ totmat[1][1] = ownermat[1][1];
+ totmat[1][2] = ownermat[1][2];
Normalize(totmat[1]);
- /* the z axis gets mapped onto
- a third orthogonal vector */
+ /* the z axis gets mapped onto a third orthogonal vector */
Crossf(totmat[2], totmat[0], totmat[1]);
}
break;
case TRACK_nZ: /* LOCK Y TRACK -Z */
{
/* Projection of Vector on the plane */
- Projf(vec2, vec, ob->obmat[1]);
+ Projf(vec2, vec, ownermat[1]);
VecSubf(totmat[2], vec, vec2);
Normalize(totmat[2]);
VecMulf(totmat[2],-1);
- /* the y axis is fixed*/
- totmat[1][0] = ob->obmat[1][0];
- totmat[1][1] = ob->obmat[1][1];
- totmat[1][2] = ob->obmat[1][2];
+ /* the y axis is fixed */
+ totmat[1][0] = ownermat[1][0];
+ totmat[1][1] = ownermat[1][1];
+ totmat[1][2] = ownermat[1][2];
Normalize(totmat[1]);
- /* the z axis gets mapped onto
- a third orthogonal vector */
+ /* the z axis gets mapped onto a third orthogonal vector */
Crossf(totmat[0], totmat[1], totmat[2]);
}
break;
@@ -1680,74 +1951,70 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
case TRACK_X: /* LOCK Z TRACK X */
{
/* Projection of Vector on the plane */
- Projf(vec2, vec, ob->obmat[2]);
+ Projf(vec2, vec, ownermat[2]);
VecSubf(totmat[0], vec, vec2);
Normalize(totmat[0]);
- /* the z axis is fixed*/
- totmat[2][0] = ob->obmat[2][0];
- totmat[2][1] = ob->obmat[2][1];
- totmat[2][2] = ob->obmat[2][2];
+ /* the z axis is fixed */
+ totmat[2][0] = ownermat[2][0];
+ totmat[2][1] = ownermat[2][1];
+ totmat[2][2] = ownermat[2][2];
Normalize(totmat[2]);
- /* the x axis gets mapped onto
- a third orthogonal vector */
+ /* the x axis gets mapped onto a third orthogonal vector */
Crossf(totmat[1], totmat[2], totmat[0]);
}
break;
case TRACK_Y: /* LOCK Z TRACK Y */
{
/* Projection of Vector on the plane */
- Projf(vec2, vec, ob->obmat[2]);
+ Projf(vec2, vec, ownermat[2]);
VecSubf(totmat[1], vec, vec2);
Normalize(totmat[1]);
- /* the z axis is fixed*/
- totmat[2][0] = ob->obmat[2][0];
- totmat[2][1] = ob->obmat[2][1];
- totmat[2][2] = ob->obmat[2][2];
+ /* the z axis is fixed */
+ totmat[2][0] = ownermat[2][0];
+ totmat[2][1] = ownermat[2][1];
+ totmat[2][2] = ownermat[2][2];
Normalize(totmat[2]);
- /* the x axis gets mapped onto
- a third orthogonal vector */
+ /* the x axis gets mapped onto a third orthogonal vector */
Crossf(totmat[0], totmat[1], totmat[2]);
}
break;
case TRACK_nX: /* LOCK Z TRACK -X */
{
/* Projection of Vector on the plane */
- Projf(vec2, vec, ob->obmat[2]);
+ Projf(vec2, vec, ownermat[2]);
VecSubf(totmat[0], vec, vec2);
Normalize(totmat[0]);
VecMulf(totmat[0],-1);
- /* the z axis is fixed*/
- totmat[2][0] = ob->obmat[2][0];
- totmat[2][1] = ob->obmat[2][1];
- totmat[2][2] = ob->obmat[2][2];
+ /* the z axis is fixed */
+ totmat[2][0] = ownermat[2][0];
+ totmat[2][1] = ownermat[2][1];
+ totmat[2][2] = ownermat[2][2];
Normalize(totmat[2]);
- /* the x axis gets mapped onto
- a third orthogonal vector */
+ /* the x axis gets mapped onto a third orthogonal vector */
Crossf(totmat[1], totmat[2], totmat[0]);
}
break;
case TRACK_nY: /* LOCK Z TRACK -Y */
{
/* Projection of Vector on the plane */
- Projf(vec2, vec, ob->obmat[2]);
+ Projf(vec2, vec, ownermat[2]);
VecSubf(totmat[1], vec, vec2);
Normalize(totmat[1]);
VecMulf(totmat[1],-1);
- /* the z axis is fixed*/
- totmat[2][0] = ob->obmat[2][0];
- totmat[2][1] = ob->obmat[2][1];
- totmat[2][2] = ob->obmat[2][2];
+ /* the z axis is fixed */
+ totmat[2][0] = ownermat[2][0];
+ totmat[2][1] = ownermat[2][1];
+ totmat[2][2] = ownermat[2][2];
Normalize(totmat[2]);
- /* the x axis gets mapped onto
- a third orthogonal vector */
+ /* the x axis gets mapped onto a third orthogonal vector */
Crossf(totmat[0], totmat[1], totmat[2]);
}
break;
@@ -1770,19 +2037,19 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
break;
}
/* Block to keep matrix heading */
- tmpmat[0][0] = ob->obmat[0][0];tmpmat[0][1] = ob->obmat[0][1];tmpmat[0][2] = ob->obmat[0][2];
- tmpmat[1][0] = ob->obmat[1][0];tmpmat[1][1] = ob->obmat[1][1];tmpmat[1][2] = ob->obmat[1][2];
- tmpmat[2][0] = ob->obmat[2][0];tmpmat[2][1] = ob->obmat[2][1];tmpmat[2][2] = ob->obmat[2][2];
+ tmpmat[0][0] = ownermat[0][0];tmpmat[0][1] = ownermat[0][1];tmpmat[0][2] = ownermat[0][2];
+ tmpmat[1][0] = ownermat[1][0];tmpmat[1][1] = ownermat[1][1];tmpmat[1][2] = ownermat[1][2];
+ tmpmat[2][0] = ownermat[2][0];tmpmat[2][1] = ownermat[2][1];tmpmat[2][2] = ownermat[2][2];
Normalize(tmpmat[0]);
Normalize(tmpmat[1]);
Normalize(tmpmat[2]);
Mat3Inv(invmat,tmpmat);
- Mat3MulMat3(tmpmat,totmat,invmat);
+ Mat3MulMat3(tmpmat, totmat, invmat);
totmat[0][0] = tmpmat[0][0];totmat[0][1] = tmpmat[0][1];totmat[0][2] = tmpmat[0][2];
totmat[1][0] = tmpmat[1][0];totmat[1][1] = tmpmat[1][1];totmat[1][2] = tmpmat[1][2];
totmat[2][0] = tmpmat[2][0];totmat[2][1] = tmpmat[2][1];totmat[2][2] = tmpmat[2][2];
- Mat4CpyMat4(tmat, ob->obmat);
+ Mat4CpyMat4(tmat, ownermat);
mdet = Det3x3( totmat[0][0],totmat[0][1],totmat[0][2],
totmat[1][0],totmat[1][1],totmat[1][2],
@@ -1795,7 +2062,7 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
}
/* apply out transformaton to the object */
- Mat4MulMat34(ob->obmat, totmat, tmat);
+ Mat4MulMat34(ownermat, totmat, tmat);
}
}
break;
@@ -1804,27 +2071,28 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
bFollowPathConstraint *data;
float obmat[4][4];
float size[3], obsize[3];
-
+
data = constraint->data;
-
+
if (data->tar) {
/* get Object local transform (loc/rot/size) to determine transformation from path */
- object_to_mat4(ob, obmat);
+ //object_to_mat4(ob, obmat);
+ Mat4CpyMat4(obmat, ownermat); // FIXME!!!
/* get scaling of object before applying constraint */
- Mat4ToSize(ob->obmat, size);
-
+ Mat4ToSize(ownermat, size);
+
/* apply targetmat - containing location on path, and rotation */
- Mat4MulSerie(ob->obmat, targetmat, obmat, NULL, NULL, NULL, NULL, NULL, NULL);
+ Mat4MulSerie(ownermat, targetmat, obmat, NULL, NULL, NULL, NULL, NULL, NULL);
/* un-apply scaling caused by path */
- Mat4ToSize(ob->obmat, obsize);
+ Mat4ToSize(ownermat, obsize);
if (obsize[0] != 0)
- VecMulf(ob->obmat[0], size[0] / obsize[0]);
+ VecMulf(ownermat[0], size[0] / obsize[0]);
if (obsize[1] != 0)
- VecMulf(ob->obmat[1], size[1] / obsize[1]);
+ VecMulf(ownermat[1], size[1] / obsize[1]);
if (obsize[2] != 0)
- VecMulf(ob->obmat[2], size[2] / obsize[2]);
+ VecMulf(ownermat[2], size[2] / obsize[2]);
}
}
break;
@@ -1837,22 +2105,22 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
float dist;
data = constraint->data;
- Mat4ToSize (ob->obmat, size);
+ Mat4ToSize (ownermat, size);
if (data->tar) {
/* store X orientation before destroying obmat */
- xx[0] = ob->obmat[0][0];
- xx[1] = ob->obmat[0][1];
- xx[2] = ob->obmat[0][2];
+ xx[0] = ownermat[0][0];
+ xx[1] = ownermat[0][1];
+ xx[2] = ownermat[0][2];
Normalize(xx);
/* store Z orientation before destroying obmat */
- zz[0] = ob->obmat[2][0];
- zz[1] = ob->obmat[2][1];
- zz[2] = ob->obmat[2][2];
+ zz[0] = ownermat[2][0];
+ zz[1] = ownermat[2][1];
+ zz[2] = ownermat[2][2];
Normalize(zz);
- VecSubf(vec, ob->obmat[3], targetmat[3]);
+ VecSubf(vec, ownermat[3], targetmat[3]);
vec[0] /= size[0];
vec[1] /= size[1];
vec[2] /= size[2];
@@ -1888,18 +2156,19 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
} /* switch (data->volmode) */
/* Clear the object's rotation and scale */
- ob->obmat[0][0]=size[0]*scale[0];
- ob->obmat[0][1]=0;
- ob->obmat[0][2]=0;
- ob->obmat[1][0]=0;
- ob->obmat[1][1]=size[1]*scale[1];
- ob->obmat[1][2]=0;
- ob->obmat[2][0]=0;
- ob->obmat[2][1]=0;
- ob->obmat[2][2]=size[2]*scale[2];
+ ownermat[0][0]=size[0]*scale[0];
+ ownermat[0][1]=0;
+ ownermat[0][2]=0;
+ ownermat[1][0]=0;
+ ownermat[1][1]=size[1]*scale[1];
+ ownermat[1][2]=0;
+ ownermat[2][0]=0;
+ ownermat[2][1]=0;
+ ownermat[2][2]=size[2]*scale[2];
- VecSubf(vec, ob->obmat[3], targetmat[3]);
- Normalize(vec);
+ VecSubf(vec, ownermat[3], targetmat[3]);
+ Normalize(vec);
+
/* new Y aligns object target connection*/
totmat[1][0] = -vec[0];
totmat[1][1] = -vec[1];
@@ -1917,7 +2186,7 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
totmat[2][2] = orth[2];
/* we decided to keep X plane*/
- Crossf(xx,orth, vec);
+ Crossf(xx, orth, vec);
Normalize(xx);
totmat[0][0] = xx[0];
totmat[0][1] = xx[1];
@@ -1935,7 +2204,7 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
totmat[0][2] = -orth[2];
/* we decided to keep Z */
- Crossf(zz,orth, vec);
+ Crossf(zz, orth, vec);
Normalize(zz);
totmat[2][0] = zz[0];
totmat[2][1] = zz[1];
@@ -1943,9 +2212,9 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
break;
} /* switch (data->plane) */
- Mat4CpyMat4(tmat, ob->obmat);
-
- Mat4MulMat34(ob->obmat, totmat, tmat);
+ Mat4CpyMat4(tmat, ownermat);
+
+ Mat4MulMat34(ownermat, totmat, tmat);
}
}
break;
@@ -1955,79 +2224,29 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
data = constraint->data;
- /* limit location relative to origin or parent */
- if ((data->flag2 & LIMIT_NOPARENT) && ob->parent) {
- /* limiting relative to parent */
- float parmat[4][4]; /* matrix of parent */
- float objLoc[3], parLoc[3]; /* location of object, and location of parent */
- float relLoc[3]; /* objLoc - parLoc*/
-
- /* get matrix of parent */
- Mat4CpyMat4(parmat, ob->parent->obmat);
-
- /* get locations as vectors */
- objLoc[0] = ob->obmat[3][0];
- objLoc[1] = ob->obmat[3][1];
- objLoc[2] = ob->obmat[3][2];
-
- parLoc[0] = parmat[3][0];
- parLoc[1] = parmat[3][1];
- parLoc[2] = parmat[3][2];
-
- /* get relative location of obj from parent */
- VecSubf(relLoc, objLoc, parLoc);
-
- /* limiting location */
- if (data->flag & LIMIT_XMIN) {
- if(relLoc[0] < data->xmin)
- ob->obmat[3][0] = (parLoc[0]+data->xmin);
- }
- if (data->flag & LIMIT_XMAX) {
- if (relLoc[0] > data->xmax)
- ob->obmat[3][0] = (parLoc[0]+data->xmax);
- }
- if (data->flag & LIMIT_YMIN) {
- if(relLoc[1] < data->ymin)
- ob->obmat[3][1] = (parLoc[1]+data->ymin);
- }
- if (data->flag & LIMIT_YMAX) {
- if (relLoc[1] > data->ymax)
- ob->obmat[3][1] = (parLoc[1]+data->ymax);
- }
- if (data->flag & LIMIT_ZMIN) {
- if(relLoc[2] < data->zmin)
- ob->obmat[3][2] = (parLoc[2]+data->zmin);
- }
- if (data->flag & LIMIT_ZMAX) {
- if (relLoc[2] > data->zmax)
- ob->obmat[3][2] = (parLoc[2]+data->zmax);
- }
- } else {
- /* limiting relative to origin */
- if (data->flag & LIMIT_XMIN) {
- if(ob->obmat[3][0] < data->xmin)
- ob->obmat[3][0] = data->xmin;
- }
- if (data->flag & LIMIT_XMAX) {
- if (ob->obmat[3][0] > data->xmax)
- ob->obmat[3][0] = data->xmax;
- }
- if (data->flag & LIMIT_YMIN) {
- if(ob->obmat[3][1] < data->ymin)
- ob->obmat[3][1] = data->ymin;
- }
- if (data->flag & LIMIT_YMAX) {
- if (ob->obmat[3][1] > data->ymax)
- ob->obmat[3][1] = data->ymax;
- }
- if (data->flag & LIMIT_ZMIN) {
- if(ob->obmat[3][2] < data->zmin)
- ob->obmat[3][2] = data->zmin;
- }
- if (data->flag & LIMIT_ZMAX) {
- if (ob->obmat[3][2] > data->zmax)
- ob->obmat[3][2] = data->zmax;
- }
+ if (data->flag & LIMIT_XMIN) {
+ if(ownermat[3][0] < data->xmin)
+ ownermat[3][0] = data->xmin;
+ }
+ if (data->flag & LIMIT_XMAX) {
+ if (ownermat[3][0] > data->xmax)
+ ownermat[3][0] = data->xmax;
+ }
+ if (data->flag & LIMIT_YMIN) {
+ if(ownermat[3][1] < data->ymin)
+ ownermat[3][1] = data->ymin;
+ }
+ if (data->flag & LIMIT_YMAX) {
+ if (ownermat[3][1] > data->ymax)
+ ownermat[3][1] = data->ymax;
+ }
+ if (data->flag & LIMIT_ZMIN) {
+ if(ownermat[3][2] < data->zmin)
+ ownermat[3][2] = data->zmin;
+ }
+ if (data->flag & LIMIT_ZMAX) {
+ if (ownermat[3][2] > data->zmax)
+ ownermat[3][2] = data->zmax;
}
}
break;
@@ -2040,10 +2259,10 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
data = constraint->data;
- VECCOPY(loc, ob->obmat[3]);
- Mat4ToSize(ob->obmat, size);
+ VECCOPY(loc, ownermat[3]);
+ Mat4ToSize(ownermat, size);
- Mat4ToEul(ob->obmat, eul);
+ Mat4ToEul(ownermat, eul);
/* eulers: radians to degrees! */
eul[0] = (eul[0] / M_PI * 180);
@@ -2078,85 +2297,52 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
eul[1] = (eul[1] / 180 * M_PI);
eul[2] = (eul[2] / 180 * M_PI);
- LocEulSizeToMat4(ob->obmat, loc, eul, size);
+ LocEulSizeToMat4(ownermat, loc, eul, size);
}
break;
case CONSTRAINT_TYPE_SIZELIMIT:
{
bSizeLimitConstraint *data;
float obsize[3], size[3];
- int clearNegScale=0;
data = constraint->data;
- Mat4ToSize(ob->obmat, size);
- Mat4ToSize(ob->obmat, obsize);
+ Mat4ToSize(ownermat, size);
+ Mat4ToSize(ownermat, obsize);
if (data->flag & LIMIT_XMIN) {
- if (ob->transflag & OB_NEG_SCALE) {
- size[0] *= -1;
-
- if (size[0] < data->xmin) {
- size[0] = data->xmin;
- clearNegScale += 1;
- }
- } else {
- if (size[0] < data->xmin)
- size[0] = data->xmin;
- }
+ if (size[0] < data->xmin)
+ size[0] = data->xmin;
}
if (data->flag & LIMIT_XMAX) {
if (size[0] > data->xmax)
size[0] = data->xmax;
}
if (data->flag & LIMIT_YMIN) {
- if (ob->transflag & OB_NEG_SCALE) {
- size[1] *= -1;
-
- if (size[1] < data->ymin) {
- size[1] = data->ymin;
- clearNegScale += 1;
- }
- } else {
- if (size[1] < data->ymin)
- size[1] = data->ymin;
- }
+ if (size[1] < data->ymin)
+ size[1] = data->ymin;
}
if (data->flag & LIMIT_YMAX) {
if (size[1] > data->ymax)
size[1] = data->ymax;
}
if (data->flag & LIMIT_ZMIN) {
- if (ob->transflag & OB_NEG_SCALE) {
- size[2] *= -1;
-
- if (size[2] < data->zmin) {
- size[2] = data->zmin;
- clearNegScale += 1;
- }
- } else {
- if (size[2] < data->zmin)
- size[2] = data->zmin;
- }
+ if (size[2] < data->zmin)
+ size[2] = data->zmin;
}
if (data->flag & LIMIT_ZMAX) {
if (size[2] > data->zmax)
size[2] = data->zmax;
}
- if (clearNegScale != 0) {
- ob->transflag &= ~OB_NEG_SCALE; /* is this how we remove that flag? */
- }
-
- VecMulf(ob->obmat[0], size[0]/obsize[0]);
- VecMulf(ob->obmat[1], size[1]/obsize[1]);
- VecMulf(ob->obmat[2], size[2]/obsize[2]);
+ VecMulf(ownermat[0], size[0]/obsize[0]);
+ VecMulf(ownermat[1], size[1]/obsize[1]);
+ VecMulf(ownermat[2], size[2]/obsize[2]);
}
break;
case CONSTRAINT_TYPE_RIGIDBODYJOINT:
{
-
-
+ /* Do nothing. The GameEngine will take care of this.*/
}
break;
case CONSTRAINT_TYPE_CLAMPTO:
@@ -2174,7 +2360,7 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
else
cu= data->tar->data;
- Mat4CpyMat4(obmat, ob->obmat);
+ Mat4CpyMat4(obmat, ownermat);
Mat4One(targetMatrix);
VECCOPY(ownLoc, obmat[3]);
@@ -2182,7 +2368,7 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
minmax_object(data->tar, curveMin, curveMax);
/* get targetmatrix */
- if(cu->path && cu->path->data) {
+ if (cu->path && cu->path->data) {
float vec[4], dir[3], totmat[4][4];
float curvetime;
short clamp_axis;
@@ -2214,7 +2400,7 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
else if (ownLoc[clamp_axis] >= curveMax[clamp_axis])
curvetime = 1.0;
else
- curvetime = (ownLoc[clamp_axis] - curveMin[clamp_axis]) / (curveMax[clamp_axis] - curveMin[clamp_axis]); // umm
+ curvetime = (ownLoc[clamp_axis] - curveMin[clamp_axis]) / (curveMax[clamp_axis] - curveMin[clamp_axis]);
/* 3. position on curve */
if(where_on_path(data->tar, curvetime, vec, dir) ) {
@@ -2226,7 +2412,59 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
}
/* obtain final object position */
- VECCOPY(ob->obmat[3], targetMatrix[3]);
+ VECCOPY(ownermat[3], targetMatrix[3]);
+ }
+ break;
+ case CONSTRAINT_TYPE_CHILDOF:
+ {
+ bChildOfConstraint *data;
+
+ data = constraint->data;
+
+ /* only evaluate if there is a target */
+ if (data->tar) {
+ float parmat[4][4], invmat[4][4], tempmat[4][4];
+ float loc[3], eul[3], size[3];
+ float loco[3], eulo[3], sizo[3];
+
+ /* get offset (parent-inverse) matrix */
+ Mat4CpyMat4(invmat, data->invmat);
+
+ /* extract components of both matrices */
+ VECCOPY(loc, targetmat[3]);
+ Mat4ToEul(targetmat, eul);
+ Mat4ToSize(targetmat, size);
+
+ VECCOPY(loco, invmat[3]);
+ Mat4ToEul(invmat, eulo);
+ Mat4ToSize(invmat, sizo);
+
+ /* disable channels not enabled */
+ if (!(data->flag & CHILDOF_LOCX)) loc[0]= loco[0]= 0.0f;
+ if (!(data->flag & CHILDOF_LOCY)) loc[1]= loco[1]= 0.0f;
+ if (!(data->flag & CHILDOF_LOCZ)) loc[2]= loco[2]= 0.0f;
+ if (!(data->flag & CHILDOF_ROTX)) eul[0]= eulo[0]= 0.0f;
+ if (!(data->flag & CHILDOF_ROTY)) eul[1]= eulo[1]= 0.0f;
+ if (!(data->flag & CHILDOF_ROTZ)) eul[2]= eulo[2]= 0.0f;
+ if (!(data->flag & CHILDOF_SIZEX)) size[0]= sizo[0]= 1.0f;
+ if (!(data->flag & CHILDOF_SIZEY)) size[1]= sizo[1]= 1.0f;
+ if (!(data->flag & CHILDOF_SIZEZ)) size[2]= sizo[2]= 1.0f;
+
+ /* make new target mat and offset mat */
+ LocEulSizeToMat4(targetmat, loc, eul, size);
+ LocEulSizeToMat4(invmat, loco, eulo, sizo);
+
+ /* multiply target (parent matrix) by offset (parent inverse) to get
+ * the effect of the parent that will be exherted on the owner
+ */
+ Mat4MulMat4(parmat, invmat, targetmat);
+
+ /* now multiply the parent matrix by the owner matrix to get the
+ * the effect of this constraint (i.e. owner is 'parented' to parent)
+ */
+ Mat4CpyMat4(tempmat, ownermat);
+ Mat4MulMat4(ownermat, tempmat, parmat);
+ }
}
break;
default:
@@ -2234,3 +2472,65 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
break;
}
}
+
+/* this function is called whenever constraints need to be evaluated */
+void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime)
+{
+ bConstraint *con;
+ void *ownerdata;
+ float tarmat[4][4], oldmat[4][4];
+ float solution[4][4], delta[4][4], imat[4][4];
+ float enf;
+
+ /* check that there is a valid constraint object to evaluate */
+ if (cob == NULL)
+ return;
+
+ /* loop over available constraints, solving and blending them */
+ for (con= conlist->first; con; con= con->next) {
+ /* this we can skip completely */
+ if (con->flag & CONSTRAINT_DISABLE) continue;
+ /* and inverse kinematics is solved seperate */
+ if (con->type==CONSTRAINT_TYPE_KINEMATIC) continue;
+ /* rigidbody is really a game-engine thing - and is not solved here */
+ if (con->type==CONSTRAINT_TYPE_RIGIDBODYJOINT) continue;
+
+ /* influence of constraint */
+ /* value should have been set from IPO's/Constraint Channels already */
+ enf = con->enforce;
+
+ /* move target/owner into right spaces */
+ constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace);
+
+ /* Get the target matrix */
+ ownerdata= ((cob->pchan)? (void *)cob->pchan : (void *)cob->ob);
+ get_constraint_target_matrix(con, cob->type, ownerdata, tarmat, ctime);
+
+ Mat4CpyMat4(oldmat, cob->matrix);
+
+ /* solve the constraint */
+ evaluate_constraint(con, cob->matrix, tarmat);
+
+ /* Interpolate the enforcement, to blend result of constraint into final owner transform */
+ /* 1. Remove effects of original matrix from constraint solution ==> delta */
+ Mat4Invert(imat, oldmat);
+ Mat4CpyMat4(solution, cob->matrix);
+ Mat4MulMat4(delta, solution, imat);
+
+ /* 2. If constraint influence is not full strength, then interpolate
+ * identity_matrix --> delta_matrix to get the effect the constraint actually exerts
+ */
+ if (enf < 1.0) {
+ float identity[4][4];
+ Mat4One(identity);
+ Mat4BlendMat4(delta, identity, delta, enf);
+ }
+
+ /* 3. Now multiply the delta by the matrix in use before the evaluation */
+ Mat4MulMat4(cob->matrix, delta, oldmat);
+
+ /* move target/owner back into worldspace for next constraint/other business */
+ if ((con->flag & CONSTRAINT_SPACEONCE) == 0)
+ constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD);
+ }
+}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 713ee3b2f5d..922931ca0b8 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -772,6 +772,7 @@ Object *add_only_object(int type, char *name)
ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0;
ob->size[0]= ob->size[1]= ob->size[2]= 1.0;
+ Mat4One(ob->constinv);
Mat4One(ob->parentinv);
Mat4One(ob->obmat);
ob->dt= OB_SHADED;
@@ -1560,9 +1561,18 @@ void where_is_object_time(Object *ob, float ctime)
}
- /* constraints need ctime, not stime. it calls where_is_object_time and bsystem_time */
- solve_constraints (ob, TARGET_OBJECT, NULL, ctime);
-
+ /* solve constraints */
+ if (ob->constraints.first) {
+ bConstraintOb *cob;
+
+ cob= constraints_make_evalob(ob, NULL, TARGET_OBJECT);
+
+ /* constraints need ctime, not stime. Some call where_is_object_time and bsystem_time */
+ solve_constraints (&ob->constraints, cob, ctime);
+
+ constraints_clear_evalob(cob);
+ }
+
if(ob->scriptlink.totscript && !during_script()) {
if (G.f & G_DOSCRIPTLINKS) BPY_do_pyscript((ID *)ob, SCRIPT_REDRAW);
}
@@ -1728,122 +1738,17 @@ for a lamp that is the child of another object */
if(ob->track)
solve_tracking(ob, ob->track->obmat);
- solve_constraints(ob, TARGET_OBJECT, NULL, G.scene->r.cfra);
+ /* solve constraints */
+ if (ob->constraints.first) {
+ bConstraintOb *cob;
+
+ cob= constraints_make_evalob(ob, NULL, TARGET_OBJECT);
+ solve_constraints (&ob->constraints, cob, G.scene->r.cfra);
+ constraints_clear_evalob(cob);
+ }
/* WATCH IT!!! */
ob->ipo= ipo;
-
-}
-
-void solve_constraints (Object *ob, short obtype, void *obdata, float ctime)
-{
- bConstraint *con;
- float tmat[4][4], focusmat[4][4], lastmat[4][4];
- int i, clear=1, tot=0;
- float a=0;
- float aquat[4], quat[4];
- float aloc[3], loc[3];
- float asize[3], size[3];
- float oldmat[4][4];
- float smat[3][3], rmat[3][3], mat[3][3];
- float enf;
-
- for (con = ob->constraints.first; con; con=con->next) {
- // inverse kinematics is solved seperate
- if (con->type==CONSTRAINT_TYPE_KINEMATIC) continue;
- // and this we can skip completely
- if (con->flag & CONSTRAINT_DISABLE) continue;
- // local constraints are handled in armature.c only
- if (con->flag & CONSTRAINT_LOCAL) continue;
-
- /* Clear accumulators if necessary*/
- if (clear) {
- clear= 0;
- a= 0;
- tot= 0;
- memset(aquat, 0, sizeof(float)*4);
- memset(aloc, 0, sizeof(float)*3);
- memset(asize, 0, sizeof(float)*3);
- }
-
- enf = con->enforce; // value from ipos (from action channels)
-
- /* Get the targetmat */
- get_constraint_target_matrix(con, obtype, obdata, tmat, size, ctime);
-
- Mat4CpyMat4(focusmat, tmat);
-
- /* Extract the components & accumulate */
- Mat4ToQuat(focusmat, quat);
- VECCOPY(loc, focusmat[3]);
- Mat3CpyMat4(mat, focusmat);
- Mat3ToSize(mat, size);
-
- a+= enf;
- tot++;
-
- for(i=0; i<3; i++) {
- aquat[i+1]+=(quat[i+1]) * enf;
- aloc[i]+=(loc[i]) * enf;
- asize[i]+=(size[i]-1.0f) * enf;
- }
- aquat[0]+=(quat[0])*enf;
- Mat4CpyMat4(lastmat, focusmat);
-
- /* removed for now, probably becomes option? (ton) */
-
- /* If the next constraint is not the same type (or there isn't one),
- * then evaluate the accumulator & request a clear */
- if (TRUE) { //(!con->next)||(con->next && con->next->type!=con->type)) {
- clear= 1;
- Mat4CpyMat4(oldmat, ob->obmat);
-
- /* If we have several inputs, do a blend of them */
- if (tot) {
- if (tot>1) {
- if (a) {
- for (i=0; i<3; i++) {
- asize[i]=1.0f + (asize[i]/(a));
- aloc[i]=(aloc[i]/a);
- }
-
- NormalQuat(aquat);
-
- QuatToMat3(aquat, rmat);
- SizeToMat3(asize, smat);
- Mat3MulMat3(mat, rmat, smat);
- Mat4CpyMat3(focusmat, mat);
- VECCOPY(focusmat[3], aloc);
-
- evaluate_constraint(con, ob, obtype, obdata, focusmat);
- }
-
- }
- /* If we only have one, blend with the current obmat */
- else {
- float solution[4][4];
- float delta[4][4];
- float imat[4][4];
- float identity[4][4];
-
- /* solve the constraint then blend it to the previous one */
- evaluate_constraint(con, ob, obtype, obdata, lastmat);
-
- Mat4CpyMat4 (solution, ob->obmat);
-
- /* Interpolate the enforcement */
- Mat4Invert (imat, oldmat);
- Mat4MulMat4 (delta, solution, imat);
-
- if (a<1.0) {
- Mat4One(identity);
- Mat4BlendMat4(delta, identity, delta, a);
- }
- Mat4MulMat4 (ob->obmat, delta, oldmat);
- }
- }
- }
- }
}
/* for calculation of the inverse parent transform, only used for editor */
@@ -1853,6 +1758,7 @@ void what_does_parent(Object *ob)
clear_workob();
Mat4One(workob.obmat);
Mat4One(workob.parentinv);
+ Mat4One(workob.constinv);
workob.parent= ob->parent;
workob.track= ob->track;
diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h
index 1c476c08984..4ee01f7fe33 100644
--- a/source/blender/blenlib/BLI_arithb.h
+++ b/source/blender/blenlib/BLI_arithb.h
@@ -221,6 +221,7 @@ void Mat3TransMulVecfl(float mat[][3], float *vec);
void VecUpMat3old(float *vec, float mat[][3], short axis);
void VecUpMat3(float *vec, float mat[][3], short axis);
void VecRotToMat3(float *vec, float phi, float mat[][3]);
+void VecRotToMat4(float *vec, float phi, float mat[][4]);
void VecCopyf(float *v1, float *v2);
int VecLen(int *v1, int *v2);
@@ -325,6 +326,7 @@ void i_rotate(float angle, char axis, float mat[][4]);
void MinMax3(float *min, float *max, float *vec);
void SizeToMat3(float *size, float mat[][3]);
+void SizeToMat4(float *size, float mat[][4]);
void printmatrix3(char *str, float m[][3]);
void printmatrix4(char *str, float m[][4]);
diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c
index c700f901ea3..125c24a7ada 100644
--- a/source/blender/blenlib/intern/arithb.c
+++ b/source/blender/blenlib/intern/arithb.c
@@ -765,39 +765,22 @@ void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweig
float squat[4], dquat[4], fquat[4];
float ssize[3], dsize[3], fsize[4];
float sloc[3], dloc[3], floc[3];
- float mat3[3][3], dstweight;
- float qmat[3][3], smat[3][3];
- int i;
-
- dstweight = 1.0F-srcweight;
-
- Mat3CpyMat4(mat3, dst);
- Mat3ToQuat(mat3, dquat);
- Mat3ToSize(mat3, dsize);
+
+ Mat4ToQuat(dst, dquat);
+ Mat4ToSize(dst, dsize);
VecCopyf(dloc, dst[3]);
- Mat3CpyMat4(mat3, src);
- Mat3ToQuat(mat3, squat);
- Mat3ToSize(mat3, ssize);
+ Mat4ToQuat(src, squat);
+ Mat4ToSize(src, ssize);
VecCopyf(sloc, src[3]);
- /* Do the actual blend */
- for (i=0; i<3; i++){
- floc[i] = (dloc[i]*dstweight) + (sloc[i]*srcweight);
- fsize[i] = 1.0f + ((dsize[i]-1.0f)*dstweight) + ((ssize[i]-1.0f)*srcweight);
- fquat[i+1] = (dquat[i+1]*dstweight) + (squat[i+1]*srcweight);
- }
-
- /* Do one more iteration for the quaternions only and normalize the quaternion if needed */
- fquat[0] = 1.0f + ((dquat[0]-1.0f)*dstweight) + ((squat[0]-1.0f)*srcweight);
- NormalQuat (fquat);
+ /* do blending */
+ VecLerpf(floc, dloc, sloc, srcweight);
+ QuatInterpol(fquat, dquat, squat, srcweight);
+ VecLerpf(fsize, dsize, ssize, srcweight);
- QuatToMat3(fquat, qmat);
- SizeToMat3(fsize, smat);
-
- Mat3MulMat3(mat3, qmat, smat);
- Mat4CpyMat3(out, mat3);
- VecCopyf(out[3], floc);
+ /* compose new matrix */
+ LocQuatSizeToMat4(out, floc, fquat, fsize);
}
void Mat4Clr(float *m)
@@ -2428,6 +2411,15 @@ void VecRotToMat3( float *vec, float phi, float mat[][3])
}
+void VecRotToMat4( float *vec, float phi, float mat[][4])
+{
+ float tmat[3][3];
+
+ VecRotToMat3(vec, phi, tmat);
+ Mat4One(mat);
+ Mat4CpyMat3(mat, tmat);
+}
+
void VecRotToQuat( float *vec, float phi, float *quat)
{
/* rotation of phi radials around vec */
@@ -2436,7 +2428,7 @@ void VecRotToQuat( float *vec, float phi, float *quat)
quat[1]= vec[0];
quat[2]= vec[1];
quat[3]= vec[2];
-
+
if( Normalize(quat+1) == 0.0) {
QuatOne(quat);
}
@@ -2614,6 +2606,15 @@ void SizeToMat3( float *size, float mat[][3])
mat[2][0]= 0.0;
}
+void SizeToMat4( float *size, float mat[][4])
+{
+ float tmat[3][3];
+
+ SizeToMat3(size, tmat);
+ Mat4One(mat);
+ Mat4CpyMat3(mat, tmat);
+}
+
void Mat3ToSize( float mat[][3], float *size)
{
float vec[3];
@@ -3286,43 +3287,47 @@ int point_in_tri_prism(float p[3], float v1[3], float v2[3], float v3[3])
/********************************************************/
/* make a 4x4 matrix out of 3 transform components */
+/* matrices are made in the order: scale * rot * loc */
void LocEulSizeToMat4(float mat[][4], float loc[3], float eul[3], float size[3])
{
- float tmat[3][3];
+ float rmat[3][3], smat[3][3], tmat[3][3];
- /* make base matrix */
- EulToMat3(eul, tmat);
-
- /* make new matrix */
+ /* initialise new matrix */
Mat4One(mat);
- mat[0][0] = tmat[0][0] * size[0];
- mat[0][1] = tmat[0][1] * size[1];
- mat[0][2] = tmat[0][2] * size[2];
-
- mat[1][0] = tmat[1][0] * size[0];
- mat[1][1] = tmat[1][1] * size[1];
- mat[1][2] = tmat[1][2] * size[2];
+ /* make rotation + scaling part */
+ EulToMat3(eul, rmat);
+ SizeToMat3(size, smat);
+ Mat3MulMat3(tmat, rmat, smat);
- mat[2][0] = tmat[2][0] * size[0];
- mat[2][1] = tmat[2][1] * size[1];
- mat[2][2] = tmat[2][2] * size[2];
+ /* copy rot/scale part to output matrix*/
+ Mat4CpyMat3(mat, tmat);
+ /* copy location to matrix */
mat[3][0] = loc[0];
mat[3][1] = loc[1];
mat[3][2] = loc[2];
}
/* make a 4x4 matrix out of 3 transform components */
+/* matrices are made in the order: scale * rot * loc */
void LocQuatSizeToMat4(float mat[][4], float loc[3], float quat[4], float size[3])
{
- float eul[3];
+ float rmat[3][3], smat[3][3], tmat[3][3];
- /* convert quaternion component to euler
- * NOTE: not as good as using quat directly. Todo for later.
- */
- QuatToEul(quat, eul);
+ /* initialise new matrix */
+ Mat4One(mat);
+
+ /* make rotation + scaling part */
+ QuatToMat3(quat, rmat);
+ SizeToMat3(size, smat);
+ Mat3MulMat3(tmat, rmat, smat);
+
+ /* copy rot/scale part to output matrix*/
+ Mat4CpyMat3(mat, tmat);
- /* make into matrix using exisiting code */
- LocEulSizeToMat4(mat, loc, eul, size);
+ /* copy location to matrix */
+ mat[3][0] = loc[0];
+ mat[3][1] = loc[1];
+ mat[3][2] = loc[2];
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 778c1df7cd2..c140ebb804e 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1633,21 +1633,21 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
bLocateLikeConstraint *data;
data= ((bLocateLikeConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
- };
+ }
break;
case CONSTRAINT_TYPE_ROTLIKE:
{
bRotateLikeConstraint *data;
data= ((bRotateLikeConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
- };
+ }
break;
case CONSTRAINT_TYPE_SIZELIKE:
{
bSizeLikeConstraint *data;
data= ((bSizeLikeConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
- };
+ }
break;
case CONSTRAINT_TYPE_KINEMATIC:
{
@@ -1675,44 +1675,43 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
bLockTrackConstraint *data;
data= ((bLockTrackConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
- };
+ }
break;
case CONSTRAINT_TYPE_FOLLOWPATH:
{
bFollowPathConstraint *data;
data= ((bFollowPathConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
- };
- break;
- case CONSTRAINT_TYPE_DISTANCELIMIT:
- {
- bDistanceLimitConstraint *data;
- data= ((bDistanceLimitConstraint*)con->data);
- data->tar = newlibadr(fd, id->lib, data->tar);
- };
+ }
break;
case CONSTRAINT_TYPE_STRETCHTO:
{
bStretchToConstraint *data;
data= ((bStretchToConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
- };
+ }
break;
case CONSTRAINT_TYPE_RIGIDBODYJOINT:
{
bRigidBodyJointConstraint *data;
data= ((bRigidBodyJointConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
- };
+ }
break;
case CONSTRAINT_TYPE_CLAMPTO:
{
bClampToConstraint *data;
data= ((bClampToConstraint*)con->data);
data->tar = newlibadr(fd, id->lib, data->tar);
- };
+ }
+ break;
+ case CONSTRAINT_TYPE_CHILDOF:
+ {
+ bChildOfConstraint *data;
+ data= ((bChildOfConstraint*)con->data);
+ data->tar = newlibadr(fd, id->lib, data->tar);
+ }
break;
-
case CONSTRAINT_TYPE_NULL:
break;
}
@@ -6481,6 +6480,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
if(main->versionfile <= 244) {
Scene *sce;
bScreen *sc;
+ Object *ob;
if(main->versionfile != 244 || main->subversionfile < 2) {
Mesh *me;
@@ -6528,6 +6528,91 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
}
+ if (main->subversionfile < 3) {
+ for(ob = main->object.first; ob; ob= ob->id.next) {
+ ListBase *list;
+ list = &ob->constraints;
+ float temp_size[3];
+
+ /* fix up constraints due to constraint recode changes */
+ if (list) {
+ bConstraint *curcon;
+ for (curcon = list->first; curcon; curcon=curcon->next) {
+ /* old CONSTRAINT_LOCAL check -> convert to CONSTRAINT_SPACE_LOCAL */
+ if (curcon->flag & 0x20) {
+ curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
+ curcon->tarspace = CONSTRAINT_SPACE_LOCAL;
+ }
+
+ switch (curcon->type) {
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data= (bActionConstraint *)curcon->data;
+
+ if (data->local)
+ curcon->tarspace = CONSTRAINT_SPACE_LOCAL;
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ {
+ bLocLimitConstraint *data= (bLocLimitConstraint *)curcon->data;
+
+ if (data->flag2) {
+ curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
+ curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ /* correctly initialise constinv matrix */
+ Mat4One(ob->constinv);
+
+ if (ob->type == OB_ARMATURE) {
+ if (ob->pose) {
+ bConstraint *curcon;
+ bPoseChannel *pchan;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+ /* make sure constraints are all up to date */
+ for (curcon = pchan->constraints.first; curcon; curcon=curcon->next) {
+ /* old CONSTRAINT_LOCAL check -> convert to CONSTRAINT_SPACE_LOCAL */
+ if (curcon->flag & 0x20) {
+ curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
+ curcon->tarspace = CONSTRAINT_SPACE_LOCAL;
+ }
+
+ switch (curcon->type) {
+ case CONSTRAINT_TYPE_ACTION:
+ {
+ bActionConstraint *data= (bActionConstraint *)curcon->data;
+
+ if (data->local)
+ curcon->tarspace = CONSTRAINT_SPACE_LOCAL;
+ }
+ break;
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ {
+ bLocLimitConstraint *data= (bLocLimitConstraint *)curcon->data;
+
+ if (data->flag2) {
+ curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
+ curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
+ }
+ }
+ break;
+ }
+ }
+
+ /* correctly initialise constinv matrix */
+ Mat4One(pchan->constinv);
+ }
+ }
+ }
+ }
+ }
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
@@ -6923,13 +7008,15 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
for (curcon=lb->first; curcon; curcon=curcon->next) {
switch (curcon->type) {
+ case CONSTRAINT_TYPE_NULL:
+ break;
case CONSTRAINT_TYPE_PYTHON:
{
bPythonConstraint *data = (bPythonConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
expand_doit(fd, mainvar, data->text);
- break;
}
+ break;
case CONSTRAINT_TYPE_ACTION:
{
bActionConstraint *data = (bActionConstraint*)curcon->data;
@@ -6941,75 +7028,73 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
{
bLocateLikeConstraint *data = (bLocateLikeConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
- break;
}
+ break;
case CONSTRAINT_TYPE_ROTLIKE:
{
bRotateLikeConstraint *data = (bRotateLikeConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
- break;
}
+ break;
case CONSTRAINT_TYPE_SIZELIKE:
{
bSizeLikeConstraint *data = (bSizeLikeConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
- break;
}
+ break;
case CONSTRAINT_TYPE_KINEMATIC:
{
bKinematicConstraint *data = (bKinematicConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
- break;
}
+ break;
case CONSTRAINT_TYPE_TRACKTO:
{
bTrackToConstraint *data = (bTrackToConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
- break;
}
+ break;
case CONSTRAINT_TYPE_MINMAX:
{
bMinMaxConstraint *data = (bMinMaxConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
- break;
}
+ break;
case CONSTRAINT_TYPE_LOCKTRACK:
{
bLockTrackConstraint *data = (bLockTrackConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
- break;
}
+ break;
case CONSTRAINT_TYPE_FOLLOWPATH:
{
bFollowPathConstraint *data = (bFollowPathConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
- break;
- }
- case CONSTRAINT_TYPE_DISTANCELIMIT:
- {
- bDistanceLimitConstraint *data = (bDistanceLimitConstraint*)curcon->data;
- expand_doit(fd, mainvar, data->tar);
- break;
}
+ break;
case CONSTRAINT_TYPE_STRETCHTO:
{
bStretchToConstraint *data = (bStretchToConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
- break;
}
+ break;
case CONSTRAINT_TYPE_RIGIDBODYJOINT:
{
bRigidBodyJointConstraint *data = (bRigidBodyJointConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
- break;
}
+ break;
case CONSTRAINT_TYPE_CLAMPTO:
{
bClampToConstraint *data = (bClampToConstraint*)curcon->data;
expand_doit(fd, mainvar, data->tar);
- break;
}
- case CONSTRAINT_TYPE_NULL:
+ break;
+ case CONSTRAINT_TYPE_CHILDOF:
+ {
+ bChildOfConstraint *data = (bChildOfConstraint*)curcon->data;
+ expand_doit(fd, mainvar, data->tar);
+ }
break;
default:
break;
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 94f51a3c2b1..5b29703fe35 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -707,11 +707,14 @@ static void write_constraints(WriteData *wd, ListBase *conlist)
bPythonConstraint *data = (bPythonConstraint*) con->data;
writestruct(wd, DATA, "bPythonConstraint", 1, data);
- /*Write ID Properties -- and copy this comment EXACTLY for easy finding
+ /* Write ID Properties -- and copy this comment EXACTLY for easy finding
of library blocks that implement this.*/
IDP_WriteProperty(data->prop, wd);
}
break;
+ case CONSTRAINT_TYPE_CHILDOF:
+ writestruct(wd, DATA, "bChildOfConstraint", 1, con->data);
+ break;
case CONSTRAINT_TYPE_TRACKTO:
writestruct(wd, DATA, "bTrackToConstraint", 1, con->data);
break;
@@ -780,6 +783,7 @@ static void write_pose(WriteData *wd, bPose *pose)
/* prevent crashes with autosave, when a bone duplicated in editmode has not yet been assigned to its posechannel */
if (chan->bone)
chan->selectflag= chan->bone->flag & (BONE_SELECTED|BONE_ACTIVE); /* gets restored on read, for library armatures */
+
writestruct(wd, DATA, "bPoseChannel", 1, chan);
}
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index 259167b6e6e..855252e1ef4 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -69,6 +69,7 @@ typedef struct bPoseChannel {
float chan_mat[4][4]; /* matrix result of loc/quat/size , and where we put deform in, see next line */
float pose_mat[4][4]; /* constraints accumulate here. in the end, pose_mat = bone->arm_mat * chan_mat */
+ float constinv[4][4]; /* inverse result of constraints. doesn't include effect of restposition, parent, and local transform*/
float pose_head[3]; /* actually pose_mat[3] */
float pose_tail[3]; /* also used for drawing help lines... */
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 3179d1035ff..a1a136b8836 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -25,7 +25,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): 2007, Joshua Leung, major recode
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
* Constraint DNA data
@@ -45,24 +45,29 @@ struct PyObject;
#endif
/* channels reside in Object or Action (ListBase) constraintChannels */
-typedef struct bConstraintChannel{
+typedef struct bConstraintChannel {
struct bConstraintChannel *next, *prev;
Ipo *ipo;
short flag;
char name[30];
} bConstraintChannel;
-typedef struct bConstraint{
+/* A Constraint */
+typedef struct bConstraint {
struct bConstraint *next, *prev;
void *data; /* Constraint data (a valid constraint type) */
short type; /* Constraint type */
- short flag; /* Flag */
- short reserved1;
+ short flag; /* Flag - General Settings */
+
+ char ownspace; /* Space that owner should be evaluated in */
+ char tarspace; /* Space that target should be evaluated in */
+
char name[30]; /* Constraint name */
-
- float enforce;
+
+ float enforce; /* Amount of influence exherted by constraint (0.0-1.0) */
} bConstraint;
+
/* Python Script Constraint */
typedef struct bPythonConstraint {
Object *tar; /* object to use as target (if required) */
@@ -75,8 +80,9 @@ typedef struct bPythonConstraint {
int pad;
} bPythonConstraint;
-/* Single-target subobject constraints */
-typedef struct bKinematicConstraint{
+/* Single-target subobject constraints --------------------- */
+/* Inverse-Kinematics (IK) constraint */
+typedef struct bKinematicConstraint {
Object *tar;
short iterations; /* Maximum number of iterations to try */
short flag; /* Like CONSTRAINT_IK_TIP */
@@ -89,7 +95,8 @@ typedef struct bKinematicConstraint{
int pad;
} bKinematicConstraint;
-typedef struct bTrackToConstraint{
+/* Track To Constraint */
+typedef struct bTrackToConstraint {
Object *tar;
int reserved1; /* I'll be using reserved1 and reserved2 as Track and Up flags, not sure if that's what they were intented for anyway. Not sure either if it would create backward incompatibility if I were to rename them. - theeth*/
int reserved2;
@@ -98,21 +105,24 @@ typedef struct bTrackToConstraint{
char subtarget[32];
} bTrackToConstraint;
-typedef struct bRotateLikeConstraint{
+/* Copy Rotation Constraint */
+typedef struct bRotateLikeConstraint {
Object *tar;
int flag;
int reserved1;
char subtarget[32];
} bRotateLikeConstraint;
-typedef struct bLocateLikeConstraint{
+/* Copy Location Constraint */
+typedef struct bLocateLikeConstraint {
Object *tar;
int flag;
int reserved1;
char subtarget[32];
} bLocateLikeConstraint;
-typedef struct bMinMaxConstraint{
+/* Floor Constraint */
+typedef struct bMinMaxConstraint {
Object *tar;
int minmaxflag;
float offset;
@@ -122,17 +132,19 @@ typedef struct bMinMaxConstraint{
char subtarget[32];
} bMinMaxConstraint;
-typedef struct bSizeLikeConstraint{
+/* Copy Scale Constraint */
+typedef struct bSizeLikeConstraint {
Object *tar;
int flag;
int reserved1;
char subtarget[32];
} bSizeLikeConstraint;
-typedef struct bActionConstraint{
+/* Action Constraint */
+typedef struct bActionConstraint {
Object *tar;
short type;
- short local;
+ short local; /* was used in versions prior to the Constraints recode */
int start;
int end;
float min;
@@ -143,7 +155,7 @@ typedef struct bActionConstraint{
} bActionConstraint;
/* Locked Axis Tracking constraint */
-typedef struct bLockTrackConstraint{
+typedef struct bLockTrackConstraint {
Object *tar;
int trackflag;
int lockflag;
@@ -151,7 +163,7 @@ typedef struct bLockTrackConstraint{
} bLockTrackConstraint;
/* Follow Path constraints */
-typedef struct bFollowPathConstraint{
+typedef struct bFollowPathConstraint {
Object *tar; /* Must be path object */
float offset; /* Offset in time on the path (in frame) */
int followflag;
@@ -159,26 +171,8 @@ typedef struct bFollowPathConstraint{
int upflag;
} bFollowPathConstraint;
-/* Distance Limiting constraints */
-typedef struct bDistanceLimitConstraint{
- Object *tar;
- char subtarget[32];
- float pad1;
- float pad2;
- float distance;
- float offset[3];
-} bDistanceLimitConstraint;
-
-
-/* Zero-target constraints */
-typedef struct bRotationConstraint{
- float xmin, xmax;
- float ymin, ymax;
- float zmin, zmax;
-} bRotationConstraint;
-
/* Stretch to constraint */
-typedef struct bStretchToConstraint{
+typedef struct bStretchToConstraint {
Object *tar;
int volmode;
int plane;
@@ -187,33 +181,8 @@ typedef struct bStretchToConstraint{
char subtarget[32];
} bStretchToConstraint;
-/* transform limiting constraints - zero target */
-typedef struct bLocLimitConstraint{
- float xmin, xmax;
- float ymin, ymax;
- float zmin, zmax;
- short flag;
- short flag2;
-} bLocLimitConstraint;
-
-typedef struct bRotLimitConstraint{
- float xmin, xmax;
- float ymin, ymax;
- float zmin, zmax;
- short flag;
- short pad1;
-} bRotLimitConstraint;
-
-typedef struct bSizeLimitConstraint{
- float xmin, xmax;
- float ymin, ymax;
- float zmin, zmax;
- short flag;
- short pad1;
-} bSizeLimitConstraint;
-
/* Rigid Body constraint */
-typedef struct bRigidBodyJointConstraint{
+typedef struct bRigidBodyJointConstraint {
Object *tar;
Object *child;
int type;
@@ -232,16 +201,53 @@ typedef struct bRigidBodyJointConstraint{
short pad2;
} bRigidBodyJointConstraint;
-/* ClampTo Constraint */
+/* Clamp-To Constraint */
typedef struct bClampToConstraint {
Object *tar; /* 'target' must be a curve */
int flag; /* which axis/plane to compare owner's location on */
int pad;
} bClampToConstraint;
+/* Child Of Constraint */
+typedef struct bChildOfConstraint {
+ Object *tar; /* object which may/may not be the parent */
+ int flag; /* settings */
+ int pad;
+ float invmat[4][4]; /* parent-inverse matrix to use */
+ char subtarget[32]; /* string to specify a subobject target */
+} bChildOfConstraint;
+
+/* transform limiting constraints - zero target ---------------------------- */
+/* Limit Location Constraint */
+typedef struct bLocLimitConstraint {
+ float xmin, xmax;
+ float ymin, ymax;
+ float zmin, zmax;
+ short flag;
+ short flag2;
+} bLocLimitConstraint;
+
+/* Limit Rotation Constraint */
+typedef struct bRotLimitConstraint {
+ float xmin, xmax;
+ float ymin, ymax;
+ float zmin, zmax;
+ short flag;
+ short pad1;
+} bRotLimitConstraint;
+
+/* Limit Scaling Constraint */
+typedef struct bSizeLimitConstraint {
+ float xmin, xmax;
+ float ymin, ymax;
+ float zmin, zmax;
+ short flag;
+ short pad1;
+} bSizeLimitConstraint;
+
/* bConstraint.type */
#define CONSTRAINT_TYPE_NULL 0
-#define CONSTRAINT_TYPE_CHILDOF 1 /* Unimplemented */
+#define CONSTRAINT_TYPE_CHILDOF 1 /* Unimplemented non longer :) - during constraints recode, Aligorith */
#define CONSTRAINT_TYPE_TRACKTO 2
#define CONSTRAINT_TYPE_KINEMATIC 3
#define CONSTRAINT_TYPE_FOLLOWPATH 4
@@ -251,10 +257,10 @@ typedef struct bClampToConstraint {
#define CONSTRAINT_TYPE_ROTLIKE 8
#define CONSTRAINT_TYPE_LOCLIKE 9
#define CONSTRAINT_TYPE_SIZELIKE 10
-#define CONSTRAINT_TYPE_PYTHON 11 /* Unimplemented */
+#define CONSTRAINT_TYPE_PYTHON 11 /* Unimplemented no longer :) - Aligorith. Scripts */
#define CONSTRAINT_TYPE_ACTION 12
#define CONSTRAINT_TYPE_LOCKTRACK 13 /* New Tracking constraint that locks an axis in place - theeth */
-#define CONSTRAINT_TYPE_DISTANCELIMIT 14
+#define CONSTRAINT_TYPE_DISTANCELIMIT 14 /* was never properly coded - removed! */
#define CONSTRAINT_TYPE_STRETCHTO 15 /* claiming this to be mine :) is in tuhopuu bjornmose */
#define CONSTRAINT_TYPE_MINMAX 16 /* floor constraint */
#define CONSTRAINT_TYPE_RIGIDBODYJOINT 17 /* rigidbody constraint */
@@ -268,9 +274,19 @@ typedef struct bClampToConstraint {
/* flags 0x2 and 0x8 were used in past, skip this */
/* to indicate which Ipo should be shown, maybe for 3d access later too */
#define CONSTRAINT_ACTIVE 0x10
- /* only for Pose, evaluates constraints in posechannel local space */
-#define CONSTRAINT_LOCAL 0x20
-
+ /* flag 0x20 was used to indicate that a constraint was evaluated using a 'local' hack for posebones only */
+ /* to indicate that the owner's space should only be changed into ownspace, but not out of it */
+#define CONSTRAINT_SPACEONCE 0x40
+
+/* bConstraint.ownspace/tarspace */
+ /* default for all - worldspace */
+#define CONSTRAINT_SPACE_WORLD 0
+ /* for objects (relative to parent/without parent influence), for bones (along normals of bone, without parent/restposi) */
+#define CONSTRAINT_SPACE_LOCAL 1
+ /* for posechannels - pose space */
+#define CONSTRAINT_SPACE_POSE 2
+ /* for posechannels - local with parent */
+#define CONSTRAINT_SPACE_PARLOCAL 3
/* bConstraintChannel.flag */
#define CONSTRAINT_CHANNEL_SELECT 0x01
@@ -334,6 +350,7 @@ typedef struct bClampToConstraint {
#define PLANE_Y 0x01
#define PLANE_Z 0x02
+/* Clamp-To Constraint ->flag */
#define CLAMPTO_AUTO 0
#define CLAMPTO_X 1
#define CLAMPTO_Y 2
@@ -364,12 +381,25 @@ typedef struct bClampToConstraint {
#define LIMIT_YROT 0x02
#define LIMIT_ZROT 0x04
+/* not used anymore - for older Limit Location constraints only */
#define LIMIT_NOPARENT 0x01
/* python constraint -> flag */
#define PYCON_USETARGETS 0x01
#define PYCON_SCRIPTERROR 0x02
+/* ChildOf Constraint -> flag */
+#define CHILDOF_LOCX 0x001
+#define CHILDOF_LOCY 0x002
+#define CHILDOF_LOCZ 0x004
+#define CHILDOF_ROTX 0x008
+#define CHILDOF_ROTY 0x010
+#define CHILDOF_ROTZ 0x020
+#define CHILDOF_SIZEX 0x040
+#define CHILDOF_SIZEY 0x080
+#define CHILDOF_SIZEZ 0x100
+
+/* Rigid-Body Constraint */
#define CONSTRAINT_DRAW_PIVOT 0x40
/* important: these defines need to match up with PHY_DynamicTypes headerfile */
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 411c02cfbb0..eb76f9ea9c1 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -115,7 +115,8 @@ typedef struct Object {
float rot[3], drot[3];
float quat[4], dquat[4];
float obmat[4][4];
- float parentinv[4][4];
+ float parentinv[4][4]; /* inverse result of parent, so that object doesn't 'stick' to parent */
+ float constinv[4][4]; /* inverse result of constraints. doesn't include effect of parent or object local transform */
float imat[4][4]; /* for during render, old game engine, temporally: ipokeys of transform */
unsigned int lay; /* copy of Base */
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h
index 34271efc4f1..0d466d5af7e 100644
--- a/source/blender/python/BPY_extern.h
+++ b/source/blender/python/BPY_extern.h
@@ -51,7 +51,7 @@ struct bPythonConstraint; /* DNA_constraint_types.h */
extern "C" {
#endif
- void BPY_pyconstraint_eval(struct bPythonConstraint *con, float obmat[][4], short ownertype, void *ownerdata, float targetmat[][4]);
+ void BPY_pyconstraint_eval(struct bPythonConstraint *con, float ownermat[][4], float targetmat[][4]);
void BPY_pyconstraint_settings(void *arg1, void *arg2);
int BPY_pyconstraint_targets(struct bPythonConstraint *con, float targetmat[][4]);
int BPY_is_pyconstraint(struct Text *text);
diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c
index 93f02b75bc9..f5de2b48c6a 100644
--- a/source/blender/python/BPY_interface.c
+++ b/source/blender/python/BPY_interface.c
@@ -1164,7 +1164,7 @@ int BPY_is_pyconstraint(Text *text)
}
/* This evals py constraints. It is passed all the arguments the normal constraints recieve */
-void BPY_pyconstraint_eval(bPythonConstraint *con, float obmat[][4], short ownertype, void *ownerdata, float targetmat[][4])
+void BPY_pyconstraint_eval(bPythonConstraint *con, float ownermat[][4], float targetmat[][4])
{
PyObject *srcmat, *tarmat, *idprop;
PyObject *globals;
@@ -1178,7 +1178,7 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, float obmat[][4], short owner
globals = CreateGlobalDictionary();
- srcmat = newMatrixObject( (float*)obmat, 4, 4, Py_NEW );
+ srcmat = newMatrixObject( (float*)ownermat, 4, 4, Py_NEW );
tarmat = newMatrixObject( (float*)targetmat, 4, 4, Py_NEW );
idprop = BPy_Wrap_IDProperty( NULL, con->prop, NULL);
@@ -1276,7 +1276,7 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, float obmat[][4], short owner
/* this is the reverse of code taken from newMatrix() */
for(row = 0; row < 4; row++) {
for(col = 0; col < 4; col++) {
- obmat[row][col] = retmat->contigPtr[row*4+col];
+ ownermat[row][col] = retmat->contigPtr[row*4+col];
}
}
diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c
index f274c9dba59..8c7164fe999 100644
--- a/source/blender/python/api2_2x/Constraint.c
+++ b/source/blender/python/api2_2x/Constraint.c
@@ -61,6 +61,12 @@ enum constraint_constants {
EXPP_CONSTR_XROT = 0,
EXPP_CONSTR_YROT = 1,
EXPP_CONSTR_ZROT = 2,
+ EXPP_CONSTR_XSIZE = 10,
+ EXPP_CONSTR_YSIZE = 11,
+ EXPP_CONSTR_ZSIZE = 12,
+ EXPP_CONSTR_XLOC = 20,
+ EXPP_CONSTR_YLOC = 21,
+ EXPP_CONSTR_ZLOC = 22,
EXPP_CONSTR_MAXX = TRACK_X,
EXPP_CONSTR_MAXY = TRACK_Y,
@@ -80,7 +86,6 @@ enum constraint_constants {
EXPP_CONSTR_USETIP,
EXPP_CONSTR_ACTION,
- EXPP_CONSTR_LOCAL,
EXPP_CONSTR_START,
EXPP_CONSTR_END,
EXPP_CONSTR_MIN,
@@ -126,11 +131,11 @@ enum constraint_constants {
EXPP_CONSTR_ZMIN,
EXPP_CONSTR_ZMAX,
- EXPP_CONSTR_LIMLOCALBONE,
- EXPP_CONSTR_LIMLOCALNOPAR,
-
EXPP_CONSTR_SCRIPT,
EXPP_CONSTR_PROPS,
+
+ EXPP_CONSTR_OWNSPACE,
+ EXPP_CONSTR_TARSPACE,
EXPP_CONSTR_RB_TYPE,
EXPP_CONSTR_RB_BALL,
@@ -498,8 +503,6 @@ static PyObject *action_getter( BPy_Constraint * self, int type )
return PyString_FromString( con->subtarget );
case EXPP_CONSTR_ACTION:
return Action_CreatePyObject( con->act );
- case EXPP_CONSTR_LOCAL:
- return PyBool_FromLong( (long)( con->local & SELECT ) );
case EXPP_CONSTR_START:
return PyInt_FromLong( (long)con->start );
case EXPP_CONSTR_END:
@@ -546,8 +549,6 @@ static int action_setter( BPy_Constraint *self, int type, PyObject *value )
con->act = act;
return 0;
}
- case EXPP_CONSTR_LOCAL:
- return EXPP_setBitfield( value, &con->local, SELECT, 'h' );
case EXPP_CONSTR_START:
return EXPP_setIValueClamped( value, &con->start, 1, MAXFRAME, 'h' );
case EXPP_CONSTR_END:
@@ -558,7 +559,7 @@ static int action_setter( BPy_Constraint *self, int type, PyObject *value )
return EXPP_setFloatClamped( value, &con->max, -180.0, 180.0 );
case EXPP_CONSTR_KEYON:
return EXPP_setIValueRange( value, &con->type,
- EXPP_CONSTR_XROT, EXPP_CONSTR_ZROT, 'h' );
+ EXPP_CONSTR_XROT, EXPP_CONSTR_ZLOC, 'h' );
default:
return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
}
@@ -885,11 +886,6 @@ static PyObject *locatelike_getter( BPy_Constraint * self, int type )
return PyString_FromString( con->subtarget );
case EXPP_CONSTR_COPY:
return PyInt_FromLong( (long)con->flag );
- case EXPP_CONSTR_LOCAL:
- if( get_armature( con->tar ) )
- return PyBool_FromLong( (long)
- ( self->con->flag & CONSTRAINT_LOCAL ) ) ;
- Py_RETURN_NONE;
default:
return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
}
@@ -921,12 +917,6 @@ static int locatelike_setter( BPy_Constraint *self, int type, PyObject *value )
case EXPP_CONSTR_COPY:
return EXPP_setIValueRange( value, &con->flag,
0, LOCLIKE_X | LOCLIKE_Y | LOCLIKE_Z | LOCLIKE_X_INVERT | LOCLIKE_Y_INVERT | LOCLIKE_Z_INVERT, 'i' );
- case EXPP_CONSTR_LOCAL:
- if( !get_armature( con->tar ) )
- return EXPP_ReturnIntError( PyExc_RuntimeError,
- "only armature targets have LOCAL key" );
- return EXPP_setBitfield( value, &self->con->flag,
- CONSTRAINT_LOCAL, 'h' );
default:
return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
}
@@ -943,11 +933,6 @@ static PyObject *rotatelike_getter( BPy_Constraint * self, int type )
return PyString_FromString( con->subtarget );
case EXPP_CONSTR_COPY:
return PyInt_FromLong( (long)con->flag );
- case EXPP_CONSTR_LOCAL:
- if( get_armature( con->tar ) )
- return PyBool_FromLong( (long)
- ( self->con->flag & CONSTRAINT_LOCAL ) ) ;
- Py_RETURN_NONE;
default:
return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
}
@@ -978,13 +963,7 @@ static int rotatelike_setter( BPy_Constraint *self, int type, PyObject *value )
}
case EXPP_CONSTR_COPY:
return EXPP_setIValueRange( value, &con->flag,
- 0, LOCLIKE_X | LOCLIKE_Y | LOCLIKE_Z | LOCLIKE_X_INVERT | LOCLIKE_Y_INVERT | LOCLIKE_Z_INVERT, 'i' );
- case EXPP_CONSTR_LOCAL:
- if( !get_armature( con->tar ) )
- return EXPP_ReturnIntError( PyExc_RuntimeError,
- "only armature targets have LOCAL key" );
- return EXPP_setBitfield( value, &self->con->flag,
- CONSTRAINT_LOCAL, 'h' );
+ 0, ROTLIKE_X | ROTLIKE_Y | ROTLIKE_Z | ROTLIKE_X_INVERT | ROTLIKE_Y_INVERT | ROTLIKE_Z_INVERT, 'i' );
default:
return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
}
@@ -1001,13 +980,6 @@ static PyObject *sizelike_getter( BPy_Constraint * self, int type )
return PyString_FromString( con->subtarget );
case EXPP_CONSTR_COPY:
return PyInt_FromLong( (long)con->flag );
-#if 0
- case EXPP_CONSTR_LOCAL:
- if( get_armature( con->tar ) )
- return PyBool_FromLong( (long)
- ( self->con->flag & CONSTRAINT_LOCAL ) ) ;
- Py_RETURN_NONE;
-#endif
default:
return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
}
@@ -1038,15 +1010,7 @@ static int sizelike_setter( BPy_Constraint *self, int type, PyObject *value )
}
case EXPP_CONSTR_COPY:
return EXPP_setIValueRange( value, &con->flag,
- 0, LOCLIKE_X | LOCLIKE_Y | LOCLIKE_Z | LOCLIKE_X_INVERT | LOCLIKE_Y_INVERT | LOCLIKE_Z_INVERT, 'i' );
-#if 0
- case EXPP_CONSTR_LOCAL:
- if( !get_armature( con->tar ) )
- return EXPP_ReturnIntError( PyExc_RuntimeError,
- "only armature targets have LOCAL key" );
- return EXPP_setBitfield( value, &self->con->flag,
- CONSTRAINT_LOCAL, 'h' );
-#endif
+ 0, SIZELIKE_X | SIZELIKE_Y | SIZELIKE_Z, 'i' );
default:
return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
}
@@ -1059,12 +1023,6 @@ static PyObject *loclimit_getter( BPy_Constraint * self, int type)
switch( type ) {
case EXPP_CONSTR_LIMIT:
return PyInt_FromLong( (long)con->flag );
- case EXPP_CONSTR_LIMLOCALBONE:
- return PyBool_FromLong( (long)
- ( self->con->flag & CONSTRAINT_LOCAL ) ) ;
- case EXPP_CONSTR_LIMLOCALNOPAR:
- return PyBool_FromLong( (long)
- ( con->flag2 & LIMIT_NOPARENT ) ) ;
case EXPP_CONSTR_XMIN:
return PyFloat_FromDouble( (double)con->xmin );
case EXPP_CONSTR_XMAX:
@@ -1090,12 +1048,6 @@ static int loclimit_setter( BPy_Constraint *self, int type, PyObject *value )
case EXPP_CONSTR_LIMIT:
return EXPP_setIValueRange( value, &con->flag, 0,
LIMIT_XMIN | LIMIT_XMAX | LIMIT_YMIN | LIMIT_YMAX | LIMIT_ZMIN | LIMIT_ZMAX , 'i' );
- case EXPP_CONSTR_LIMLOCALBONE:
- return EXPP_setBitfield( value, &self->con->flag,
- CONSTRAINT_LOCAL, 'h' );
- case EXPP_CONSTR_LIMLOCALNOPAR:
- return EXPP_setBitfield( value, &con->flag2,
- LIMIT_NOPARENT, 'h' );
case EXPP_CONSTR_XMIN:
return EXPP_setFloatClamped( value, &con->xmin, -1000.0, 1000.0 );
case EXPP_CONSTR_XMAX:
@@ -1120,9 +1072,6 @@ static PyObject *rotlimit_getter( BPy_Constraint * self, int type )
switch( type ) {
case EXPP_CONSTR_LIMIT:
return PyInt_FromLong( (long)con->flag );
- case EXPP_CONSTR_LIMLOCALBONE:
- return PyBool_FromLong( (long)
- (self->con->flag & CONSTRAINT_LOCAL ) );
case EXPP_CONSTR_XMIN:
return PyFloat_FromDouble( (double)con->xmin );
case EXPP_CONSTR_XMAX:
@@ -1148,9 +1097,6 @@ static int rotlimit_setter( BPy_Constraint *self, int type, PyObject *value )
case EXPP_CONSTR_LIMIT:
return EXPP_setIValueRange( value, &con->flag, 0,
LIMIT_XROT | LIMIT_YROT | LIMIT_ZROT, 'i' );
- case EXPP_CONSTR_LIMLOCALBONE:
- return EXPP_setBitfield( value, &self->con->flag,
- CONSTRAINT_LOCAL, 'h' );
case EXPP_CONSTR_XMIN:
return EXPP_setFloatClamped( value, &con->xmin, -360.0, 360.0 );
case EXPP_CONSTR_XMAX:
@@ -1393,6 +1339,54 @@ static int rigidbody_setter( BPy_Constraint *self, int type, PyObject *value )
}
}
+static PyObject *childof_getter( BPy_Constraint * self, int type )
+{
+ bChildOfConstraint *con = (bChildOfConstraint *)(self->con->data);
+
+ switch( type ) {
+ case EXPP_CONSTR_TARGET:
+ return Object_CreatePyObject( con->tar );
+ case EXPP_CONSTR_BONE:
+ return PyString_FromString( con->subtarget );
+ case EXPP_CONSTR_COPY:
+ return PyInt_FromLong( (long)con->flag );
+ default:
+ return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static int childof_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+ bChildOfConstraint *con = (bChildOfConstraint *)(self->con->data);
+
+ switch( type ) {
+ case EXPP_CONSTR_TARGET: {
+ Object *obj = (( BPy_Object * )value)->object;
+ if( !BPy_Object_Check( value ) )
+ return EXPP_ReturnIntError( PyExc_TypeError,
+ "expected BPy object argument" );
+ con->tar = obj;
+ return 0;
+ }
+ case EXPP_CONSTR_BONE: {
+ char *name = PyString_AsString( value );
+ if( !name )
+ return EXPP_ReturnIntError( PyExc_TypeError,
+ "expected string arg" );
+
+ BLI_strncpy( con->subtarget, name, sizeof( con->subtarget ) );
+
+ return 0;
+ }
+ case EXPP_CONSTR_COPY:
+ return EXPP_setIValueRange( value, &con->flag,
+ 0, CHILDOF_LOCX| CHILDOF_LOCY | CHILDOF_LOCZ | CHILDOF_ROTX | CHILDOF_ROTY | CHILDOF_ROTZ |
+ CHILDOF_SIZEX |CHILDOF_SIZEY| CHILDOF_SIZEZ, 'i' );
+ default:
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+ }
+}
+
/*
* get data from a constraint
*/
@@ -1445,7 +1439,8 @@ static PyObject *Constraint_getData( BPy_Constraint * self, PyObject * key )
return clampto_getter( self, setting );
case CONSTRAINT_TYPE_PYTHON:
return script_getter( self, setting );
- case CONSTRAINT_TYPE_CHILDOF: /* Unimplemented */
+ case CONSTRAINT_TYPE_CHILDOF:
+ return childof_getter( self, setting );
default:
return EXPP_ReturnPyObjError( PyExc_KeyError,
"unknown constraint type" );
@@ -1514,9 +1509,11 @@ static int Constraint_setData( BPy_Constraint * self, PyObject * key,
case CONSTRAINT_TYPE_PYTHON:
result = script_setter( self, key_int, arg);
break;
+ case CONSTRAINT_TYPE_CHILDOF:
+ result = childof_setter( self, key_int, arg);
+ break;
case CONSTRAINT_TYPE_NULL:
return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
- case CONSTRAINT_TYPE_CHILDOF: /* Unimplemented */
default:
return EXPP_ReturnIntError( PyExc_RuntimeError,
"unsupported constraint setting" );
@@ -1986,6 +1983,8 @@ static PyObject *M_Constraint_TypeDict( void )
PyInt_FromLong( CONSTRAINT_TYPE_CLAMPTO ) );
PyConstant_Insert( d, "PYTHON",
PyInt_FromLong( CONSTRAINT_TYPE_PYTHON ) );
+ PyConstant_Insert( d, "CHILDOF",
+ PyInt_FromLong( CONSTRAINT_TYPE_CHILDOF ) );
}
return S;
}
@@ -2002,6 +2001,18 @@ static PyObject *M_Constraint_SettingsDict( void )
PyInt_FromLong( EXPP_CONSTR_YROT ) );
PyConstant_Insert( d, "ZROT",
PyInt_FromLong( EXPP_CONSTR_ZROT ) );
+ PyConstant_Insert( d, "XSIZE",
+ PyInt_FromLong( EXPP_CONSTR_XSIZE ) );
+ PyConstant_Insert( d, "YSIZE",
+ PyInt_FromLong( EXPP_CONSTR_YSIZE ) );
+ PyConstant_Insert( d, "ZSIZE",
+ PyInt_FromLong( EXPP_CONSTR_ZSIZE ) );
+ PyConstant_Insert( d, "XLOC",
+ PyInt_FromLong( EXPP_CONSTR_XLOC ) );
+ PyConstant_Insert( d, "YLOC",
+ PyInt_FromLong( EXPP_CONSTR_YLOC ) );
+ PyConstant_Insert( d, "ZLOC",
+ PyInt_FromLong( EXPP_CONSTR_ZLOC ) );
PyConstant_Insert( d, "UPX",
PyInt_FromLong( UP_X ) );
@@ -2072,6 +2083,25 @@ static PyObject *M_Constraint_SettingsDict( void )
PyConstant_Insert( d, "COPYZINVERT",
PyInt_FromLong( LOCLIKE_Z_INVERT ) );
+ PyConstant_Insert( d, "PARLOCX",
+ PyInt_FromLong( CHILDOF_LOCX ) );
+ PyConstant_Insert( d, "PARLOCY",
+ PyInt_FromLong( CHILDOF_LOCY ) );
+ PyConstant_Insert( d, "PARLOCZ",
+ PyInt_FromLong( CHILDOF_LOCZ ) );
+ PyConstant_Insert( d, "PARROTX",
+ PyInt_FromLong( CHILDOF_ROTX ) );
+ PyConstant_Insert( d, "PARROTY",
+ PyInt_FromLong( CHILDOF_ROTY ) );
+ PyConstant_Insert( d, "PARROTZ",
+ PyInt_FromLong( CHILDOF_ROTZ ) );
+ PyConstant_Insert( d, "PARSIZEX",
+ PyInt_FromLong( CHILDOF_LOCX ) );
+ PyConstant_Insert( d, "PARSIZEY",
+ PyInt_FromLong( CHILDOF_SIZEY ) );
+ PyConstant_Insert( d, "PARSIZEZ",
+ PyInt_FromLong( CHILDOF_SIZEZ ) );
+
PyConstant_Insert( d, "CLAMPAUTO",
PyInt_FromLong( CLAMPTO_AUTO ) );
PyConstant_Insert( d, "CLAMPX",
@@ -2102,8 +2132,6 @@ static PyObject *M_Constraint_SettingsDict( void )
PyConstant_Insert( d, "ACTION",
PyInt_FromLong( EXPP_CONSTR_ACTION ) );
- PyConstant_Insert( d, "LOCAL",
- PyInt_FromLong( EXPP_CONSTR_LOCAL ) );
PyConstant_Insert( d, "START",
PyInt_FromLong( EXPP_CONSTR_START ) );
PyConstant_Insert( d, "END",
@@ -2178,17 +2206,12 @@ static PyObject *M_Constraint_SettingsDict( void )
PyInt_FromLong( EXPP_CONSTR_ZMIN ) );
PyConstant_Insert( d, "ZMAX",
PyInt_FromLong( EXPP_CONSTR_ZMAX ) );
-
- PyConstant_Insert( d, "LIMIT_LOCAL_BONE",
- PyInt_FromLong( EXPP_CONSTR_LIMLOCALBONE ) );
- PyConstant_Insert( d, "LIMIT_LOCAL_NOPARENT",
- PyInt_FromLong( EXPP_CONSTR_LIMLOCALNOPAR ) );
-
+
PyConstant_Insert( d, "SCRIPT",
PyInt_FromLong( EXPP_CONSTR_SCRIPT ) );
PyConstant_Insert( d, "PROPERTIES",
PyInt_FromLong( EXPP_CONSTR_PROPS ) );
-
+
PyConstant_Insert( d, "CONSTR_RB_TYPE",
PyInt_FromLong( EXPP_CONSTR_RB_TYPE ) );
PyConstant_Insert( d, "CONSTR_RB_BALL",
@@ -2239,6 +2262,21 @@ static PyObject *M_Constraint_SettingsDict( void )
PyInt_FromLong( EXPP_CONSTR_RB_EXTRAFZ ) );
PyConstant_Insert( d, "CONSTR_RB_FLAG",
PyInt_FromLong( EXPP_CONSTR_RB_FLAG ) );
+
+
+ PyConstant_Insert( d, "OWNERSPACE",
+ PyInt_FromLong( EXPP_CONSTR_OWNSPACE ) );
+ PyConstant_Insert( d, "TARGETSPACE",
+ PyInt_FromLong( EXPP_CONSTR_TARSPACE ) );
+
+ PyConstant_Insert( d, "SPACE_WORLD",
+ PyInt_FromLong( CONSTRAINT_SPACE_WORLD) );
+ PyConstant_Insert( d, "SPACE_LOCAL",
+ PyInt_FromLong( CONSTRAINT_SPACE_LOCAL ) );
+ PyConstant_Insert( d, "SPACE_POSE",
+ PyInt_FromLong( CONSTRAINT_SPACE_POSE) );
+ PyConstant_Insert( d, "SPACE_PARLOCAL",
+ PyInt_FromLong( CONSTRAINT_SPACE_PARLOCAL ) );
}
return S;
}
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index 7d2c5dd5f00..eb9fb72110e 100644
--- a/source/blender/src/buttons_object.c
+++ b/source/blender/src/buttons_object.c
@@ -513,22 +513,105 @@ void autocomplete_vgroup(char *str, void *arg_v)
}
}
+/* ChildOf Constraint - set inverse */
+static void childof_const_setinv (void *conv, void *unused)
+{
+ bChildOfConstraint *data= (bChildOfConstraint *)conv;
+ Object *ob= OBACT;
+ bPoseChannel *pchan= NULL;
+
+ if (ob && ob->pose)
+ pchan= get_active_posechannel(ob);
+
+ // for now, try using constinv if available
+ if (pchan)
+ Mat4CpyMat4(data->invmat, pchan->constinv);
+ else if (ob)
+ Mat4CpyMat4(data->invmat, ob->constinv);
+ else
+ Mat4One(data->invmat);
+}
+
+/* ChildOf Constraint - clear inverse */
+static void childof_const_clearinv (void *conv, void *unused)
+{
+ bChildOfConstraint *data= (bChildOfConstraint *)conv;
+
+ Mat4One(data->invmat);
+}
+
+/* Helper function for draw constraint - draws constraint space stuff
+ * This function should not be called if no menus are required
+ * owner/target: -1 = don't draw menu; 0= not posemode, 1 = posemode
+ */
+static void draw_constraint_spaceselect (uiBlock *block, bConstraint *con, short xco, short yco, short owner, short target)
+{
+ short ownx, tarx;
+ short bwidth;
+
+ /* calculate sizes and placement of menus */
+ if (owner == -1) {
+ bwidth = 125;
+ ownx = 0;
+ tarx = 120;
+ }
+ else if (target == -1) {
+ bwidth = 125;
+ ownx = 120;
+ tarx = 0;
+ }
+ else {
+ bwidth = 100;
+ ownx = 95;
+ tarx = ownx + bwidth;
+ }
+
+
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "CSpace:", xco, yco, 80,18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+
+ uiBlockBeginAlign(block);
+
+ /* Owner-Space */
+ if (owner == 1) {
+ uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Owner Space %t|World Space %x0|Pose Space %x3|Local with Parent %x4|Local Space %x1",
+ ownx, yco, bwidth, 18, &con->ownspace, 0, 0, 0, 0, "Choose space that owner is evaluated in");
+ }
+ else if (owner == 0) {
+ uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Owner Space %t|World Space %x0|Local Space %x1",
+ ownx, yco, bwidth, 18, &con->ownspace, 0, 0, 0, 0, "Choose space that owner is evaluated in");
+ }
+
+ /* Target-Space */
+ if (target == 1) {
+ uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Pose Space %x3|Local with Parent %x4|Local Space %x1",
+ tarx, yco, bwidth, 18, &con->tarspace, 0, 0, 0, 0, "Choose space that target is evaluated in");
+ }
+ else if (target == 0) {
+ uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Local Space %x1",
+ tarx, yco, bwidth, 18, &con->tarspace, 0, 0, 0, 0, "Choose space that target is evaluated in");
+ }
+
+ uiBlockEndAlign(block);
+}
+
/* draw panel showing settings for a constraint */
static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, short *xco, short *yco)
{
Object *ob= OBACT, *target;
uiBut *but;
char typestr[64], *subtarget;
- short height, width = 265, is_armature_target;
+ short height, width = 265;
+ short is_armature_target, is_armature_owner;
int curCol, rb_col;
target= get_constraint_target(con, &subtarget);
is_armature_target= (target && target->type==OB_ARMATURE);
+ is_armature_owner= ((ob->type == OB_ARMATURE) && (ob->flag & OB_POSEMODE));
/* unless button has own callback, it adds this callback to button */
uiBlockSetFunc(block, constraint_active_func, ob, con);
- get_constraint_typestring (typestr, con);
+ get_constraint_typestring(typestr, con);
curCol = get_constraint_col(con);
@@ -552,20 +635,13 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
uiButSetFunc(but, constraint_moveDown, ob, con);
if (con->flag & CONSTRAINT_EXPAND) {
-
if (con->flag & CONSTRAINT_DISABLE) {
BIF_ThemeColor(TH_REDALERT);
uiBlockSetCol(block, TH_REDALERT);
}
- else {
+ else
BIF_ThemeColor(curCol);
- }
-
- /*if (type==TARGET_BONE)
- but = uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Bone Constraint%t|Track To%x2|IK Solver%x3|Copy Rotation%x8|Copy Location%x9|Action%x12|Null%x0", *xco+20, *yco, 100, 20, &con->type, 0.0, 0.0, 0.0, 0.0, "Constraint type");
- else
- but = uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Object Constraint%t|Track To%x2|Copy Rotation%x8|Copy Location%x9|Null%x0", *xco+20, *yco, 100, 20, &con->type, 0.0, 0.0, 0.0, 0.0, "Constraint type");
- */
+
uiBlockSetEmboss(block, UI_EMBOSS);
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, *xco+10, *yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
@@ -575,14 +651,13 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
}
else {
uiBlockSetEmboss(block, UI_EMBOSSN);
-
+
if (con->flag & CONSTRAINT_DISABLE) {
uiBlockSetCol(block, TH_REDALERT);
BIF_ThemeColor(TH_REDALERT);
}
- else {
+ else
BIF_ThemeColor(curCol);
- }
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, *xco+10, *yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
@@ -599,12 +674,12 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
uiBlockSetEmboss(block, UI_EMBOSS);
- /* Draw constraint data*/
- if (!(con->flag & CONSTRAINT_EXPAND)) {
- (*yco)-=21;
+ /* Draw constraint data */
+ if ((con->flag & CONSTRAINT_EXPAND) == 0) {
+ (*yco) -= 21;
}
else {
- switch (con->type){
+ switch (con->type) {
case CONSTRAINT_TYPE_PYTHON:
{
bPythonConstraint *data = con->data;
@@ -612,7 +687,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
static int pyconindex=0;
char *menustr;
- height = 90;
+ height = 110;
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, "Script:", *xco+60, *yco-24, 55, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
@@ -630,7 +705,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
/* Draw target parameters */
uiBlockBeginAlign(block);
uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-48, 150, 18, &data->tar, "Target Object");
-
+
if (is_armature_target) {
but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-66,150,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar);
@@ -653,22 +728,27 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Refresh", *xco+((width/2)+10), *yco-88, (width/2),18, NULL, 0, 24, 0, 0, "Force constraint to refresh it's settings");
uiBlockEndAlign(block);
+
+ /* constraint space settings */
+ if ((data->flag & PYCON_USETARGETS)==0) is_armature_target = -1;
+ draw_constraint_spaceselect(block, con, *xco, *yco-109, is_armature_owner, is_armature_target);
}
break;
case CONSTRAINT_TYPE_ACTION:
{
bActionConstraint *data = con->data;
+ float minval, maxval;
- height = 88;
+ height = 108;
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 */
uiBlockBeginAlign(block);
uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object");
-
- if (is_armature_target){
+
+ if (is_armature_target) {
but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar);
}
@@ -677,20 +757,91 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
}
uiBlockEndAlign(block);
-
- /* Draw action button */
+
+ /* Draw action/type buttons */
uiBlockBeginAlign(block);
- uiDefButS(block, TOG, B_CONSTRAINT_TEST, "Local", *xco+((width/2)-117), *yco-46, 78, 18, &data->local, 0, 0, 0, 0, "Use true local rotation difference");
uiDefIDPoinBut(block, test_actionpoin_but, ID_AC, B_CONSTRAINT_TEST, "AC:", *xco+((width/2)-117), *yco-64, 78, 18, &data->act, "Action containing the keyed motion for this bone");
- uiDefButS(block, MENU, B_CONSTRAINT_TEST, "Key on%t|X Rot%x0|Y Rot%x1|Z Rot%x2", *xco+((width/2)-117), *yco-84, 78, 18, &data->type, 0, 24, 0, 0, "Specify which transformation channel from the target is used to key the action");
-
+ uiDefButS(block, MENU, B_CONSTRAINT_TEST, "Key on%t|Loc X%x20|Loc Y%x21|Loc Z%x22|Rot X%x0|Rot Y%x1|Rot Z%x2|Size X%x10|Size Y%x11|Size Z%x12", *xco+((width/2)-117), *yco-84, 78, 18, &data->type, 0, 24, 0, 0, "Specify which transformation channel from the target is used to key the action");
+
+ /* Draw start/end frame buttons */
uiBlockBeginAlign(block);
uiDefButI(block, NUM, B_CONSTRAINT_TEST, "Start:", *xco+((width/2)-36), *yco-64, 78, 18, &data->start, 1, MAXFRAME, 0.0, 0.0, "Starting frame of the keyed motion");
uiDefButI(block, NUM, B_CONSTRAINT_TEST, "End:", *xco+((width/2)-36), *yco-84, 78, 18, &data->end, 1, MAXFRAME, 0.0, 0.0, "Ending frame of the keyed motion");
+ /* Draw minimum/maximum transform range buttons */
+ uiBlockBeginAlign(block);
+ if (data->type < 10) { /* rotation */
+ minval = -180.0f;
+ maxval = 180.0f;
+ }
+ else if (data->type < 20) { /* scaling */
+ minval = 0.0001f;
+ maxval = 1000.0f;
+ }
+ else { /* location */
+ minval = -1000.0f;
+ maxval = 1000.0f;
+ }
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Min:", *xco+((width/2)+45), *yco-64, 78, 18, &data->min, minval, maxval, 0, 0, "Minimum value for target channel range");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Max:", *xco+((width/2)+45), *yco-84, 78, 18, &data->max, minval, maxval, 0, 0, "Maximum value for target channel range");
+ uiBlockEndAlign(block);
+
+ /* constraint space settings */
+ draw_constraint_spaceselect(block, con, *xco, *yco-104, -1, is_armature_target);
+ }
+ break;
+ case CONSTRAINT_TYPE_CHILDOF:
+ {
+ bChildOfConstraint *data = con->data;
+ short normButWidth = (width/3);
+
+ height = 165;
+ 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, "Parent:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+
+ /* Draw target parameters */
+ uiBlockBeginAlign(block);
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object to use as Parent");
+
+ if (is_armature_target) {
+ but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone to use as Parent");
+ uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar);
+ }
+ else {
+ strcpy (data->subtarget, "");
+ }
+
+ uiBlockEndAlign(block);
+
+ /* Draw triples of channel toggles */
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Use Channel(s):", *xco+65, *yco-64, 150, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOG, CHILDOF_LOCX, B_CONSTRAINT_TEST, "Loc X", *xco, *yco-84, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Parent affects x-location");
+ uiDefButBitI(block, TOG, CHILDOF_LOCY, B_CONSTRAINT_TEST, "Loc Y", *xco+normButWidth, *yco-84, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Parent affects y-location");
+ uiDefButBitI(block, TOG, CHILDOF_LOCZ, B_CONSTRAINT_TEST, "Loc Z", *xco+(normButWidth * 2), *yco-84, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Parent affects z-location");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOG, CHILDOF_ROTX, B_CONSTRAINT_TEST, "Rot X", *xco, *yco-105, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Parent affects x-rotation");
+ uiDefButBitI(block, TOG, CHILDOF_ROTY, B_CONSTRAINT_TEST, "Rot Y", *xco+normButWidth, *yco-105, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Parent affects y-rotation");
+ uiDefButBitI(block, TOG, CHILDOF_ROTZ, B_CONSTRAINT_TEST, "Rot Z", *xco+(normButWidth * 2), *yco-105, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Parent affects z-rotation");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitI(block, TOG, CHILDOF_SIZEX, B_CONSTRAINT_TEST, "Scale X", *xco, *yco-126, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Parent affects x-scaling");
+ uiDefButBitI(block, TOG, CHILDOF_SIZEY, B_CONSTRAINT_TEST, "Scale Y", *xco+normButWidth, *yco-126, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Parent affects y-scaling");
+ uiDefButBitI(block, TOG, CHILDOF_SIZEZ, B_CONSTRAINT_TEST, "Scale Z", *xco+(normButWidth * 2), *yco-126, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Parent affects z-scaling");
+ uiBlockEndAlign(block);
+
+
+ /* Inverse options */
uiBlockBeginAlign(block);
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Min:", *xco+((width/2)+45), *yco-64, 78, 18, &data->min, -180, 180, 0, 0, "Minimum value for target channel range");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Max:", *xco+((width/2)+45), *yco-84, 78, 18, &data->max, -180, 180, 0, 0, "Maximum value for target channel range");
+ but=uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Set Inverse", *xco, *yco-151, (width/2),18, NULL, 0, 24, 0, 0, "Calculate current Parent-Inverse Matrix");
+ uiButSetFunc(but, childof_const_setinv, data, NULL);
+
+ but=uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Clear Inverse", *xco+((width/2)+10), *yco-151, (width/2),18, NULL, 0, 24, 0, 0, "Clear Parent-Inverse Matrix");
+ uiButSetFunc(but, childof_const_clearinv, data, NULL);
uiBlockEndAlign(block);
}
break;
@@ -698,15 +849,15 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
{
bLocateLikeConstraint *data = con->data;
- height = 91;
+ height = 111;
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 */
uiBlockBeginAlign(block);
uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object");
-
+
if (is_armature_target) {
but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar);
@@ -728,18 +879,20 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
uiBlockEndAlign(block);
/* Draw options */
- uiDefButBitI(block, TOG, LOCLIKE_OFFSET, B_CONSTRAINT_TEST, "Offset", *xco+(width/3), *yco-89, (width/3), 18, &data->flag, 0, 24, 0, 0, "Add original location onto copied location");
+ uiDefButBitI(block, TOG, LOCLIKE_OFFSET, B_CONSTRAINT_TEST, "Offset", *xco, *yco-89, (width/2), 18, &data->flag, 0, 24, 0, 0, "Add original location onto copied location");
if (is_armature_target) {
- uiDefButBitS(block, TOG, CONSTRAINT_LOCAL, B_CONSTRAINT_TEST, "Local", *xco, *yco-89, (width/3), 18, &con->flag, 0, 24, 0, 0, "Work on a Pose's local transform");
- uiDefButBitI(block, TOG, LOCLIKE_TIP, B_CONSTRAINT_TEST, "Target Bone Tip", *xco+(width/3*2), *yco-89, (width/3), 18, &data->flag, 0, 24, 0, 0, "Copy Location of Target Bone's Tip");
+ uiDefButBitI(block, TOG, LOCLIKE_TIP, B_CONSTRAINT_TEST, "Target Bone Tip", *xco+(width/2), *yco-89, (width/2), 18, &data->flag, 0, 24, 0, 0, "Copy Location of Target Bone's Tip");
}
+
+ /* constraint space settings */
+ draw_constraint_spaceselect(block, con, *xco, *yco-109, is_armature_owner, is_armature_target);
}
break;
case CONSTRAINT_TYPE_ROTLIKE:
{
bRotateLikeConstraint *data = con->data;
- height = 91;
+ height = 101;
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, "");
@@ -760,8 +913,6 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
/* Draw XYZ toggles */
uiBlockBeginAlign(block);
- if (is_armature_target)
- uiDefButBitS(block, TOG, CONSTRAINT_LOCAL, B_CONSTRAINT_TEST, "Local", *xco+((width/2)-98), *yco-64, 50, 18, &con->flag, 0, 24, 0, 0, "Work on a Pose's local transform");
but=uiDefButBitI(block, TOG, ROTLIKE_X, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component");
but=uiDefButBitI(block, TOG, ROTLIKE_X_INVERT, B_CONSTRAINT_TEST, "-", *xco+((width/2)-16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Invert X component");
but=uiDefButBitI(block, TOG, ROTLIKE_Y, B_CONSTRAINT_TEST, "Y", *xco+((width/2)+16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Y component");
@@ -769,17 +920,21 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
but=uiDefButBitI(block, TOG, ROTLIKE_Z, B_CONSTRAINT_TEST, "Z", *xco+((width/2)+96), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Z component");
but=uiDefButBitI(block, TOG, ROTLIKE_Z_INVERT, B_CONSTRAINT_TEST, "-", *xco+((width/2)+128), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Invert Z component");
uiBlockEndAlign(block);
+
+ /* constraint space settings */
+ draw_constraint_spaceselect(block, con, *xco, *yco-94, is_armature_owner, is_armature_target);
}
break;
case CONSTRAINT_TYPE_SIZELIKE:
{
bSizeLikeConstraint *data = con->data;
- height = 91;
-
+
+ height = 101;
+
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 */
uiBlockBeginAlign(block);
uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object");
@@ -796,12 +951,13 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
/* Draw XYZ toggles */
uiBlockBeginAlign(block);
- if (is_armature_target)
- uiDefButBitS(block, TOG, CONSTRAINT_LOCAL, B_CONSTRAINT_TEST, "Local", *xco+((width/2)-98), *yco-64, 50, 18, &con->flag, 0, 24, 0, 0, "Work on a Pose's local transform");
but=uiDefButBitI(block, TOG, SIZELIKE_X, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component");
but=uiDefButBitI(block, TOG, SIZELIKE_Y, B_CONSTRAINT_TEST, "Y", *xco+((width/2)-16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Y component");
but=uiDefButBitI(block, TOG, SIZELIKE_Z, B_CONSTRAINT_TEST, "Z", *xco+((width/2)+16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Z component");
uiBlockEndAlign(block);
+
+ /* constraint space settings */
+ draw_constraint_spaceselect(block, con, *xco, *yco-94, is_armature_owner, is_armature_target);
}
break;
case CONSTRAINT_TYPE_KINEMATIC:
@@ -1099,17 +1255,8 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-72, (textButWidth-5), 18, &(data->zmax), -1000, 1000, 0.1,0.5,"Highest z value to allow");
uiBlockEndAlign(block);
- uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST,"Co-ordinate Space:",*xco, *yco-100,150,18, NULL, 0.0, 0.0, 0.0, 0.0, "");
-
- if (ob->type == OB_ARMATURE && (ob->flag & OB_POSEMODE))
- uiDefButBitS(block, TOG, CONSTRAINT_LOCAL, B_CONSTRAINT_TEST, "Local", *xco+160, *yco-100, 60, 18, &con->flag, 0, 24, 0, 0, "Limit locations relative to the bone's rest-position");
- else if (ob->parent != NULL)
- uiDefButBitS(block, TOG, LIMIT_NOPARENT, B_CONSTRAINT_TEST, "Local", *xco+160, *yco-100, 60, 18, &data->flag2, 0, 24, 0, 0, "Limit locations relative to parent, not origin/world");
- else
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST,"World",*xco+160, *yco-100,60,18, NULL, 0.0, 0.0, 0.0, 0.0, "Limit locations relative to origin/world");
-
- uiBlockEndAlign(block);
+ /* constraint space settings */
+ draw_constraint_spaceselect(block, con, *xco, *yco-100, is_armature_owner, -1);
}
break;
case CONSTRAINT_TYPE_ROTLIMIT:
@@ -1117,10 +1264,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
bRotLimitConstraint *data = con->data;
int normButWidth = (width/3);
- if (ob->type == OB_ARMATURE && (ob->flag & OB_POSEMODE))
- height = 106;
- else
- height = 78;
+ height = 106;
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
@@ -1143,12 +1287,8 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max:", *xco+(normButWidth * 2), *yco-72, normButWidth, 18, &(data->zmax), -360, 360, 0.1,0.5,"Highest z value to allow");
uiBlockEndAlign(block);
- if (ob->type == OB_ARMATURE && (ob->flag & OB_POSEMODE)) {
- uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST,"Co-ordinate Space:",*xco, *yco-100,150,18, NULL, 0.0, 0.0, 0.0, 0.0, "");
- uiDefButBitS(block, TOG, CONSTRAINT_LOCAL, B_CONSTRAINT_TEST, "Local", *xco+160, *yco-100, 60, 18, &con->flag, 0, 24, 0, 0, "Work on a Pose's local transform");
- uiBlockEndAlign(block);
- }
+ /* constraint space settings */
+ draw_constraint_spaceselect(block, con, *xco, *yco-100, is_armature_owner, -1);
}
break;
case CONSTRAINT_TYPE_SIZELIMIT:
@@ -1158,10 +1298,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
int togButWidth = 50;
int textButWidth = ((width/2)-togButWidth);
- if (ob->type == OB_ARMATURE && (ob->flag & OB_POSEMODE))
- height = 106;
- else
- height = 78;
+ height = 106;
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
@@ -1175,35 +1312,31 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
uiDefButBitS(block, TOG, LIMIT_XMAX, B_CONSTRAINT_TEST, "maxX", *xco+(width-(textButWidth-5)-togButWidth), *yco-28, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum x value");
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-28, (textButWidth-5), 18, &(data->xmax), 0.0001, 1000, 0.1,0.5,"Highest x value to allow");
uiBlockEndAlign(block);
-
-
+
+
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, LIMIT_YMIN, B_CONSTRAINT_TEST, "minY", *xco, *yco-50, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y value");
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-50, (textButWidth-5), 18, &(data->ymin), 0.0001, 1000, 0.1,0.5,"Lowest y value to allow");
uiBlockEndAlign(block);
-
+
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, LIMIT_YMAX, B_CONSTRAINT_TEST, "maxY", *xco+(width-(textButWidth-5)-togButWidth), *yco-50, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum y value");
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-50, (textButWidth-5), 18, &(data->ymax), 0.0001, 1000, 0.1,0.5,"Highest y value to allow");
uiBlockEndAlign(block);
-
-
+
+
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, LIMIT_ZMIN, B_CONSTRAINT_TEST, "minZ", *xco, *yco-72, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum z value");
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-72, (textButWidth-5), 18, &(data->zmin), 0.0001, 1000, 0.1,0.5,"Lowest z value to allow");
uiBlockEndAlign(block);
-
+
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, LIMIT_ZMAX, B_CONSTRAINT_TEST, "maxZ", *xco+(width-(textButWidth-5)-togButWidth), *yco-72, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum z value");
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-72, (textButWidth-5), 18, &(data->zmax), 0.0001, 1000, 0.1,0.5,"Highest z value to allow");
uiBlockEndAlign(block);
- if (ob->type == OB_ARMATURE && (ob->flag & OB_POSEMODE)) {
- uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST,"Co-ordinate Space:",*xco, *yco-100,150,18, NULL, 0.0, 0.0, 0.0, 0.0, "");
- uiDefButBitS(block, TOG, CONSTRAINT_LOCAL, B_CONSTRAINT_TEST, "Local", *xco+160, *yco-100, 60, 18, &con->flag, 0, 24, 0, 0, "Work on a Pose's local transform");
- uiBlockEndAlign(block);
- }
+ /* constraint space settings */
+ draw_constraint_spaceselect(block, con, *xco, *yco-100, is_armature_owner, -1);
}
break;
case CONSTRAINT_TYPE_RIGIDBODYJOINT:
@@ -1236,7 +1369,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Ax Y:", *xco+135, *yco-100, 130, 18, &data->axY, -360, 360, 1500, 0.0, "Rotate pivot on Y Axis (in degrees)");
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Ax Z:", *xco+135, *yco-125, 130, 18, &data->axZ, -360, 360, 1500, 0.0, "Rotate pivot on Z Axis (in degrees)");
- if (data->type==CONSTRAINT_RB_GENERIC6DOF){
+ if (data->type==CONSTRAINT_RB_GENERIC6DOF) {
/* Draw Pairs of LimitToggle+LimitValue */
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, 1, B_CONSTRAINT_TEST, "LinMinX", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x limit");
@@ -1359,44 +1492,48 @@ static uiBlock *add_constraintmenu(void *arg_unused)
block= uiNewBlock(&curarea->uiblocks, "add_constraintmenu", UI_EMBOSSP, UI_HELV, curarea->win);
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCLIKE,"Copy Location", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_ROTLIKE,"Copy Rotation", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_SIZELIKE,"Copy Scale", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_CHILDOF, "Child Of", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCLIMIT,"Limit Location", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_ROTLIMIT,"Limit Rotation", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_SIZELIMIT,"Limit Scale", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCLIKE, "Copy Location", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_ROTLIKE, "Copy Rotation", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_SIZELIKE, "Copy Scale", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_TRACKTO,"Track To", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_MINMAX,"Floor", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCKTRACK,"Locked Track", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_FOLLOWPATH,"Follow Path", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_CLAMPTO,"Clamp To", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCLIMIT, "Limit Location", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_ROTLIMIT, "Limit Rotation", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_SIZELIMIT, "Limit Scale", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_STRETCHTO,"Stretch To", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_TRACKTO, "Track To", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_MINMAX, "Floor", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCKTRACK, "Locked Track", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_FOLLOWPATH, "Follow Path", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_CLAMPTO, "Clamp To", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_STRETCHTO, "Stretch To", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_RIGIDBODYJOINT,"Rigid Body Joint", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");//rcruiz
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_RIGIDBODYJOINT, "Rigid Body Joint", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");//rcruiz
if (ob->flag & OB_POSEMODE) {
uiDefBut(block, SEPR, 0, "", 0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_KINEMATIC,"IK Solver", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_ACTION,"Action", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_KINEMATIC, "IK Solver", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_ACTION, "Action", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
}
uiDefBut(block, SEPR, 0, "", 0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
uiDefBut(block, BUTM, B_CONSTRAINT_ADD_PYTHON, "Script", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
- uiDefBut(block, SEPR, 0, "", 0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
- uiDefBut(block, BUTM, B_CONSTRAINT_ADD_NULL,"Null", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_NULL, "Null", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
uiTextBoundsBlock(block, 50);
@@ -1408,183 +1545,187 @@ static uiBlock *add_constraintmenu(void *arg_unused)
void do_constraintbuts(unsigned short event)
{
Object *ob= OBACT;
+ bConstraint *con;
switch(event) {
case B_CONSTRAINT_TEST:
break; // no handling
case B_CONSTRAINT_INF:
/* influence; do not execute actions for 1 dag_flush */
- if(ob->pose)
+ if (ob->pose)
ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
case B_CONSTRAINT_CHANGETARGET:
- if(ob->pose) ob->pose->flag |= POSE_RECALC; // checks & sorts pose channels
+ if (ob->pose) ob->pose->flag |= POSE_RECALC; // checks & sorts pose channels
DAG_scene_sort(G.scene);
break;
- case B_CONSTRAINT_ADD_PYTHON:
+ case B_CONSTRAINT_ADD_NULL:
{
- bConstraint *con;
-
- con = add_new_constraint(CONSTRAINT_TYPE_PYTHON);
+ con = add_new_constraint(CONSTRAINT_TYPE_NULL);
add_constraint_to_active(ob, con);
BIF_undo_push("Add constraint");
}
break;
- case B_CONSTRAINT_ADD_NULL:
+ case B_CONSTRAINT_ADD_PYTHON:
{
- bConstraint *con;
-
- con = add_new_constraint(CONSTRAINT_TYPE_NULL);
+ con = add_new_constraint(CONSTRAINT_TYPE_PYTHON);
add_constraint_to_active(ob, con);
-
+
BIF_undo_push("Add constraint");
}
- break;
+ break;
case B_CONSTRAINT_ADD_KINEMATIC:
{
- bConstraint *con;
-
con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
add_constraint_to_active(ob, con);
-
+
+ BIF_undo_push("Add constraint");
+ }
+ break;
+ case B_CONSTRAINT_ADD_CHILDOF:
+ {
+ con= add_new_constraint(CONSTRAINT_TYPE_CHILDOF);
+ add_constraint_to_active(ob, con);
+
+ /* if this constraint is being added to a posechannel, make sure
+ * the constraint gets evaluated in pose-space
+ */
+ if (ob->flag & OB_POSEMODE) {
+ con->ownspace = CONSTRAINT_SPACE_POSE;
+ con->flag |= CONSTRAINT_SPACEONCE;
+ }
+
BIF_undo_push("Add constraint");
}
break;
case B_CONSTRAINT_ADD_TRACKTO:
{
- bConstraint *con;
-
con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
add_constraint_to_active(ob, con);
-
+
BIF_undo_push("Add constraint");
}
break;
case B_CONSTRAINT_ADD_MINMAX:
{
- bConstraint *con;
-
con = add_new_constraint(CONSTRAINT_TYPE_MINMAX);
add_constraint_to_active(ob, con);
-
+
BIF_undo_push("Add constraint");
}
break;
case B_CONSTRAINT_ADD_ROTLIKE:
{
- bConstraint *con;
-
con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE);
add_constraint_to_active(ob, con);
-
+
BIF_undo_push("Add constraint");
}
break;
case B_CONSTRAINT_ADD_LOCLIKE:
{
- bConstraint *con;
-
con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE);
add_constraint_to_active(ob, con);
-
+
BIF_undo_push("Add constraint");
}
break;
case B_CONSTRAINT_ADD_SIZELIKE:
{
- bConstraint *con;
-
con = add_new_constraint(CONSTRAINT_TYPE_SIZELIKE);
add_constraint_to_active(ob, con);
-
+
BIF_undo_push("Add constraint");
}
break;
case B_CONSTRAINT_ADD_ACTION:
{
- bConstraint *con;
-
con = add_new_constraint(CONSTRAINT_TYPE_ACTION);
add_constraint_to_active(ob, con);
-
+
BIF_undo_push("Add constraint");
}
break;
case B_CONSTRAINT_ADD_LOCKTRACK:
{
- bConstraint *con;
-
con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
add_constraint_to_active(ob, con);
-
+
BIF_undo_push("Add constraint");
}
break;
case B_CONSTRAINT_ADD_FOLLOWPATH:
{
- bConstraint *con;
-
con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
add_constraint_to_active(ob, con);
-
+
+ BIF_undo_push("Add constraint");
}
break;
case B_CONSTRAINT_ADD_STRETCHTO:
{
- bConstraint *con;
con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
add_constraint_to_active(ob, con);
-
+
BIF_undo_push("Add constraint");
}
break;
case B_CONSTRAINT_ADD_LOCLIMIT:
{
- bConstraint *con;
-
con = add_new_constraint(CONSTRAINT_TYPE_LOCLIMIT);
add_constraint_to_active(ob, con);
-
+
BIF_undo_push("Add constraint");
}
break;
case B_CONSTRAINT_ADD_ROTLIMIT:
{
- bConstraint *con;
-
con = add_new_constraint(CONSTRAINT_TYPE_ROTLIMIT);
add_constraint_to_active(ob, con);
-
+
BIF_undo_push("Add constraint");
}
break;
case B_CONSTRAINT_ADD_SIZELIMIT:
{
- bConstraint *con;
-
con = add_new_constraint(CONSTRAINT_TYPE_SIZELIMIT);
add_constraint_to_active(ob, con);
-
+
BIF_undo_push("Add constraint");
}
break;
case B_CONSTRAINT_ADD_RIGIDBODYJOINT:
{
- bConstraint *con;
+ bRigidBodyJointConstraint *data;
+ Base *base_iter;
+
con = add_new_constraint(CONSTRAINT_TYPE_RIGIDBODYJOINT);
add_constraint_to_active(ob, con);
-
+
+ /* set selected first object as target - moved from new_constraint_data */
+ data = (bRigidBodyJointConstraint*)con->data;
+ base_iter = G.scene->base.first;
+ while ( base_iter && !data->tar ) {
+ if( ( ( base_iter->flag & SELECT ) &&
+// ( base_iter->lay & G.vd->lay ) ) &&
+ ( base_iter != G.scene->basact ) ))
+ {
+ data->tar=base_iter->object;
+ break;
+ }
+ base_iter = base_iter->next;
+ }
+
BIF_undo_push("Add constraint");
}
break;
case B_CONSTRAINT_ADD_CLAMPTO:
{
- bConstraint *con;
con = add_new_constraint(CONSTRAINT_TYPE_CLAMPTO);
add_constraint_to_active(ob, con);
-
+
BIF_undo_push("Add constraint");
}
break;
@@ -2192,17 +2333,17 @@ void object_panel_constraint(char *context)
/* so first we make it default height */
uiNewPanelHeight(block, 204);
+ /* do not allow this panel to draw in editmode - why?*/
if(G.obedit==OBACT) return; // ??
conlist = get_active_constraints(OBACT);
if (conlist) {
-
uiDefBlockBut(block, add_constraintmenu, NULL, "Add Constraint", 0, 190, 130, 20, "Add a new constraint");
/* print active object or bone */
str[0]= 0;
- if (ob->flag & OB_POSEMODE){
+ if (ob->flag & OB_POSEMODE) {
bPoseChannel *pchan= get_active_posechannel(ob);
if(pchan) sprintf(str, "To Bone: %s", pchan->name);
}
diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c
index 2b0c8f7c14e..4e9b2451029 100644
--- a/source/blender/src/drawobject.c
+++ b/source/blender/src/drawobject.c
@@ -4182,7 +4182,7 @@ void draw_object(Base *base, int flag)
extern void make_axis_color(char *col, char *col2, char axis); // drawview.c
*/
bConstraint *curcon;
- float size[3], tmat[4][4];
+ float tmat[4][4];
char col[4], col2[4];
BIF_GetThemeColor3ubv(TH_GRID, col);
@@ -4191,7 +4191,7 @@ void draw_object(Base *base, int flag)
for (curcon = list->first; curcon; curcon=curcon->next){
if ((curcon->flag & CONSTRAINT_EXPAND)&&(curcon->type!=CONSTRAINT_TYPE_NULL)&&(constraint_has_target(curcon))){
- get_constraint_target_matrix(curcon, TARGET_OBJECT, NULL, tmat, size, bsystem_time(ob, 0, (float)(G.scene->r.cfra), ob->sf));
+ get_constraint_target_matrix(curcon, TARGET_OBJECT, NULL, tmat, bsystem_time(ob, 0, (float)(G.scene->r.cfra), ob->sf));
setlinestyle(3);
glBegin(GL_LINES);
glVertex3fv(tmat[3]);
diff --git a/source/blender/src/editconstraint.c b/source/blender/src/editconstraint.c
index 7e1178de377..248b7196b8f 100644
--- a/source/blender/src/editconstraint.c
+++ b/source/blender/src/editconstraint.c
@@ -671,21 +671,21 @@ void add_constraint(int only_IK)
else {
if(pchanact) {
if(pchansel)
- nr= pupmenu("Add Constraint to Active Bone%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|Action%x16|%l|Script%x18");
+ nr= pupmenu("Add Constraint to Active Bone%t|Child Of%x19|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
else if(obsel && obsel->type==OB_CURVE)
- nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|Stretch To%x7|Action%x16|%l|Script%x18");
+ nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|Stretch To%x7|%l|Action%x16|Script%x18");
else if(obsel)
- nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|Action%x16|%l|Script%x18");
+ nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
else
- nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Script%x18");
+ nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Script%x18");
}
else {
if(obsel && obsel->type==OB_CURVE)
- nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|%l|Script%x18");
+ nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|%l|Script%x18");
else if(obsel)
- nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Script%x18");
+ nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Script%x18");
else
- nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Script%x18");
+ nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Script%x18");
}
}
@@ -724,28 +724,31 @@ void add_constraint(int only_IK)
}
else {
- if(nr==1) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE);
- else if(nr==2) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE);
- else if(nr==3) con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
- else if(nr==4) con = add_new_constraint(CONSTRAINT_TYPE_MINMAX);
- else if(nr==5) con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
- else if(nr==6) {
+ if (nr==1) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE);
+ else if (nr==2) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE);
+ else if (nr==3) con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
+ else if (nr==4) con = add_new_constraint(CONSTRAINT_TYPE_MINMAX);
+ else if (nr==5) con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
+ else if (nr==6) {
Curve *cu= obsel->data;
cu->flag |= CU_PATH;
con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
}
- else if(nr==7) con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
- else if(nr==8) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIKE);
- else if(nr==13) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIMIT);
- else if(nr==14) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIMIT);
- else if(nr==15) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIMIT);
- else if(nr==16) con = add_new_constraint(CONSTRAINT_TYPE_ACTION);
- else if(nr==17) {
+ else if (nr==7) con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
+ else if (nr==8) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIKE);
+ else if (nr==13) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIMIT);
+ else if (nr==14) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIMIT);
+ else if (nr==15) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIMIT);
+ else if (nr==16) {
+ /* TODO: add a popup-menu to display list of available actions to use (like for pyconstraints) */
+ con = add_new_constraint(CONSTRAINT_TYPE_ACTION);
+ }
+ else if (nr==17) {
Curve *cu= obsel->data;
cu->flag |= CU_PATH;
con = add_new_constraint(CONSTRAINT_TYPE_CLAMPTO);
}
- else if(nr==18) {
+ else if (nr==18) {
char *menustr;
int scriptint= 0, dummy_int=0;
float dummy_matrix[4][4];
@@ -769,10 +772,21 @@ void add_constraint(int only_IK)
}
}
}
+ else if (nr==19) {
+ con= add_new_constraint(CONSTRAINT_TYPE_CHILDOF);
+
+ /* if this constraint is being added to a posechannel, make sure
+ * the constraint gets evaluated in pose-space
+ */
+ if (pchanact) {
+ con->ownspace = CONSTRAINT_SPACE_POSE;
+ con->flag |= CONSTRAINT_SPACEONCE;
+ }
+ }
- if(con==NULL) return; /* paranoia */
+ if (con==NULL) return; /* paranoia */
- if(pchanact) {
+ if (pchanact) {
BLI_addtail(&pchanact->constraints, con);
unique_constraint_name(con, &pchanact->constraints);
pchanact->constflag |= PCHAN_HAS_CONST; /* for draw */
@@ -784,13 +798,13 @@ void add_constraint(int only_IK)
}
/* set the target */
- if(pchansel) {
+ if (pchansel) {
set_constraint_target(con, ob, pchansel->name);
}
else if(obsel) {
set_constraint_target(con, obsel, NULL);
}
- else if(ELEM4(nr, 11, 13, 14, 15)==0) { /* add new empty as target */
+ else if (ELEM4(nr, 11, 13, 14, 15)==0) { /* add new empty as target */
Base *base= BASACT, *newbase;
Object *obt;
@@ -801,7 +815,7 @@ void add_constraint(int only_IK)
obt->lay= newbase->lay;
/* transform cent to global coords for loc */
- if(pchanact) {
+ if (pchanact) {
if(only_IK)
VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_tail);
else
@@ -816,8 +830,7 @@ void add_constraint(int only_IK)
BASACT= base;
base->flag |= SELECT;
}
-
-
+
/* active flag */
con->flag |= CONSTRAINT_ACTIVE;
for(con= con->prev; con; con= con->prev)
@@ -825,7 +838,7 @@ void add_constraint(int only_IK)
DAG_scene_sort(G.scene); // sort order of objects
- if(pchanact) {
+ if (pchanact) {
ob->pose->flag |= POSE_RECALC; // sort pose channels
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); // and all its relations
}
@@ -836,7 +849,7 @@ void add_constraint(int only_IK)
allqueue (REDRAWBUTSOBJECT, 0);
allqueue (REDRAWOOPS, 0);
- if(only_IK)
+ if (only_IK)
BIF_undo_push("Add IK Constraint");
else
BIF_undo_push("Add Constraint");
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index a6c449274c8..41e08e0f5e2 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -1400,7 +1400,7 @@ void make_parent(void)
while(base) {
if TESTBASELIB(base) {
if(base!=BASACT) {
- float cmat[4][4], vec[3], size[3];
+ float cmat[4][4], vec[3];
con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
strcpy (con->name, "AutoPath");
@@ -1410,7 +1410,7 @@ void make_parent(void)
add_constraint_to_object(con, base->object);
- get_constraint_target_matrix(con, TARGET_OBJECT, NULL, cmat, size, G.scene->r.cfra - base->object->sf);
+ get_constraint_target_matrix(con, TARGET_OBJECT, NULL, cmat, G.scene->r.cfra - base->object->sf);
VecSubf(vec, base->object->obmat[3], cmat[3]);
base->object->loc[0] = vec[0];
@@ -1423,7 +1423,7 @@ void make_parent(void)
allqueue(REDRAWVIEW3D, 0);
DAG_scene_sort(G.scene);
- BIF_undo_push("make Parent");
+ BIF_undo_push("Make Parent");
return;
}
}
diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c
index 3879bf21e0c..5e92a4db95b 100755
--- a/source/blender/src/transform_conversions.c
+++ b/source/blender/src/transform_conversions.c
@@ -511,6 +511,7 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr
{
Bone *bone= pchan->bone;
float pmat[3][3], omat[3][3];
+ float lmat[3][3], tmat[3][3];
float vec[3];
VECCOPY(vec, pchan->pose_mat[3]);
@@ -530,21 +531,18 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr
QUATCOPY(td->ext->iquat, pchan->quat);
VECCOPY(td->ext->isize, pchan->size);
- /* proper way to get the parent transform + own transform */
+ /* matrix to convert from dataspace to worldspace is
+ * world_mat = obmat * (pose_mat - chan_mat)
+ */
Mat3CpyMat4(omat, ob->obmat);
- if(pchan->parent) {
- if(pchan->bone->flag & BONE_HINGE)
- Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
- else
- Mat3CpyMat4(pmat, pchan->parent->pose_mat);
-
- Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0); // dang mulserie swaps args
- }
- else {
- Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat); // huh, transposed?
- }
- Mat3Inv (td->smtx, td->mtx);
+ Mat3CpyMat4(tmat, pchan->chan_mat);
+ Mat3Inv(lmat, tmat);
+ Mat3CpyMat4(pmat, pchan->pose_mat);
+ Mat3MulMat3(tmat, lmat, pmat); // argh... order of args is reversed
+ Mat3MulMat3(td->mtx, omat, pmat);
+
+ Mat3Inv(td->smtx, td->mtx);
/* for axismat we use bone's own transform */
Mat3CpyMat4(pmat, pchan->pose_mat);
@@ -2046,29 +2044,13 @@ static void ipokey_to_transdata(IpoKey *ik, TransData *td)
static void ObjectToTransData(TransData *td, Object *ob)
{
float obmtx[3][3];
- Object *tr;
- void *cfirst, *clast;
- /* set axismtx BEFORE clearing constraints to have the real orientation */
+ /* axismtx has the real orientation */
Mat3CpyMat4(td->axismtx, ob->obmat);
Mat3Ortho(td->axismtx);
- /* then why are constraints and track disabled here?
- they dont alter loc/rot/size itself (ton) */
- cfirst = ob->constraints.first;
- clast = ob->constraints.last;
- ob->constraints.first=ob->constraints.last=NULL;
-
- tr= ob->track;
- ob->track= NULL;
-
where_is_object(ob);
- ob->track= tr;
-
- ob->constraints.first = cfirst;
- ob->constraints.last = clast;
-
td->ob = ob;
td->loc = ob->loc;
@@ -2084,11 +2066,11 @@ static void ObjectToTransData(TransData *td, Object *ob)
VECCOPY(td->center, ob->obmat[3]);
- if (ob->parent)
+ if (ob->parent || ob->track || ob->constraints.first)
{
float totmat[3][3], obinv[3][3];
- /* we calculate smtx without obmat: so a parmat */
+ /* get the effect of parenting, and/or tracking, and/or constraints */
object_to_mat3(ob, obmtx);
Mat3CpyMat4(totmat, ob->obmat);
Mat3Inv(obinv, totmat);