diff options
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); |