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:
authorJoshua Leung <aligorith@gmail.com>2007-07-15 07:35:37 +0400
committerJoshua Leung <aligorith@gmail.com>2007-07-15 07:35:37 +0400
commitaf55d208f48017872e30faa76a66d777c983106d (patch)
tree818c07d693d001230e7730efd10575813f98f178
parent0f692d999a3529b73d6b153f6beaf9b570396d36 (diff)
== Constraints System ==
After just over a week of coding, I've finished doing a major refactor/cleanup of the constraints code. In the process, quite a few old kludges and ugly hacks have been removed. Also, some new features which will greatly benefit riggers have been implemented. === What's New === * The long-awaited ``ChildOf Constraint'': This allows you to animate parent influences, and choose which transformation channels the parent affects the child on (i.e. no translation/rotation/scaling). It should be noted that disabling some combinations may not totally work as expected. Also, the 'Set Inverse' and 'Clear Inverse' buttons at the bottom of this constraint's panel set/clear the inverse correction for the parent's effects. Use these to make the owner not stick/be glued to the parent. * Constraint/Target Evaluation Spaces: In some constraints, there are now 1-2 combo boxes at the bottom of their panel, which allows you to pick which `co-ordinate space' they are evaluated in. This is much more flexible than the old 'local' options for bones only were. * Action Constraint - Loc/Rot/Size Inputs The Action Constraint can finally use the target's location/rotation/scaling transforms as input, to control the owner of the constraint. This should work much more reliably than it used to. The target evaluation should now also be more accurate due to the new space conversion stuff. * Transform - No longer in Crazy Space (TM) Transforming objects/bones with constraints applied should no longer occur in Crazy Space. They are now correctly inverse-corrected. This also applies to old-style object tracking. === General Code Changes === * solve_constraints is now in constraints.c. I've removed the old `blend consecutive constraints of same type' junk, which made the code more complex than it needed to be. * evaluate_constraint is now only passed the constraint, and two matrices. A few unused variables have been removed from here. * A tempolary struct, bConstraintOb, is now passed to solve_constraints instead of relying on an ugly, static workobject in some cases. This works much better. * Made the formatting of constraint code consistent * There's a version patch for older files so that constraint settings are correctly converted to the new system. This is currently done for MajorVersion <= 244, and SubVersion < 3. I've bumped up the subversion to 3 for this purpose. However, with the imminent 2.45 release, this may need to be adjusted accordingly. * LocEulSizeToMat4 and LocQuatSizeToMat4 now work in the order Size, Rot, Location. I've also added a few other math functions. * Mat4BlendMat4 is now in arithb. I've modified it's method slightly, to use other arithb functions, instead of its crazy blending scheme. * Moved some of the RigidBodyJoint constraint's code out of blenkernel, and into src. It shouldn't be setting its target in its data initialisation function based + accessing scene stuff where it was doing so. === Future Work === * Geometry to act as targets for constraints. A space has been reserved for this already. * Tidy up UI buttons of constraints
-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);