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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/scripttemplate_pyconstraint.py20
-rw-r--r--source/blender/blenkernel/BKE_bad_level_calls.h7
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_constraint.h87
-rw-r--r--source/blender/blenkernel/bad_level_call_stubs/stubs.c10
-rw-r--r--source/blender/blenkernel/intern/armature.c50
-rw-r--r--source/blender/blenkernel/intern/constraint.c4573
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c165
-rw-r--r--source/blender/blenkernel/intern/object.c69
-rw-r--r--source/blender/blenloader/intern/readfile.c93
-rw-r--r--source/blender/blenloader/intern/writefile.c89
-rw-r--r--source/blender/include/BIF_editconstraint.h3
-rw-r--r--source/blender/include/butspace.h1
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h168
-rw-r--r--source/blender/python/BPY_extern.h10
-rw-r--r--source/blender/python/BPY_interface.c535
-rw-r--r--source/blender/python/api2_2x/Constraint.c71
-rw-r--r--source/blender/src/buttons_object.c956
-rw-r--r--source/blender/src/drawobject.c53
-rw-r--r--source/blender/src/editarmature.c57
-rw-r--r--source/blender/src/editconstraint.c192
-rw-r--r--source/blender/src/editobject.c19
-rw-r--r--source/blender/src/header_text.c20
-rw-r--r--source/blender/src/outliner.c6
-rw-r--r--source/blender/src/poseobject.c33
25 files changed, 4050 insertions, 3239 deletions
diff --git a/release/scripts/scripttemplate_pyconstraint.py b/release/scripts/scripttemplate_pyconstraint.py
index 8dcc04360d0..68aa9194435 100644
--- a/release/scripts/scripttemplate_pyconstraint.py
+++ b/release/scripts/scripttemplate_pyconstraint.py
@@ -21,17 +21,21 @@ from Blender import Draw
from Blender import Mathutils
import math
-USE_TARGET = True
+'''
+ This variable specifies the number of targets
+ that this constraint can use
+'''
+NUM_TARGETS = 1
'''
This function is called to evaluate the constraint
- obmatrix: (Matrix) copy of owner's worldspace matrix
- targetmatrix: (Matrix) copy of target's worldspace matrix (where applicable)
+ obmatrix: (Matrix) copy of owner's 'ownerspace' matrix
+ targetmatrices: (List) list of copies of the 'targetspace' matrices of the targets (where applicable)
idprop: (IDProperties) wrapped data referring to this
constraint instance's idproperties
'''
-def doConstraint(obmatrix, targetmatrix, idprop):
+def doConstraint(obmatrix, targetmatrices, idprop):
# Separate out the tranformation components for easy access.
obloc = obmatrix.translationPart() # Translation
obrot = obmatrix.toEuler() # Rotation
@@ -60,9 +64,9 @@ def doConstraint(obmatrix, targetmatrix, idprop):
'''
- This function manipulates the target matrix prior to sending it to doConstraint()
+ This function manipulates the matrix of a target prior to sending it to doConstraint()
target_object: wrapped data, representing the target object
- subtarget_bone: wrapped data, representing the subtarget pose-bone (where applicable)
+ subtarget_bone: wrapped data, representing the subtarget pose-bone/vertex-group (where applicable)
target_matrix: (Matrix) the transformation matrix of the target
id_properties_of_constraint: (IDProperties) wrapped idproperties
'''
@@ -72,8 +76,8 @@ def doTarget(target_object, subtarget_bone, target_matrix, id_properties_of_cons
'''
This function draws a pupblock that lets the user set
- the values of custom settings the constraint defines.
- This function is called when the user presses the settings button.
+ the values of custom settings the constraint defines.
+ This function is called when the user presses the settings button.
idprop: (IDProperties) wrapped data referring to this
constraint instance's idproperties
'''
diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h
index 296fd5837b5..32128c68af5 100644
--- a/source/blender/blenkernel/BKE_bad_level_calls.h
+++ b/source/blender/blenkernel/BKE_bad_level_calls.h
@@ -65,6 +65,7 @@ struct IpoDriver; /* DNA_curve_types.h */
struct Object;
struct bPythonConstraint;
struct bConstraintOb;
+struct bConstraintTarget;
void BPY_do_pyscript (struct ID *id, short int event);
void BPY_clear_script (struct Script *script);
void BPY_free_compiled_text (struct Text *text);
@@ -74,9 +75,9 @@ float BPY_pydriver_eval(struct IpoDriver *driver);
void BPY_pydriver_update(void);
/* button python evaluation */
int BPY_button_eval(char *expr, double *value);
-void BPY_pyconstraint_eval(struct bPythonConstraint *con, float ownermat[][4], float targetmat[][4]);
-void BPY_pyconstraint_driver(struct bPythonConstraint *con, struct bConstraintOb *cob, struct Object *target, char subtarget[]);
-int BPY_pyconstraint_targets(struct bPythonConstraint *con, float targetmat[][4]);
+/* pyconstraints */
+void BPY_pyconstraint_eval(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets);
+void BPY_pyconstraint_targets(struct bPythonConstraint *con, struct bConstraintTarget *ct);
/* writefile.c */
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 7f7ea79fcc6..55a542f51d5 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 245
-#define BLENDER_SUBVERSION 6
+#define BLENDER_SUBVERSION 7
#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 39a3cf13087..40fd8c5ed18 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -33,22 +33,12 @@
#ifndef BKE_CONSTRAINT_H
#define BKE_CONSTRAINT_H
-
struct bConstraint;
+struct bConstraintTarget;
struct ListBase;
struct Object;
struct bConstraintChannel;
struct bPoseChannel;
-struct bAction;
-struct bArmature;
-
-/* ---------------------------------------------------------------------------- */
-
-/* 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 */
/* ---------------------------------------------------------------------------- */
@@ -65,26 +55,77 @@ typedef struct bConstraintOb {
/* ---------------------------------------------------------------------------- */
+/* Constraint Type-Info (shorthand in code = cti):
+ * This struct provides function pointers for runtime, so that functions can be
+ * written more generally (with fewer/no special exceptions for various constraints).
+ *
+ * Callers of these functions must check that they actually point to something useful,
+ * as some constraints don't define some of these.
+ *
+ * Warning: it is not too advisable to reorder order of members of this struct,
+ * as you'll have to edit quite a few ($NUM_CONSTRAINT_TYPES) of these
+ * structs.
+ */
+typedef struct bConstraintTypeInfo {
+ /* admin/ident */
+ short type; /* CONSTRAINT_TYPE_### */
+ short size; /* size in bytes of the struct */
+ char name[32]; /* name constraint in interface */
+ char structName[32]; /* name of struct for SDNA */
+
+ /* data management function pointers - special handling */
+ /* free any data that is allocated separately (optional) */
+ void (*free_data)(struct bConstraint *con);
+ /* adjust pointer to other ID-data using ID_NEW(), but not to targets (optional) */
+ void (*relink_data)(struct bConstraint *con);
+ /* copy any special data that is allocated separately (optional) */
+ void (*copy_data)(struct bConstraint *con, struct bConstraint *src);
+ /* set settings for data that will be used for bConstraint.data (memory already allocated) */
+ void (*new_data)(void *cdata);
+
+ /* target handling function pointers */
+ /* for multi-target constraints: return that list; otherwise make a temporary list */
+ void (*get_constraint_targets)(struct bConstraint *con, struct ListBase *list);
+ /* for single-target constraints only: flush data back to source data, and the free memory used */
+ void (*flush_constraint_targets)(struct bConstraint *con, struct ListBase *list, short nocopy);
+
+ /* evaluation */
+ /* set the ct->matrix for the given constraint target (at the given ctime) */
+ void (*get_target_matrix)(struct bConstraint *con, struct bConstraintOb *cob, struct bConstraintTarget *ct, float ctime);
+ /* evaluate the constraint for the given time */
+ void (*evaluate_constraint)(struct bConstraint *con, struct bConstraintOb *cob, struct ListBase *targets);
+} bConstraintTypeInfo;
+
+/* Function Prototypes for bConstraintTypeInfo's */
+bConstraintTypeInfo *constraint_get_typeinfo(struct bConstraint *con);
+bConstraintTypeInfo *get_constraint_typeinfo(int type);
+
+/* ---------------------------------------------------------------------------- */
+/* Useful macros for testing various common flag combinations */
+
+/* Constraint Target Macros */
+#define VALID_CONS_TARGET(ct) ((ct) && (ct->tar))
+
+
+/* ---------------------------------------------------------------------------- */
+
/* Constraint function prototypes */
void unique_constraint_name(struct bConstraint *con, struct ListBase *list);
-void *new_constraint_data(short type);
+
void free_constraints(struct ListBase *conlist);
void copy_constraints(struct ListBase *dst, struct ListBase *src);
void relink_constraints(struct ListBase *list);
void free_constraint_data(struct bConstraint *con);
+
/* 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, int onlydrivers);
-void copy_constraint_channels(ListBase *dst, ListBase *src);
+struct bConstraintChannel *get_constraint_channel(struct ListBase *list, const char *name);
+struct bConstraintChannel *verify_constraint_channel(struct ListBase *list, const char *name);
+void do_constraint_channels(struct ListBase *conbase, struct ListBase *chanbase, float ctime, short onlydrivers);
+void copy_constraint_channels(struct ListBase *dst, struct ListBase *src);
void clone_constraint_channels(struct ListBase *dst, struct ListBase *src);
-void free_constraint_channels(ListBase *chanbase);
+void free_constraint_channels(struct ListBase *chanbase);
-/* 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);
@@ -92,8 +133,8 @@ void constraints_clear_evalob(struct bConstraintOb *cob);
void constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, float mat[][4], short from, short to);
-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);
+void get_constraint_target_matrix(struct bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float ctime);
+void solve_constraints(struct ListBase *conlist, struct bConstraintOb *cob, float ctime);
#endif
diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
index 2524a804e53..9d00db8076d 100644
--- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c
+++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
@@ -57,6 +57,8 @@ struct RenderResult;
struct Object;
struct bPythonConstraint;
struct bConstraintOb;
+struct bConstraintTarget;
+struct ListBase;
char *getIpoCurveName( struct IpoCurve * icu );
void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast);
@@ -128,16 +130,12 @@ int BPY_button_eval(char *expr, double *value)
}
/* PyConstraints - BPY_interface.c */
-void BPY_pyconstraint_eval(struct bPythonConstraint *con, float ownermat[][4], float targetmat[][4])
+void BPY_pyconstraint_eval(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets)
{
}
-void BPY_pyconstraint_driver(struct bPythonConstraint *con, struct bConstraintOb *cob, struct Object *target, char subtarget[])
+void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTarget *ct)
{
}
-int BPY_pyconstraint_targets(struct bPythonConstraint *con, float targetmat[][4])
-{
- return 0;
-}
/* writefile.c */
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 10b2a364827..2030859000f 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -1239,7 +1239,6 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
bPose *pose= ob->pose, *frompose= from->pose;
bPoseChannel *pchan, *pchanp, pchanw;
bConstraint *con;
- char *str;
if(frompose==NULL) return;
@@ -1267,8 +1266,23 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
copy_constraints(&pchanw.constraints, &pchanp->constraints);
for(con= pchanw.constraints.first; con; con= con->next) {
- if(from==get_constraint_target(con, &str))
- set_constraint_target(con, ob, NULL);
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ if (ct->tar == from) {
+ ct->tar = ob;
+ strcpy(ct->subtarget, "");
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
}
/* free stuff from current channel */
@@ -1609,45 +1623,47 @@ static void execute_posetree(Object *ob, PoseTree *tree)
Mat4MulMat4 (imat, rootmat, ob->obmat);
Mat4Invert (goalinv, imat);
- for(target=tree->targets.first; target; target=target->next) {
+ for (target=tree->targets.first; target; target=target->next) {
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, 1.0);
-
+
+ /* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though
+ * strictly speaking, it is a posechannel)
+ */
+ get_constraint_target_matrix(target->con, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
+
/* and set and transform goal */
Mat4MulMat4(goal, rootmat, goalinv);
-
+
VECCOPY(goalpos, goal[3]);
Mat3CpyMat4(goalrot, goal);
-
+
/* do we need blending? */
- if(target->con->enforce!=1.0) {
+ if (target->con->enforce!=1.0) {
float q1[4], q2[4], q[4];
float fac= target->con->enforce;
float mfac= 1.0-fac;
pchan= tree->pchan[target->tip];
-
+
/* end effector in world space */
Mat4CpyMat4(end_pose, pchan->pose_mat);
VECCOPY(end_pose[3], pchan->pose_tail);
Mat4MulSerie(world_pose, goalinv, ob->obmat, end_pose, 0, 0, 0, 0, 0);
-
+
/* blend position */
goalpos[0]= fac*goalpos[0] + mfac*world_pose[3][0];
goalpos[1]= fac*goalpos[1] + mfac*world_pose[3][1];
goalpos[2]= fac*goalpos[2] + mfac*world_pose[3][2];
-
+
/* blend rotation */
Mat3ToQuat(goalrot, q1);
Mat4ToQuat(world_pose, q2);
QuatInterpol(q, q1, q2, mfac);
QuatToMat3(q, goalrot);
}
-
+
iktarget= iktree[target->tip];
-
+
if(data->weight != 0.0)
IK_SolverAddGoal(solver, iktarget, goalpos, data->weight);
if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0) && (data->flag & CONSTRAINT_IK_AUTO)==0)
@@ -1932,7 +1948,7 @@ static void where_is_pose_bone(Object *ob, bPoseChannel *pchan, float ctime)
/* prepare PoseChannel for Constraint solving
* - makes a copy of matrix, and creates temporary struct to use
*/
- cob= constraints_make_evalob(ob, pchan, TARGET_BONE);
+ cob= constraints_make_evalob(ob, pchan, CONSTRAINT_OBTYPE_BONE);
/* Solve PoseChannel's Constraints */
solve_constraints(&pchan->constraints, cob, ctime); // ctime doesnt alter objects
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 020350d9e6f..b46504b0e6d 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -48,6 +48,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_lattice_types.h"
#include "DNA_scene_types.h"
+#include "DNA_text_types.h"
#include "BKE_utildefines.h"
#include "BKE_action.h"
@@ -79,39 +80,18 @@
#endif
-/* ********************* Data level ****************** */
-
-void free_constraint_data (bConstraint *con)
-{
- if (con->data) {
- /* any constraint-type specific stuff here */
- switch (con->type) {
- case CONSTRAINT_TYPE_PYTHON:
- {
- bPythonConstraint *data= con->data;
- IDP_FreeProperty(data->prop);
- MEM_freeN(data->prop);
- }
- break;
- }
-
- MEM_freeN(con->data);
- }
-}
-
-void free_constraints (ListBase *conlist)
-{
- bConstraint *con;
-
- /* Do any specific freeing */
- for (con=conlist->first; con; con=con->next) {
- free_constraint_data(con);
- }
-
- /* Free the whole list */
- BLI_freelistN(conlist);
-}
+/* ******************* Constraint Channels ********************** */
+/* Constraint Channels exist in one of two places:
+ * - Under Action Channels in an Action (act->chanbase->achan->constraintChannels)
+ * - Under Object without object-level action yet (ob->constraintChannels)
+ *
+ * The main purpose that constraint channels serve is to act as a link
+ * between an IPO-block which
+ */
+/* ------------ Data Management ----------- */
+
+/* Free constraint channels, and reduce the number of users of the related ipo-blocks */
void free_constraint_channels (ListBase *chanbase)
{
bConstraintChannel *chan;
@@ -125,27 +105,14 @@ void free_constraint_channels (ListBase *chanbase)
BLI_freelistN(chanbase);
}
-void relink_constraints (struct ListBase *list)
-{
- bConstraint *con;
-
- for (con = list->first; con; con=con->next) {
- /* check if constraint has a target that needs relinking */
- if (constraint_has_target(con)) {
- Object *tar;
- char *subtarget;
-
- tar = get_constraint_target(con, &subtarget);
- ID_NEW(tar);
- }
- }
-}
-
+/* Make a copy of the constraint channels from dst to src, and also give the
+ * new constraint channels their own copy of the original's IPO.
+ */
void copy_constraint_channels (ListBase *dst, ListBase *src)
{
bConstraintChannel *dchan, *schan;
- dst->first=dst->last=NULL;
+ dst->first = dst->last = NULL;
duplicatelist(dst, src);
for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next) {
@@ -153,11 +120,14 @@ void copy_constraint_channels (ListBase *dst, ListBase *src)
}
}
+/* Make a copy of the constraint channels from dst to src, but make the
+ * new constraint channels use the same IPO-data as their twin.
+ */
void clone_constraint_channels (ListBase *dst, ListBase *src)
{
bConstraintChannel *dchan, *schan;
- dst->first=dst->last=NULL;
+ dst->first = dst->last = NULL;
duplicatelist(dst, src);
for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next) {
@@ -165,354 +135,81 @@ void clone_constraint_channels (ListBase *dst, ListBase *src)
}
}
-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;
-
- pycon->prop = IDP_CopyProperty(opycon->prop);
- }
- }
-}
-
-/* **************** Editor Functions **************** */
+/* ------------- Constraint Channel Tools ------------ */
-char constraint_has_target (bConstraint *con)
+/* Find the constraint channel with a given name */
+bConstraintChannel *get_constraint_channel (ListBase *list, const char name[])
{
- switch (con->type) {
- case CONSTRAINT_TYPE_PYTHON:
- {
- bPythonConstraint *data = con->data;
- if (data->tar) return 1;
- }
- break;
- case CONSTRAINT_TYPE_TRACKTO:
- {
- bTrackToConstraint *data = con->data;
- if (data->tar) return 1;
- }
- break;
- case CONSTRAINT_TYPE_KINEMATIC:
- {
- bKinematicConstraint *data = con->data;
- if (data->tar) return 1;
- }
- break;
- case CONSTRAINT_TYPE_FOLLOWPATH:
- {
- bFollowPathConstraint *data = con->data;
- if (data->tar) return 1;
- }
- break;
- case CONSTRAINT_TYPE_ROTLIKE:
- {
- bRotateLikeConstraint *data = con->data;
- if (data->tar) return 1;
- }
- break;
- case CONSTRAINT_TYPE_LOCLIKE:
- {
- bLocateLikeConstraint *data = con->data;
- if (data->tar) return 1;
- }
- break;
- case CONSTRAINT_TYPE_SIZELIKE:
- {
- bSizeLikeConstraint *data = con->data;
- if (data->tar) return 1;
- }
- break;
- case CONSTRAINT_TYPE_MINMAX:
- {
- bMinMaxConstraint *data = con->data;
- if (data->tar) return 1;
- }
- break;
- case CONSTRAINT_TYPE_ACTION:
- {
- bActionConstraint *data = con->data;
- if (data->tar) return 1;
- }
- break;
- case CONSTRAINT_TYPE_LOCKTRACK:
- {
- bLockTrackConstraint *data = con->data;
- if (data->tar) return 1;
- }
- case CONSTRAINT_TYPE_STRETCHTO:
- {
- bStretchToConstraint *data = con->data;
- if (data->tar) return 1;
- }
- break;
- case CONSTRAINT_TYPE_RIGIDBODYJOINT:
- {
- bRigidBodyJointConstraint *data = con->data;
- if (data->tar) return 1;
- }
- break;
- case CONSTRAINT_TYPE_CLAMPTO:
- {
- bClampToConstraint *data = con->data;
- if (data->tar) return 1;
- }
- break;
- case CONSTRAINT_TYPE_CHILDOF:
- {
- bChildOfConstraint *data = con->data;
- if (data->tar) return 1;
- }
- break;
- case CONSTRAINT_TYPE_TRANSFORM:
- {
- bTransformConstraint *data = con->data;
- if (data->tar) return 1;
+ bConstraintChannel *chan;
+
+ for (chan = list->first; chan; chan=chan->next) {
+ if (!strcmp(name, chan->name)) {
+ return chan;
}
- break;
}
- /* Unknown types or CONSTRAINT_TYPE_NULL or no target */
- return 0;
+ return NULL;
}
-Object *get_constraint_target(bConstraint *con, char **subtarget)
+/* Find or create a new constraint channel */
+bConstraintChannel *verify_constraint_channel (ListBase *list, const char name[])
{
- /* If the target for this constraint is target, return a pointer
- * to the name for this constraints subtarget ... NULL otherwise
- */
- switch (con->type) {
- case CONSTRAINT_TYPE_PYTHON:
- {
- bPythonConstraint *data=con->data;
- *subtarget = data->subtarget;
- return data->tar;
- }
- break;
- case CONSTRAINT_TYPE_ACTION:
- {
- bActionConstraint *data = con->data;
- *subtarget= data->subtarget;
- return data->tar;
- }
- break;
- case CONSTRAINT_TYPE_LOCLIKE:
- {
- bLocateLikeConstraint *data = con->data;
- *subtarget= data->subtarget;
- return data->tar;
- }
- break;
- case CONSTRAINT_TYPE_ROTLIKE:
- {
- bRotateLikeConstraint *data = con->data;
- *subtarget= data->subtarget;
- return data->tar;
- }
- break;
- case CONSTRAINT_TYPE_SIZELIKE:
- {
- bSizeLikeConstraint *data = con->data;
- *subtarget= data->subtarget;
- return data->tar;
- }
- break;
- case CONSTRAINT_TYPE_KINEMATIC:
- {
- bKinematicConstraint *data = con->data;
- *subtarget= data->subtarget;
- return data->tar;
- }
- break;
- case CONSTRAINT_TYPE_TRACKTO:
- {
- bTrackToConstraint *data = con->data;
- *subtarget= data->subtarget;
- return data->tar;
- }
- break;
- case CONSTRAINT_TYPE_MINMAX:
- {
- bMinMaxConstraint *data = con->data;
- *subtarget= data->subtarget;
- return data->tar;
- }
- break;
- case CONSTRAINT_TYPE_LOCKTRACK:
- {
- bLockTrackConstraint *data = con->data;
- *subtarget= data->subtarget;
- return data->tar;
- }
- break;
- case CONSTRAINT_TYPE_FOLLOWPATH:
- {
- bFollowPathConstraint *data = con->data;
- *subtarget= NULL;
- return data->tar;
- }
- break;
- case CONSTRAINT_TYPE_STRETCHTO:
- {
- bStretchToConstraint *data = con->data;
- *subtarget= data->subtarget;
- return data->tar;
- }
- break;
- case CONSTRAINT_TYPE_RIGIDBODYJOINT:
- {
- bRigidBodyJointConstraint *data = con->data;
- *subtarget= NULL;
- return data->tar;
- }
- break;
- case CONSTRAINT_TYPE_CLAMPTO:
- {
- bClampToConstraint *data = con->data;
- *subtarget= NULL;
- return data->tar;
- }
- break;
- case CONSTRAINT_TYPE_CHILDOF:
- {
- bChildOfConstraint *data = con->data;
- *subtarget= data->subtarget;
- return data->tar;
- }
- break;
- case CONSTRAINT_TYPE_TRANSFORM:
- {
- bTransformConstraint *data = con->data;
- *subtarget= data->subtarget;
- return data->tar;
- }
- break;
- default:
- *subtarget= NULL;
- break;
+ bConstraintChannel *chan;
+
+ chan= get_constraint_channel(list, name);
+
+ if (chan == NULL) {
+ chan= MEM_callocN(sizeof(bConstraintChannel), "new constraint channel");
+ BLI_addtail(list, chan);
+ strcpy(chan->name, name);
}
- return NULL;
+ return chan;
}
-void set_constraint_target(bConstraint *con, Object *ob, char *subtarget)
+/* --------- Constraint Channel Evaluation/Execution --------- */
+
+/* IPO-system call: calculate IPO-block for constraint channels, and flush that
+ * info onto the corresponding constraint.
+ */
+void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime, short onlydrivers)
{
- /* 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);
- }
- break;
- case CONSTRAINT_TYPE_ACTION:
- {
- bActionConstraint *data = con->data;
- data->tar= ob;
- 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);
- }
- break;
- case CONSTRAINT_TYPE_ROTLIKE:
- {
- bRotateLikeConstraint *data = con->data;
- data->tar= ob;
- 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);
- }
- break;
- case CONSTRAINT_TYPE_KINEMATIC:
- {
- bKinematicConstraint *data = con->data;
- data->tar= ob;
- 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);
- }
- break;
- case CONSTRAINT_TYPE_LOCKTRACK:
- {
- bLockTrackConstraint *data = con->data;
- data->tar= ob;
- if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
- }
- break;
- case CONSTRAINT_TYPE_FOLLOWPATH:
- {
- bFollowPathConstraint *data = con->data;
- data->tar= ob;
- }
- break;
- case CONSTRAINT_TYPE_STRETCHTO:
- {
- bStretchToConstraint *data = con->data;
- data->tar= ob;
- if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
- }
- break;
- case CONSTRAINT_TYPE_RIGIDBODYJOINT:
- {
- bRigidBodyJointConstraint *data = con->data;
- data->tar= ob;
- }
- break;
- case CONSTRAINT_TYPE_MINMAX:
- {
- bMinMaxConstraint *data = (bMinMaxConstraint*)con->data;
- data->tar= ob;
- if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
- }
- break;
- case CONSTRAINT_TYPE_CLAMPTO:
- {
- bClampToConstraint *data = con->data;
- data->tar= ob;
- }
- break;
- case CONSTRAINT_TYPE_CHILDOF:
- {
- bChildOfConstraint *data = con->data;
- data->tar= ob;
- if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
- }
- break;
- case CONSTRAINT_TYPE_TRANSFORM:
- {
- bTransformConstraint *data = con->data;
- data->tar= ob;
- if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
+ bConstraint *con;
+ bConstraintChannel *chan;
+ 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) {
+ calc_ipo(chan->ipo, ctime);
+
+ for (icu=chan->ipo->curve.first; icu; icu=icu->next) {
+ if (!onlydrivers || icu->driver) {
+ switch (icu->adrcode) {
+ case CO_ENFORCE:
+ {
+ /* Influence is clamped to 0.0f -> 1.0f range */
+ con->enforce = CLAMPIS(icu->curval, 0.0f, 1.0f);
+ }
+ break;
+ }
+ }
+ }
}
- break;
}
}
+/* ************************ Constraints - General Utilities *************************** */
+/* These functions here don't act on any specific constraints, and are therefore should/will
+ * not require any of the special function-pointers afforded by the relevant constraint
+ * type-info structs.
+ */
+
+/* -------------- Naming -------------- */
+
+/* Find the first available, non-duplicate name for a given constraint */
void unique_constraint_name (bConstraint *con, ListBase *list)
{
bConstraint *curcon;
@@ -536,11 +233,11 @@ void unique_constraint_name (bConstraint *con, ListBase *list)
}
}
- if (!exists)
+ if (exists == 0)
return;
/* Strip off the suffix */
- dot=strchr(con->name, '.');
+ dot = strchr(con->name, '.');
if (dot)
*dot=0;
@@ -549,248 +246,21 @@ void unique_constraint_name (bConstraint *con, ListBase *list)
exists = 0;
for (curcon=list->first; curcon; curcon=curcon->next) {
- if (con!=curcon) {
- if (!strcmp(curcon->name, tempname)) {
+ if (con != curcon) {
+ if (strcmp(curcon->name, tempname)==0) {
exists = 1;
break;
}
}
}
- if (!exists) {
+ if (exists == 0) {
strcpy(con->name, tempname);
return;
}
}
}
-void *new_constraint_data (short type)
-{
- void *result;
-
- switch (type) {
- case CONSTRAINT_TYPE_PYTHON:
- {
- bPythonConstraint *data;
- data = MEM_callocN(sizeof(bPythonConstraint), "pythonConstraint");
-
- /* everything should be set correctly by calloc, except for the prop->type constant.*/
- data->prop = MEM_callocN(sizeof(IDProperty), "PyConstraintProps");
- data->prop->type = IDP_GROUP;
-
- result = data;
- }
- break;
- case CONSTRAINT_TYPE_KINEMATIC:
- {
- bKinematicConstraint *data;
- data = MEM_callocN(sizeof(bKinematicConstraint), "kinematicConstraint");
-
- data->weight= (float)1.0;
- data->orientweight= (float)1.0;
- data->iterations = 500;
- data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_STRETCH|CONSTRAINT_IK_POS;
-
- result = data;
- }
- break;
- case CONSTRAINT_TYPE_TRACKTO:
- {
- bTrackToConstraint *data;
- data = MEM_callocN(sizeof(bTrackToConstraint), "tracktoConstraint");
-
- data->reserved1 = TRACK_Y;
- data->reserved2 = UP_Z;
-
- result = data;
- }
- break;
- case CONSTRAINT_TYPE_MINMAX:
- {
- bMinMaxConstraint *data;
- data = MEM_callocN(sizeof(bMinMaxConstraint), "minmaxConstraint");
-
- data->minmaxflag = TRACK_Z;
- data->offset = 0.0f;
- data->cache[0] = data->cache[1] = data->cache[2] = 0.0f;
- data->flag = 0;
-
- result = data;
- }
- break;
- case CONSTRAINT_TYPE_LOCLIKE:
- {
- bLocateLikeConstraint *data;
- data = MEM_callocN(sizeof(bLocateLikeConstraint), "LocLikeConstraint");
- data->flag = LOCLIKE_X|LOCLIKE_Y|LOCLIKE_Z;
- result = data;
- }
- break;
- case CONSTRAINT_TYPE_ROTLIKE:
- {
- bRotateLikeConstraint *data;
- data = MEM_callocN(sizeof(bRotateLikeConstraint), "RotLikeConstraint");
- data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z;
- result = data;
- }
- break;
- case CONSTRAINT_TYPE_SIZELIKE:
- {
- bSizeLikeConstraint *data;
- data = MEM_callocN(sizeof(bLocateLikeConstraint), "SizeLikeConstraint");
- data->flag = SIZELIKE_X|SIZELIKE_Y|SIZELIKE_Z;
- result = data;
- }
- break;
- case CONSTRAINT_TYPE_ACTION:
- {
- bActionConstraint *data;
- 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;
- }
- break;
- case CONSTRAINT_TYPE_LOCKTRACK:
- {
- bLockTrackConstraint *data;
- data = MEM_callocN(sizeof(bLockTrackConstraint), "locktrackConstraint");
-
- data->trackflag = TRACK_Y;
- data->lockflag = LOCK_Z;
-
- result = data;
- }
- break;
- case CONSTRAINT_TYPE_FOLLOWPATH:
- {
- bFollowPathConstraint *data;
- data = MEM_callocN(sizeof(bFollowPathConstraint), "followpathConstraint");
-
- data->trackflag = TRACK_Y;
- data->upflag = UP_Z;
- data->offset = 0;
- data->followflag = 0;
-
- result = data;
- }
- break;
- case CONSTRAINT_TYPE_STRETCHTO:
- {
- bStretchToConstraint *data;
- data = MEM_callocN(sizeof(bStretchToConstraint), "StretchToConstraint");
-
- data->volmode = 0;
- data->plane = 0;
- data->orglength = 0.0;
- data->bulge = 1.0;
- result = data;
- }
- break;
- case CONSTRAINT_TYPE_LOCLIMIT:
- {
- bLocLimitConstraint *data;
- data = MEM_callocN(sizeof(bLocLimitConstraint), "LocLimitConstraint");
- result = data;
- }
- break;
- case CONSTRAINT_TYPE_ROTLIMIT:
- {
- bRotLimitConstraint *data;
- data = MEM_callocN(sizeof(bRotLimitConstraint), "RotLimitConstraint");
- result = data;
- }
- break;
- case CONSTRAINT_TYPE_SIZELIMIT:
- {
- bSizeLimitConstraint *data;
- data = MEM_callocN(sizeof(bSizeLimitConstraint), "SizeLimitConstraint");
- result = data;
- }
- break;
- case CONSTRAINT_TYPE_RIGIDBODYJOINT:
- {
- bRigidBodyJointConstraint *data;
- data = MEM_callocN(sizeof(bRigidBodyJointConstraint), "RigidBodyToConstraint");
-
- // removed code which set target of this constraint
- data->type=1;
-
- result = data;
- }
- break;
- case CONSTRAINT_TYPE_CLAMPTO:
- {
- bClampToConstraint *data;
- data = MEM_callocN(sizeof(bClampToConstraint), "ClampToConstraint");
- 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;
- case CONSTRAINT_TYPE_TRANSFORM:
- {
- bTransformConstraint *data;
- data = MEM_callocN(sizeof(bTransformConstraint), "TransformationConstraint");
-
- data->map[0]= 0;
- data->map[1]= 1;
- data->map[2]= 2;
-
- result = data;
- }
- break;
-
- default:
- result = NULL;
- break;
- }
-
- return result;
-}
-
-bConstraintChannel *get_constraint_channel (ListBase *list, const char *name)
-{
- bConstraintChannel *chan;
-
- for (chan = list->first; chan; chan=chan->next) {
- if (!strcmp(name, chan->name)) {
- return chan;
- }
- }
- return NULL;
-}
-
-/* finds or creates new constraint channel */
-bConstraintChannel *verify_constraint_channel (ListBase *list, const char *name)
-{
- bConstraintChannel *chan;
-
- chan= get_constraint_channel(list, name);
-
- if(chan == NULL) {
- chan= MEM_callocN(sizeof(bConstraintChannel), "new constraint chan");
- BLI_addtail(list, chan);
- strcpy(chan->name, name);
- }
-
- return chan;
-}
-
-
-/* ***************** Evaluating ********************* */
+/* ----------------- Evaluation Loop Preparation --------------- */
/* 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 */
@@ -803,7 +273,7 @@ bConstraintOb *constraints_make_evalob (Object *ob, void *subdata, short datatyp
/* based on type of available data */
switch (datatype) {
- case TARGET_OBJECT:
+ case CONSTRAINT_OBTYPE_OBJECT:
{
/* disregard subdata... calloc should set other values right */
if (ob) {
@@ -817,7 +287,7 @@ bConstraintOb *constraints_make_evalob (Object *ob, void *subdata, short datatyp
Mat4CpyMat4(cob->startmat, cob->matrix);
}
break;
- case TARGET_BONE:
+ case CONSTRAINT_OBTYPE_BONE:
{
/* only set if we have valid bone, otherwise default */
if (ob && subdata) {
@@ -835,7 +305,7 @@ bConstraintOb *constraints_make_evalob (Object *ob, void *subdata, short datatyp
}
break;
- default: // other types not yet handled
+ default: /* other types not yet handled */
Mat4One(cob->matrix);
Mat4One(cob->startmat);
break;
@@ -859,22 +329,28 @@ void constraints_clear_evalob (bConstraintOb *cob)
/* copy matrices back to source */
switch (cob->type) {
- case TARGET_OBJECT:
+ case CONSTRAINT_OBTYPE_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);
+ /* cob->ob might not exist! */
+ if (cob->ob) {
+ /* 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:
+ case CONSTRAINT_OBTYPE_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);
+ /* cob->ob or cob->pchan might not exist */
+ if (cob->ob && cob->pchan) {
+ /* 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;
}
@@ -883,40 +359,7 @@ void constraints_clear_evalob (bConstraintOb *cob)
MEM_freeN(cob);
}
-/* -------------------------------- Constraint Channels ---------------------------- */
-
-/* does IPO's of constraint channels only */
-void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime, int onlydrivers)
-{
- bConstraint *con;
- bConstraintChannel *chan;
- 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) {
- calc_ipo(chan->ipo, ctime);
-
- for (icu=chan->ipo->curve.first; icu; icu=icu->next) {
- if(!onlydrivers || icu->driver) {
- switch (icu->adrcode) {
- case CO_ENFORCE:
- {
- /* Influence is clamped to 0.0f -> 1.0f range */
- con->enforce = CLAMPIS(icu->curval, 0.0f, 1.0f);
- }
- break;
- }
- }
- }
- }
- }
-}
-
-/* ------------------------------- Space-Conversion API ---------------------------- */
+/* -------------- Space-Conversion API -------------- */
/* This function is responsible for the correct transformations/conversions
* of a matrix from one space to another for constraint evaluation.
@@ -1112,7 +555,7 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
}
}
-/* ------------------------------- Target ---------------------------- */
+/* ------------ General Target Matrix Tools ---------- */
/* function that sets the given matrix based on given vertex group in mesh */
static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4])
@@ -1311,18 +754,277 @@ static void constraint_target_to_mat4 (Object *ob, char *substring, float mat[][
}
}
+/* ************************* Specific Constraints ***************************** */
+/* Each constraint defines a set of functions, which will be called at the appropriate
+ * times. In addition to this, each constraint should have a type-info struct, where
+ * its functions are attached for use.
+ */
+
+/* Template for type-info data:
+ * - make a copy of this when creating new constraints, and just change the functions
+ * pointed to as necessary
+ * - although the naming of functions doesn't matter, it would help for code
+ * readability, to follow the same naming convention as is presented here
+ * - any functions that a constraint doesn't need to define, don't define
+ * for such cases, just use NULL
+ * - these should be defined after all the functions have been defined, so that
+ * forward-definitions/prototypes don't need to be used!
+ * - keep this copy #if-def'd so that future constraints can get based off this
+ */
+#if 0
+static bConstraintTypeInfo CTI_CONSTRNAME = {
+ CONSTRAINT_TYPE_CONSTRNAME, /* type */
+ sizeof(bConstrNameConstraint), /* size */
+ "ConstrName", /* name */
+ "bConstrNameConstraint", /* struct name */
+ constrname_free, /* free data */
+ constrname_relink, /* relink data */
+ constrname_copy, /* copy data */
+ constrname_new_data, /* new data */
+ constrname_get_tars, /* get constraint targets */
+ constrname_flush_tars, /* flush constraint targets */
+ constrname_get_tarmat, /* get target matrix */
+ constrname_evaluate /* evaluate */
+};
+#endif
-/* stupid little cross product function, 0:x, 1:y, 2:z axes */
-static int basis_cross(int n, int m)
+/* This function should be used for the get_target_matrix member of all
+ * constraints that are not picky about what happens to their target matrix.
+ */
+static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
{
- if(n-m == 1) return 1;
- if(n-m == -1) return -1;
- if(n-m == 2) return -1;
- if(n-m == -2) return 1;
- else return 0;
+ if (VALID_CONS_TARGET(ct))
+ constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space);
+ else if (ct)
+ Mat4One(ct->matrix);
}
-static void vectomat(float *vec, float *target_up, short axis, short upflag, short flags, float m[][3])
+/* This following macro should be used for all standard single-target *_get_tars functions
+ * to save typing and reduce maintainance woes.
+ * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
+ * really just to help this code easier to read)
+ */
+#define SINGLETARGET_GET_TARS(con, data, ct, list) \
+ { \
+ ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \
+ \
+ ct->tar= data->tar; \
+ strcpy(ct->subtarget, data->subtarget); \
+ ct->space= con->tarspace; \
+ ct->flag= CONSTRAINT_TAR_TEMP; \
+ \
+ if (ct->tar) { \
+ if ((ct->tar->type==OB_ARMATURE) && (ct->subtarget[0])) ct->type = CONSTRAINT_OBTYPE_BONE; \
+ else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) ct->type = CONSTRAINT_OBTYPE_VERT; \
+ else ct->type = CONSTRAINT_OBTYPE_OBJECT; \
+ } \
+ \
+ BLI_addtail(list, ct); \
+ }
+
+/* This following macro should be used for all standard single-target *_get_tars functions
+ * to save typing and reduce maintainance woes. It does not do the subtarget related operations
+ * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
+ * really just to help this code easier to read)
+ */
+#define SINGLETARGETNS_GET_TARS(con, data, ct, list) \
+ { \
+ ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \
+ \
+ ct->tar= data->tar; \
+ ct->space= con->tarspace; \
+ ct->flag= CONSTRAINT_TAR_TEMP; \
+ \
+ if (ct->tar) ct->type = CONSTRAINT_OBTYPE_OBJECT; \
+ \
+ BLI_addtail(list, ct); \
+ }
+
+/* This following macro should be used for all standard single-target *_flush_tars functions
+ * to save typing and reduce maintainance woes.
+ * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
+ * really just to help this code easier to read)
+ */
+#define SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy) \
+ { \
+ if (ct) { \
+ if (nocopy == 0) { \
+ data->tar= ct->tar; \
+ strcpy(data->subtarget, ct->subtarget); \
+ con->tarspace= ct->space; \
+ } \
+ \
+ BLI_freelistN(list); \
+ } \
+ }
+
+/* This following macro should be used for all standard single-target *_flush_tars functions
+ * to save typing and reduce maintainance woes. It does not do the subtarget related operations
+ * (Hopefully all compilers will be happy with the lines with just a space on them. Those are
+ * really just to help this code easier to read)
+ */
+#define SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy) \
+ { \
+ if (ct) { \
+ if (nocopy == 0) { \
+ data->tar= ct->tar; \
+ con->tarspace= ct->space; \
+ } \
+ \
+ BLI_freelistN(list); \
+ } \
+ }
+
+/* --------- ChildOf Constraint ------------ */
+
+static void childof_new_data (void *cdata)
+{
+ bChildOfConstraint *data= (bChildOfConstraint *)cdata;
+
+ data->flag = (CHILDOF_LOCX | CHILDOF_LOCY | CHILDOF_LOCZ |
+ CHILDOF_ROTX |CHILDOF_ROTY | CHILDOF_ROTZ |
+ CHILDOF_SIZEX | CHILDOF_SIZEY | CHILDOF_SIZEZ);
+ Mat4One(data->invmat);
+}
+
+static void childof_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bChildOfConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* standard target-getting macro for single-target constraints */
+ SINGLETARGET_GET_TARS(con, data, ct, list)
+ }
+}
+
+static void childof_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+ if (con && list) {
+ bChildOfConstraint *data= con->data;
+ bConstraintTarget *ct= list->first;
+
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ }
+}
+
+static void childof_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bChildOfConstraint *data= con->data;
+ bConstraintTarget *ct= targets->first;
+
+ /* only evaluate if there is a target */
+ if (VALID_CONS_TARGET(ct)) {
+ 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, ct->matrix[3]);
+ Mat4ToEul(ct->matrix, eul);
+ Mat4ToSize(ct->matrix, 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(ct->matrix, 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, ct->matrix);
+
+ /* 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, cob->matrix);
+ Mat4MulMat4(cob->matrix, tempmat, parmat);
+ }
+}
+
+static bConstraintTypeInfo CTI_CHILDOF = {
+ CONSTRAINT_TYPE_CHILDOF, /* type */
+ sizeof(bChildOfConstraint), /* size */
+ "ChildOf", /* name */
+ "bChildOfConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ childof_new_data, /* new data */
+ childof_get_tars, /* get constraint targets */
+ childof_flush_tars, /* flush constraint targets */
+ default_get_tarmat, /* get a target matrix */
+ childof_evaluate /* evaluate */
+};
+
+/* -------- TrackTo Constraint ------- */
+
+static void trackto_new_data (void *cdata)
+{
+ bTrackToConstraint *data= (bTrackToConstraint *)cdata;
+
+ data->reserved1 = TRACK_Y;
+ data->reserved2 = UP_Z;
+}
+
+static void trackto_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bTrackToConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* standard target-getting macro for single-target constraints */
+ SINGLETARGET_GET_TARS(con, data, ct, list)
+ }
+}
+
+static void trackto_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+ if (con && list) {
+ bTrackToConstraint *data= con->data;
+ bConstraintTarget *ct= list->first;
+
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ }
+}
+
+
+static int basis_cross (int n, int m)
+{
+ switch (n-m) {
+ case 1:
+ case -2:
+ return 1;
+
+ case -1:
+ case 2:
+ return -1;
+
+ default:
+ return 0;
+ }
+}
+
+static void vectomat (float *vec, float *target_up, short axis, short upflag, short flags, float m[][3])
{
float n[3];
float u[3]; /* vector specifying the up axis */
@@ -1332,17 +1034,16 @@ static void vectomat(float *vec, float *target_up, short axis, short upflag, sho
int right_index;
VecCopyf(n, vec);
- if(Normalize(n) == 0.0) {
+ if (Normalize(n) == 0.0) {
n[0] = 0.0;
n[1] = 0.0;
n[2] = 1.0;
}
- if(axis > 2) axis -= 3;
+ if (axis > 2) axis -= 3;
else VecMulf(n,-1);
/* n specifies the transformation of the track axis */
-
- if(flags & TARGET_Z_UP) {
+ if (flags & TARGET_Z_UP) {
/* target Z axis is the global up axis */
u[0] = target_up[0];
u[1] = target_up[1];
@@ -1360,7 +1061,7 @@ static void vectomat(float *vec, float *target_up, short axis, short upflag, sho
VecSubf(proj, u, proj); /* then onto the plane */
/* proj specifies the transformation of the up axis */
- if(Normalize(proj) == 0.0) { /* degenerate projection */
+ if (Normalize(proj) == 0.0) { /* degenerate projection */
proj[0] = 0.0;
proj[1] = 1.0;
proj[2] = 0.0;
@@ -1370,19 +1071,19 @@ static void vectomat(float *vec, float *target_up, short axis, short upflag, sho
Crossf(right, proj, n);
Normalize(right);
- if(axis != upflag) {
+ if (axis != upflag) {
right_index = 3 - axis - upflag;
- neg = (float) basis_cross(axis, upflag);
-
+ neg = (float)basis_cross(axis, upflag);
+
/* account for up direction, track direction */
m[right_index][0] = neg * right[0];
m[right_index][1] = neg * right[1];
m[right_index][2] = neg * right[2];
-
+
m[upflag][0] = proj[0];
m[upflag][1] = proj[1];
m[upflag][2] = proj[2];
-
+
m[axis][0] = n[0];
m[axis][1] = n[1];
m[axis][2] = n[2];
@@ -1397,1449 +1098,2209 @@ 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 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 ctime)
+static void trackto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
{
- short valid=0;
+ bTrackToConstraint *data= con->data;
+ bConstraintTarget *ct= targets->first;
+
+ if (VALID_CONS_TARGET(ct)) {
+ float size[3], vec[3];
+ float totmat[3][3];
+ float tmat[4][4];
+
+ /* Get size property, since ob->size is only the object's own relative size, not its global one */
+ Mat4ToSize(cob->matrix, size);
+
+ /* Clear the object's rotation */
+ cob->matrix[0][0]=size[0];
+ cob->matrix[0][1]=0;
+ cob->matrix[0][2]=0;
+ cob->matrix[1][0]=0;
+ cob->matrix[1][1]=size[1];
+ cob->matrix[1][2]=0;
+ cob->matrix[2][0]=0;
+ cob->matrix[2][1]=0;
+ cob->matrix[2][2]=size[2];
+
+ /* targetmat[2] instead of ownermat[2] is passed to vectomat
+ * for backwards compatability it seems... (Aligorith)
+ */
+ VecSubf(vec, cob->matrix[3], ct->matrix[3]);
+ vectomat(vec, ct->matrix[2],
+ (short)data->reserved1, (short)data->reserved2,
+ data->flags, totmat);
+
+ Mat4CpyMat4(tmat, cob->matrix);
+ Mat4MulMat34(cob->matrix, totmat, tmat);
+ }
+}
- switch (con->type) {
- case CONSTRAINT_TYPE_NULL:
- {
- Mat4One(mat);
- }
- break;
- case CONSTRAINT_TYPE_ACTION:
- {
- if (ownertype == TARGET_BONE) {
- extern void chan_calc_mat(bPoseChannel *chan);
- bActionConstraint *data = (bActionConstraint*)con->data;
- bPose *pose;
- bPoseChannel *pchan, *tchan;
- float tempmat[4][4], vec[3];
- float s, t;
- short axis;
-
- /* initialise return matrix */
- Mat4One(mat);
-
- /* only continue if there is a target */
- if (data->tar==NULL) return 0;
-
- /* 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 {
- /* extract location */
- VECCOPY(vec, tempmat[3]);
- axis= data->type - 20;
- }
-
- /* Target defines the animation */
- 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);
-
- chan_calc_mat(tchan);
-
- Mat4CpyMat4(mat, tchan->chan_mat);
-
- /* Clean up */
- free_pose_channels(pose);
- MEM_freeN(pose);
- }
- }
- break;
- case CONSTRAINT_TYPE_LOCLIKE:
- {
- bLocateLikeConstraint *data = (bLocateLikeConstraint*)con->data;
- Object *ob= data->tar;
-
- if (data->tar) {
- if (data->tar->type==OB_ARMATURE && strlen(data->subtarget)) {
- /* Pose-Channels for the CopyLoc target are handled specially, so that
- * we can support using the bone-tip as an option.
- */
- bPoseChannel *pchan;
- float tmat[4][4];
-
- pchan = get_pose_channel(ob->pose, data->subtarget);
- if (pchan) {
- Mat4CpyMat4(tmat, pchan->pose_mat);
-
- if (data->flag & LOCLIKE_TIP) {
- VECCOPY(tmat[3], pchan->pose_tail);
- }
-
- Mat4MulMat4(mat, tmat, ob->obmat);
- }
- else
- Mat4CpyMat4(mat, ob->obmat);
-
- /* convert matrix space as required */
- constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
- }
- else {
- /* get target matrix as is done normally for other constraints */
- constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
- }
- valid=1;
- }
- else
- Mat4One(mat);
- }
- break;
- case CONSTRAINT_TYPE_ROTLIKE:
- {
- bRotateLikeConstraint *data;
- data = (bRotateLikeConstraint*)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;
- case CONSTRAINT_TYPE_SIZELIKE:
- {
- bSizeLikeConstraint *data;
- data = (bSizeLikeConstraint*)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;
- case CONSTRAINT_TYPE_MINMAX:
- {
- bMinMaxConstraint *data = (bMinMaxConstraint*)con->data;
-
- if (data->tar) {
- constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
- valid=1;
+static bConstraintTypeInfo CTI_TRACKTO = {
+ CONSTRAINT_TYPE_TRACKTO, /* type */
+ sizeof(bTrackToConstraint), /* size */
+ "TrackTo", /* name */
+ "bTrackToConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ trackto_new_data, /* new data */
+ trackto_get_tars, /* get constraint targets */
+ trackto_flush_tars, /* flush constraint targets */
+ default_get_tarmat, /* get target matrix */
+ trackto_evaluate /* evaluate */
+};
+
+/* --------- Inverse-Kinemetics --------- */
+
+static void kinematic_new_data (void *cdata)
+{
+ bKinematicConstraint *data= (bKinematicConstraint *)cdata;
+
+ data->weight= (float)1.0;
+ data->orientweight= (float)1.0;
+ data->iterations = 500;
+ data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_STRETCH|CONSTRAINT_IK_POS;
+}
+
+static void kinematic_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bKinematicConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* standard target-getting macro for single-target constraints */
+ SINGLETARGET_GET_TARS(con, data, ct, list)
+ }
+}
+
+static void kinematic_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+ if (con && list) {
+ bKinematicConstraint *data= con->data;
+ bConstraintTarget *ct= list->first;
+
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ }
+}
+
+static void kinematic_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+ bKinematicConstraint *data= con->data;
+
+ if (VALID_CONS_TARGET(ct))
+ constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space);
+ else if (ct) {
+ if (data->flag & CONSTRAINT_IK_AUTO) {
+ Object *ob= cob->ob;
+
+ if (ob == NULL) {
+ Mat4One(ct->matrix);
}
- else
- 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, CONSTRAINT_SPACE_WORLD, con->tarspace);
- valid=1;
+ else {
+ float vec[3];
+ /* move grabtarget into world space */
+ VECCOPY(vec, data->grabtarget);
+ Mat4MulVecfl(ob->obmat, vec);
+ Mat4CpyMat4(ct->matrix, ob->obmat);
+ VECCOPY(ct->matrix[3], vec);
}
- else
- Mat4One (mat);
}
- break;
- case CONSTRAINT_TYPE_KINEMATIC:
- {
- bKinematicConstraint *data;
- data = (bKinematicConstraint*)con->data;
-
- if (data->tar) {
- 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= (Object *)ownerdata;
-
- if (ob==NULL)
- Mat4One(mat);
- else {
- float vec[3];
- /* move grabtarget into world space */
- VECCOPY(vec, data->grabtarget);
- Mat4MulVecfl(ob->obmat, vec);
- Mat4CpyMat4(mat, ob->obmat);
- VECCOPY(mat[3], vec);
- }
- }
- else
- Mat4One(mat);
- }
- break;
- case CONSTRAINT_TYPE_LOCKTRACK:
- {
- bLockTrackConstraint *data;
- data = (bLockTrackConstraint*)con->data;
+ else
+ Mat4One(ct->matrix);
+ }
+}
+
+static bConstraintTypeInfo CTI_KINEMATIC = {
+ CONSTRAINT_TYPE_KINEMATIC, /* type */
+ sizeof(bKinematicConstraint), /* size */
+ "IK", /* name */
+ "bKinematicConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ kinematic_new_data, /* new data */
+ kinematic_get_tars, /* get constraint targets */
+ kinematic_flush_tars, /* flush constraint targets */
+ kinematic_get_tarmat, /* get target matrix */
+ NULL /* evaluate - solved as separate loop */
+};
+
+/* -------- Follow-Path Constraint ---------- */
+
+static void followpath_new_data (void *cdata)
+{
+ bFollowPathConstraint *data= (bFollowPathConstraint *)cdata;
+
+ data->trackflag = TRACK_Y;
+ data->upflag = UP_Z;
+ data->offset = 0;
+ data->followflag = 0;
+}
+
+static void followpath_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bFollowPathConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* standard target-getting macro for single-target constraints without subtargets */
+ SINGLETARGETNS_GET_TARS(con, data, ct, list)
+ }
+}
+
+static void followpath_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+ if (con && list) {
+ bFollowPathConstraint *data= con->data;
+ bConstraintTarget *ct= list->first;
+
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy)
+ }
+}
+
+static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+ bFollowPathConstraint *data= con->data;
+
+ if (VALID_CONS_TARGET(ct)) {
+ Curve *cu= ct->tar->data;
+ float q[4], vec[4], dir[3], *quat, x1;
+ float totmat[4][4];
+ float curvetime;
+
+ Mat4One(totmat);
+ Mat4One(ct->matrix);
+
+ /* 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)
+ */
+
+ /* only happens on reload file, but violates depsgraph still... fix! */
+ if (cu->path==NULL || cu->path->data==NULL)
+ makeDispListCurveTypes(ct->tar, 0);
+
+ if (cu->path && cu->path->data) {
+ curvetime= bsystem_time(ct->tar, (float)ctime, 0.0) - data->offset;
- if (data->tar) {
- constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
- valid=1;
+ if (calc_ipo_spec(cu->ipo, CU_SPEED, &curvetime)==0) {
+ curvetime /= cu->pathlen;
+ CLAMP(curvetime, 0.0, 1.0);
}
- else
- 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;
- float totmat[4][4];
- float curvetime;
-
- Mat4One(totmat);
- Mat4One(mat);
-
- 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! */
- makeDispListCurveTypes(data->tar, 0);
- if (cu->path && cu->path->data) {
- curvetime= bsystem_time(data->tar, (float)ctime, 0.0) - data->offset;
+ if ( where_on_path(ct->tar, curvetime, vec, dir) ) {
+ if (data->followflag) {
+ quat= vectoquat(dir, (short) data->trackflag, (short) data->upflag);
- if (calc_ipo_spec(cu->ipo, CU_SPEED, &curvetime)==0) {
- curvetime /= cu->pathlen;
- CLAMP(curvetime, 0.0, 1.0);
- }
+ Normalize(dir);
+ q[0]= (float)cos(0.5*vec[3]);
+ x1= (float)sin(0.5*vec[3]);
+ q[1]= -x1*dir[0];
+ q[2]= -x1*dir[1];
+ q[3]= -x1*dir[2];
+ QuatMul(quat, q, quat);
- if (where_on_path(data->tar, curvetime, vec, dir) ) {
- if (data->followflag) {
- quat= vectoquat(dir, (short) data->trackflag, (short) data->upflag);
-
- Normalize(dir);
- q[0]= (float)cos(0.5*vec[3]);
- x1= (float)sin(0.5*vec[3]);
- q[1]= -x1*dir[0];
- q[2]= -x1*dir[1];
- q[3]= -x1*dir[2];
- QuatMul(quat, q, quat);
-
- QuatToMat4(quat, totmat);
- }
- VECCOPY(totmat[3], vec);
-
- Mat4MulSerie(mat, data->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
- }
+ QuatToMat4(quat, totmat);
}
- valid=1;
+ VECCOPY(totmat[3], vec);
+
+ Mat4MulSerie(ct->matrix, ct->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
}
- else
- Mat4One(mat);
}
- break;
- case CONSTRAINT_TYPE_STRETCHTO:
- {
- bStretchToConstraint *data;
- data = (bStretchToConstraint*)con->data;
+ }
+ else if (ct)
+ Mat4One(ct->matrix);
+}
+
+static void followpath_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bConstraintTarget *ct= targets->first;
+
+ /* only evaluate if there is a target */
+ if (VALID_CONS_TARGET(ct)) {
+ float obmat[4][4];
+ float size[3], obsize[3];
+
+ /* get Object local transform (loc/rot/size) to determine transformation from path */
+ //object_to_mat4(ob, obmat);
+ Mat4CpyMat4(obmat, cob->matrix); // FIXME!!!
+
+ /* get scaling of object before applying constraint */
+ Mat4ToSize(cob->matrix, size);
+
+ /* apply targetmat - containing location on path, and rotation */
+ Mat4MulSerie(cob->matrix, ct->matrix, obmat, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ /* un-apply scaling caused by path */
+ Mat4ToSize(cob->matrix, obsize);
+ if (obsize[0])
+ VecMulf(cob->matrix[0], size[0] / obsize[0]);
+ if (obsize[1])
+ VecMulf(cob->matrix[1], size[1] / obsize[1]);
+ if (obsize[2])
+ VecMulf(cob->matrix[2], size[2] / obsize[2]);
+ }
+}
+
+static bConstraintTypeInfo CTI_FOLLOWPATH = {
+ CONSTRAINT_TYPE_FOLLOWPATH, /* type */
+ sizeof(bFollowPathConstraint), /* size */
+ "Follow Path", /* name */
+ "bFollowPathConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ followpath_new_data, /* new data */
+ followpath_get_tars, /* get constraint targets */
+ followpath_flush_tars, /* flush constraint targets */
+ followpath_get_tarmat, /* get target matrix */
+ followpath_evaluate /* evaluate */
+};
+
+/* --------- Limit Location --------- */
+
+
+static void loclimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bLocLimitConstraint *data = con->data;
+
+ if (data->flag & LIMIT_XMIN) {
+ if (cob->matrix[3][0] < data->xmin)
+ cob->matrix[3][0] = data->xmin;
+ }
+ if (data->flag & LIMIT_XMAX) {
+ if (cob->matrix[3][0] > data->xmax)
+ cob->matrix[3][0] = data->xmax;
+ }
+ if (data->flag & LIMIT_YMIN) {
+ if (cob->matrix[3][1] < data->ymin)
+ cob->matrix[3][1] = data->ymin;
+ }
+ if (data->flag & LIMIT_YMAX) {
+ if (cob->matrix[3][1] > data->ymax)
+ cob->matrix[3][1] = data->ymax;
+ }
+ if (data->flag & LIMIT_ZMIN) {
+ if (cob->matrix[3][2] < data->zmin)
+ cob->matrix[3][2] = data->zmin;
+ }
+ if (data->flag & LIMIT_ZMAX) {
+ if (cob->matrix[3][2] > data->zmax)
+ cob->matrix[3][2] = data->zmax;
+ }
+}
+
+static bConstraintTypeInfo CTI_LOCLIMIT = {
+ CONSTRAINT_TYPE_LOCLIMIT, /* type */
+ sizeof(bLocLimitConstraint), /* size */
+ "Limit Location", /* name */
+ "bLocLimitConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ NULL, /* new data */
+ NULL, /* get constraint targets */
+ NULL, /* flush constraint targets */
+ NULL, /* get target matrix */
+ loclimit_evaluate /* evaluate */
+};
+
+/* -------- Limit Rotation --------- */
+
+static void rotlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bRotLimitConstraint *data = con->data;
+ float loc[3];
+ float eul[3];
+ float size[3];
+
+ VECCOPY(loc, cob->matrix[3]);
+ Mat4ToSize(cob->matrix, size);
+
+ Mat4ToEul(cob->matrix, eul);
+
+ /* eulers: radians to degrees! */
+ eul[0] = (eul[0] / M_PI * 180);
+ eul[1] = (eul[1] / M_PI * 180);
+ eul[2] = (eul[2] / M_PI * 180);
+
+ /* limiting of euler values... */
+ if (data->flag & LIMIT_XROT) {
+ if (eul[0] < data->xmin)
+ eul[0] = data->xmin;
- if (data->tar) {
- constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
- valid = 1;
- }
- else
- Mat4One(mat);
- }
- break;
- case CONSTRAINT_TYPE_PYTHON:
- {
- bPythonConstraint *data;
- data = (bPythonConstraint*)con->data;
+ if (eul[0] > data->xmax)
+ eul[0] = data->xmax;
+ }
+ if (data->flag & LIMIT_YROT) {
+ if (eul[1] < data->ymin)
+ eul[1] = data->ymin;
- /* special exception for curves - depsgraph issues */
- if (data->tar && data->tar->type == OB_CURVE) {
- Curve *cu= data->tar->data;
-
- /* this check is to make sure curve objects get updated on file load correctly.*/
- if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
- makeDispListCurveTypes(data->tar, 0);
- }
+ if (eul[1] > data->ymax)
+ eul[1] = data->ymax;
+ }
+ if (data->flag & LIMIT_ZROT) {
+ if (eul[2] < data->zmin)
+ eul[2] = data->zmin;
+
+ if (eul[2] > data->zmax)
+ eul[2] = data->zmax;
+ }
+
+ /* eulers: degrees to radians ! */
+ eul[0] = (eul[0] / 180 * M_PI);
+ eul[1] = (eul[1] / 180 * M_PI);
+ eul[2] = (eul[2] / 180 * M_PI);
+
+ LocEulSizeToMat4(cob->matrix, loc, eul, size);
+}
+
+static bConstraintTypeInfo CTI_ROTLIMIT = {
+ CONSTRAINT_TYPE_ROTLIMIT, /* type */
+ sizeof(bRotLimitConstraint), /* size */
+ "Limit Rotation", /* name */
+ "bRotLimitConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ NULL, /* new data */
+ NULL, /* get constraint targets */
+ NULL, /* flush constraint targets */
+ NULL, /* get target matrix */
+ rotlimit_evaluate /* evaluate */
+};
+
+/* --------- Limit Scaling --------- */
+
+
+static void sizelimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bSizeLimitConstraint *data = con->data;
+ float obsize[3], size[3];
+
+ Mat4ToSize(cob->matrix, size);
+ Mat4ToSize(cob->matrix, obsize);
+
+ if (data->flag & LIMIT_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 (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 (size[2] < data->zmin)
+ size[2] = data->zmin;
+ }
+ if (data->flag & LIMIT_ZMAX) {
+ if (size[2] > data->zmax)
+ size[2] = data->zmax;
+ }
+
+ if (obsize[0])
+ VecMulf(cob->matrix[0], size[0]/obsize[0]);
+ if (obsize[1])
+ VecMulf(cob->matrix[1], size[1]/obsize[1]);
+ if (obsize[2])
+ VecMulf(cob->matrix[2], size[2]/obsize[2]);
+}
+
+static bConstraintTypeInfo CTI_SIZELIMIT = {
+ CONSTRAINT_TYPE_SIZELIMIT, /* type */
+ sizeof(bSizeLimitConstraint), /* size */
+ "Limit Scaling", /* name */
+ "bSizeLimitConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ NULL, /* new data */
+ NULL, /* get constraint targets */
+ NULL, /* flush constraint targets */
+ NULL, /* get target matrix */
+ sizelimit_evaluate /* evaluate */
+};
+
+/* ----------- Copy Location ------------- */
+
+static void loclike_new_data (void *cdata)
+{
+ bLocateLikeConstraint *data= (bLocateLikeConstraint *)cdata;
+
+ data->flag = LOCLIKE_X|LOCLIKE_Y|LOCLIKE_Z;
+}
+
+static void loclike_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bLocateLikeConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* standard target-getting macro for single-target constraints */
+ SINGLETARGET_GET_TARS(con, data, ct, list)
+ }
+}
+
+static void loclike_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+ if (con && list) {
+ bLocateLikeConstraint *data= con->data;
+ bConstraintTarget *ct= list->first;
+
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ }
+}
+
+static void loclike_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+ bLocateLikeConstraint *data = con->data;
+
+ if (VALID_CONS_TARGET(ct)) {
+ if (ct->tar->type==OB_ARMATURE && strlen(ct->subtarget)) {
+ /* Pose-Channels for the CopyLoc target are handled specially, so that
+ * we can support using the bone-tip as an option.
+ */
+ bPoseChannel *pchan;
+ float tmat[4][4];
- /* if the script doesn't set the target matrix for any reason, fall back to standard methods */
- if (data->tar) {
- constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
- if (BPY_pyconstraint_targets(data, mat) >= 1) {
- valid = 1;
+ pchan = get_pose_channel(ct->tar->pose, ct->subtarget);
+ if (pchan) {
+ Mat4CpyMat4(tmat, pchan->pose_mat);
+
+ if (data->flag & LOCLIKE_TIP) {
+ VECCOPY(tmat[3], pchan->pose_tail);
}
+
+ Mat4MulMat4(ct->matrix, tmat, ct->tar->obmat);
}
- if (!valid)
- Mat4One(mat);
+ else
+ Mat4CpyMat4(ct->matrix, ct->tar->obmat);
+
+ /* convert matrix space as required */
+ constraint_mat_convertspace(ct->tar, pchan, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space);
}
- break;
- case CONSTRAINT_TYPE_CLAMPTO:
- {
- bClampToConstraint *data;
- data = (bClampToConstraint*)con->data;
+ else {
+ /* get target matrix as is done normally for other constraints */
+ constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space);
+ }
+ }
+ else if (ct)
+ Mat4One(ct->matrix);
+}
+
+static void loclike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bLocateLikeConstraint *data= con->data;
+ bConstraintTarget *ct= targets->first;
+
+ if (VALID_CONS_TARGET(ct)) {
+ float offset[3] = {0.0f, 0.0f, 0.0f};
+
+ if (data->flag & LOCLIKE_OFFSET)
+ VECCOPY(offset, cob->matrix[3]);
- 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! */
- makeDispListCurveTypes(data->tar, 0);
-
- valid = 1;
- }
+ if (data->flag & LOCLIKE_X) {
+ cob->matrix[3][0] = ct->matrix[3][0];
- Mat4One(mat);
+ if (data->flag & LOCLIKE_X_INVERT) cob->matrix[3][0] *= -1;
+ cob->matrix[3][0] += offset[0];
}
- break;
- case CONSTRAINT_TYPE_CHILDOF:
- {
- bChildOfConstraint *data;
- data= (bChildOfConstraint *)con->data;
+ if (data->flag & LOCLIKE_Y) {
+ cob->matrix[3][1] = ct->matrix[3][1];
- if (data->tar) {
- constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
- valid = 1;
- }
- else
- Mat4One(mat);
+ if (data->flag & LOCLIKE_Y_INVERT) cob->matrix[3][1] *= -1;
+ cob->matrix[3][1] += offset[1];
}
- break;
- case CONSTRAINT_TYPE_TRANSFORM:
- {
- bTransformConstraint *data;
- data= (bTransformConstraint *)con->data;
+ if (data->flag & LOCLIKE_Z) {
+ cob->matrix[3][2] = ct->matrix[3][2];
- if (data->tar) {
- constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
- valid = 1;
- }
- else
- Mat4One(mat);
+ if (data->flag & LOCLIKE_Z_INVERT) cob->matrix[3][2] *= -1;
+ cob->matrix[3][2] += offset[2];
}
- break;
-
- default:
- Mat4One(mat);
- break;
}
+}
- return valid;
+static bConstraintTypeInfo CTI_LOCLIKE = {
+ CONSTRAINT_TYPE_LOCLIKE, /* type */
+ sizeof(bLocateLikeConstraint), /* size */
+ "Copy Location", /* name */
+ "bLocateLikeConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ loclike_new_data, /* new data */
+ loclike_get_tars, /* get constraint targets */
+ loclike_flush_tars, /* flush constraint targets */
+ loclike_get_tarmat, /* get target matrix */
+ loclike_evaluate /* evaluate */
+};
+
+/* ----------- Copy Rotation ------------- */
+
+static void rotlike_new_data (void *cdata)
+{
+ bRotateLikeConstraint *data= (bRotateLikeConstraint *)cdata;
+
+ data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z;
}
-/* ---------------------------------------------- Constraint Evaluation ------------------------------------------------- */
+static void rotlike_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bRotateLikeConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* standard target-getting macro for single-target constraints */
+ SINGLETARGET_GET_TARS(con, data, ct, list)
+ }
+}
-/* 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])
+static void rotlike_flush_tars (bConstraint *con, ListBase *list, short nocopy)
{
- if (constraint == NULL || constraint->data == NULL)
- return;
+ if (con && list) {
+ bRotateLikeConstraint *data= con->data;
+ bConstraintTarget *ct= list->first;
- switch (constraint->type) {
- case CONSTRAINT_TYPE_NULL:
- case CONSTRAINT_TYPE_KINEMATIC: /* removed */
- break;
- case CONSTRAINT_TYPE_PYTHON:
- {
- bPythonConstraint *data;
-
- data = constraint->data;
- BPY_pyconstraint_eval(data, ownermat, targetmat);
- }
- break;
- case CONSTRAINT_TYPE_ACTION:
- {
- bActionConstraint *data;
- float temp[4][4];
-
- data = constraint->data;
- Mat4CpyMat4(temp, ownermat);
-
- Mat4MulMat4(ownermat, targetmat, temp);
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ }
+}
+
+static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bRotateLikeConstraint *data= con->data;
+ bConstraintTarget *ct= targets->first;
+
+ if (VALID_CONS_TARGET(ct)) {
+ float loc[3];
+ float eul[3], obeul[3];
+ float size[3];
+
+ VECCOPY(loc, cob->matrix[3]);
+ Mat4ToSize(cob->matrix, size);
+
+ Mat4ToEul(ct->matrix, eul);
+ Mat4ToEul(cob->matrix, obeul);
+
+ if ((data->flag & ROTLIKE_X)==0) {
+ eul[0] = obeul[0];
}
- break;
- case CONSTRAINT_TYPE_LOCLIKE:
- {
- bLocateLikeConstraint *data;
- float offset[3] = {0.0f, 0.0f, 0.0f};
+ else if (data->flag & ROTLIKE_X_INVERT) {
+ eul[0] *= -1;
+ }
+
+ if ((data->flag & ROTLIKE_Y)==0) {
+ eul[1] = obeul[1];
+ }
+ else if (data->flag & ROTLIKE_Y_INVERT) {
+ eul[1] *= -1;
+ }
+
+ if ((data->flag & ROTLIKE_Z)==0) {
+ eul[2] = obeul[2];
+ }
+ else if (data->flag & ROTLIKE_Z_INVERT) {
+ eul[2] *= -1;
+ }
+
+ compatible_eul(eul, obeul);
+ LocEulSizeToMat4(cob->matrix, loc, eul, size);
+ }
+}
- data = constraint->data;
-
- if (data->flag & LOCLIKE_OFFSET)
- VECCOPY(offset, ownermat[3]);
+static bConstraintTypeInfo CTI_ROTLIKE = {
+ CONSTRAINT_TYPE_ROTLIKE, /* type */
+ sizeof(bRotateLikeConstraint), /* size */
+ "Copy Rotation", /* name */
+ "bRotateLikeConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ rotlike_new_data, /* new data */
+ rotlike_get_tars, /* get constraint targets */
+ rotlike_flush_tars, /* flush constraint targets */
+ default_get_tarmat, /* get target matrix */
+ rotlike_evaluate /* evaluate */
+};
+
+/* ---------- Copy Scaling ---------- */
+
+static void sizelike_new_data (void *cdata)
+{
+ bSizeLikeConstraint *data= (bSizeLikeConstraint *)cdata;
+
+ data->flag = SIZELIKE_X|SIZELIKE_Y|SIZELIKE_Z;
+}
+
+static void sizelike_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bSizeLikeConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* standard target-getting macro for single-target constraints */
+ SINGLETARGET_GET_TARS(con, data, ct, list)
+ }
+}
+
+static void sizelike_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+ if (con && list) {
+ bSizeLikeConstraint *data= con->data;
+ bConstraintTarget *ct= list->first;
+
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ }
+}
+
+static void sizelike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bSizeLikeConstraint *data= con->data;
+ bConstraintTarget *ct= targets->first;
+
+ if (VALID_CONS_TARGET(ct)) {
+ float obsize[3], size[3];
+
+ Mat4ToSize(ct->matrix, size);
+ Mat4ToSize(cob->matrix, obsize);
+
+ if ((data->flag & SIZELIKE_X) && obsize[0] != 0)
+ VecMulf(cob->matrix[0], size[0] / obsize[0]);
+ if ((data->flag & SIZELIKE_Y) && obsize[1] != 0)
+ VecMulf(cob->matrix[1], size[1] / obsize[1]);
+ if ((data->flag & SIZELIKE_Z) && obsize[2] != 0)
+ VecMulf(cob->matrix[2], size[2] / obsize[2]);
+ }
+}
+
+static bConstraintTypeInfo CTI_SIZELIKE = {
+ CONSTRAINT_TYPE_SIZELIKE, /* type */
+ sizeof(bSizeLikeConstraint), /* size */
+ "Copy Scale", /* name */
+ "bSizeLikeConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ sizelike_new_data, /* new data */
+ sizelike_get_tars, /* get constraint targets */
+ sizelike_flush_tars, /* flush constraint targets */
+ default_get_tarmat, /* get target matrix */
+ sizelike_evaluate /* evaluate */
+};
+
+/* ----------- Python Constraint -------------- */
+
+static void pycon_free (bConstraint *con)
+{
+ bPythonConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* id-properties */
+ IDP_FreeProperty(data->prop);
+ MEM_freeN(data->prop);
+
+ /* multiple targets */
+ while ( (ct = data->targets.first) )
+ MEM_freeN(ct);
+}
+
+static void pycon_relink (bConstraint *con)
+{
+ bPythonConstraint *data= con->data;
+
+ ID_NEW(data->text);
+}
+
+static void pycon_copy (bConstraint *con, bConstraint *srccon)
+{
+ bPythonConstraint *pycon = (bPythonConstraint *)con->data;
+ bPythonConstraint *opycon = (bPythonConstraint *)srccon->data;
+
+ pycon->prop = IDP_CopyProperty(opycon->prop);
+ duplicatelist(&pycon->targets, &opycon->targets);
+}
+
+static void pycon_new_data (void *cdata)
+{
+ bPythonConstraint *data= (bPythonConstraint *)cdata;
+
+ /* everything should be set correctly by calloc, except for the prop->type constant.*/
+ data->prop = MEM_callocN(sizeof(IDProperty), "PyConstraintProps");
+ data->prop->type = IDP_GROUP;
+}
+
+static void pycon_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bPythonConstraint *data= con->data;
+
+ list->first = data->targets.first;
+ list->last = data->targets.last;
+ }
+}
+
+/* Whether this approach is maintained remains to be seen (aligorith) */
+static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+ bPythonConstraint *data= con->data;
+
+ if (VALID_CONS_TARGET(ct)) {
+ /* special exception for curves - depsgraph issues */
+ if (ct->tar->type == OB_CURVE) {
+ Curve *cu= ct->tar->data;
- if (data->flag & LOCLIKE_X) {
- ownermat[3][0] = targetmat[3][0];
-
- if(data->flag & LOCLIKE_X_INVERT) ownermat[3][0] *= -1;
- ownermat[3][0] += offset[0];
- }
- if (data->flag & LOCLIKE_Y) {
- ownermat[3][1] = targetmat[3][1];
-
- if(data->flag & LOCLIKE_Y_INVERT) ownermat[3][1] *= -1;
- ownermat[3][1] += offset[1];
- }
- if (data->flag & LOCLIKE_Z) {
- ownermat[3][2] = targetmat[3][2];
-
- if(data->flag & LOCLIKE_Z_INVERT) ownermat[3][2] *= -1;
- ownermat[3][2] += offset[2];
- }
+ /* this check is to make sure curve objects get updated on file load correctly.*/
+ if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */
+ makeDispListCurveTypes(ct->tar, 0);
}
- break;
- case CONSTRAINT_TYPE_ROTLIKE:
- {
- bRotateLikeConstraint *data;
- float loc[3];
- float eul[3], obeul[3];
- float size[3];
-
- data = constraint->data;
-
- VECCOPY(loc, ownermat[3]);
- Mat4ToSize(ownermat, size);
-
- Mat4ToEul(targetmat, eul);
- Mat4ToEul(ownermat, obeul);
-
- if ((data->flag & ROTLIKE_X)==0) {
- eul[0] = obeul[0];
- }
- else if (data->flag & ROTLIKE_X_INVERT) {
- eul[0] *= -1;
- }
-
- if ((data->flag & ROTLIKE_Y)==0) {
- eul[1] = obeul[1];
- }
- else if (data->flag & ROTLIKE_Y_INVERT) {
- eul[1] *= -1;
- }
-
- if ((data->flag & ROTLIKE_Z)==0) {
- eul[2] = obeul[2];
- }
- else if (data->flag & ROTLIKE_Z_INVERT) {
- eul[2] *= -1;
- }
-
- compatible_eul(eul, obeul);
- LocEulSizeToMat4(ownermat, loc, eul, size);
+
+ /* firstly calculate the matrix the normal way, then let the py-function override
+ * this matrix if it needs to do so
+ */
+ constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space);
+ BPY_pyconstraint_target(data, ct);
+ }
+ else if (ct)
+ Mat4One(ct->matrix);
+}
+
+static void pycon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bPythonConstraint *data= con->data;
+
+/* currently removed, until I this can be re-implemented for multiple targets */
+#if 0
+ /* Firstly, run the 'driver' function which has direct access to the objects involved
+ * Technically, this is potentially dangerous as users may abuse this and cause dependency-problems,
+ * but it also allows certain 'clever' rigging hacks to work.
+ */
+ BPY_pyconstraint_driver(data, cob, targets);
+#endif
+
+ /* Now, run the actual 'constraint' function, which should only access the matrices */
+ BPY_pyconstraint_eval(data, cob, targets);
+}
+
+static bConstraintTypeInfo CTI_PYTHON = {
+ CONSTRAINT_TYPE_PYTHON, /* type */
+ sizeof(bPythonConstraint), /* size */
+ "Script", /* name */
+ "bPythonConstraint", /* struct name */
+ pycon_free, /* free data */
+ pycon_relink, /* relink data */
+ pycon_copy, /* copy data */
+ pycon_new_data, /* new data */
+ pycon_get_tars, /* get constraint targets */
+ NULL, /* flush constraint targets */
+ pycon_get_tarmat, /* get target matrix */
+ pycon_evaluate /* evaluate */
+};
+
+/* -------- Action Constraint ----------- */
+
+static void actcon_relink (bConstraint *con)
+{
+ bActionConstraint *data= con->data;
+ ID_NEW(data->act);
+}
+
+static void actcon_new_data (void *cdata)
+{
+ bActionConstraint *data= (bActionConstraint *)cdata;
+
+ /* set type to 20 (Loc X), as 0 is Rot X for backwards compatability */
+ data->type = 20;
+}
+
+static void actcon_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bActionConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* standard target-getting macro for single-target constraints */
+ SINGLETARGET_GET_TARS(con, data, ct, list)
+ }
+}
+
+static void actcon_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+ if (con && list) {
+ bActionConstraint *data= con->data;
+ bConstraintTarget *ct= list->first;
+
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ }
+}
+
+static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+ extern void chan_calc_mat(bPoseChannel *chan);
+ bActionConstraint *data = con->data;
+
+ if (VALID_CONS_TARGET(ct)) {
+ bPose *pose;
+ bPoseChannel *pchan, *tchan;
+ float tempmat[4][4], vec[3];
+ float s, t;
+ short axis;
+
+ /* initialise return matrix */
+ Mat4One(ct->matrix);
+
+ /* currently, only pose-channels are supported owners for action constraints, as
+ * the method for extracting the pose from the actions is currently hardcoded for
+ * poses... this may change in the future
+ */
+ if (cob->type != CONSTRAINT_OBTYPE_BONE)
+ return;
+
+ /* get the transform matrix of the target */
+ constraint_target_to_mat4(ct->tar, ct->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, ct->space);
+
+ /* 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 {
+ /* extract location */
+ VECCOPY(vec, tempmat[3]);
+ axis= data->type - 20;
}
- break;
- case CONSTRAINT_TYPE_SIZELIKE:
- {
- bSizeLikeConstraint *data;
- float obsize[3], size[3];
-
- data = constraint->data;
-
- Mat4ToSize(targetmat, size);
- Mat4ToSize(ownermat, obsize);
-
- 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:
+
+ /* Target defines the animation */
+ 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 */
+ /* a temporary pose is made for this...
+ * TODO: extend this to objects too
+ */
+ pose = MEM_callocN(sizeof(bPose), "pose");
+
+ pchan = cob->pchan;
+ tchan= verify_pose_channel(pose, pchan->name);
+ extract_pose_from_action(pose, data->act, t);
+
+ chan_calc_mat(tchan);
+
+ Mat4CpyMat4(ct->matrix, tchan->chan_mat);
+
+ /* Clean up */
+ free_pose_channels(pose);
+ MEM_freeN(pose);
+ }
+}
+
+static void actcon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bConstraintTarget *ct= targets->first;
+
+ if (VALID_CONS_TARGET(ct)) {
+ float temp[4][4];
+
+ /* Nice and simple... we just need to multiply the matrices, as the get_target_matrix
+ * function has already taken care of everything else.
+ */
+ Mat4CpyMat4(temp, cob->matrix);
+ Mat4MulMat4(cob->matrix, ct->matrix, temp);
+ }
+}
+
+static bConstraintTypeInfo CTI_ACTION = {
+ CONSTRAINT_TYPE_ACTION, /* type */
+ sizeof(bActionConstraint), /* size */
+ "Action", /* name */
+ "bActionConstraint", /* struct name */
+ NULL, /* free data */
+ actcon_relink, /* relink data */
+ NULL, /* copy data */
+ actcon_new_data, /* new data */
+ actcon_get_tars, /* get constraint targets */
+ actcon_flush_tars, /* flush constraint targets */
+ actcon_get_tarmat, /* get target matrix */
+ actcon_evaluate /* evaluate */
+};
+
+/* --------- Locked Track ---------- */
+
+static void locktrack_new_data (void *cdata)
+{
+ bLockTrackConstraint *data= (bLockTrackConstraint *)cdata;
+
+ data->trackflag = TRACK_Y;
+ data->lockflag = LOCK_Z;
+}
+
+static void locktrack_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bLockTrackConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGET_GET_TARS(con, data, ct, list)
+ }
+}
+
+static void locktrack_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+ if (con && list) {
+ bLockTrackConstraint *data= con->data;
+ bConstraintTarget *ct= list->first;
+
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ }
+}
+
+static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bLockTrackConstraint *data= con->data;
+ bConstraintTarget *ct= targets->first;
+
+ if (VALID_CONS_TARGET(ct)) {
+ float vec[3],vec2[3];
+ float totmat[3][3];
+ float tmpmat[3][3];
+ float invmat[3][3];
+ float tmat[4][4];
+ float mdet;
+
+ /* Vector object -> target */
+ VecSubf(vec, ct->matrix[3], cob->matrix[3]);
+ switch (data->lockflag){
+ case LOCK_X: /* LOCK X */
{
- bMinMaxConstraint *data;
- float obmat[4][4], imat[4][4], tarmat[4][4], tmat[4][4];
- float val1, val2;
- int index;
-
- data = constraint->data;
-
- 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);
- Mat4One(tarmat);
- }
-
- switch (data->minmaxflag) {
- case TRACK_Z:
- val1 = tarmat[3][2];
- val2 = obmat[3][2]-data->offset;
- index = 2;
- break;
- case TRACK_Y:
- val1 = tarmat[3][1];
- val2 = obmat[3][1]-data->offset;
- index = 1;
- break;
- case TRACK_X:
- val1 = tarmat[3][0];
- val2 = obmat[3][0]-data->offset;
- index = 0;
- break;
- case TRACK_nZ:
- val2 = tarmat[3][2];
- val1 = obmat[3][2]-data->offset;
- index = 2;
- break;
- case TRACK_nY:
- val2 = tarmat[3][1];
- val1 = obmat[3][1]-data->offset;
- index = 1;
- break;
- case TRACK_nX:
- val2 = tarmat[3][0];
- val1 = obmat[3][0]-data->offset;
- index = 0;
- break;
- default:
- return;
- }
-
- if (val1 > val2) {
- obmat[3][index] = tarmat[3][index] + data->offset;
- if (data->flag & MINMAX_STICKY) {
- if (data->flag & MINMAX_STUCK) {
- VECCOPY(obmat[3], data->cache);
- }
- else {
- VECCOPY(data->cache, obmat[3]);
- data->flag |= MINMAX_STUCK;
- }
+ switch (data->trackflag) {
+ case TRACK_Y: /* LOCK X TRACK Y */
+ {
+ /* Projection of Vector on the plane */
+ Projf(vec2, vec, cob->matrix[0]);
+ VecSubf(totmat[1], vec, vec2);
+ Normalize(totmat[1]);
+
+ /* the x axis is fixed */
+ totmat[0][0] = cob->matrix[0][0];
+ totmat[0][1] = cob->matrix[0][1];
+ totmat[0][2] = cob->matrix[0][2];
+ Normalize(totmat[0]);
+
+ /* the z axis gets mapped onto a third orthogonal vector */
+ Crossf(totmat[2], totmat[0], totmat[1]);
}
- if (data->flag & MINMAX_USEROT) {
- /* get out of localspace */
- Mat4MulMat4(tmat, obmat, targetmat);
- Mat4CpyMat4(ownermat, tmat);
- }
- else {
- VECCOPY(ownermat[3], obmat[3]);
+ break;
+ case TRACK_Z: /* LOCK X TRACK Z */
+ {
+ /* Projection of Vector on the plane */
+ Projf(vec2, vec, cob->matrix[0]);
+ VecSubf(totmat[2], vec, vec2);
+ Normalize(totmat[2]);
+
+ /* the x axis is fixed */
+ totmat[0][0] = cob->matrix[0][0];
+ totmat[0][1] = cob->matrix[0][1];
+ totmat[0][2] = cob->matrix[0][2];
+ Normalize(totmat[0]);
+
+ /* the z axis gets mapped onto a third orthogonal vector */
+ Crossf(totmat[1], totmat[2], totmat[0]);
}
- }
- else {
- data->flag &= ~MINMAX_STUCK;
+ break;
+ case TRACK_nY: /* LOCK X TRACK -Y */
+ {
+ /* Projection of Vector on the plane */
+ Projf(vec2, vec, cob->matrix[0]);
+ VecSubf(totmat[1], vec, vec2);
+ Normalize(totmat[1]);
+ VecMulf(totmat[1],-1);
+
+ /* the x axis is fixed */
+ totmat[0][0] = cob->matrix[0][0];
+ totmat[0][1] = cob->matrix[0][1];
+ totmat[0][2] = cob->matrix[0][2];
+ Normalize(totmat[0]);
+
+ /* 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, cob->matrix[0]);
+ VecSubf(totmat[2], vec, vec2);
+ Normalize(totmat[2]);
+ VecMulf(totmat[2],-1);
+
+ /* the x axis is fixed */
+ totmat[0][0] = cob->matrix[0][0];
+ totmat[0][1] = cob->matrix[0][1];
+ totmat[0][2] = cob->matrix[0][2];
+ Normalize(totmat[0]);
+
+ /* the z axis gets mapped onto a third orthogonal vector */
+ Crossf(totmat[1], totmat[2], totmat[0]);
+ }
+ break;
+ default:
+ {
+ totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+ totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+ totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+ }
+ break;
}
}
- break;
- case CONSTRAINT_TYPE_TRACKTO:
+ break;
+ case LOCK_Y: /* LOCK Y */
{
- bTrackToConstraint *data;
- float size[3], vec[3];
- float totmat[3][3];
- float tmat[4][4];
-
- data = constraint->data;
-
- if (data->tar) {
- /* Get size property, since ob->size is only the object's own relative size, not its global one */
- Mat4ToSize(ownermat, size);
-
- /* Clear the object's rotation */
- 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];
-
- /* targetmat[2] instead of ownermat[2] is passed to vectomat
- * for backwards compatability it seems... (Aligorith)
- */
- VecSubf(vec, ownermat[3], targetmat[3]);
- vectomat(vec, targetmat[2],
- (short)data->reserved1, (short)data->reserved2,
- data->flags, totmat);
-
- Mat4CpyMat4(tmat, ownermat);
- Mat4MulMat34(ownermat, totmat, tmat);
+ switch (data->trackflag) {
+ case TRACK_X: /* LOCK Y TRACK X */
+ {
+ /* Projection of Vector on the plane */
+ Projf(vec2, vec, cob->matrix[1]);
+ VecSubf(totmat[0], vec, vec2);
+ Normalize(totmat[0]);
+
+ /* the y axis is fixed */
+ totmat[1][0] = cob->matrix[1][0];
+ totmat[1][1] = cob->matrix[1][1];
+ totmat[1][2] = cob->matrix[1][2];
+ Normalize(totmat[1]);
+
+ /* 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, cob->matrix[1]);
+ VecSubf(totmat[2], vec, vec2);
+ Normalize(totmat[2]);
+
+ /* the y axis is fixed */
+ totmat[1][0] = cob->matrix[1][0];
+ totmat[1][1] = cob->matrix[1][1];
+ totmat[1][2] = cob->matrix[1][2];
+ Normalize(totmat[1]);
+
+ /* 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, cob->matrix[1]);
+ VecSubf(totmat[0], vec, vec2);
+ Normalize(totmat[0]);
+ VecMulf(totmat[0],-1);
+
+ /* the y axis is fixed */
+ totmat[1][0] = cob->matrix[1][0];
+ totmat[1][1] = cob->matrix[1][1];
+ totmat[1][2] = cob->matrix[1][2];
+ Normalize(totmat[1]);
+
+ /* 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, cob->matrix[1]);
+ VecSubf(totmat[2], vec, vec2);
+ Normalize(totmat[2]);
+ VecMulf(totmat[2],-1);
+
+ /* the y axis is fixed */
+ totmat[1][0] = cob->matrix[1][0];
+ totmat[1][1] = cob->matrix[1][1];
+ totmat[1][2] = cob->matrix[1][2];
+ Normalize(totmat[1]);
+
+ /* the z axis gets mapped onto a third orthogonal vector */
+ Crossf(totmat[0], totmat[1], totmat[2]);
+ }
+ break;
+ default:
+ {
+ totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+ totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+ totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+ }
+ break;
}
}
- break;
- case CONSTRAINT_TYPE_LOCKTRACK:
+ break;
+ case LOCK_Z: /* LOCK Z */
{
- bLockTrackConstraint *data;
- float vec[3],vec2[3];
- float totmat[3][3];
- float tmpmat[3][3];
- float invmat[3][3];
- float tmat[4][4];
- float mdet;
-
- data = constraint->data;
-
- if (data->tar) {
- /* Vector object -> target */
- VecSubf(vec, targetmat[3], ownermat[3]);
- switch (data->lockflag){
- case LOCK_X: /* LOCK X */
+ switch (data->trackflag) {
+ case TRACK_X: /* LOCK Z TRACK X */
{
- switch (data->trackflag) {
- case TRACK_Y: /* LOCK X TRACK Y */
- {
- /* Projection of Vector on the plane */
- Projf(vec2, vec, ownermat[0]);
- VecSubf(totmat[1], vec, vec2);
- Normalize(totmat[1]);
-
- /* 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 */
- Crossf(totmat[2], totmat[0], totmat[1]);
- }
- break;
- case TRACK_Z: /* LOCK X TRACK Z */
- {
- /* Projection of Vector on the plane */
- Projf(vec2, vec, ownermat[0]);
- VecSubf(totmat[2], vec, vec2);
- Normalize(totmat[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]);
+ /* Projection of Vector on the plane */
+ Projf(vec2, vec, cob->matrix[2]);
+ VecSubf(totmat[0], vec, vec2);
+ Normalize(totmat[0]);
- /* 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, ownermat[0]);
- VecSubf(totmat[1], vec, vec2);
- Normalize(totmat[1]);
- VecMulf(totmat[1],-1);
-
- /* 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 */
- Crossf(totmat[2], totmat[0], totmat[1]);
- }
- break;
- case TRACK_nZ: /* LOCK X TRACK -Z */
- {
- /* Projection of Vector on the plane */
- 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] = 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 */
- Crossf(totmat[1], totmat[2], totmat[0]);
- }
- break;
- default:
- {
- totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
- totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
- totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
- }
- break;
- }
+ /* the z axis is fixed */
+ totmat[2][0] = cob->matrix[2][0];
+ totmat[2][1] = cob->matrix[2][1];
+ totmat[2][2] = cob->matrix[2][2];
+ Normalize(totmat[2]);
+
+ /* the x axis gets mapped onto a third orthogonal vector */
+ Crossf(totmat[1], totmat[2], totmat[0]);
}
break;
- case LOCK_Y: /* LOCK Y */
+ case TRACK_Y: /* LOCK Z TRACK Y */
{
- switch (data->trackflag) {
- case TRACK_X: /* LOCK Y TRACK X */
- {
- /* Projection of Vector on the plane */
- Projf(vec2, vec, ownermat[1]);
- VecSubf(totmat[0], vec, vec2);
- Normalize(totmat[0]);
-
- /* 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 */
- Crossf(totmat[2], totmat[0], totmat[1]);
- }
- break;
- case TRACK_Z: /* LOCK Y TRACK Z */
- {
- /* Projection of Vector on the plane */
- Projf(vec2, vec, ownermat[1]);
- VecSubf(totmat[2], vec, vec2);
- Normalize(totmat[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 */
- Crossf(totmat[0], totmat[1], totmat[2]);
- }
- break;
- case TRACK_nX: /* LOCK Y TRACK -X */
- {
- /* Projection of Vector on the plane */
- 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] = 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 */
- Crossf(totmat[2], totmat[0], totmat[1]);
- }
- break;
- case TRACK_nZ: /* LOCK Y TRACK -Z */
- {
- /* Projection of Vector on the plane */
- 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] = 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 */
- Crossf(totmat[0], totmat[1], totmat[2]);
- }
- break;
- default:
- {
- totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
- totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
- totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
- }
- break;
- }
+ /* Projection of Vector on the plane */
+ Projf(vec2, vec, cob->matrix[2]);
+ VecSubf(totmat[1], vec, vec2);
+ Normalize(totmat[1]);
+
+ /* the z axis is fixed */
+ totmat[2][0] = cob->matrix[2][0];
+ totmat[2][1] = cob->matrix[2][1];
+ totmat[2][2] = cob->matrix[2][2];
+ Normalize(totmat[2]);
+
+ /* the x axis gets mapped onto a third orthogonal vector */
+ Crossf(totmat[0], totmat[1], totmat[2]);
}
break;
- case LOCK_Z: /* LOCK Z */
+ case TRACK_nX: /* LOCK Z TRACK -X */
{
- switch (data->trackflag) {
- case TRACK_X: /* LOCK Z TRACK X */
- {
- /* Projection of Vector on the plane */
- Projf(vec2, vec, ownermat[2]);
- VecSubf(totmat[0], vec, vec2);
- Normalize(totmat[0]);
-
- /* 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 */
- Crossf(totmat[1], totmat[2], totmat[0]);
- }
- break;
- case TRACK_Y: /* LOCK Z TRACK Y */
- {
- /* Projection of Vector on the plane */
- Projf(vec2, vec, ownermat[2]);
- VecSubf(totmat[1], vec, vec2);
- Normalize(totmat[1]);
-
- /* 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 */
- Crossf(totmat[0], totmat[1], totmat[2]);
- }
- break;
- case TRACK_nX: /* LOCK Z TRACK -X */
- {
- /* Projection of Vector on the plane */
- 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] = 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 */
- Crossf(totmat[1], totmat[2], totmat[0]);
- }
- break;
- case TRACK_nY: /* LOCK Z TRACK -Y */
- {
- /* Projection of Vector on the plane */
- 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] = 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 */
- Crossf(totmat[0], totmat[1], totmat[2]);
- }
- break;
- default:
- {
- totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
- totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
- totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
- }
- break;
- }
+ /* Projection of Vector on the plane */
+ Projf(vec2, vec, cob->matrix[2]);
+ VecSubf(totmat[0], vec, vec2);
+ Normalize(totmat[0]);
+ VecMulf(totmat[0],-1);
+
+ /* the z axis is fixed */
+ totmat[2][0] = cob->matrix[2][0];
+ totmat[2][1] = cob->matrix[2][1];
+ totmat[2][2] = cob->matrix[2][2];
+ Normalize(totmat[2]);
+
+ /* 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, cob->matrix[2]);
+ VecSubf(totmat[1], vec, vec2);
+ Normalize(totmat[1]);
+ VecMulf(totmat[1],-1);
+
+ /* the z axis is fixed */
+ totmat[2][0] = cob->matrix[2][0];
+ totmat[2][1] = cob->matrix[2][1];
+ totmat[2][2] = cob->matrix[2][2];
+ Normalize(totmat[2]);
+
+ /* the x axis gets mapped onto a third orthogonal vector */
+ Crossf(totmat[0], totmat[1], totmat[2]);
}
break;
default:
- {
+ {
totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
- }
- break;
}
- /* Block to keep matrix heading */
- 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);
- 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, ownermat);
-
- mdet = Det3x3( totmat[0][0],totmat[0][1],totmat[0][2],
- totmat[1][0],totmat[1][1],totmat[1][2],
- totmat[2][0],totmat[2][1],totmat[2][2]);
- if (mdet==0) {
- totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
- totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
- totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
- }
-
- /* apply out transformaton to the object */
- Mat4MulMat34(ownermat, totmat, tmat);
+ break;
}
}
- break;
- case CONSTRAINT_TYPE_FOLLOWPATH:
- {
- 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);
- Mat4CpyMat4(obmat, ownermat); // FIXME!!!
-
- /* get scaling of object before applying constraint */
- Mat4ToSize(ownermat, size);
-
- /* apply targetmat - containing location on path, and rotation */
- Mat4MulSerie(ownermat, targetmat, obmat, NULL, NULL, NULL, NULL, NULL, NULL);
-
- /* un-apply scaling caused by path */
- Mat4ToSize(ownermat, obsize);
- if (obsize[0] != 0)
- VecMulf(ownermat[0], size[0] / obsize[0]);
- if (obsize[1] != 0)
- VecMulf(ownermat[1], size[1] / obsize[1]);
- if (obsize[2] != 0)
- VecMulf(ownermat[2], size[2] / obsize[2]);
+ break;
+ default:
+ {
+ totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+ totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+ totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
}
+ break;
}
- break;
- case CONSTRAINT_TYPE_STRETCHTO:
- {
- bStretchToConstraint *data;
- float size[3],scale[3],vec[3],xx[3],zz[3],orth[3];
- float totmat[3][3];
- float tmat[4][4];
- float dist;
-
- data = constraint->data;
- Mat4ToSize (ownermat, size);
-
- if (data->tar) {
- /* store X orientation before destroying obmat */
- 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] = ownermat[2][0];
- zz[1] = ownermat[2][1];
- zz[2] = ownermat[2][2];
- Normalize(zz);
-
- VecSubf(vec, ownermat[3], targetmat[3]);
- vec[0] /= size[0];
- vec[1] /= size[1];
- vec[2] /= size[2];
-
- dist = Normalize(vec);
- //dist = VecLenf( ob->obmat[3], targetmat[3]);
-
- if (data->orglength == 0) data->orglength = dist;
- if (data->bulge == 0) data->bulge = 1.0;
-
- scale[1] = dist/data->orglength;
- switch (data->volmode) {
- /* volume preserving scaling */
- case VOLUME_XZ :
- scale[0] = 1.0f - (float)sqrt(data->bulge) + (float)sqrt(data->bulge*(data->orglength/dist));
- scale[2] = scale[0];
- break;
- case VOLUME_X:
- scale[0] = 1.0f + data->bulge * (data->orglength /dist - 1);
- scale[2] = 1.0;
- break;
- case VOLUME_Z:
- scale[0] = 1.0;
- scale[2] = 1.0f + data->bulge * (data->orglength /dist - 1);
- break;
- /* don't care for volume */
- case NO_VOLUME:
- scale[0] = 1.0;
- scale[2] = 1.0;
- break;
- default: /* should not happen, but in case*/
- return;
- } /* switch (data->volmode) */
-
- /* Clear the object's rotation and scale */
- 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, ownermat[3], targetmat[3]);
- Normalize(vec);
-
- /* new Y aligns object target connection*/
- totmat[1][0] = -vec[0];
- totmat[1][1] = -vec[1];
- totmat[1][2] = -vec[2];
- switch (data->plane) {
- case PLANE_X:
- /* build new Z vector */
- /* othogonal to "new Y" "old X! plane */
- Crossf(orth, vec, xx);
- Normalize(orth);
-
- /* new Z*/
- totmat[2][0] = orth[0];
- totmat[2][1] = orth[1];
- totmat[2][2] = orth[2];
-
- /* we decided to keep X plane*/
- Crossf(xx, orth, vec);
- Normalize(xx);
- totmat[0][0] = xx[0];
- totmat[0][1] = xx[1];
- totmat[0][2] = xx[2];
- break;
- case PLANE_Z:
- /* build new X vector */
- /* othogonal to "new Y" "old Z! plane */
- Crossf(orth, vec, zz);
- Normalize(orth);
-
- /* new X */
- totmat[0][0] = -orth[0];
- totmat[0][1] = -orth[1];
- totmat[0][2] = -orth[2];
-
- /* we decided to keep Z */
- Crossf(zz, orth, vec);
- Normalize(zz);
- totmat[2][0] = zz[0];
- totmat[2][1] = zz[1];
- totmat[2][2] = zz[2];
- break;
- } /* switch (data->plane) */
-
- Mat4CpyMat4(tmat, ownermat);
-
- Mat4MulMat34(ownermat, totmat, tmat);
- }
- }
- break;
- case CONSTRAINT_TYPE_LOCLIMIT:
- {
- bLocLimitConstraint *data;
+ /* Block to keep matrix heading */
+ tmpmat[0][0] = cob->matrix[0][0];tmpmat[0][1] = cob->matrix[0][1];tmpmat[0][2] = cob->matrix[0][2];
+ tmpmat[1][0] = cob->matrix[1][0];tmpmat[1][1] = cob->matrix[1][1];tmpmat[1][2] = cob->matrix[1][2];
+ tmpmat[2][0] = cob->matrix[2][0];tmpmat[2][1] = cob->matrix[2][1];tmpmat[2][2] = cob->matrix[2][2];
+ Normalize(tmpmat[0]);
+ Normalize(tmpmat[1]);
+ Normalize(tmpmat[2]);
+ Mat3Inv(invmat, tmpmat);
+ 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, cob->matrix);
+
+ mdet = Det3x3( totmat[0][0],totmat[0][1],totmat[0][2],
+ totmat[1][0],totmat[1][1],totmat[1][2],
+ totmat[2][0],totmat[2][1],totmat[2][2]);
+ if (mdet==0) {
+ totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+ totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+ totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+ }
+
+ /* apply out transformaton to the object */
+ Mat4MulMat34(cob->matrix, totmat, tmat);
+ }
+}
- data = constraint->data;
-
- 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;
- }
+static bConstraintTypeInfo CTI_LOCKTRACK = {
+ CONSTRAINT_TYPE_LOCKTRACK, /* type */
+ sizeof(bLockTrackConstraint), /* size */
+ "Locked Track", /* name */
+ "bLockTrackConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ locktrack_new_data, /* new data */
+ locktrack_get_tars, /* get constraint targets */
+ locktrack_flush_tars, /* flush constraint targets */
+ default_get_tarmat, /* get target matrix */
+ locktrack_evaluate /* evaluate */
+};
+
+/* ---------- Stretch To ------------ */
+
+static void stretchto_new_data (void *cdata)
+{
+ bStretchToConstraint *data= (bStretchToConstraint *)cdata;
+
+ data->volmode = 0;
+ data->plane = 0;
+ data->orglength = 0.0;
+ data->bulge = 1.0;
+}
+
+static void stretchto_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bStretchToConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* standard target-getting macro for single-target constraints */
+ SINGLETARGET_GET_TARS(con, data, ct, list)
+ }
+}
+
+static void stretchto_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+ if (con && list) {
+ bStretchToConstraint *data= con->data;
+ bConstraintTarget *ct= list->first;
+
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ }
+}
+
+static void stretchto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bStretchToConstraint *data= con->data;
+ bConstraintTarget *ct= targets->first;
+
+ /* only evaluate if there is a target */
+ if (VALID_CONS_TARGET(ct)) {
+ float size[3], scale[3], vec[3], xx[3], zz[3], orth[3];
+ float totmat[3][3];
+ float tmat[4][4];
+ float dist;
+
+ /* store scaling before destroying obmat */
+ Mat4ToSize(cob->matrix, size);
+
+ /* store X orientation before destroying obmat */
+ xx[0] = cob->matrix[0][0];
+ xx[1] = cob->matrix[0][1];
+ xx[2] = cob->matrix[0][2];
+ Normalize(xx);
+
+ /* store Z orientation before destroying obmat */
+ zz[0] = cob->matrix[2][0];
+ zz[1] = cob->matrix[2][1];
+ zz[2] = cob->matrix[2][2];
+ Normalize(zz);
+
+ VecSubf(vec, cob->matrix[3], ct->matrix[3]);
+ vec[0] /= size[0];
+ vec[1] /= size[1];
+ vec[2] /= size[2];
+
+ dist = Normalize(vec);
+ //dist = VecLenf( ob->obmat[3], targetmat[3]);
+
+ /* data->orglength==0 occurs on first run, and after 'R' button is clicked */
+ if (data->orglength == 0)
+ data->orglength = dist;
+ if (data->bulge == 0)
+ data->bulge = 1.0;
+
+ scale[1] = dist/data->orglength;
+ switch (data->volmode) {
+ /* volume preserving scaling */
+ case VOLUME_XZ :
+ scale[0] = 1.0f - (float)sqrt(data->bulge) + (float)sqrt(data->bulge*(data->orglength/dist));
+ scale[2] = scale[0];
+ break;
+ case VOLUME_X:
+ scale[0] = 1.0f + data->bulge * (data->orglength /dist - 1);
+ scale[2] = 1.0;
+ break;
+ case VOLUME_Z:
+ scale[0] = 1.0;
+ scale[2] = 1.0f + data->bulge * (data->orglength /dist - 1);
+ break;
+ /* don't care for volume */
+ case NO_VOLUME:
+ scale[0] = 1.0;
+ scale[2] = 1.0;
+ break;
+ default: /* should not happen, but in case*/
+ return;
+ } /* switch (data->volmode) */
+
+ /* Clear the object's rotation and scale */
+ cob->matrix[0][0]=size[0]*scale[0];
+ cob->matrix[0][1]=0;
+ cob->matrix[0][2]=0;
+ cob->matrix[1][0]=0;
+ cob->matrix[1][1]=size[1]*scale[1];
+ cob->matrix[1][2]=0;
+ cob->matrix[2][0]=0;
+ cob->matrix[2][1]=0;
+ cob->matrix[2][2]=size[2]*scale[2];
+
+ VecSubf(vec, cob->matrix[3], ct->matrix[3]);
+ Normalize(vec);
+
+ /* new Y aligns object target connection*/
+ totmat[1][0] = -vec[0];
+ totmat[1][1] = -vec[1];
+ totmat[1][2] = -vec[2];
+ switch (data->plane) {
+ case PLANE_X:
+ /* build new Z vector */
+ /* othogonal to "new Y" "old X! plane */
+ Crossf(orth, vec, xx);
+ Normalize(orth);
+
+ /* new Z*/
+ totmat[2][0] = orth[0];
+ totmat[2][1] = orth[1];
+ totmat[2][2] = orth[2];
+
+ /* we decided to keep X plane*/
+ Crossf(xx, orth, vec);
+ Normalize(xx);
+ totmat[0][0] = xx[0];
+ totmat[0][1] = xx[1];
+ totmat[0][2] = xx[2];
+ break;
+ case PLANE_Z:
+ /* build new X vector */
+ /* othogonal to "new Y" "old Z! plane */
+ Crossf(orth, vec, zz);
+ Normalize(orth);
+
+ /* new X */
+ totmat[0][0] = -orth[0];
+ totmat[0][1] = -orth[1];
+ totmat[0][2] = -orth[2];
+
+ /* we decided to keep Z */
+ Crossf(zz, orth, vec);
+ Normalize(zz);
+ totmat[2][0] = zz[0];
+ totmat[2][1] = zz[1];
+ totmat[2][2] = zz[2];
+ break;
+ } /* switch (data->plane) */
+
+ Mat4CpyMat4(tmat, cob->matrix);
+ Mat4MulMat34(cob->matrix, totmat, tmat);
+ }
+}
+
+static bConstraintTypeInfo CTI_STRETCHTO = {
+ CONSTRAINT_TYPE_STRETCHTO, /* type */
+ sizeof(bStretchToConstraint), /* size */
+ "Stretch To", /* name */
+ "bStretchToConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ stretchto_new_data, /* new data */
+ stretchto_get_tars, /* get constraint targets */
+ stretchto_flush_tars, /* flush constraint targets */
+ default_get_tarmat, /* get target matrix */
+ stretchto_evaluate /* evaluate */
+};
+
+/* ---------- Floor ------------ */
+
+static void minmax_new_data (void *cdata)
+{
+ bMinMaxConstraint *data= (bMinMaxConstraint *)cdata;
+
+ data->minmaxflag = TRACK_Z;
+ data->offset = 0.0f;
+ data->cache[0] = data->cache[1] = data->cache[2] = 0.0f;
+ data->flag = 0;
+}
+
+static void minmax_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bMinMaxConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* standard target-getting macro for single-target constraints */
+ SINGLETARGET_GET_TARS(con, data, ct, list)
+ }
+}
+
+static void minmax_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+ if (con && list) {
+ bMinMaxConstraint *data= con->data;
+ bConstraintTarget *ct= list->first;
+
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ }
+}
+
+static void minmax_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bMinMaxConstraint *data= con->data;
+ bConstraintTarget *ct= targets->first;
+
+ /* only evaluate if there is a target */
+ if (VALID_CONS_TARGET(ct)) {
+ float obmat[4][4], imat[4][4], tarmat[4][4], tmat[4][4];
+ float val1, val2;
+ int index;
+
+ Mat4CpyMat4(obmat, cob->matrix);
+ Mat4CpyMat4(tarmat, ct->matrix);
+
+ 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);
+ Mat4One(tarmat);
}
- break;
- case CONSTRAINT_TYPE_ROTLIMIT:
- {
- bRotLimitConstraint *data;
- float loc[3];
- float eul[3];
- float size[3];
-
- data = constraint->data;
-
- VECCOPY(loc, ownermat[3]);
- Mat4ToSize(ownermat, size);
-
- Mat4ToEul(ownermat, eul);
-
- /* eulers: radians to degrees! */
- eul[0] = (eul[0] / M_PI * 180);
- eul[1] = (eul[1] / M_PI * 180);
- eul[2] = (eul[2] / M_PI * 180);
-
- /* limiting of euler values... */
- if (data->flag & LIMIT_XROT) {
- if (eul[0] < data->xmin)
- eul[0] = data->xmin;
-
- if (eul[0] > data->xmax)
- eul[0] = data->xmax;
- }
- if (data->flag & LIMIT_YROT) {
- if (eul[1] < data->ymin)
- eul[1] = data->ymin;
-
- if (eul[1] > data->ymax)
- eul[1] = data->ymax;
- }
- if (data->flag & LIMIT_ZROT) {
- if (eul[2] < data->zmin)
- eul[2] = data->zmin;
-
- if (eul[2] > data->zmax)
- eul[2] = data->zmax;
- }
-
- /* eulers: degrees to radians ! */
- eul[0] = (eul[0] / 180 * M_PI);
- eul[1] = (eul[1] / 180 * M_PI);
- eul[2] = (eul[2] / 180 * M_PI);
-
- LocEulSizeToMat4(ownermat, loc, eul, size);
+
+ switch (data->minmaxflag) {
+ case TRACK_Z:
+ val1 = tarmat[3][2];
+ val2 = obmat[3][2]-data->offset;
+ index = 2;
+ break;
+ case TRACK_Y:
+ val1 = tarmat[3][1];
+ val2 = obmat[3][1]-data->offset;
+ index = 1;
+ break;
+ case TRACK_X:
+ val1 = tarmat[3][0];
+ val2 = obmat[3][0]-data->offset;
+ index = 0;
+ break;
+ case TRACK_nZ:
+ val2 = tarmat[3][2];
+ val1 = obmat[3][2]-data->offset;
+ index = 2;
+ break;
+ case TRACK_nY:
+ val2 = tarmat[3][1];
+ val1 = obmat[3][1]-data->offset;
+ index = 1;
+ break;
+ case TRACK_nX:
+ val2 = tarmat[3][0];
+ val1 = obmat[3][0]-data->offset;
+ index = 0;
+ break;
+ default:
+ return;
}
- break;
- case CONSTRAINT_TYPE_SIZELIMIT:
- {
- bSizeLimitConstraint *data;
- float obsize[3], size[3];
-
- data = constraint->data;
-
- Mat4ToSize(ownermat, size);
- Mat4ToSize(ownermat, obsize);
-
- if (data->flag & LIMIT_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 (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 (size[2] < data->zmin)
- size[2] = data->zmin;
+
+ if (val1 > val2) {
+ obmat[3][index] = tarmat[3][index] + data->offset;
+ if (data->flag & MINMAX_STICKY) {
+ if (data->flag & MINMAX_STUCK) {
+ VECCOPY(obmat[3], data->cache);
+ }
+ else {
+ VECCOPY(data->cache, obmat[3]);
+ data->flag |= MINMAX_STUCK;
+ }
}
- if (data->flag & LIMIT_ZMAX) {
- if (size[2] > data->zmax)
- size[2] = data->zmax;
+ if (data->flag & MINMAX_USEROT) {
+ /* get out of localspace */
+ Mat4MulMat4(tmat, obmat, ct->matrix);
+ Mat4CpyMat4(cob->matrix, tmat);
+ }
+ else {
+ VECCOPY(cob->matrix[3], obmat[3]);
}
-
- VecMulf(ownermat[0], size[0]/obsize[0]);
- VecMulf(ownermat[1], size[1]/obsize[1]);
- VecMulf(ownermat[2], size[2]/obsize[2]);
+ }
+ else {
+ data->flag &= ~MINMAX_STUCK;
}
- break;
- case CONSTRAINT_TYPE_RIGIDBODYJOINT:
- {
- /* Do nothing. The GameEngine will take care of this.*/
- }
- break;
- case CONSTRAINT_TYPE_CLAMPTO:
- {
- bClampToConstraint *data;
- Curve *cu;
- float obmat[4][4], targetMatrix[4][4], ownLoc[3];
- float curveMin[3], curveMax[3];
-
- data = constraint->data;
-
- /* prevent crash if user deletes curve */
- if ((data->tar == NULL) || (data->tar->type != OB_CURVE) )
- return;
- else
- cu= data->tar->data;
-
- Mat4CpyMat4(obmat, ownermat);
- Mat4One(targetMatrix);
- VECCOPY(ownLoc, obmat[3]);
-
- INIT_MINMAX(curveMin, curveMax)
- minmax_object(data->tar, curveMin, curveMax);
-
- /* get targetmatrix */
- if (cu->path && cu->path->data) {
- float vec[4], dir[3], totmat[4][4];
- float curvetime;
- short clamp_axis;
+ }
+}
+
+static bConstraintTypeInfo CTI_MINMAX = {
+ CONSTRAINT_TYPE_MINMAX, /* type */
+ sizeof(bMinMaxConstraint), /* size */
+ "Floor", /* name */
+ "bMinMaxConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ minmax_new_data, /* new data */
+ minmax_get_tars, /* get constraint targets */
+ minmax_flush_tars, /* flush constraint targets */
+ default_get_tarmat, /* get target matrix */
+ minmax_evaluate /* evaluate */
+};
+
+/* ------- RigidBody Joint ---------- */
+
+static void rbj_new_data (void *cdata)
+{
+ bRigidBodyJointConstraint *data= (bRigidBodyJointConstraint *)cdata;
+
+ // removed code which set target of this constraint
+ data->type=1;
+}
+
+static void rbj_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bRigidBodyJointConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* standard target-getting macro for single-target constraints without subtargets */
+ SINGLETARGETNS_GET_TARS(con, data, ct, list)
+ }
+}
+
+static void rbj_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+ if (con && list) {
+ bRigidBodyJointConstraint *data= con->data;
+ bConstraintTarget *ct= list->first;
+
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy)
+ }
+}
+
+static bConstraintTypeInfo CTI_RIGIDBODYJOINT = {
+ CONSTRAINT_TYPE_RIGIDBODYJOINT, /* type */
+ sizeof(bRigidBodyJointConstraint), /* size */
+ "RigidBody Joint", /* name */
+ "bRigidBodyJointConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ rbj_new_data, /* new data */
+ rbj_get_tars, /* get constraint targets */
+ rbj_flush_tars, /* flush constraint targets */
+ default_get_tarmat, /* get target matrix */
+ NULL /* evaluate - this is not solved here... is just an interface for game-engine */
+};
+
+/* -------- Clamp To ---------- */
+
+static void clampto_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bClampToConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* standard target-getting macro for single-target constraints without subtargets */
+ SINGLETARGETNS_GET_TARS(con, data, ct, list)
+ }
+}
+
+static void clampto_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+ if (con && list) {
+ bClampToConstraint *data= con->data;
+ bConstraintTarget *ct= list->first;
+
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy)
+ }
+}
+
+static void clampto_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime)
+{
+ if (VALID_CONS_TARGET(ct)) {
+ Curve *cu= ct->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)
+ */
+
+ /* only happens on reload file, but violates depsgraph still... fix! */
+ if (cu->path==NULL || cu->path->data==NULL)
+ makeDispListCurveTypes(ct->tar, 0);
+ }
+
+ /* technically, this isn't really needed for evaluation, but we don't know what else
+ * might end up calling this...
+ */
+ if (ct)
+ Mat4One(ct->matrix);
+}
+
+static void clampto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bClampToConstraint *data= con->data;
+ bConstraintTarget *ct= targets->first;
+
+ /* only evaluate if there is a target and it is a curve */
+ if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVE)) {
+ Curve *cu= data->tar->data;
+ float obmat[4][4], targetMatrix[4][4], ownLoc[3];
+ float curveMin[3], curveMax[3];
+
+ Mat4CpyMat4(obmat, cob->matrix);
+ Mat4One(targetMatrix);
+ VECCOPY(ownLoc, obmat[3]);
+
+ INIT_MINMAX(curveMin, curveMax)
+ minmax_object(ct->tar, curveMin, curveMax);
+
+ /* get targetmatrix */
+ if (cu->path && cu->path->data) {
+ float vec[4], dir[3], totmat[4][4];
+ float curvetime;
+ short clamp_axis;
+
+ /* find best position on curve */
+ /* 1. determine which axis to sample on? */
+ if (data->flag == CLAMPTO_AUTO) {
+ float size[3];
+ VecSubf(size, curveMax, curveMin);
- /* find best position on curve */
- /* 1. determine which axis to sample on? */
- if (data->flag == CLAMPTO_AUTO) {
- float size[3];
- VecSubf(size, curveMax, curveMin);
+ /* find axis along which the bounding box has the greatest
+ * extent. Otherwise, default to the x-axis, as that is quite
+ * frequently used.
+ */
+ if ((size[2]>size[0]) && (size[2]>size[1]))
+ clamp_axis= CLAMPTO_Z - 1;
+ else if ((size[1]>size[0]) && (size[1]>size[2]))
+ clamp_axis= CLAMPTO_Y - 1;
+ else
+ clamp_axis = CLAMPTO_X - 1;
+ }
+ else
+ clamp_axis= data->flag - 1;
+
+ /* 2. determine position relative to curve on a 0-1 scale based on bounding box */
+ if (data->flag2 & CLAMPTO_CYCLIC) {
+ /* cyclic, so offset within relative bounding box is used */
+ float len= (curveMax[clamp_axis] - curveMin[clamp_axis]);
+ float offset;
+
+ /* find bounding-box range where target is located */
+ if (ownLoc[clamp_axis] < curveMin[clamp_axis]) {
+ /* bounding-box range is before */
+ offset= curveMin[clamp_axis];
- /* find axis along which the bounding box has the greatest
- * extent. Otherwise, default to the x-axis, as that is quite
- * frequently used.
- */
- if ((size[2]>size[0]) && (size[2]>size[1]))
- clamp_axis= CLAMPTO_Z - 1;
- else if ((size[1]>size[0]) && (size[1]>size[2]))
- clamp_axis= CLAMPTO_Y - 1;
- else
- clamp_axis = CLAMPTO_X - 1;
- }
- else
- clamp_axis= data->flag - 1;
+ while (ownLoc[clamp_axis] < offset)
+ offset -= len;
- /* 2. determine position relative to curve on a 0-1 scale based on bounding box */
- if (data->flag2 & CLAMPTO_CYCLIC) {
- /* cyclic, so offset within relative bounding box is used */
- float len= (curveMax[clamp_axis] - curveMin[clamp_axis]);
- float offset;
+ /* now, we calculate as per normal, except using offset instead of curveMin[clamp_axis] */
+ curvetime = (ownLoc[clamp_axis] - offset) / (len);
+ }
+ else if (ownLoc[clamp_axis] > curveMax[clamp_axis]) {
+ /* bounding-box range is after */
+ offset= curveMax[clamp_axis];
- /* find bounding-box range where target is located */
- if (ownLoc[clamp_axis] < curveMin[clamp_axis]) {
- /* bounding-box range is before */
- offset= curveMin[clamp_axis];
-
- while (ownLoc[clamp_axis] < offset)
- offset -= len;
-
- /* now, we calculate as per normal, except using offset instead of curveMin[clamp_axis] */
- curvetime = (ownLoc[clamp_axis] - offset) / (len);
- }
- else if (ownLoc[clamp_axis] > curveMax[clamp_axis]) {
- /* bounding-box range is after */
- offset= curveMax[clamp_axis];
-
- while (ownLoc[clamp_axis] > offset) {
- if ((offset + len) > ownLoc[clamp_axis])
- break;
- else
- offset += len;
- }
-
- /* now, we calculate as per normal, except using offset instead of curveMax[clamp_axis] */
- curvetime = (ownLoc[clamp_axis] - offset) / (len);
- }
- else {
- /* as the location falls within bounds, just calculate */
- curvetime = (ownLoc[clamp_axis] - curveMin[clamp_axis]) / (len);
+ while (ownLoc[clamp_axis] > offset) {
+ if ((offset + len) > ownLoc[clamp_axis])
+ break;
+ else
+ offset += len;
}
+
+ /* now, we calculate as per normal, except using offset instead of curveMax[clamp_axis] */
+ curvetime = (ownLoc[clamp_axis] - offset) / (len);
}
else {
- /* no cyclic, so position is clamped to within the bounding box */
- if (ownLoc[clamp_axis] <= curveMin[clamp_axis])
- curvetime = 0.0;
- 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]);
- }
-
- /* 3. position on curve */
- if(where_on_path(data->tar, curvetime, vec, dir) ) {
- Mat4One(totmat);
- VECCOPY(totmat[3], vec);
-
- Mat4MulSerie(targetMatrix, data->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
+ /* as the location falls within bounds, just calculate */
+ curvetime = (ownLoc[clamp_axis] - curveMin[clamp_axis]) / (len);
}
}
+ else {
+ /* no cyclic, so position is clamped to within the bounding box */
+ if (ownLoc[clamp_axis] <= curveMin[clamp_axis])
+ curvetime = 0.0;
+ 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]);
+ }
- /* obtain final object position */
- 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);
+ /* 3. position on curve */
+ if (where_on_path(ct->tar, curvetime, vec, dir) ) {
+ Mat4One(totmat);
+ VECCOPY(totmat[3], vec);
- /* 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);
+ Mat4MulSerie(targetMatrix, ct->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
}
}
- break;
- case CONSTRAINT_TYPE_TRANSFORM:
- {
- bTransformConstraint *data;
-
- data = constraint->data;
-
- /* only work if there is a target */
- if (data->tar) {
- float loc[3], eul[3], size[3];
- float dvec[3], sval[3];
- short i;
-
- /* obtain target effect */
- switch (data->from) {
- case 2: /* scale */
- Mat4ToSize(targetmat, dvec);
- break;
- case 1: /* rotation */
- Mat4ToEul(targetmat, dvec);
- break;
- default: /* location */
- VecCopyf(dvec, targetmat[3]);
- break;
+
+ /* obtain final object position */
+ VECCOPY(cob->matrix[3], targetMatrix[3]);
+ }
+}
+
+static bConstraintTypeInfo CTI_CLAMPTO = {
+ CONSTRAINT_TYPE_CLAMPTO, /* type */
+ sizeof(bClampToConstraint), /* size */
+ "Clamp To", /* name */
+ "bClampToConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ NULL, /* new data */
+ clampto_get_tars, /* get constraint targets */
+ clampto_flush_tars, /* flush constraint targets */
+ clampto_get_tarmat, /* get target matrix */
+ clampto_evaluate /* evaluate */
+};
+
+/* ---------- Transform Constraint ----------- */
+
+static void transform_new_data (void *cdata)
+{
+ bTransformConstraint *data= (bTransformConstraint *)cdata;
+
+ data->map[0]= 0;
+ data->map[1]= 1;
+ data->map[2]= 2;
+}
+
+static void transform_get_tars (bConstraint *con, ListBase *list)
+{
+ if (con && list) {
+ bTransformConstraint *data= con->data;
+ bConstraintTarget *ct;
+
+ /* standard target-getting macro for single-target constraints */
+ SINGLETARGET_GET_TARS(con, data, ct, list)
+ }
+}
+
+static void transform_flush_tars (bConstraint *con, ListBase *list, short nocopy)
+{
+ if (con && list) {
+ bTransformConstraint *data= con->data;
+ bConstraintTarget *ct= list->first;
+
+ /* the following macro is used for all standard single-target constraints */
+ SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy)
+ }
+}
+
+static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets)
+{
+ bTransformConstraint *data= con->data;
+ bConstraintTarget *ct= targets->first;
+
+ /* only evaluate if there is a target */
+ if (VALID_CONS_TARGET(ct)) {
+ float loc[3], eul[3], size[3];
+ float dvec[3], sval[3];
+ short i;
+
+ /* obtain target effect */
+ switch (data->from) {
+ case 2: /* scale */
+ Mat4ToSize(ct->matrix, dvec);
+ break;
+ case 1: /* rotation */
+ Mat4ToEul(ct->matrix, dvec);
+ break;
+ default: /* location */
+ VecCopyf(dvec, ct->matrix[3]);
+ break;
+ }
+
+ /* extract components of owner's matrix */
+ VECCOPY(loc, cob->matrix[3]);
+ Mat4ToEul(cob->matrix, eul);
+ Mat4ToSize(cob->matrix, size);
+
+ /* determine where in range current transforms lie */
+ if (data->expo) {
+ for (i=0; i<3; i++) {
+ if (data->from_max[i] - data->from_min[i])
+ sval[i]= (dvec[i] - data->from_min[i]) / (data->from_max[i] - data->from_min[i]);
+ else
+ sval[i]= 0.0f;
+ }
+ }
+ else {
+ /* clamp transforms out of range */
+ for (i=0; i<3; i++) {
+ CLAMP(dvec[i], data->from_min[i], data->from_max[i]);
+ if (data->from_max[i] - data->from_min[i])
+ sval[i]= (dvec[i] - data->from_min[i]) / (data->from_max[i] - data->from_min[i]);
+ else
+ sval[i]= 0.0f;
+ }
+ }
+
+ /* convert radian<->degree */
+ if (data->from==1 && data->to==0) {
+ /* from radians to degrees */
+ for (i=0; i<3; i++)
+ sval[i] = sval[i] / M_PI * 180;
+ }
+ else if (data->from==0 && data->to==1) {
+ /* from degrees to radians */
+ for (i=0; i<3; i++)
+ sval[i] = sval[i] / 180 * M_PI;
+ }
+
+ /* apply transforms */
+ switch (data->to) {
+ case 2: /* scaling */
+ for (i=0; i<3; i++)
+ size[i]= data->to_min[i] + (sval[data->map[i]] * (data->to_max[i] - data->to_min[i]));
+ break;
+ case 1: /* rotation */
+ for (i=0; i<3; i++) {
+ float tmin, tmax;
+
+ /* convert destination min/max ranges from degrees to radians */
+ tmin= data->to_min[i] / M_PI * 180;
+ tmax= data->to_max[i] / M_PI * 180;
+
+ eul[i]= tmin + (sval[data->map[i]] * (tmax - tmin));
}
+ break;
+ default: /* location */
+ /* get new location */
+ for (i=0; i<3; i++)
+ loc[i]= (data->to_min[i] + (sval[data->map[i]] * (data->to_max[i] - data->to_min[i])));
+
+ /* add original location back on (so that it can still be moved) */
+ VecAddf(loc, cob->matrix[3], loc);
+ break;
+ }
+
+ /* apply to matrix */
+ LocEulSizeToMat4(cob->matrix, loc, eul, size);
+ }
+}
+
+static bConstraintTypeInfo CTI_TRANSFORM = {
+ CONSTRAINT_TYPE_TRANSFORM, /* type */
+ sizeof(bTransformConstraint), /* size */
+ "Transform", /* name */
+ "bTransformConstraint", /* struct name */
+ NULL, /* free data */
+ NULL, /* relink data */
+ NULL, /* copy data */
+ transform_new_data, /* new data */
+ transform_get_tars, /* get constraint targets */
+ transform_flush_tars, /* flush constraint targets */
+ default_get_tarmat, /* get a target matrix */
+ transform_evaluate /* evaluate */
+};
+
+/* ************************* Constraints Type-Info *************************** */
+/* All of the constraints api functions use bConstraintTypeInfo structs to carry out
+ * and operations that involve constraint specifc code.
+ */
+
+/* These globals only ever get directly accessed in this file */
+static bConstraintTypeInfo *constraintsTypeInfo[NUM_CONSTRAINT_TYPES];
+static short CTI_INIT= 1; /* when non-zero, the list needs to be updated */
+
+/* This function only gets called when CTI_INIT is non-zero */
+static void constraints_init_typeinfo () {
+ constraintsTypeInfo[0]= NULL; /* 'Null' Constraint */
+ constraintsTypeInfo[1]= &CTI_CHILDOF; /* ChildOf Constraint */
+ constraintsTypeInfo[2]= &CTI_TRACKTO; /* TrackTo Constraint */
+ constraintsTypeInfo[3]= &CTI_KINEMATIC; /* IK Constraint */
+ constraintsTypeInfo[4]= &CTI_FOLLOWPATH; /* Follow-Path Constraint */
+ constraintsTypeInfo[5]= &CTI_ROTLIMIT; /* Limit Rotation Constraint */
+ constraintsTypeInfo[6]= &CTI_LOCLIMIT; /* Limit Location Constraint */
+ constraintsTypeInfo[7]= &CTI_SIZELIMIT; /* Limit Scaling Constraint */
+ constraintsTypeInfo[8]= &CTI_ROTLIKE; /* Copy Rotation Constraint */
+ constraintsTypeInfo[9]= &CTI_LOCLIKE; /* Copy Location Constraint */
+ constraintsTypeInfo[10]= &CTI_SIZELIKE; /* Copy Scaling Constraint */
+ constraintsTypeInfo[11]= &CTI_PYTHON; /* Python/Script Constraint */
+ constraintsTypeInfo[12]= &CTI_ACTION; /* Action Constraint */
+ constraintsTypeInfo[13]= &CTI_LOCKTRACK; /* Locked-Track Constraint */
+ constraintsTypeInfo[14]= NULL; /* 'Distance Limit' Constraint */
+ constraintsTypeInfo[15]= &CTI_STRETCHTO; /* StretchTo Constaint */
+ constraintsTypeInfo[16]= &CTI_MINMAX; /* Floor Constraint */
+ constraintsTypeInfo[17]= &CTI_RIGIDBODYJOINT; /* RigidBody Constraint */
+ constraintsTypeInfo[18]= &CTI_CLAMPTO; /* ClampTo Constraint */
+ constraintsTypeInfo[19]= &CTI_TRANSFORM; /* Transformation Constraint */
+}
+
+/* This function should be used for getting the appropriate type-info when only
+ * a constraint type is known
+ */
+bConstraintTypeInfo *get_constraint_typeinfo (int type)
+{
+ /* initialise the type-info list? */
+ if (CTI_INIT) {
+ constraints_init_typeinfo();
+ CTI_INIT = 0;
+ }
+
+ /* only return for valid types */
+ if ( (type >= CONSTRAINT_TYPE_NULL) &&
+ (type <= NUM_CONSTRAINT_TYPES ) )
+ {
+ /* there shouldn't be any segfaults here... */
+ return constraintsTypeInfo[type];
+ }
+ else {
+ printf("No valid constraint type-info data available. Type = %i \n", type);
+ }
+
+ return NULL;
+}
+
+/* This function should always be used to get the appropriate type-info, as it
+ * has checks which prevent segfaults in some weird cases.
+ */
+bConstraintTypeInfo *constraint_get_typeinfo (bConstraint *con)
+{
+ /* only return typeinfo for valid constraints */
+ if (con)
+ return get_constraint_typeinfo(con->type);
+ else
+ return NULL;
+}
+
+/* ************************* General Constraints API ************************** */
+/* The functions here are called by various parts of Blender. Very few (should be none if possible)
+ * constraint-specific code should occur here.
+ */
+
+/* ---------- Data Management ------- */
+
+/* Free data of a specific constraint if it has any info */
+void free_constraint_data (bConstraint *con)
+{
+ if (con->data) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+
+ /* perform any special freeing constraint may have */
+ if (cti && cti->free_data)
+ cti->free_data(con);
+
+ /* free constraint data now */
+ MEM_freeN(con->data);
+ }
+}
+
+/* Free all constraints from a constraint-stack */
+void free_constraints (ListBase *conlist)
+{
+ bConstraint *con;
+
+ /* Free constraint data and also any extra data */
+ for (con= conlist->first; con; con= con->next) {
+ free_constraint_data(con);
+ }
+
+ /* Free the whole list */
+ BLI_freelistN(conlist);
+}
+
+/* Reassign links that constraints have to other data (called during file loading?) */
+void relink_constraints (ListBase *conlist)
+{
+ bConstraint *con;
+ bConstraintTarget *ct;
+
+ for (con= conlist->first; con; con= con->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+
+ if (cti) {
+ /* relink any targets */
+ if (cti->get_constraint_targets) {
+ ListBase targets = {NULL, NULL};
- /* extract components of owner's matrix */
- VECCOPY(loc, ownermat[3]);
- Mat4ToEul(ownermat, eul);
- Mat4ToSize(ownermat, size);
+ cti->get_constraint_targets(con, &targets);
+ for (ct= targets.first; ct; ct= ct->next) {
+ ID_NEW(ct->tar);
+ }
- /* determine where in range current transforms lie */
- if (data->expo) {
- for (i=0; i<3; i++) {
- if (data->from_max[i] - data->from_min[i])
- sval[i]= (dvec[i] - data->from_min[i]) / (data->from_max[i] - data->from_min[i]);
- else
- sval[i]= 0.0f;
- }
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+
+ /* relink any other special data */
+ if (cti->relink_data)
+ cti->relink_data(con);
+ }
+ }
+}
+
+/* duplicate all of the constraints in a constraint stack */
+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) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+
+ /* make a new copy of the constraint's data */
+ con->data = MEM_dupallocN(con->data);
+
+ /* only do specific constraints if required */
+ if (cti && cti->copy_data)
+ cti->copy_data(con, srccon);
+ }
+}
+
+/* -------- Target-Matrix Stuff ------- */
+
+/* This function is a relic from the prior implementations of the constraints system, when all
+ * constraints either had one or no targets. It used to be called during the main constraint solving
+ * loop, but is now only used for the remaining cases for a few constraints.
+ *
+ * None of the actual calculations of the matricies should be done here! Also, this function is
+ * not to be used by any new constraints, particularly any that have multiple targets.
+ */
+void get_constraint_target_matrix (bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float ctime)
+{
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintOb *cob;
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ /* make 'constraint-ob' */
+ cob= MEM_callocN(sizeof(bConstraintOb), "tempConstraintOb");
+ cob->type= ownertype;
+ switch (ownertype) {
+ case CONSTRAINT_OBTYPE_OBJECT: /* it is usually this case */
+ {
+ cob->ob= (Object *)ownerdata;
+ cob->pchan= NULL;
+ if (cob->ob) {
+ Mat4CpyMat4(cob->matrix, cob->ob->obmat);
+ Mat4CpyMat4(cob->startmat, cob->matrix);
}
else {
- /* clamp transforms out of range */
- for (i=0; i<3; i++) {
- CLAMP(dvec[i], data->from_min[i], data->from_max[i]);
- if (data->from_max[i] - data->from_min[i])
- sval[i]= (dvec[i] - data->from_min[i]) / (data->from_max[i] - data->from_min[i]);
- else
- sval[i]= 0.0f;
- }
- }
-
- /* convert radian<->degree */
- if (data->from==1 && data->to==0) {
- /* from radians to degrees */
- for (i=0; i<3; i++)
- sval[i] = sval[i] / M_PI * 180;
+ Mat4One(cob->matrix);
+ Mat4One(cob->startmat);
}
- else if (data->from==0 && data->to==1) {
- /* from degrees to radians */
- for (i=0; i<3; i++)
- sval[i] = sval[i] / 180 * M_PI;
+ }
+ break;
+ case CONSTRAINT_OBTYPE_BONE: /* this may occur in some cases */
+ {
+ cob->ob= NULL; /* this might not work at all :/ */
+ cob->pchan= (bPoseChannel *)ownerdata;
+ if (cob->pchan) {
+ Mat4CpyMat4(cob->matrix, cob->pchan->pose_mat);
+ Mat4CpyMat4(cob->startmat, cob->matrix);
}
-
- /* apply transforms */
- switch (data->to) {
- case 2: /* scaling */
- for (i=0; i<3; i++)
- size[i]= data->to_min[i] + (sval[data->map[i]] * (data->to_max[i] - data->to_min[i]));
- break;
- case 1: /* rotation */
- for (i=0; i<3; i++) {
- float tmin, tmax;
-
- /* convert destination min/max ranges from degrees to radians */
- tmin= data->to_min[i] / M_PI * 180;
- tmax= data->to_max[i] / M_PI * 180;
-
- eul[i]= tmin + (sval[data->map[i]] * (tmax - tmin));
- }
- break;
- default: /* location */
- /* get new location */
- for (i=0; i<3; i++)
- loc[i]= (data->to_min[i] + (sval[data->map[i]] * (data->to_max[i] - data->to_min[i])));
-
- /* add original location back on (so that it can still be moved) */
- VecAddf(loc, ownermat[3], loc);
- break;
+ else {
+ Mat4One(cob->matrix);
+ Mat4One(cob->startmat);
}
-
- /* apply to matrix */
- LocEulSizeToMat4(ownermat, loc, eul, size);
}
+ break;
}
- break;
- default:
- printf("Error: Unknown constraint type\n");
- break;
+
+ /* get targets - we only need the first one though (and there should only be one) */
+ cti->get_constraint_targets(con, &targets);
+
+ /* only calculate the target matrix on the first target */
+ ct= (bConstraintTarget *)targets.first;
+ if (ct) {
+ if (cti->get_target_matrix)
+ cti->get_target_matrix(con, cob, ct, ctime);
+ Mat4CpyMat4(mat, ct->matrix);
+ }
+
+ /* free targets + 'constraint-ob' */
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 1);
+ MEM_freeN(cob);
+ }
+ else {
+ /* invalid constraint - perhaps... */
+ Mat4One(mat);
}
}
+
+/* ---------- Evaluation ----------- */
-/* this function is called whenever constraints need to be evaluated */
+/* This function is called whenever constraints need to be evaluated. Currently, all
+ * constraints that can be evaluated are everytime this gets run.
+ *
+ * constraints_make_evalob and constraints_clear_evalob should be called before and
+ * after running this function, to sort out cob
+ */
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 solution[4][4], delta[4][4];
+ float oldmat[4][4], imat[4][4];
float enf;
/* check that there is a valid constraint object to evaluate */
@@ -2848,43 +3309,59 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime)
/* loop over available constraints, solving and blending them */
for (con= conlist->first; con; con= con->next) {
- /* this we can skip completely */
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+
+ /* these we can skip completely (invalid constraints...) */
+ if (cti == NULL) continue;
if (con->flag & CONSTRAINT_DISABLE) continue;
+ /* these constraints can't be evaluated anyway */
+ if (cti->evaluate_constraint == NULL) continue;
/* influence == 0 should be ignored */
if (con->enforce == 0.0f) 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 */
+ /* influence of constraint
+ * - value should have been set from IPO's/Constraint Channels already
+ */
enf = con->enforce;
/* move owner matrix into right space */
constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace);
Mat4CpyMat4(oldmat, cob->matrix);
- /* get the target matrix - in right space to be used */
- ownerdata= ((cob->pchan)? (void *)cob->pchan : (void *)cob->ob);
- get_constraint_target_matrix(con, cob->type, ownerdata, tarmat, ctime);
-
-
- /* Special Hack for PyConstraints to be able to set settings on the owner and/or
- * target. Technically, this violates the design of constraints (as constraints should
- * only act on matrices to alter the final transform of an owner), but on the other
- * hand, this makes PyConstraints more powerful as it enables certain setups to be created
- * and work reliably.
- */
- if (con->type == CONSTRAINT_TYPE_PYTHON) {
- bPythonConstraint *pycon= (bPythonConstraint *)con->data;
+ /* prepare targets for constraint solving */
+ if (cti->get_constraint_targets) {
+ bConstraintTarget *ct;
+
+ /* get targets
+ * - constraints should use ct->matrix, not directly accessing values
+ * - ct->matrix members have not yet been calculated here!
+ */
+ cti->get_constraint_targets(con, &targets);
- /* as usual, the function for this is defined in BPY_interface.c */
- BPY_pyconstraint_driver(pycon, cob, pycon->tar, pycon->subtarget);
+ /* set matrices
+ * - calculate if possible, otherwise just initialise as identity matrix
+ */
+ if (cti->get_target_matrix) {
+ for (ct= targets.first; ct; ct= ct->next)
+ cti->get_target_matrix(con, cob, ct, ctime);
+ }
+ else {
+ for (ct= targets.first; ct; ct= ct->next)
+ Mat4One(ct->matrix);
+ }
}
/* Solve the constraint */
- evaluate_constraint(con, cob->matrix, tarmat);
+ cti->evaluate_constraint(con, cob, &targets);
+
+ /* clear targets after use
+ * - this should free temp targets but no data should be copied back
+ * as constraints may have done some nasty things to it...
+ */
+ if (cti->flush_constraint_targets) {
+ cti->flush_constraint_targets(con, &targets, 1);
+ }
/* Interpolate the enforcement, to blend result of constraint into final owner transform */
/* 1. Remove effects of original matrix from constraint solution ==> delta */
@@ -2904,7 +3381,7 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime)
/* 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 */
+ /* move 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/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index eb651a925e0..fc7e6d61f8a 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -368,27 +368,34 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int
if (ob->pose){
bPoseChannel *pchan;
bConstraint *con;
- Object * target;
- char *subtarget;
- for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next){
- for (con = pchan->constraints.first; con; con=con->next){
- if (constraint_has_target(con)) {
+ for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+ for (con = pchan->constraints.first; con; con=con->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
- target = get_constraint_target(con, &subtarget);
- if (target!=ob) {
- // fprintf(stderr,"armature %s target :%s \n", ob->id.name, target->id.name);
- node3 = dag_get_node(dag, target);
-
- if(subtarget && subtarget[0])
- dag_add_relation(dag,node3,node, DAG_RL_OB_DATA|DAG_RL_DATA_DATA);
- else if(ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO))
- dag_add_relation(dag,node3,node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA);
- else
- dag_add_relation(dag,node3,node, DAG_RL_OB_DATA);
-
+ for (ct= targets.first; ct; ct= ct->next) {
+ if (ct->tar != ob) {
+ // fprintf(stderr,"armature %s target :%s \n", ob->id.name, target->id.name);
+ node3 = dag_get_node(dag, ct->tar);
+
+ if (ct->subtarget[0])
+ dag_add_relation(dag,node3,node, DAG_RL_OB_DATA|DAG_RL_DATA_DATA);
+ else if(ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO))
+ dag_add_relation(dag,node3,node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA);
+ else
+ dag_add_relation(dag,node3,node, DAG_RL_OB_DATA);
+ }
}
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 1);
}
+
}
}
}
@@ -581,20 +588,35 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int
}
for (con = ob->constraints.first; con; con=con->next) {
- if (constraint_has_target(con)) {
- char *str;
- Object *obt= get_constraint_target(con, &str);
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
- node2 = dag_get_node(dag, obt);
- if(ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO))
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB);
- else {
- if(ELEM3(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && str && str[0])
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB);
+ for (ct= targets.first; ct; ct= ct->next) {
+ Object *obt;
+
+ if (ct->tar)
+ obt= ct->tar;
else
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB);
+ continue;
+
+ node2 = dag_get_node(dag, obt);
+ if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO))
+ dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB);
+ else {
+ if (ELEM3(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0]))
+ dag_add_relation(dag, node2, node, DAG_RL_DATA_OB|DAG_RL_OB_OB);
+ else
+ dag_add_relation(dag, node2, node, DAG_RL_OB_OB);
+ }
+ addtoroot = 0;
}
- addtoroot = 0;
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 1);
}
}
@@ -1718,10 +1740,23 @@ static void dag_object_time_update_flags(Object *ob)
if(ob->ipo) ob->recalc |= OB_RECALC_OB;
else if(ob->constraints.first) {
bConstraint *con;
- for (con = ob->constraints.first; con; con=con->next){
- if (constraint_has_target(con)) {
- ob->recalc |= OB_RECALC_OB;
- break;
+ for (con = ob->constraints.first; con; con=con->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ if (ct->tar) {
+ ob->recalc |= OB_RECALC_OB;
+ break;
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 1);
}
}
}
@@ -2076,42 +2111,50 @@ void DAG_pose_sort(Object *ob)
dag_add_parent_relation(dag, node2, node, 0);
addtoroot = 0;
}
- for (con = pchan->constraints.first; con; con=con->next){
- if (constraint_has_target(con)) {
- char *subtarget;
- Object *target = get_constraint_target(con, &subtarget);
+ for (con = pchan->constraints.first; con; con=con->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
- if (target==ob && subtarget) {
- bPoseChannel *target= get_pose_channel(ob->pose, subtarget);
- if(target) {
- node2= dag_get_node(dag, target);
- dag_add_relation(dag, node2, node, 0);
- dag_add_parent_relation(dag, node2, node, 0);
-
- if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
- bKinematicConstraint *data = (bKinematicConstraint*)con->data;
- bPoseChannel *parchan;
- int segcount= 0;
+ for (ct= targets.first; ct; ct= ct->next) {
+ if (ct->tar==ob && ct->subtarget[0]) {
+ bPoseChannel *target= get_pose_channel(ob->pose, ct->subtarget);
+ if (target) {
+ node2= dag_get_node(dag, target);
+ dag_add_relation(dag, node2, node, 0);
+ dag_add_parent_relation(dag, node2, node, 0);
- /* exclude tip from chain? */
- if(!(data->flag & CONSTRAINT_IK_TIP))
- parchan= pchan->parent;
- else
- parchan= pchan;
-
- /* Walk to the chain's root */
- while (parchan){
- node3= dag_get_node(dag, parchan);
- dag_add_relation(dag, node2, node3, 0);
- dag_add_parent_relation(dag, node2, node3, 0);
+ if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
+ bKinematicConstraint *data = (bKinematicConstraint *)con->data;
+ bPoseChannel *parchan;
+ int segcount= 0;
- segcount++;
- if(segcount==data->rootbone || segcount>255) break; // 255 is weak
- parchan= parchan->parent;
+ /* exclude tip from chain? */
+ if(!(data->flag & CONSTRAINT_IK_TIP))
+ parchan= pchan->parent;
+ else
+ parchan= pchan;
+
+ /* Walk to the chain's root */
+ while (parchan) {
+ node3= dag_get_node(dag, parchan);
+ dag_add_relation(dag, node2, node3, 0);
+ dag_add_parent_relation(dag, node2, node3, 0);
+
+ segcount++;
+ if (segcount==data->rootbone || segcount>255) break; // 255 is weak
+ parchan= parchan->parent;
+ }
}
}
}
}
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 1);
}
}
if (addtoroot == 1 ) {
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 20d61456f05..9f4c8f1607b 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -264,7 +264,6 @@ void unlink_object(Object *ob)
bConstraint *con;
bActionStrip *strip;
int a;
- char *str;
unlink_controllers(&ob->controllers);
unlink_actuators(&ob->actuators);
@@ -313,9 +312,23 @@ void unlink_object(Object *ob)
bPoseChannel *pchan;
for(pchan= obt->pose->chanbase.first; pchan; pchan= pchan->next) {
for (con = pchan->constraints.first; con; con=con->next) {
- if(ob==get_constraint_target(con, &str)) {
- set_constraint_target(con, NULL, NULL);
- obt->recalc |= OB_RECALC_DATA;
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ if (ct->tar == ob) {
+ ct->tar = NULL;
+ strcpy(ct->subtarget, "");
+ obt->recalc |= OB_RECALC_DATA;
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
}
}
if(pchan->custom==ob)
@@ -326,9 +339,23 @@ void unlink_object(Object *ob)
sca_remove_ob_poin(obt, ob);
for (con = obt->constraints.first; con; con=con->next) {
- if(ob==get_constraint_target(con, &str)) {
- set_constraint_target(con, NULL, NULL);
- obt->recalc |= OB_RECALC_OB;
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ if (ct->tar == ob) {
+ ct->tar = NULL;
+ strcpy(ct->subtarget, "");
+ obt->recalc |= OB_RECALC_DATA;
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
}
}
@@ -925,11 +952,27 @@ static void copy_object_pose(Object *obn, Object *ob)
for (chan = obn->pose->chanbase.first; chan; chan=chan->next){
bConstraint *con;
- char *str;
+
chan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE);
- for(con= chan->constraints.first; con; con= con->next) {
- if(ob==get_constraint_target(con, &str))
- set_constraint_target(con, obn, NULL);
+
+ for (con= chan->constraints.first; con; con= con->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ if (ct->tar == ob) {
+ ct->tar = obn;
+ strcpy(ct->subtarget, "");
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
}
}
}
@@ -1606,7 +1649,7 @@ void where_is_object_time(Object *ob, float ctime)
if (ob->constraints.first) {
bConstraintOb *cob;
- cob= constraints_make_evalob(ob, NULL, TARGET_OBJECT);
+ cob= constraints_make_evalob(ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
/* constraints need ctime, not stime. Some call where_is_object_time and bsystem_time */
solve_constraints (&ob->constraints, cob, ctime);
@@ -1783,7 +1826,7 @@ for a lamp that is the child of another object */
if (ob->constraints.first) {
bConstraintOb *cob;
- cob= constraints_make_evalob(ob, NULL, TARGET_OBJECT);
+ cob= constraints_make_evalob(ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
solve_constraints (&ob->constraints, cob, G.scene->r.cfra);
constraints_clear_evalob(cob);
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index d07f05ddab1..7b0cdedddf2 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1620,9 +1620,12 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
switch (con->type) {
case CONSTRAINT_TYPE_PYTHON:
{
- bPythonConstraint *data;
- data= (bPythonConstraint*)con->data;
- data->tar = newlibadr(fd, id->lib, data->tar);
+ bPythonConstraint *data= (bPythonConstraint*)con->data;
+ bConstraintTarget *ct;
+
+ for (ct= data->targets.first; ct; ct= ct->next)
+ ct->tar = newlibadr(fd, id->lib, ct->tar);
+
data->text = newlibadr(fd, id->lib, data->text);
//IDP_LibLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
@@ -5257,7 +5260,9 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
if (ob->track){
bConstraint *con;
+ bConstraintTypeInfo *cti;
bTrackToConstraint *data;
+ void *cdata;
list = &ob->constraints;
if (list)
@@ -5268,9 +5273,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
con->flag |= CONSTRAINT_EXPAND;
con->enforce=1.0F;
con->type = CONSTRAINT_TYPE_TRACKTO;
- data = (bTrackToConstraint *)
- new_constraint_data(CONSTRAINT_TYPE_TRACKTO);
-
+
+ cti= get_constraint_typeinfo(CONSTRAINT_TYPE_TRACKTO);
+ cdata= MEM_callocN(cti->size, cti->structName);
+ cti->new_data(cdata);
+ data = (bTrackToConstraint *)cdata;
+
data->tar = ob->track;
data->reserved1 = ob->trackflag;
data->reserved2 = ob->upflag;
@@ -5279,7 +5287,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
ob->track = 0;
}
-
+
ob = ob->id.next;
}
@@ -6757,14 +6765,16 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
bArmature *arm;
ModifierData *md;
Object *ob;
-
+
for(arm= main->armature.first; arm; arm= arm->id.next)
arm->deformflag |= ARM_DEF_B_BONE_REST;
-
- for(ob = main->object.first; ob; ob= ob->id.next)
- for(md=ob->modifiers.first; md; md=md->next)
+
+ for(ob = main->object.first; ob; ob= ob->id.next) {
+ for(md=ob->modifiers.first; md; md=md->next) {
if(md->type==eModifierType_Armature)
((ArmatureModifierData*)md)->deformflag |= ARM_DEF_B_BONE_REST;
+ }
+ }
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 5)) {
@@ -6785,6 +6795,61 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
}
+
+ if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 7)) {
+ Object *ob;
+ bPoseChannel *pchan;
+ bConstraint *con;
+ bConstraintTarget *ct;
+
+ for(ob = main->object.first; ob; ob= ob->id.next) {
+ if(ob->pose) {
+ for(pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+ for(con=pchan->constraints.first; con; con=con->next) {
+ if(con->type==CONSTRAINT_TYPE_PYTHON) {
+ bPythonConstraint *data= (bPythonConstraint *)con->data;
+ if (data->tar) {
+ /* version patching needs to be done */
+ ct= MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
+
+ ct->tar = data->tar;
+ strcpy(ct->subtarget, data->subtarget);
+ ct->space = con->tarspace;
+
+ BLI_addtail(&data->targets, ct);
+ data->tarnum++;
+
+ /* clear old targets to avoid problems */
+ data->tar = NULL;
+ strcpy(data->subtarget, "");
+ }
+ }
+ }
+ }
+ }
+
+ for(con=ob->constraints.first; con; con=con->next) {
+ if(con->type==CONSTRAINT_TYPE_PYTHON) {
+ bPythonConstraint *data= (bPythonConstraint *)con->data;
+ if (data->tar) {
+ /* version patching needs to be done */
+ ct= MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
+
+ ct->tar = data->tar;
+ strcpy(ct->subtarget, data->subtarget);
+ ct->space = con->tarspace;
+
+ BLI_addtail(&data->targets, ct);
+ data->tarnum++;
+
+ /* clear old targets to avoid problems */
+ data->tar = NULL;
+ strcpy(data->subtarget, "");
+ }
+ }
+ }
+ }
+ }
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
@@ -7185,7 +7250,11 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
case CONSTRAINT_TYPE_PYTHON:
{
bPythonConstraint *data = (bPythonConstraint*)curcon->data;
- expand_doit(fd, mainvar, data->tar);
+ bConstraintTarget *ct;
+
+ for (ct= data->targets.first; ct; ct= ct->next)
+ expand_doit(fd, mainvar, ct->tar);
+
expand_doit(fd, mainvar, data->text);
}
break;
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 4f09f51bc87..a059bf2a2c5 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -698,74 +698,27 @@ static void write_constraints(WriteData *wd, ListBase *conlist)
bConstraint *con;
for (con=conlist->first; con; con=con->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+
/* Write the specific data */
- switch (con->type) {
- case CONSTRAINT_TYPE_NULL:
- break;
- case CONSTRAINT_TYPE_PYTHON:
- {
- bPythonConstraint *data = (bPythonConstraint*) con->data;
- writestruct(wd, DATA, "bPythonConstraint", 1, data);
-
- /* Write ID Properties -- and copy this comment EXACTLY for easy finding
- of library blocks that implement this.*/
- IDP_WriteProperty(data->prop, wd);
+ if (cti && con->data) {
+ /* firstly, just write the plain con->data struct */
+ writestruct(wd, DATA, cti->structName, 1, con->data);
+
+ /* do any constraint specific stuff */
+ switch (con->type) {
+ case CONSTRAINT_TYPE_PYTHON:
+ {
+ bPythonConstraint *data = (bPythonConstraint*) con->data;
+
+ /* Write ID Properties -- and copy this comment EXACTLY for easy finding
+ of library blocks that implement this.*/
+ IDP_WriteProperty(data->prop, wd);
+ }
+ break;
}
- 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;
- case CONSTRAINT_TYPE_KINEMATIC:
- writestruct(wd, DATA, "bKinematicConstraint", 1, con->data);
- break;
- case CONSTRAINT_TYPE_ROTLIKE:
- writestruct(wd, DATA, "bRotateLikeConstraint", 1, con->data);
- break;
- case CONSTRAINT_TYPE_LOCLIKE:
- writestruct(wd, DATA, "bLocateLikeConstraint", 1, con->data);
- break;
- case CONSTRAINT_TYPE_SIZELIKE:
- writestruct(wd, DATA, "bSizeLikeConstraint", 1, con->data);
- break;
- case CONSTRAINT_TYPE_ACTION:
- writestruct(wd, DATA, "bActionConstraint", 1, con->data);
- break;
- case CONSTRAINT_TYPE_LOCKTRACK:
- writestruct(wd, DATA, "bLockTrackConstraint", 1, con->data);
- break;
- case CONSTRAINT_TYPE_FOLLOWPATH:
- writestruct(wd, DATA, "bFollowPathConstraint", 1, con->data);
- break;
- case CONSTRAINT_TYPE_STRETCHTO:
- writestruct(wd, DATA, "bStretchToConstraint", 1, con->data);
- break;
- case CONSTRAINT_TYPE_MINMAX:
- writestruct(wd, DATA, "bMinMaxConstraint", 1, con->data);
- break;
- case CONSTRAINT_TYPE_LOCLIMIT:
- writestruct(wd, DATA, "bLocLimitConstraint", 1, con->data);
- break;
- case CONSTRAINT_TYPE_ROTLIMIT:
- writestruct(wd, DATA, "bRotLimitConstraint", 1, con->data);
- break;
- case CONSTRAINT_TYPE_SIZELIMIT:
- writestruct(wd, DATA, "bSizeLimitConstraint", 1, con->data);
- break;
- case CONSTRAINT_TYPE_RIGIDBODYJOINT:
- writestruct(wd, DATA, "bRigidBodyJointConstraint", 1, con->data);
- break;
- case CONSTRAINT_TYPE_CLAMPTO:
- writestruct(wd, DATA, "bClampToConstraint", 1, con->data);
- break;
- case CONSTRAINT_TYPE_TRANSFORM:
- writestruct(wd, DATA, "bTransformConstraint", 1, con->data);
- break;
- default:
- break;
}
+
/* Write the constraint */
writestruct(wd, DATA, "bConstraint", 1, con);
}
@@ -819,12 +772,12 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
for (md=modbase->first; md; md= md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (mti == NULL) return;
-
+
writestruct(wd, DATA, mti->structName, 1, md);
-
+
if (md->type==eModifierType_Hook) {
HookModifierData *hmd = (HookModifierData*) md;
-
+
writedata(wd, DATA, sizeof(int)*hmd->totindex, hmd->indexar);
}
}
diff --git a/source/blender/include/BIF_editconstraint.h b/source/blender/include/BIF_editconstraint.h
index f9ed4048fc7..47f20f2f879 100644
--- a/source/blender/include/BIF_editconstraint.h
+++ b/source/blender/include/BIF_editconstraint.h
@@ -61,9 +61,10 @@ char *get_con_subtarget_name(struct bConstraint *con, struct Object *target);
void rename_constraint(struct Object *ob, struct bConstraint *con, char *newname);
-/* two special functions for PyConstraints */
+/* a few special functions for PyConstraints */
char *buildmenu_pyconstraints(struct Text *con_text, int *pyconindex);
void validate_pyconstraint_cb(void *arg1, void *arg2);
+void update_pyconstraint_cb(void *arg1, void *arg2);
/* two special functions for ChildOf Constriant */
void childof_const_setinv (void *conv, void *unused);
diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h
index 4f09ad716d7..4806b23bd57 100644
--- a/source/blender/include/butspace.h
+++ b/source/blender/include/butspace.h
@@ -86,7 +86,6 @@ extern int mod_moveDown(void *ob_v, void *md_v);
extern void const_moveUp(void *ob_v, void *con_v);
extern void const_moveDown(void *ob_v, void *con_v);
extern void del_constr_func (void *ob_v, void *con_v);
-extern void get_constraint_typestring(char *str, void *con_v);
extern void get_constraint_ipo_context(void *ob_v, char *actname);
/* editing */
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index fcde95371ac..e06063a11a1 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -36,13 +36,11 @@
#include "DNA_ID.h"
#include "DNA_ipo_types.h"
+#include "DNA_listBase.h"
#include "DNA_object_types.h"
struct Action;
struct Text;
-#ifndef __cplusplus
-struct PyObject;
-#endif
/* channels reside in Object or Action (ListBase) constraintChannels */
typedef struct bConstraintChannel {
@@ -55,29 +53,67 @@ typedef struct bConstraintChannel {
/* A Constraint */
typedef struct bConstraint {
struct bConstraint *next, *prev;
+
void *data; /* Constraint data (a valid constraint type) */
short type; /* Constraint type */
short flag; /* Flag - General Settings */
char ownspace; /* Space that owner should be evaluated in */
- char tarspace; /* Space that target should be evaluated in */
+ char tarspace; /* Space that target should be evaluated in (only used if 1 target) */
- char name[30]; /* Constraint name */
+ char name[30]; /* Constraint name */
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) */
- char subtarget[32]; /* bone to use as subtarget (if required) */
+/* Multiple-target constraints --------------------- */
+
+/* This struct defines a constraint target.
+ * It is used during constraint solving regardless of how many targets the
+ * constraint has.
+ */
+typedef struct bConstraintTarget {
+ struct bConstraintTarget *next, *prev;
+
+ Object *tar; /* object to use as target */
+ char subtarget[32]; /* subtarget - pchan or vgroup name */
+
+ float matrix[4][4]; /* matrix used during constraint solving - should be cleared before each use */
+ short space; /* space that target should be evaluated in (overrides bConstraint->tarspace) */
+ short flag; /* runtime settings (for editor, etc.) */
+ short type; /* type of target (B_CONSTRAINT_OB_TYPE) */
+ short pad;
+} bConstraintTarget;
+
+/* bConstraintTarget -> flag */
+typedef enum B_CONSTRAINT_TARGET_FLAG {
+ CONSTRAINT_TAR_TEMP = (1<<0), /* temporary target-struct that needs to be freed after use */
+} B_CONSTRAINT_TARGET_FLAG;
+
+/* bConstraintTarget/bConstraintOb -> type */
+typedef enum B_CONSTRAINT_OB_TYPE {
+ CONSTRAINT_OBTYPE_OBJECT = 1, /* string is "" */
+ CONSTRAINT_OBTYPE_BONE, /* string is bone-name */
+ CONSTRAINT_OBTYPE_VERT, /* string is vertex-group name */
+ CONSTRAINT_OBTYPE_CV /* string is vertex-group name - is not available until curves get vgroups */
+} B_CONSTRAINT_OB_TYPE;
+
+
+
+/* Python Script Constraint */
+typedef struct bPythonConstraint {
struct Text *text; /* text-buffer (containing script) to execute */
IDProperty *prop; /* 'id-properties' used to store custom properties for constraint */
int flag; /* general settings/state indicators accessed by bitmapping */
- int pad;
+ int tarnum; /* number of targets - usually only 1-3 are needed */
+
+ ListBase targets; /* a list of targets that this constraint has (bConstraintTarget-s) */
+
+ Object *tar; /* target from previous implementation (version-patch sets this to NULL on file-load) */
+ char subtarget[32]; /* subtarger from previous implentation (version-patch sets this to "" on file-load) */
} bPythonConstraint;
/* Single-target subobject constraints --------------------- */
@@ -125,10 +161,10 @@ typedef struct bLocateLikeConstraint {
typedef struct bMinMaxConstraint {
Object *tar;
int minmaxflag;
- float offset;
- int flag;
- short sticky, stuck, pad1, pad2; /* for backward compatability */
- float cache[3];
+ float offset;
+ int flag;
+ short sticky, stuck, pad1, pad2; /* for backward compatability */
+ float cache[3];
char subtarget[32];
} bMinMaxConstraint;
@@ -143,13 +179,13 @@ typedef struct bSizeLikeConstraint {
/* Action Constraint */
typedef struct bActionConstraint {
Object *tar;
- short type;
+ short type; /* what transform 'channel' drives the result */
short local; /* was used in versions prior to the Constraints recode */
- int start;
- int end;
+ int start;
+ int end;
float min;
float max;
- int pad;
+ int pad;
struct bAction *act;
char subtarget[32];
} bActionConstraint;
@@ -261,53 +297,73 @@ typedef struct bSizeLimitConstraint {
short pad1;
} bSizeLimitConstraint;
-/* bConstraint.type */
-#define CONSTRAINT_TYPE_NULL 0
-#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
-#define CONSTRAINT_TYPE_ROTLIMIT 5 /* Unimplemented no longer :) - Aligorith */
-#define CONSTRAINT_TYPE_LOCLIMIT 6 /* Unimplemented no longer :) - Aligorith */
-#define CONSTRAINT_TYPE_SIZELIMIT 7 /* Unimplemented no longer :) - Aligorith */
-#define CONSTRAINT_TYPE_ROTLIKE 8
-#define CONSTRAINT_TYPE_LOCLIKE 9
-#define CONSTRAINT_TYPE_SIZELIKE 10
-#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 /* 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 */
-#define CONSTRAINT_TYPE_CLAMPTO 18 /* clampto constraint */
-#define CONSTRAINT_TYPE_TRANSFORM 19 /* transformation constraint */
+/* ------------------------------------------ */
+
+/* bConstraint->type
+ * - Do not ever change the order of these, or else files could get
+ * broken as their correct value cannot be resolved
+ */
+typedef enum B_CONSTAINT_TYPES {
+ CONSTRAINT_TYPE_NULL = 0, /* Invalid/legacy constraint */
+ CONSTRAINT_TYPE_CHILDOF, /* Unimplemented non longer :) - during constraints recode, Aligorith */
+ CONSTRAINT_TYPE_TRACKTO,
+ CONSTRAINT_TYPE_KINEMATIC,
+ CONSTRAINT_TYPE_FOLLOWPATH,
+ CONSTRAINT_TYPE_ROTLIMIT, /* Unimplemented no longer :) - Aligorith */
+ CONSTRAINT_TYPE_LOCLIMIT, /* Unimplemented no longer :) - Aligorith */
+ CONSTRAINT_TYPE_SIZELIMIT, /* Unimplemented no longer :) - Aligorith */
+ CONSTRAINT_TYPE_ROTLIKE,
+ CONSTRAINT_TYPE_LOCLIKE,
+ CONSTRAINT_TYPE_SIZELIKE,
+ CONSTRAINT_TYPE_PYTHON, /* Unimplemented no longer :) - Aligorith. Scripts */
+ CONSTRAINT_TYPE_ACTION,
+ CONSTRAINT_TYPE_LOCKTRACK, /* New Tracking constraint that locks an axis in place - theeth */
+ CONSTRAINT_TYPE_DISTANCELIMIT, /* was never properly coded - removed! */
+ CONSTRAINT_TYPE_STRETCHTO, /* claiming this to be mine :) is in tuhopuu bjornmose */
+ CONSTRAINT_TYPE_MINMAX, /* floor constraint */
+ CONSTRAINT_TYPE_RIGIDBODYJOINT, /* rigidbody constraint */
+ CONSTRAINT_TYPE_CLAMPTO, /* clampto constraint */
+ CONSTRAINT_TYPE_TRANSFORM, /* transformation (loc/rot/size -> loc/rot/size) constraint */
+
+ /* NOTE: everytime a new constraint is added, update this */
+ NUM_CONSTRAINT_TYPES= CONSTRAINT_TYPE_TRANSFORM
+} B_CONSTRAINT_TYPES;
/* bConstraint->flag */
+/* flags 0x2 (1<<1) and 0x8 (1<<3) were used in past */
+/* flag 0x20 (1<<5) was used to indicate that a constraint was evaluated using a 'local' hack for posebones only */
+typedef enum B_CONSTRAINT_FLAG {
/* expand for UI */
-#define CONSTRAINT_EXPAND 0x01
+ CONSTRAINT_EXPAND = (1<<0),
/* pre-check for illegal object name or bone name */
-#define CONSTRAINT_DISABLE 0x04
- /* 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
- /* flag 0x20 was used to indicate that a constraint was evaluated using a 'local' hack for posebones only */
+ CONSTRAINT_DISABLE = (1<<2),
+ /* to indicate which Ipo should be shown, maybe for 3d access later too */
+ CONSTRAINT_ACTIVE = (1<<4),
/* to indicate that the owner's space should only be changed into ownspace, but not out of it */
-#define CONSTRAINT_SPACEONCE 0x40
+ CONSTRAINT_SPACEONCE = (1<<6)
+} B_CONSTRAINT_FLAG;
/* 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
+typedef enum B_CONSTRAINT_SPACETYPES {
+ /* default for all - worldspace */
+ CONSTRAINT_SPACE_WORLD = 0,
+ /* for objects (relative to parent/without parent influence),
+ * for bones (along normals of bone, without parent/restpositions)
+ */
+ CONSTRAINT_SPACE_LOCAL,
+ /* for posechannels - pose space */
+ CONSTRAINT_SPACE_POSE,
+ /* for posechannels - local with parent */
+ CONSTRAINT_SPACE_PARLOCAL,
+} B_CONSTRAINT_SPACETYPES;
/* bConstraintChannel.flag */
-#define CONSTRAINT_CHANNEL_SELECT 0x01
-#define CONSTRAINT_CHANNEL_PROTECTED 0x02
+typedef enum B_CONSTRAINTCHANNEL_FLAG {
+ CONSTRAINT_CHANNEL_SELECT = (1<<0),
+ CONSTRAINT_CHANNEL_PROTECTED = (1<<1)
+} B_CONSTRAINTCHANNEL_FLAG;
+
+/* -------------------------------------- */
/**
* The flags for ROTLIKE, LOCLIKE and SIZELIKE should be kept identical
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h
index 0e662c38d31..e4986727ab1 100644
--- a/source/blender/python/BPY_extern.h
+++ b/source/blender/python/BPY_extern.h
@@ -46,8 +46,10 @@ struct SpaceScript; /* DNA_space_types.h */
struct Script; /* BPI_script.h */
struct ScrArea; /* DNA_screen_types.h */
struct bScreen; /* DNA_screen_types.h */
+struct bConstraint; /* DNA_constraint_types.h */
struct bPythonConstraint; /* DNA_constraint_types.h */
-struct bConstraintOb; /* BKE_constraint.h */
+struct bConstraintOb; /* DNA_constraint_types.h */
+struct bConstraintTarget; /* DNA_constraint_types.h*/
#ifdef __cplusplus
extern "C" {
#endif
@@ -71,10 +73,10 @@ extern "C" {
void BPy_Set_DrawButtonsList(void *list);
void BPy_Free_DrawButtonsList(void);
- void BPY_pyconstraint_eval(struct bPythonConstraint *con, float ownermat[][4], float targetmat[][4]);
- void BPY_pyconstraint_driver(struct bPythonConstraint *con, struct bConstraintOb *cob, struct Object *target, char subtarget[]);
+ void BPY_pyconstraint_eval(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets);
void BPY_pyconstraint_settings(void *arg1, void *arg2);
- int BPY_pyconstraint_targets(struct bPythonConstraint *con, float targetmat[][4]);
+ void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTarget *ct);
+ void BPY_pyconstraint_update(struct Object *owner, struct bConstraint *con);
int BPY_is_pyconstraint(struct Text *text);
void BPY_start_python( int argc, char **argv );
diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c
index 9fbd1d9a204..27cfc2fa11c 100644
--- a/source/blender/python/BPY_interface.c
+++ b/source/blender/python/BPY_interface.c
@@ -45,6 +45,7 @@
#include "BKE_object.h" /* during_scriptlink() */
#include "BKE_text.h"
#include "BKE_constraint.h" /* for bConstraintOb */
+#include "BKE_idprop.h"
#include "DNA_curve_types.h" /* for struct IpoDriver */
#include "DNA_ID.h" /* ipo driver */
@@ -59,6 +60,7 @@
#include "BPI_script.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "BKE_armature.h"
#include "api2_2x/EXPP_interface.h"
#include "api2_2x/constant.h"
#include "api2_2x/gen_utils.h"
@@ -1157,13 +1159,16 @@ static float pydriver_error(IpoDriver *driver) {
/********PyConstraints*********/
+/* This function checks whether a text-buffer is a PyConstraint candidate.
+ * It uses simple text parsing that could be easily confused!
+ */
int BPY_is_pyconstraint(Text *text)
{
TextLine *tline = text->lines.first;
if (tline && (tline->len > 10)) {
char *line = tline->line;
-
+
/* Expected format: #BPYCONSTRAINT
* The actual checks are forgiving, so slight variations also work. */
if (line && line[0] == '#' && strstr(line, "BPYCONSTRAINT")) return 1;
@@ -1171,26 +1176,138 @@ int BPY_is_pyconstraint(Text *text)
return 0;
}
+/* This function is called to update PyConstraint data so that it is compatible with the script.
+ * Some of the allocating/freeing of memory for constraint targets occurs here, espcially
+ * if the number of targets changes.
+ */
+void BPY_pyconstraint_update(Object *owner, bConstraint *con)
+{
+ bPythonConstraint *data= con->data;
+
+ if (data->text) {
+ /* script does exist. it is assumed that this is a valid pyconstraint script */
+ PyObject *globals;
+ PyObject *retval, *gval;
+ int num;
+
+ /* clear the flag first */
+ data->flag = 0;
+
+ /* populate globals dictionary */
+ globals = CreateGlobalDictionary();
+ retval = RunPython(data->text, globals);
+
+ if (retval == NULL) {
+ BPY_Err_Handle(data->text->id.name);
+ ReleaseGlobalDictionary(globals);
+ data->flag |= PYCON_SCRIPTERROR;
+ return;
+ }
+
+ Py_XDECREF(retval);
+ retval = NULL;
+
+ /* try to find NUM_TARGETS */
+ gval = PyDict_GetItemString(globals, "NUM_TARGETS");
+ if ( (gval) && (num= PyInt_AsLong(gval)) ) {
+ /* NUM_TARGETS is defined... and non-zero */
+ bConstraintTarget *ct;
+
+ /* check if it is valid (just make sure it is not negative)
+ * TODO: PyInt_AsLong may return -1 as sign of invalid input...
+ */
+ num = abs(num);
+ data->flag |= PYCON_USETARGETS;
+
+ /* check if the number of targets has changed */
+ if (num < data->tarnum) {
+ /* free a few targets */
+ for (ct=data->targets.last; num > -1; num--, ct=data->targets.last, data->tarnum--)
+ BLI_freelinkN(&data->targets, ct);
+ }
+ else if (num > data->tarnum) {
+ /* add a few targets */
+ for ( ; num > -1; num--, data->tarnum++) {
+ ct= MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
+ BLI_addtail(&data->targets, ct);
+ }
+ }
+
+ /* validate targets */
+ for (ct= data->targets.first; ct; ct= ct->next) {
+ if (!exist_object(ct->tar)) {
+ ct->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ break;
+ }
+
+ if ( (ct->tar == owner) &&
+ (!get_named_bone(get_armature(owner), ct->subtarget)) )
+ {
+ con->flag |= CONSTRAINT_DISABLE;
+ break;
+ }
+ }
+
+ /* clear globals */
+ ReleaseGlobalDictionary(globals);
+ }
+ else {
+ /* NUM_TARGETS is not defined or equals 0 */
+ ReleaseGlobalDictionary(globals);
+
+ /* free all targets */
+ BLI_freelistN(&data->targets);
+ data->tarnum = 0;
+ data->flag &= ~PYCON_USETARGETS;
+
+ return;
+ }
+ }
+ else {
+ /* no script, so clear any settings/data now */
+ data->tarnum = 0;
+ data->flag = 0;
+
+ BLI_freelistN(&data->targets);
+
+ /* supposedly this should still leave the base struct... */
+ IDP_FreeProperty(data->prop);
+ }
+}
+
/* PyConstraints Evaluation Function (only called from evaluate_constraint)
* This function is responsible for modifying the ownermat that it is passed.
*/
-void BPY_pyconstraint_eval(bPythonConstraint *con, float ownermat[][4], float targetmat[][4])
+void BPY_pyconstraint_eval(bPythonConstraint *con, bConstraintOb *cob, ListBase *targets)
{
- PyObject *srcmat, *tarmat, *idprop;
+ PyObject *srcmat, *tarmat, *tarmats, *idprop;
PyObject *globals;
PyObject *gval;
PyObject *pyargs, *retval;
+ bConstraintTarget *ct;
MatrixObject *retmat;
- int row, col;
+ int row, col, index;
- if ( !con->text ) return;
- if ( con->flag & PYCON_SCRIPTERROR) return;
+ if (!con->text) return;
+ if (con->flag & PYCON_SCRIPTERROR) return;
globals = CreateGlobalDictionary();
- srcmat = newMatrixObject( (float*)ownermat, 4, 4, Py_NEW );
- tarmat = newMatrixObject( (float*)targetmat, 4, 4, Py_NEW );
- idprop = BPy_Wrap_IDProperty( NULL, con->prop, NULL);
+ /* wrap blender-data as PyObjects for evaluation
+ * - we expose the owner's matrix as pymatrix
+ * - id-properties are wrapped using the id-properties pyapi
+ * - targets are presented as a list of matrices
+ */
+ srcmat = newMatrixObject((float *)cob->matrix, 4, 4, Py_NEW);
+ idprop = BPy_Wrap_IDProperty(NULL, con->prop, NULL);
+
+ tarmats= PyList_New(con->tarnum);
+ for (ct=targets->first, index=0; ct; ct=ct->next, index++) {
+ tarmat = newMatrixObject((float *)ct->matrix, 4, 4, Py_NEW);
+ PyList_SetItem(tarmats, index, tarmat);
+ }
+
/* since I can't remember what the armature weakrefs do, I'll just leave this here
commented out. This function was based on pydrivers, and it might still be relevent.
@@ -1199,17 +1316,20 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, float ownermat[][4], float ta
return result;
}
*/
- retval = RunPython( con->text, globals );
-
- if ( retval == NULL ) {
+
+ retval = RunPython(con->text, globals);
+
+ if (retval == NULL) {
BPY_Err_Handle(con->text->id.name);
- ReleaseGlobalDictionary( globals );
con->flag |= PYCON_SCRIPTERROR;
-
+
/* free temp objects */
- Py_XDECREF( idprop );
- Py_XDECREF( srcmat );
- Py_XDECREF( tarmat );
+ Py_XDECREF(idprop);
+ Py_XDECREF(srcmat);
+ Py_XDECREF(tarmats);
+
+ ReleaseGlobalDictionary(globals);
+
return;
}
@@ -1218,29 +1338,34 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, float ownermat[][4], float ta
gval = PyDict_GetItemString(globals, "doConstraint");
if (!gval) {
- ReleaseGlobalDictionary( globals );
-
- /* free temp objects */
- Py_XDECREF( idprop );
- Py_XDECREF( srcmat );
- Py_XDECREF( tarmat );
printf("ERROR: no doConstraint function in constraint!\n");
+
+ /* free temp objects */
+ Py_XDECREF(idprop);
+ Py_XDECREF(srcmat);
+ Py_XDECREF(tarmats);
+
+ ReleaseGlobalDictionary(globals);
+
return;
}
/* Now for the fun part! Try and find the functions we need. */
- if (PyFunction_Check(gval) ) {
- pyargs = Py_BuildValue("OOO", srcmat, tarmat, idprop);
+ if (PyFunction_Check(gval)) {
+ pyargs = Py_BuildValue("OOO", srcmat, tarmats, idprop);
retval = PyObject_CallObject(gval, pyargs);
- Py_XDECREF( pyargs );
- } else {
+ Py_XDECREF(pyargs);
+ }
+ else {
printf("ERROR: doConstraint is supposed to be a function!\n");
con->flag |= PYCON_SCRIPTERROR;
- ReleaseGlobalDictionary( globals );
- Py_XDECREF( idprop );
- Py_XDECREF( srcmat );
- Py_XDECREF( tarmat );
+ Py_XDECREF(idprop);
+ Py_XDECREF(srcmat);
+ Py_XDECREF(tarmats);
+
+ ReleaseGlobalDictionary(globals);
+
return;
}
@@ -1249,11 +1374,12 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, float ownermat[][4], float ta
con->flag |= PYCON_SCRIPTERROR;
/* free temp objects */
- ReleaseGlobalDictionary( globals );
+ Py_XDECREF(idprop);
+ Py_XDECREF(srcmat);
+ Py_XDECREF(tarmats);
+
+ ReleaseGlobalDictionary(globals);
- Py_XDECREF( idprop );
- Py_XDECREF( srcmat );
- Py_XDECREF( tarmat );
return;
}
@@ -1261,177 +1387,78 @@ void BPY_pyconstraint_eval(bPythonConstraint *con, float ownermat[][4], float ta
if (!PyObject_TypeCheck(retval, &matrix_Type)) {
printf("Error in PyConstraint - doConstraint: Function not returning a matrix!\n");
con->flag |= PYCON_SCRIPTERROR;
- ReleaseGlobalDictionary( globals );
- Py_XDECREF( idprop );
- Py_XDECREF( srcmat );
- Py_XDECREF( tarmat );
- Py_XDECREF( retval );
+ Py_XDECREF(idprop);
+ Py_XDECREF(srcmat);
+ Py_XDECREF(tarmats);
+ Py_XDECREF(retval);
+
+ ReleaseGlobalDictionary(globals);
+
return;
}
- retmat = (MatrixObject*) retval;
+ retmat = (MatrixObject *)retval;
if (retmat->rowSize != 4 || retmat->colSize != 4) {
printf("Error in PyConstraint - doConstraint: Matrix returned is the wrong size!\n");
con->flag |= PYCON_SCRIPTERROR;
- ReleaseGlobalDictionary( globals );
- Py_XDECREF( idprop );
- Py_XDECREF( srcmat );
- Py_XDECREF( tarmat );
- Py_XDECREF( retval );
+ Py_XDECREF(idprop);
+ Py_XDECREF(srcmat);
+ Py_XDECREF(tarmats);
+ Py_XDECREF(retval);
+
+ ReleaseGlobalDictionary(globals);
+
return;
}
/* this is the reverse of code taken from newMatrix() */
for(row = 0; row < 4; row++) {
for(col = 0; col < 4; col++) {
- ownermat[row][col] = retmat->contigPtr[row*4+col];
+ cob->matrix[row][col] = retmat->contigPtr[row*4+col];
}
}
- /* clear globals */
- ReleaseGlobalDictionary( globals );
-
/* free temp objects */
- Py_XDECREF( idprop );
- Py_XDECREF( srcmat );
- Py_XDECREF( tarmat );
- Py_XDECREF( retval );
-}
-
-/* PyConstraints 'Driver' Function
- * This function is responsible for running any code that requires full access to the owner and the target
- * It should be used sparringly, and only for doing 'hacks' which are not possible any other way.
- */
-void BPY_pyconstraint_driver(bPythonConstraint *con, bConstraintOb *cob, Object *target, char subtarget[])
-{
- PyObject *owner, *subowner, *tar, *subtar;
- PyObject *idprop;
- PyObject *globals, *gval;
- PyObject *pyargs, *retval;
-
- if ( !con->text ) return;
- if ( con->flag & PYCON_SCRIPTERROR) return;
-
- globals = CreateGlobalDictionary();
-
- owner = Object_CreatePyObject( cob->ob );
- subowner = PyPoseBone_FromPosechannel( cob->pchan );
-
- tar = Object_CreatePyObject( target );
- if ( (target) && (target->type==OB_ARMATURE) ) {
- bPoseChannel *pchan;
- pchan = get_pose_channel( target->pose, subtarget );
- subtar = PyPoseBone_FromPosechannel( pchan );
- }
- else
- subtar = PyString_FromString(subtarget);
-
- idprop = BPy_Wrap_IDProperty( NULL, con->prop, NULL);
-
-/* since I can't remember what the armature weakrefs do, I'll just leave this here
- commented out. This function was based on pydrivers, and it might still be relevent.
- if( !setup_armature_weakrefs()){
- fprintf( stderr, "Oops - weakref dict setup\n");
- return result;
- }
-*/
- retval = RunPython( con->text, globals );
-
- if ( retval == NULL ) {
- BPY_Err_Handle(con->text->id.name);
- ReleaseGlobalDictionary( globals );
- con->flag |= PYCON_SCRIPTERROR;
-
- /* free temp objects */
- Py_XDECREF( idprop );
- Py_XDECREF( owner );
- Py_XDECREF( subowner );
- Py_XDECREF( tar );
- Py_XDECREF( subtar );
- return;
- }
-
- if (retval) {Py_XDECREF( retval );}
- retval = NULL;
-
- gval = PyDict_GetItemString(globals, "doDriver");
- if (!gval) {
- ReleaseGlobalDictionary( globals );
-
- /* free temp objects */
- Py_XDECREF( idprop );
- Py_XDECREF( owner );
- Py_XDECREF( subowner );
- Py_XDECREF( tar );
- Py_XDECREF( subtar );
- return;
- }
-
- /* Now for the fun part! Try and find the functions we need. */
- if (PyFunction_Check(gval) ) {
- pyargs = Py_BuildValue("OOOOO", owner, subowner, tar, subtar, idprop);
- retval = PyObject_CallObject(gval, pyargs);
- Py_XDECREF( pyargs );
- } else {
- printf("ERROR: doDriver is supposed to be a function!\n");
- con->flag |= PYCON_SCRIPTERROR;
- ReleaseGlobalDictionary( globals );
-
- Py_XDECREF( idprop );
- Py_XDECREF( owner );
- Py_XDECREF( subowner );
- Py_XDECREF( tar );
- Py_XDECREF( subtar );
- return;
- }
-
- /* an error occurred while running the function? */
- if (!retval) {
- BPY_Err_Handle(con->text->id.name);
- con->flag |= PYCON_SCRIPTERROR;
- }
+ Py_XDECREF(idprop);
+ Py_XDECREF(srcmat);
+ Py_XDECREF(tarmats);
+ Py_XDECREF(retval);
/* clear globals */
- ReleaseGlobalDictionary( globals );
-
- /* free temp objects */
- Py_XDECREF( idprop );
- Py_XDECREF( owner );
- Py_XDECREF( subowner );
- Py_XDECREF( tar );
- Py_XDECREF( subtar );
+ ReleaseGlobalDictionary(globals);
}
-/* This evaluates whether constraint uses targets, and also the target matrix
- * Return code of 0 = doesn't use targets, 1 = uses targets + matrix set, -1 = uses targets + matrix not set
+/* This evaluates the target matrix for each target the PyConstraint uses.
+ * NOTE: it only does one target at a time!
*/
-int BPY_pyconstraint_targets(bPythonConstraint *con, float targetmat[][4])
+void BPY_pyconstraint_target(bPythonConstraint *con, bConstraintTarget *ct)
{
PyObject *tar, *subtar;
PyObject *tarmat, *idprop;
PyObject *globals;
- PyObject *gval, *gval2;
+ PyObject *gval;
PyObject *pyargs, *retval;
MatrixObject *retmat;
int row, col;
- if ( !con->text ) return 0;
- if ( con->flag & PYCON_SCRIPTERROR) return 0;
+ if (!con->text) return;
+ if (con->flag & PYCON_SCRIPTERROR) return;
+ if (!ct) return;
globals = CreateGlobalDictionary();
- tar = Object_CreatePyObject( con->tar );
- if ( (con->tar) && (con->tar->type==OB_ARMATURE) ) {
+ tar = Object_CreatePyObject(ct->tar);
+ if ((ct->tar) && (ct->tar->type==OB_ARMATURE)) {
bPoseChannel *pchan;
- pchan = get_pose_channel( con->tar->pose, con->subtarget );
- subtar = PyPoseBone_FromPosechannel( pchan );
+ pchan = get_pose_channel(ct->tar->pose, ct->subtarget);
+ subtar = PyPoseBone_FromPosechannel(pchan);
}
else
- subtar = PyString_FromString(con->subtarget);
+ subtar = PyString_FromString(ct->subtarget);
- tarmat = newMatrixObject( (float*)targetmat, 4, 4, Py_NEW );
+ tarmat = newMatrixObject((float *)ct->matrix, 4, 4, Py_NEW);
idprop = BPy_Wrap_IDProperty( NULL, con->prop, NULL);
/* since I can't remember what the armature weakrefs do, I'll just leave this here
@@ -1441,123 +1468,118 @@ int BPY_pyconstraint_targets(bPythonConstraint *con, float targetmat[][4])
return result;
}
*/
- retval = RunPython( con->text, globals );
+ retval = RunPython(con->text, globals);
- if ( retval == NULL ) {
+ if (retval == NULL) {
BPY_Err_Handle(con->text->id.name);
- ReleaseGlobalDictionary( globals );
con->flag |= PYCON_SCRIPTERROR;
-
+
/* free temp objects */
- Py_XDECREF( tar );
- Py_XDECREF( subtar );
- Py_XDECREF( idprop );
- Py_XDECREF( tarmat );
- return 0;
+ Py_XDECREF(tar);
+ Py_XDECREF(subtar);
+ Py_XDECREF(idprop);
+ Py_XDECREF(tarmat);
+
+ ReleaseGlobalDictionary(globals);
+
+ return;
}
- Py_XDECREF( retval );
+ Py_XDECREF(retval);
retval = NULL;
- /* try to find USE_TARGET global constant */
- gval = PyDict_GetItemString(globals, "USE_TARGET");
- if (!gval || PyObject_IsTrue(gval) != 1) {
- ReleaseGlobalDictionary( globals );
-
- /* free temp objects */
- Py_XDECREF( tar );
- Py_XDECREF( subtar );
- Py_XDECREF( idprop );
- Py_XDECREF( tarmat );
- return 0;
- }
-
/* try to find doTarget function to set the target matrix */
- gval2 = PyDict_GetItemString(globals, "doTarget");
- if (!gval2) {
- ReleaseGlobalDictionary( globals );
-
+ gval = PyDict_GetItemString(globals, "doTarget");
+ if (!gval) {
/* free temp objects */
- Py_XDECREF( tar );
- Py_XDECREF( subtar );
- Py_XDECREF( idprop );
- Py_XDECREF( tarmat );
- return -1;
+ Py_XDECREF(tar);
+ Py_XDECREF(subtar);
+ Py_XDECREF(idprop);
+ Py_XDECREF(tarmat);
+
+ ReleaseGlobalDictionary(globals);
+
+ return;
}
/* Now for the fun part! Try and find the functions we need.*/
- if (PyFunction_Check(gval2) ) {
+ if (PyFunction_Check(gval)) {
pyargs = Py_BuildValue("OOOO", tar, subtar, tarmat, idprop);
- retval = PyObject_CallObject(gval2, pyargs);
- Py_XDECREF( pyargs );
- } else {
+ retval = PyObject_CallObject(gval, pyargs);
+ Py_XDECREF(pyargs);
+ }
+ else {
printf("ERROR: doTarget is supposed to be a function!\n");
con->flag |= PYCON_SCRIPTERROR;
- ReleaseGlobalDictionary( globals );
- Py_XDECREF( tar );
- Py_XDECREF( subtar );
- Py_XDECREF( idprop );
- Py_XDECREF( tarmat );
- return -1;
+ Py_XDECREF(tar);
+ Py_XDECREF(subtar);
+ Py_XDECREF(idprop);
+ Py_XDECREF(tarmat);
+
+ ReleaseGlobalDictionary(globals);
+ return;
}
if (!retval) {
BPY_Err_Handle(con->text->id.name);
con->flag |= PYCON_SCRIPTERROR;
+
/* free temp objects */
- ReleaseGlobalDictionary( globals );
+ Py_XDECREF(tar);
+ Py_XDECREF(subtar);
+ Py_XDECREF(idprop);
+ Py_XDECREF(tarmat);
- Py_XDECREF( tar );
- Py_XDECREF( subtar );
- Py_XDECREF( idprop );
- Py_XDECREF( tarmat );
- return -1;
+ ReleaseGlobalDictionary(globals);
+ return;
}
if (!PyObject_TypeCheck(retval, &matrix_Type)) {
- ReleaseGlobalDictionary( globals );
+ con->flag |= PYCON_SCRIPTERROR;
- Py_XDECREF( tar );
- Py_XDECREF( subtar );
- Py_XDECREF( idprop );
- Py_XDECREF( tarmat );
- Py_XDECREF( retval );
- return -1;
+ Py_XDECREF(tar);
+ Py_XDECREF(subtar);
+ Py_XDECREF(idprop);
+ Py_XDECREF(tarmat);
+ Py_XDECREF(retval);
+
+ ReleaseGlobalDictionary(globals);
+ return;
}
- retmat = (MatrixObject*) retval;
+ retmat = (MatrixObject *)retval;
if (retmat->rowSize != 4 || retmat->colSize != 4) {
printf("Error in PyConstraint - doTarget: Matrix returned is the wrong size!\n");
con->flag |= PYCON_SCRIPTERROR;
- ReleaseGlobalDictionary( globals );
- Py_XDECREF( tar );
- Py_XDECREF( subtar );
- Py_XDECREF( idprop );
- Py_XDECREF( tarmat );
- Py_XDECREF( retval );
- return -1;
+ Py_XDECREF(tar);
+ Py_XDECREF(subtar);
+ Py_XDECREF(idprop);
+ Py_XDECREF(tarmat);
+ Py_XDECREF(retval);
+
+ ReleaseGlobalDictionary(globals);
+ return;
}
/* this is the reverse of code taken from newMatrix() */
for(row = 0; row < 4; row++) {
for(col = 0; col < 4; col++) {
- targetmat[row][col] = retmat->contigPtr[row*4+col];
+ ct->matrix[row][col] = retmat->contigPtr[row*4+col];
}
}
- /* clear globals */
- ReleaseGlobalDictionary( globals );
-
/* free temp objects */
- Py_XDECREF( tar );
- Py_XDECREF( subtar );
- Py_XDECREF( idprop );
- Py_XDECREF( tarmat );
- Py_XDECREF( retval );
- return 1;
+ Py_XDECREF(tar);
+ Py_XDECREF(subtar);
+ Py_XDECREF(idprop);
+ Py_XDECREF(tarmat);
+ Py_XDECREF(retval);
+
+ /* clear globals */
+ ReleaseGlobalDictionary(globals);
}
/* This draws+handles the user-defined interface for editing pyconstraints idprops */
@@ -1569,22 +1591,22 @@ void BPY_pyconstraint_settings(void *arg1, void *arg2)
PyObject *gval;
PyObject *retval;
- if ( !con->text ) return;
- if ( con->flag & PYCON_SCRIPTERROR) return;
+ if (!con->text) return;
+ if (con->flag & PYCON_SCRIPTERROR) return;
globals = CreateGlobalDictionary();
idprop = BPy_Wrap_IDProperty( NULL, con->prop, NULL);
- retval = RunPython( con->text, globals );
+ retval = RunPython(con->text, globals);
- if ( retval == NULL ) {
+ if (retval == NULL) {
BPY_Err_Handle(con->text->id.name);
- ReleaseGlobalDictionary( globals );
+ ReleaseGlobalDictionary(globals);
con->flag |= PYCON_SCRIPTERROR;
/* free temp objects */
- Py_XDECREF( idprop );
+ Py_XDECREF(idprop);
return;
}
@@ -1597,18 +1619,19 @@ void BPY_pyconstraint_settings(void *arg1, void *arg2)
/* free temp objects */
ReleaseGlobalDictionary( globals );
- Py_XDECREF( idprop );
+ Py_XDECREF(idprop);
return;
}
/* Now for the fun part! Try and find the functions we need. */
- if (PyFunction_Check(gval) ) {
+ if (PyFunction_Check(gval)) {
retval = PyObject_CallFunction(gval, "O", idprop);
- } else {
+ }
+ else {
printf("ERROR: getSettings is supposed to be a function!\n");
ReleaseGlobalDictionary( globals );
- Py_XDECREF( idprop );
+ Py_XDECREF(idprop);
return;
}
@@ -1617,17 +1640,17 @@ void BPY_pyconstraint_settings(void *arg1, void *arg2)
con->flag |= PYCON_SCRIPTERROR;
/* free temp objects */
- ReleaseGlobalDictionary( globals );
- Py_XDECREF( idprop );
+ ReleaseGlobalDictionary(globals);
+ Py_XDECREF(idprop);
return;
}
else {
/* clear globals */
- ReleaseGlobalDictionary( globals );
+ ReleaseGlobalDictionary(globals);
/* free temp objects */
- Py_XDECREF( idprop );
- Py_DECREF( retval );
+ Py_XDECREF(idprop);
+ Py_DECREF(retval);
return;
}
}
diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c
index 4dddd274a0e..1836c0c6bc2 100644
--- a/source/blender/python/api2_2x/Constraint.c
+++ b/source/blender/python/api2_2x/Constraint.c
@@ -534,7 +534,10 @@ static int constspace_setter( BPy_Constraint *self, int type, PyObject *value )
Object *tar;
char *subtarget;
- tar= get_constraint_target(con, &subtarget);
+ // FIXME!!!
+ //tar= get_constraint_target(con, &subtarget);
+ tar = NULL;
+ subtarget = NULL;
/* only copy depending on target-type */
if (tar && subtarget[0]) {
@@ -1318,10 +1321,11 @@ static PyObject *script_getter( BPy_Constraint * self, int type )
bPythonConstraint *con = (bPythonConstraint *)(self->con->data);
switch( type ) {
- case EXPP_CONSTR_TARGET:
- return Object_CreatePyObject( con->tar );
- case EXPP_CONSTR_BONE:
- return PyString_FromString( con->subtarget );
+ // FIXME!!!
+ //case EXPP_CONSTR_TARGET:
+ // return Object_CreatePyObject( con->tar );
+ //case EXPP_CONSTR_BONE:
+ // return PyString_FromString( con->subtarget );
case EXPP_CONSTR_SCRIPT:
return Text_CreatePyObject( con->text );
case EXPP_CONSTR_PROPS:
@@ -1336,24 +1340,25 @@ static int script_setter( BPy_Constraint *self, int type, PyObject *value )
bPythonConstraint *con = (bPythonConstraint *)(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;
- }
+ // FIXME!!!
+ //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_SCRIPT: {
Text *text = (( BPy_Text * )value)->text;
if( !BPy_Object_Check( value ) )
@@ -1852,14 +1857,20 @@ static int Constraint_compare( BPy_Constraint * a, BPy_Constraint * b )
static PyObject *Constraint_repr( BPy_Constraint * self )
{
- char type[32];
+ bConstraintTypeInfo *cti;
- if( !self->con )
- return PyString_FromString( "[Constraint - Removed]");
-
- get_constraint_typestring (type, self->con);
- return PyString_FromFormat( "[Constraint \"%s\", Type \"%s\"]",
- self->con->name, type );
+ if (!self->con)
+ return PyString_FromString("[Constraint - Removed]");
+ else
+ cti= constraint_get_typeinfo(self->con);
+
+ if (cti) {
+ return PyString_FromFormat("[Constraint \"%s\", Type \"%s\"]",
+ self->con->name, cti->name);
+ }
+ else {
+ return PyString_FromString("[Constraint \"%s\", Type \"Unknown\"]");
+ }
}
/* Three Python Constraint_Type helper functions needed by the Object module: */
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index 55b36ce43db..906160d66c9 100644
--- a/source/blender/src/buttons_object.c
+++ b/source/blender/src/buttons_object.c
@@ -325,74 +325,6 @@ static void verify_constraint_name_func (void *con_v, void *name_v)
allqueue(REDRAWACTION, 0);
}
-void get_constraint_typestring (char *str, void *con_v)
-{
- bConstraint *con= con_v;
-
- switch (con->type) {
- case CONSTRAINT_TYPE_PYTHON:
- strcpy(str, "Script");
- return;
- case CONSTRAINT_TYPE_CHILDOF:
- strcpy(str, "Child Of");
- return;
- case CONSTRAINT_TYPE_NULL:
- strcpy(str, "Null");
- return;
- case CONSTRAINT_TYPE_TRACKTO:
- strcpy(str, "Track To");
- return;
- case CONSTRAINT_TYPE_MINMAX:
- strcpy(str, "Floor");
- return;
- case CONSTRAINT_TYPE_KINEMATIC:
- strcpy(str, "IK Solver");
- return;
- case CONSTRAINT_TYPE_ROTLIKE:
- strcpy(str, "Copy Rotation");
- return;
- case CONSTRAINT_TYPE_LOCLIKE:
- strcpy(str, "Copy Location");
- return;
- case CONSTRAINT_TYPE_SIZELIKE:
- strcpy(str, "Copy Scale");
- return;
- case CONSTRAINT_TYPE_ACTION:
- strcpy(str, "Action");
- return;
- case CONSTRAINT_TYPE_LOCKTRACK:
- strcpy(str, "Locked Track");
- return;
- case CONSTRAINT_TYPE_FOLLOWPATH:
- strcpy(str, "Follow Path");
- return;
- case CONSTRAINT_TYPE_STRETCHTO:
- strcpy(str, "Stretch To");
- return;
- case CONSTRAINT_TYPE_LOCLIMIT:
- strcpy(str, "Limit Location");
- return;
- case CONSTRAINT_TYPE_ROTLIMIT:
- strcpy(str, "Limit Rotation");
- return;
- case CONSTRAINT_TYPE_SIZELIMIT:
- strcpy(str, "Limit Scale");
- return;
- case CONSTRAINT_TYPE_RIGIDBODYJOINT:
- strcpy(str, "Rigid Body");
- return;
- case CONSTRAINT_TYPE_CLAMPTO:
- strcpy(str, "Clamp To");
- return;
- case CONSTRAINT_TYPE_TRANSFORM:
- strcpy(str, "Transformation");
- break;
- default:
- strcpy (str, "Unknown");
- return;
- }
-}
-
void const_moveUp(void *ob_v, void *con_v)
{
bConstraint *con, *constr= con_v;
@@ -478,6 +410,11 @@ void autocomplete_vgroup(char *str, void *arg_v)
}
}
+/* some commonly used macros in the constraints drawing code */
+#define is_armature_target(target) (target && target->type==OB_ARMATURE)
+#define is_armature_owner(ob) ((ob->type == OB_ARMATURE) && (ob->flag & OB_POSEMODE))
+#define is_geom_target(target) (target && (ELEM(target->type, OB_MESH, OB_LATTICE)) )
+
/* 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
@@ -536,22 +473,24 @@ static void draw_constraint_spaceselect (uiBlock *block, bConstraint *con, short
/* 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;
+ Object *ob= OBACT;
+ bConstraintTypeInfo *cti;
uiBut *but;
- char typestr[64], *subtarget;
+ char typestr[64];
short height, width = 265;
- short is_armature_target, is_geom_target, is_armature_owner;
int 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));
- is_geom_target= (target && (ELEM(target->type, OB_MESH, OB_LATTICE)) );
-
+ cti= constraint_get_typeinfo(con);
+ if (cti == NULL) {
+ printf("Argh! No valid constraint type-info... aborting constraint drawing. \n");
+ return;
+ }
+ else {
+ strcpy(typestr, cti->name);
+ }
+
/* unless button has own callback, it adds this callback to button */
uiBlockSetFunc(block, constraint_active_func, ob, con);
-
- get_constraint_typestring(typestr, con);
/* Draw constraint header */
uiBlockSetEmboss(block, UI_EMBOSSN);
@@ -615,11 +554,14 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
case CONSTRAINT_TYPE_PYTHON:
{
bPythonConstraint *data = con->data;
+ bConstraintTarget *ct;
uiBut *but2;
+ int tarnum, theight;
static int pyconindex=0;
char *menustr;
- height = 110;
+ theight = (data->tarnum)? (data->tarnum * 38) : (38);
+ height = theight + 78;
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, "");
@@ -632,42 +574,62 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
uiButSetFunc(but2, validate_pyconstraint_cb, data, &pyconindex);
MEM_freeN(menustr);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+60, *yco-48, 55, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ /* draw target(s) */
if (data->flag & PYCON_USETARGETS) {
/* 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);
- }
- else if (is_geom_target) {
- but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-66,150,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
- uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
- }
- else {
- strcpy (data->subtarget, "");
+ for (ct=data->targets.first, tarnum=1; ct; ct=ct->next, tarnum++) {
+ char tarstr[32];
+
+ /* target label */
+ sprintf(tarstr, "Target %02d:", tarnum);
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, tarstr, *xco+60, *yco-48, 55, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+
+ /* target space-selector - per target */
+ if (is_armature_target(ct->tar)) {
+ uiDefButS(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Pose Space %x3|Local with Parent %x4|Local Space %x1",
+ *xco+60, *yco-66, 55, 18, &ct->space, 0, 0, 0, 0, "Choose space that target is evaluated in");
+ }
+ else {
+ uiDefButS(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Local (Without Parent) Space %x1",
+ *xco+60, *yco-66, 55, 18, &ct->space, 0, 0, 0, 0, "Choose space that target is evaluated in");
+ }
+
+ uiBlockBeginAlign(block);
+ /* target object */
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-48, 150, 18, &ct->tar, "Target Object");
+
+ /* subtarget */
+ if (is_armature_target(ct->tar)) {
+ but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-66,150,18, &ct->subtarget, 0, 24, 0, 0, "Subtarget Bone");
+ uiButSetCompleteFunc(but, autocomplete_bone, (void *)ct->tar);
+ }
+ else if (is_geom_target(ct->tar)) {
+ but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-66,150,18, &ct->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ct->tar);
+ }
+ else {
+ strcpy(ct->subtarget, "");
+ }
+ uiBlockEndAlign(block);
}
-
- uiBlockEndAlign(block);
}
else {
/* Draw indication that no target needed */
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+60, *yco-48, 55, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Not Applicable", *xco+120, *yco-48, 150, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
}
/* settings */
uiBlockBeginAlign(block);
- but=uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Options", *xco, *yco-88, (width/2),18, NULL, 0, 24, 0, 0, "Change some of the constraint's settings.");
- uiButSetFunc(but, BPY_pyconstraint_settings, data, NULL);
-
- 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");
+ but=uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Options", *xco, *yco-(52+theight), (width/2),18, NULL, 0, 24, 0, 0, "Change some of the constraint's settings.");
+ uiButSetFunc(but, BPY_pyconstraint_settings, data, NULL);
+
+ but=uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Refresh", *xco+((width/2)+10), *yco-(52+theight), (width/2),18, NULL, 0, 24, 0, 0, "Force constraint to refresh it's settings");
+ uiButSetFunc(but, update_pyconstraint_cb, ob, con);
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);
+ draw_constraint_spaceselect(block, con, *xco, *yco-(73+theight), is_armature_owner(ob), -1);
}
break;
case CONSTRAINT_TYPE_ACTION:
@@ -682,48 +644,50 @@ 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-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);
- }
- else {
- strcpy (data->subtarget, "");
- }
+ 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(data->tar)) {
+ 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);
+ }
+ else {
+ strcpy(data->subtarget, "");
+ }
uiBlockEndAlign(block);
/* Draw action/type buttons */
uiBlockBeginAlign(block);
- 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|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");
+ 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|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");
+ uiBlockEndAlign(block);
/* 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");
+ 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");
+ uiBlockEndAlign(block);
/* 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");
+ 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);
+ draw_constraint_spaceselect(block, con, *xco, *yco-104, -1, is_armature_target(data->tar));
}
break;
case CONSTRAINT_TYPE_CHILDOF:
@@ -735,53 +699,52 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
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 if (is_geom_target) {
- but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
- uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
- }
- else {
- strcpy (data->subtarget, "");
- }
-
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object to use as Parent");
+
+ if (is_armature_target(data->tar)) {
+ 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 if (is_geom_target(data->tar)) {
+ but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
+ }
+ else {
+ strcpy(data->subtarget, "");
+ }
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");
+ 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");
+ 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");
+ 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);
- but=uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Set Offset", *xco, *yco-151, (width/2),18, NULL, 0, 24, 0, 0, "Calculate current Parent-Inverse Matrix (i.e. restore offset from parent)");
- uiButSetFunc(but, childof_const_setinv, data, NULL);
-
- but=uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Clear Offset", *xco+((width/2)+10), *yco-151, (width/2),18, NULL, 0, 24, 0, 0, "Clear Parent-Inverse Matrix (i.e. clear offset from parent)");
- uiButSetFunc(but, childof_const_clearinv, data, NULL);
+ but=uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Set Offset", *xco, *yco-151, (width/2),18, NULL, 0, 24, 0, 0, "Calculate current Parent-Inverse Matrix (i.e. restore offset from parent)");
+ uiButSetFunc(but, childof_const_setinv, data, NULL);
+
+ but=uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Clear Offset", *xco+((width/2)+10), *yco-151, (width/2),18, NULL, 0, 24, 0, 0, "Clear Parent-Inverse Matrix (i.e. clear offset from parent)");
+ uiButSetFunc(but, childof_const_clearinv, data, NULL);
uiBlockEndAlign(block);
}
break;
@@ -796,40 +759,39 @@ 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-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);
- }
- else if (is_geom_target) {
- but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
- uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
- }
- else {
- strcpy (data->subtarget, "");
- }
-
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object");
+
+ if (is_armature_target(data->tar)) {
+ 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);
+ }
+ else if (is_geom_target(data->tar)) {
+ but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
+ }
+ else {
+ strcpy(data->subtarget, "");
+ }
uiBlockEndAlign(block);
/* Draw XYZ toggles */
uiBlockBeginAlign(block);
- but=uiDefButBitI(block, TOG, LOCLIKE_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, LOCLIKE_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, LOCLIKE_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, LOCLIKE_Y_INVERT, B_CONSTRAINT_TEST, "-", *xco+((width/2)+48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Invert Y component");
- but=uiDefButBitI(block, TOG, LOCLIKE_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, LOCLIKE_Z_INVERT, B_CONSTRAINT_TEST, "-", *xco+((width/2)+128), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Invert Z component");
+ uiDefButBitI(block, TOG, LOCLIKE_X, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component");
+ uiDefButBitI(block, TOG, LOCLIKE_X_INVERT, B_CONSTRAINT_TEST, "-", *xco+((width/2)-16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Invert X component");
+ uiDefButBitI(block, TOG, LOCLIKE_Y, B_CONSTRAINT_TEST, "Y", *xco+((width/2)+16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Y component");
+ uiDefButBitI(block, TOG, LOCLIKE_Y_INVERT, B_CONSTRAINT_TEST, "-", *xco+((width/2)+48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Invert Y component");
+ uiDefButBitI(block, TOG, LOCLIKE_Z, B_CONSTRAINT_TEST, "Z", *xco+((width/2)+96), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Z component");
+ uiDefButBitI(block, TOG, LOCLIKE_Z_INVERT, B_CONSTRAINT_TEST, "-", *xco+((width/2)+128), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Invert Z component");
uiBlockEndAlign(block);
/* Draw options */
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) {
+ if (is_armature_target(data->tar)) {
uiDefButBitI(block, TOG, LOCLIKE_TIP, B_CONSTRAINT_TEST, "Target Bone Tail", *xco+(width/2), *yco-89, (width/2), 18, &data->flag, 0, 24, 0, 0, "Copy Location of Target Bone's Tail");
}
/* constraint space settings */
- draw_constraint_spaceselect(block, con, *xco, *yco-109, is_armature_owner, is_armature_target);
+ draw_constraint_spaceselect(block, con, *xco, *yco-109, is_armature_owner(ob), is_armature_target(data->tar));
}
break;
case CONSTRAINT_TYPE_ROTLIKE:
@@ -840,37 +802,36 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
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);
- }
- else if (is_geom_target) {
- but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
- uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
- }
- else {
- strcpy (data->subtarget, "");
- }
-
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object");
+
+ if (is_armature_target(data->tar)) {
+ 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);
+ }
+ else if (is_geom_target(data->tar)) {
+ but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
+ }
+ else {
+ strcpy(data->subtarget, "");
+ }
uiBlockEndAlign(block);
/* Draw XYZ toggles */
uiBlockBeginAlign(block);
- 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");
- but=uiDefButBitI(block, TOG, ROTLIKE_Y_INVERT, B_CONSTRAINT_TEST, "-", *xco+((width/2)+48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Invert Y component");
- 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");
+ 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");
+ 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");
+ 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");
+ uiDefButBitI(block, TOG, ROTLIKE_Y_INVERT, B_CONSTRAINT_TEST, "-", *xco+((width/2)+48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Invert Y component");
+ 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");
+ 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);
+ draw_constraint_spaceselect(block, con, *xco, *yco-94, is_armature_owner(ob), is_armature_target(data->tar));
}
break;
case CONSTRAINT_TYPE_SIZELIKE:
@@ -885,31 +846,30 @@ 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-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);
- }
- else if (is_geom_target) {
- but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
- uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
- }
- else {
- strcpy (data->subtarget, "");
- }
-
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object");
+
+ if (is_armature_target(data->tar)) {
+ 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);
+ }
+ else if (is_geom_target(data->tar)) {
+ but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
+ }
+ else {
+ strcpy(data->subtarget, "");
+ }
uiBlockEndAlign(block);
/* Draw XYZ toggles */
uiBlockBeginAlign(block);
- 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");
+ 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");
+ 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");
+ 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);
+ draw_constraint_spaceselect(block, con, *xco, *yco-94, is_armature_owner(ob), is_armature_target(data->tar));
}
break;
case CONSTRAINT_TYPE_KINEMATIC:
@@ -925,33 +885,38 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
uiDefButBitS(block, TOG, CONSTRAINT_IK_ROT, B_CONSTRAINT_TEST, "Rot", *xco, *yco-24,60,19, &data->flag, 0, 0, 0, 0, "Chain follows rotation of target");
uiBlockBeginAlign(block);
- uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 19, &data->tar, "Target Object");
-
- if (is_armature_target) {
- but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,19, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
- uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar);
- }
- else if (is_geom_target) {
- but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
- uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
- }
- else {
- strcpy (data->subtarget, "");
- }
-
- uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, CONSTRAINT_IK_TIP, B_CONSTRAINT_TEST, "Use Tail", *xco, *yco-64, 137, 19, &data->flag, 0, 0, 0, 0, "Include Bone's tail as last element in Chain");
- uiDefButI(block, NUM, B_CONSTRAINT_TEST, "ChainLen:", *xco, *yco-84,137,19, &data->rootbone, 0, 255, 0, 0, "If not zero, the amount of bones in this chain");
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 19, &data->tar, "Target Object");
+
+ if (is_armature_target(data->tar)) {
+ but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,19, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
+ uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar);
+ }
+ else if (is_geom_target(data->tar)) {
+ but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
+ }
+ else {
+ strcpy(data->subtarget, "");
+ }
+ uiBlockEndAlign(block);
uiBlockBeginAlign(block);
- uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "PosW ", *xco+147, *yco-64, 137, 19, &data->weight, 0.01, 1.0, 2, 2, "For Tree-IK: weight of position control for this target");
- uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "RotW ", *xco+147, *yco-84, 137, 19, &data->orientweight, 0.01, 1.0, 2, 2, "For Tree-IK: Weight of orientation control for this target");
-
+ uiDefButBitS(block, TOG, CONSTRAINT_IK_TIP, B_CONSTRAINT_TEST, "Use Tail", *xco, *yco-64, 137, 19, &data->flag, 0, 0, 0, 0, "Include Bone's tail as last element in Chain");
+ uiDefButI(block, NUM, B_CONSTRAINT_TEST, "ChainLen:", *xco, *yco-84,137,19, &data->rootbone, 0, 255, 0, 0, "If not zero, the amount of bones in this chain");
+ uiBlockEndAlign(block);
+
uiBlockBeginAlign(block);
- uiDefButS(block, NUM, B_CONSTRAINT_TEST, "Iterations:", *xco, *yco-109, 137, 19, &data->iterations, 1, 10000, 0, 0, "Maximum number of solving iterations");
+ uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "PosW ", *xco+147, *yco-64, 137, 19, &data->weight, 0.01, 1.0, 2, 2, "For Tree-IK: weight of position control for this target");
+ uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "RotW ", *xco+147, *yco-84, 137, 19, &data->orientweight, 0.01, 1.0, 2, 2, "For Tree-IK: Weight of orientation control for this target");
+ uiBlockEndAlign(block);
+
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, CONSTRAINT_IK_STRETCH, B_CONSTRAINT_TEST, "Stretch", *xco+147, *yco-109,137,19, &data->flag, 0, 0, 0, 0, "Enable IK stretching");
+ uiDefButS(block, NUM, B_CONSTRAINT_TEST, "Iterations:", *xco, *yco-109, 137, 19, &data->iterations, 1, 10000, 0, 0, "Maximum number of solving iterations");
+ uiBlockEndAlign(block);
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, CONSTRAINT_IK_STRETCH, B_CONSTRAINT_TEST, "Stretch", *xco+147, *yco-109,137,19, &data->flag, 0, 0, 0, 0, "Enable IK stretching");
+ uiBlockEndAlign(block);
}
break;
case CONSTRAINT_TYPE_TRACKTO:
@@ -962,95 +927,93 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
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);
- }
- else if (is_geom_target) {
- but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
- uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
- }
- else {
- strcpy (data->subtarget, "");
- }
-
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object");
+
+ if (is_armature_target(data->tar)) {
+ 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);
+ }
+ else if (is_geom_target(data->tar)) {
+ but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
+ }
+ else {
+ strcpy(data->subtarget, "");
+ }
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Align:", *xco+5, *yco-42, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
-
- uiDefButBitI(block, TOG, 1, B_CONSTRAINT_TEST, "TargetZ", *xco+60, *yco-42, 50, 18, &data->flags, 0, 1, 0, 0, "Target Z axis, not world Z axis, will constrain up direction");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Align:", *xco+5, *yco-42, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+
+ uiDefButBitI(block, TOG, 1, B_CONSTRAINT_TEST, "TargetZ", *xco+60, *yco-42, 50, 18, &data->flags, 0, 1, 0, 0, "Target Z axis, not world Z axis, will constrain up direction");
uiBlockEndAlign(block);
-
+
uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "To:", *xco+12, *yco-64, 25, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
-
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+39, *yco-64,17,18, &data->reserved1, 12.0, 0.0, 0, 0, "X axis points to the target object");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y", *xco+56, *yco-64,17,18, &data->reserved1, 12.0, 1.0, 0, 0, "Y axis points to the target object");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+73, *yco-64,17,18, &data->reserved1, 12.0, 2.0, 0, 0, "Z axis points to the target object");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-X", *xco+90, *yco-64,24,18, &data->reserved1, 12.0, 3.0, 0, 0, "-X axis points to the target object");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Y", *xco+114, *yco-64,24,18, &data->reserved1, 12.0, 4.0, 0, 0, "-Y axis points to the target object");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Z", *xco+138, *yco-64,24,18, &data->reserved1, 12.0, 5.0, 0, 0, "-Z axis points to the target object");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "To:", *xco+12, *yco-64, 25, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+
+ uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+39, *yco-64,17,18, &data->reserved1, 12.0, 0.0, 0, 0, "X axis points to the target object");
+ uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y", *xco+56, *yco-64,17,18, &data->reserved1, 12.0, 1.0, 0, 0, "Y axis points to the target object");
+ uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+73, *yco-64,17,18, &data->reserved1, 12.0, 2.0, 0, 0, "Z axis points to the target object");
+ uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-X", *xco+90, *yco-64,24,18, &data->reserved1, 12.0, 3.0, 0, 0, "-X axis points to the target object");
+ uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Y", *xco+114, *yco-64,24,18, &data->reserved1, 12.0, 4.0, 0, 0, "-Y axis points to the target object");
+ uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Z", *xco+138, *yco-64,24,18, &data->reserved1, 12.0, 5.0, 0, 0, "-Z axis points to the target object");
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Up:", *xco+174, *yco-64, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
-
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+204, *yco-64,17,18, &data->reserved2, 13.0, 0.0, 0, 0, "X axis points upward");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y", *xco+221, *yco-64,17,18, &data->reserved2, 13.0, 1.0, 0, 0, "Y axis points upward");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+238, *yco-64,17,18, &data->reserved2, 13.0, 2.0, 0, 0, "Z axis points upward");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Up:", *xco+174, *yco-64, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+
+ uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+204, *yco-64,17,18, &data->reserved2, 13.0, 0.0, 0, 0, "X axis points upward");
+ uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y", *xco+221, *yco-64,17,18, &data->reserved2, 13.0, 1.0, 0, 0, "Y axis points upward");
+ uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+238, *yco-64,17,18, &data->reserved2, 13.0, 2.0, 0, 0, "Z axis points upward");
uiBlockEndAlign(block);
/* constraint space settings */
- draw_constraint_spaceselect(block, con, *xco, *yco-94, is_armature_owner, is_armature_target);
+ draw_constraint_spaceselect(block, con, *xco, *yco-94, is_armature_owner(ob), is_armature_target(data->tar));
}
break;
case CONSTRAINT_TYPE_MINMAX:
{
bMinMaxConstraint *data = con->data;
-
+
height = 66;
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, "");
-
+
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Offset:", *xco, *yco-44, 100, 18, &data->offset, -100, 100, 100.0, 0.0, "Offset from the position of the object center");
-
+
/* 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);
- }
- else if (is_geom_target) {
- but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
- uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
- }
- else {
- strcpy (data->subtarget, "");
- }
-
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object");
+
+ if (is_armature_target(data->tar)) {
+ 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);
+ }
+ else if (is_geom_target(data->tar)) {
+ but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
+ }
+ else {
+ strcpy(data->subtarget, "");
+ }
uiBlockEndAlign(block);
-
- but=uiDefButI(block, TOG|BIT|0, B_CONSTRAINT_TEST, "Sticky", *xco, *yco-24, 44, 18, &data->flag, 0, 24, 0, 0, "Immobilize object while constrained");
- but=uiDefButI(block, TOG|BIT|2, B_CONSTRAINT_TEST, "Use Rot", *xco+44, *yco-24, 64, 18, &data->flag, 0, 24, 0, 0, "Use target object rotation");
+
+ uiDefButBitI(block, TOG, 0, B_CONSTRAINT_TEST, "Sticky", *xco, *yco-24, 44, 18, &data->flag, 0, 24, 0, 0, "Immobilize object while constrained");
+ uiDefButBitI(block, TOG, 2, B_CONSTRAINT_TEST, "Use Rot", *xco+44, *yco-24, 64, 18, &data->flag, 0, 24, 0, 0, "Use target object rotation");
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Max/Min:", *xco-8, *yco-64, 54, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
-
+
uiBlockBeginAlign(block);
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+51, *yco-64,17,18, &data->minmaxflag, 12.0, 0.0, 0, 0, "Will not pass below X of target");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y", *xco+67, *yco-64,17,18, &data->minmaxflag, 12.0, 1.0, 0, 0, "Will not pass below Y of target");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+85, *yco-64,17,18, &data->minmaxflag, 12.0, 2.0, 0, 0, "Will not pass below Z of target");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-X", *xco+102, *yco-64,24,18, &data->minmaxflag, 12.0, 3.0, 0, 0, "Will not pass above X of target");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Y", *xco+126, *yco-64,24,18, &data->minmaxflag, 12.0, 4.0, 0, 0, "Will not pass above Y of target");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Z", *xco+150, *yco-64,24,18, &data->minmaxflag, 12.0, 5.0, 0, 0, "Will not pass above Z of target");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"X", *xco+51, *yco-64,17,18, &data->minmaxflag, 12.0, 0.0, 0, 0, "Will not pass below X of target");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"Y", *xco+67, *yco-64,17,18, &data->minmaxflag, 12.0, 1.0, 0, 0, "Will not pass below Y of target");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"Z", *xco+85, *yco-64,17,18, &data->minmaxflag, 12.0, 2.0, 0, 0, "Will not pass below Z of target");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"-X", *xco+102, *yco-64,24,18, &data->minmaxflag, 12.0, 3.0, 0, 0, "Will not pass above X of target");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"-Y", *xco+126, *yco-64,24,18, &data->minmaxflag, 12.0, 4.0, 0, 0, "Will not pass above Y of target");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"-Z", *xco+150, *yco-64,24,18, &data->minmaxflag, 12.0, 5.0, 0, 0, "Will not pass above Z of target");
uiBlockEndAlign(block);
}
break;
@@ -1064,39 +1027,38 @@ 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-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);
- }
- else if (is_geom_target) {
- but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
- uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
- }
- else {
- strcpy (data->subtarget, "");
- }
-
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object");
+
+ if (is_armature_target(data->tar)) {
+ 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);
+ }
+ else if (is_geom_target(data->tar)) {
+ but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
+ }
+ else {
+ strcpy(data->subtarget, "");
+ }
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "To:", *xco+12, *yco-64, 25, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
-
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+39, *yco-64,17,18, &data->trackflag, 12.0, 0.0, 0, 0, "X axis points to the target object");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y", *xco+56, *yco-64,17,18, &data->trackflag, 12.0, 1.0, 0, 0, "Y axis points to the target object");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+73, *yco-64,17,18, &data->trackflag, 12.0, 2.0, 0, 0, "Z axis points to the target object");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-X", *xco+90, *yco-64,24,18, &data->trackflag, 12.0, 3.0, 0, 0, "-X axis points to the target object");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Y", *xco+114, *yco-64,24,18, &data->trackflag, 12.0, 4.0, 0, 0, "-Y axis points to the target object");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Z", *xco+138, *yco-64,24,18, &data->trackflag, 12.0, 5.0, 0, 0, "-Z axis points to the target object");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "To:", *xco+12, *yco-64, 25, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"X", *xco+39, *yco-64,17,18, &data->trackflag, 12.0, 0.0, 0, 0, "X axis points to the target object");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"Y", *xco+56, *yco-64,17,18, &data->trackflag, 12.0, 1.0, 0, 0, "Y axis points to the target object");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"Z", *xco+73, *yco-64,17,18, &data->trackflag, 12.0, 2.0, 0, 0, "Z axis points to the target object");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"-X", *xco+90, *yco-64,24,18, &data->trackflag, 12.0, 3.0, 0, 0, "-X axis points to the target object");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"-Y", *xco+114, *yco-64,24,18, &data->trackflag, 12.0, 4.0, 0, 0, "-Y axis points to the target object");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"-Z", *xco+138, *yco-64,24,18, &data->trackflag, 12.0, 5.0, 0, 0, "-Z axis points to the target object");
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Lock:", *xco+166, *yco-64, 38, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
-
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+204, *yco-64,17,18, &data->lockflag, 13.0, 0.0, 0, 0, "X axis is locked");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y", *xco+221, *yco-64,17,18, &data->lockflag, 13.0, 1.0, 0, 0, "Y axis is locked");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+238, *yco-64,17,18, &data->lockflag, 13.0, 2.0, 0, 0, "Z axis is locked");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Lock:", *xco+166, *yco-64, 38, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"X", *xco+204, *yco-64,17,18, &data->lockflag, 13.0, 0.0, 0, 0, "X axis is locked");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"Y", *xco+221, *yco-64,17,18, &data->lockflag, 13.0, 1.0, 0, 0, "Y axis is locked");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"Z", *xco+238, *yco-64,17,18, &data->lockflag, 13.0, 2.0, 0, 0, "Z axis is locked");
uiBlockEndAlign(block);
}
break;
@@ -1113,28 +1075,28 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object");
/* Draw Curve Follow toggle */
- but=uiDefButBitI(block, TOG, 1, B_CONSTRAINT_TEST, "CurveFollow", *xco+39, *yco-44, 100, 18, &data->followflag, 0, 24, 0, 0, "Object will follow the heading and banking of the curve");
+ uiDefButBitI(block, TOG, 1, B_CONSTRAINT_TEST, "CurveFollow", *xco+39, *yco-44, 100, 18, &data->followflag, 0, 24, 0, 0, "Object will follow the heading and banking of the curve");
/* Draw Offset number button */
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Offset:", *xco+155, *yco-44, 100, 18, &data->offset, -MAXFRAMEF, MAXFRAMEF, 100.0, 0.0, "Offset from the position corresponding to the time frame");
uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Fw:", *xco+12, *yco-64, 27, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
-
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+39, *yco-64,17,18, &data->trackflag, 12.0, 0.0, 0, 0, "The axis that points forward along the path");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y", *xco+56, *yco-64,17,18, &data->trackflag, 12.0, 1.0, 0, 0, "The axis that points forward along the path");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+73, *yco-64,17,18, &data->trackflag, 12.0, 2.0, 0, 0, "The axis that points forward along the path");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-X", *xco+90, *yco-64,24,18, &data->trackflag, 12.0, 3.0, 0, 0, "The axis that points forward along the path");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Y", *xco+114, *yco-64,24,18, &data->trackflag, 12.0, 4.0, 0, 0, "The axis that points forward along the path");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Z", *xco+138, *yco-64,24,18, &data->trackflag, 12.0, 5.0, 0, 0, "The axis that points forward along the path");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Fw:", *xco+12, *yco-64, 27, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"X", *xco+39, *yco-64,17,18, &data->trackflag, 12.0, 0.0, 0, 0, "The axis that points forward along the path");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"Y", *xco+56, *yco-64,17,18, &data->trackflag, 12.0, 1.0, 0, 0, "The axis that points forward along the path");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"Z", *xco+73, *yco-64,17,18, &data->trackflag, 12.0, 2.0, 0, 0, "The axis that points forward along the path");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"-X", *xco+90, *yco-64,24,18, &data->trackflag, 12.0, 3.0, 0, 0, "The axis that points forward along the path");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"-Y", *xco+114, *yco-64,24,18, &data->trackflag, 12.0, 4.0, 0, 0, "The axis that points forward along the path");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"-Z", *xco+138, *yco-64,24,18, &data->trackflag, 12.0, 5.0, 0, 0, "The axis that points forward along the path");
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Up:", *xco+174, *yco-64, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
-
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+204, *yco-64,17,18, &data->upflag, 13.0, 0.0, 0, 0, "The axis that points upward");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y", *xco+221, *yco-64,17,18, &data->upflag, 13.0, 1.0, 0, 0, "The axis that points upward");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+238, *yco-64,17,18, &data->upflag, 13.0, 2.0, 0, 0, "The axis that points upward");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Up:", *xco+174, *yco-64, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"X", *xco+204, *yco-64,17,18, &data->upflag, 13.0, 0.0, 0, 0, "The axis that points upward");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"Y", *xco+221, *yco-64,17,18, &data->upflag, 13.0, 1.0, 0, 0, "The axis that points upward");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST,"Z", *xco+238, *yco-64,17,18, &data->upflag, 13.0, 2.0, 0, 0, "The axis that points upward");
uiBlockEndAlign(block);
}
break;
@@ -1146,46 +1108,44 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
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);
- }
- else if (is_geom_target) {
- but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
- uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
- }
- else {
- strcpy (data->subtarget, "");
- }
-
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object");
+
+ if (is_armature_target(data->tar)) {
+ 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);
+ }
+ else if (is_geom_target(data->tar)) {
+ but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
+ }
+ else {
+ strcpy(data->subtarget, "");
+ }
uiBlockEndAlign(block);
-
+
uiBlockBeginAlign(block);
- uiDefButF(block,BUTM,B_CONSTRAINT_TEST,"R",*xco, *yco-60,20,18,&(data->orglength),0.0,0,0,0,"Recalculate RLength");
- uiDefButF(block,NUM,B_CONSTRAINT_TEST,"Rest Length:",*xco+18, *yco-60,237,18,&(data->orglength),0.0,100,0.5,0.5,"Length at Rest Position");
+ uiDefButF(block,BUTM,B_CONSTRAINT_TEST,"R",*xco, *yco-60,20,18,&(data->orglength),0.0,0,0,0,"Recalculate RLength");
+ uiDefButF(block,NUM,B_CONSTRAINT_TEST,"Rest Length:",*xco+18, *yco-60,237,18,&(data->orglength),0.0,100,0.5,0.5,"Length at Rest Position");
uiBlockEndAlign(block);
-
+
uiDefButF(block,NUM,B_CONSTRAINT_TEST,"Volume Variation:",*xco+18, *yco-82,237,18,&(data->bulge),0.0,100,0.5,0.5,"Factor between volume variation and stretching");
-
+
uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Vol:",*xco+14, *yco-104,30,18, NULL, 0.0, 0.0, 0.0, 0.0, "");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"XZ", *xco+44, *yco-104,30,18, &data->volmode, 12.0, 0.0, 0, 0, "Keep Volume: Scaling X & Z");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+74, *yco-104,20,18, &data->volmode, 12.0, 1.0, 0, 0, "Keep Volume: Scaling X");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+94, *yco-104,20,18, &data->volmode, 12.0, 2.0, 0, 0, "Keep Volume: Scaling Z");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"NONE", *xco+114, *yco-104,50,18, &data->volmode, 12.0, 3.0, 0, 0, "Ignore Volume");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Vol:",*xco+14, *yco-104,30,18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ uiDefButI(block, ROW,B_CONSTRAINT_TEST,"XZ", *xco+44, *yco-104,30,18, &data->volmode, 12.0, 0.0, 0, 0, "Keep Volume: Scaling X & Z");
+ uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+74, *yco-104,20,18, &data->volmode, 12.0, 1.0, 0, 0, "Keep Volume: Scaling X");
+ uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+94, *yco-104,20,18, &data->volmode, 12.0, 2.0, 0, 0, "Keep Volume: Scaling Z");
+ uiDefButI(block, ROW,B_CONSTRAINT_TEST,"NONE", *xco+114, *yco-104,50,18, &data->volmode, 12.0, 3.0, 0, 0, "Ignore Volume");
uiBlockEndAlign(block);
-
uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST,"Plane:",*xco+175, *yco-104,40,18, NULL, 0.0, 0.0, 0.0, 0.0, "");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+215, *yco-104,20,18, &data->plane, 12.0, 0.0, 0, 0, "Keep X axis");
- uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+235, *yco-104,20,18, &data->plane, 12.0, 2.0, 0, 0, "Keep Z axis");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST,"Plane:",*xco+175, *yco-104,40,18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+215, *yco-104,20,18, &data->plane, 12.0, 0.0, 0, 0, "Keep X axis");
+ uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+235, *yco-104,20,18, &data->plane, 12.0, 2.0, 0, 0, "Keep Z axis");
uiBlockEndAlign(block);
}
break;
@@ -1201,37 +1161,37 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
/* Draw Pairs of LimitToggle+LimitValue */
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, LIMIT_XMIN, B_CONSTRAINT_TEST, "minX", *xco, *yco-28, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x value");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-28, (textButWidth-5), 18, &(data->xmin), -1000, 1000, 0.1,0.5,"Lowest x value to allow");
+ uiDefButBitS(block, TOG, LIMIT_XMIN, B_CONSTRAINT_TEST, "minX", *xco, *yco-28, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x value");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-28, (textButWidth-5), 18, &(data->xmin), -1000, 1000, 0.1,0.5,"Lowest x value to allow");
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
- 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), -1000, 1000, 0.1,0.5,"Highest x value to allow");
+ 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), -1000, 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), -1000, 1000, 0.1,0.5,"Lowest y value to allow");
+ 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), -1000, 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), -1000, 1000, 0.1,0.5,"Highest y value to allow");
+ 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), -1000, 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), -1000, 1000, 0.1,0.5,"Lowest z value to allow");
+ 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), -1000, 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), -1000, 1000, 0.1,0.5,"Highest z value to allow");
+ 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), -1000, 1000, 0.1,0.5,"Highest z value to allow");
uiBlockEndAlign(block);
/* constraint space settings */
- draw_constraint_spaceselect(block, con, *xco, *yco-100, is_armature_owner, -1);
+ draw_constraint_spaceselect(block, con, *xco, *yco-100, is_armature_owner(ob), -1);
}
break;
case CONSTRAINT_TYPE_ROTLIMIT:
@@ -1245,25 +1205,25 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
/* Draw Pairs of LimitToggle+LimitValue */
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, LIMIT_XROT, B_CONSTRAINT_TEST, "LimitX", *xco, *yco-28, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Limit rotation on x-axis");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min:", *xco+normButWidth, *yco-28, normButWidth, 18, &(data->xmin), -360, 360, 0.1,0.5,"Lowest x value to allow");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max:", *xco+(normButWidth * 2), *yco-28, normButWidth, 18, &(data->xmax), -360, 360, 0.1,0.5,"Highest x value to allow");
+ uiDefButBitS(block, TOG, LIMIT_XROT, B_CONSTRAINT_TEST, "LimitX", *xco, *yco-28, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Limit rotation on x-axis");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min:", *xco+normButWidth, *yco-28, normButWidth, 18, &(data->xmin), -360, 360, 0.1,0.5,"Lowest x value to allow");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max:", *xco+(normButWidth * 2), *yco-28, normButWidth, 18, &(data->xmax), -360, 360, 0.1,0.5,"Highest x value to allow");
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, LIMIT_YROT, B_CONSTRAINT_TEST, "LimitY", *xco, *yco-50, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Limit rotation on y-axis");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min:", *xco+normButWidth, *yco-50, normButWidth, 18, &(data->ymin), -360, 360, 0.1,0.5,"Lowest y value to allow");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max:", *xco+(normButWidth * 2), *yco-50, normButWidth, 18, &(data->ymax), -360, 360, 0.1,0.5,"Highest y value to allow");
+ uiDefButBitS(block, TOG, LIMIT_YROT, B_CONSTRAINT_TEST, "LimitY", *xco, *yco-50, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Limit rotation on y-axis");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min:", *xco+normButWidth, *yco-50, normButWidth, 18, &(data->ymin), -360, 360, 0.1,0.5,"Lowest y value to allow");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max:", *xco+(normButWidth * 2), *yco-50, normButWidth, 18, &(data->ymax), -360, 360, 0.1,0.5,"Highest y value to allow");
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, LIMIT_ZROT, B_CONSTRAINT_TEST, "LimitZ", *xco, *yco-72, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Limit rotation on z-axis");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min:", *xco+normButWidth, *yco-72, normButWidth, 18, &(data->zmin), -360, 360, 0.1,0.5,"Lowest z value to allow");
- 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");
+ uiDefButBitS(block, TOG, LIMIT_ZROT, B_CONSTRAINT_TEST, "LimitZ", *xco, *yco-72, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Limit rotation on z-axis");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min:", *xco+normButWidth, *yco-72, normButWidth, 18, &(data->zmin), -360, 360, 0.1,0.5,"Lowest z value to allow");
+ 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);
/* constraint space settings */
- draw_constraint_spaceselect(block, con, *xco, *yco-100, is_armature_owner, -1);
+ draw_constraint_spaceselect(block, con, *xco, *yco-100, is_armature_owner(ob), -1);
}
break;
case CONSTRAINT_TYPE_SIZELIMIT:
@@ -1279,39 +1239,39 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
/* Draw Pairs of LimitToggle+LimitValue */
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, LIMIT_XMIN, B_CONSTRAINT_TEST, "minX", *xco, *yco-28, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x value");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-28, (textButWidth-5), 18, &(data->xmin), 0.0001, 1000, 0.1,0.5,"Lowest x value to allow");
+ uiDefButBitS(block, TOG, LIMIT_XMIN, B_CONSTRAINT_TEST, "minX", *xco, *yco-28, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x value");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-28, (textButWidth-5), 18, &(data->xmin), 0.0001, 1000, 0.1,0.5,"Lowest x value to allow");
uiBlockEndAlign(block);
-
+
uiBlockBeginAlign(block);
- 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");
+ 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");
+ 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");
+ 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");
+ 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");
+ 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);
/* constraint space settings */
- draw_constraint_spaceselect(block, con, *xco, *yco-100, is_armature_owner, -1);
+ draw_constraint_spaceselect(block, con, *xco, *yco-100, is_armature_owner(ob), -1);
}
break;
case CONSTRAINT_TYPE_RIGIDBODYJOINT:
@@ -1324,7 +1284,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
int togButWidth = 70;
int offsetY = 150;
int textButWidth = ((width/2)-togButWidth);
-
+
uiDefButI(block, MENU, B_CONSTRAINT_TEST, "Joint Types%t|Ball%x1|Hinge%x2|Cone Twist%x4|Generic (experimental)%x12",//|Extra Force%x6",
*xco, *yco-25, 150, 18, &data->type, 0, 0, 0, 0, "Choose the joint type");
height = 140;
@@ -1334,10 +1294,10 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
height = 200;
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
-
+
uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "toObject:", *xco, *yco-50, 130, 18, &data->tar, "Child Object");
uiDefButBitS(block, TOG, CONSTRAINT_DRAW_PIVOT, B_CONSTRAINT_TEST, "ShowPivot", *xco+135, *yco-50, 130, 18, &data->flag, 0, 24, 0, 0, "Show pivot position and rotation");
-
+
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Pivot X:", *xco, *yco-75, 130, 18, &data->pivX, -1000, 1000, 100, 0.0, "Offset pivot on X");
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Pivot Y:", *xco, *yco-100, 130, 18, &data->pivY, -1000, 1000, 100, 0.0, "Offset pivot on Y");
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Pivot Z:", *xco, *yco-125, 130, 18, &data->pivZ, -1000, 1000, 100, 0.0, "Offset pivot on z");
@@ -1349,58 +1309,69 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
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");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[0]), -extremeLin, extremeLin, 0.1,0.5,"min x limit");
-
+ uiDefButBitS(block, TOG, 1, B_CONSTRAINT_TEST, "LinMinX", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x limit");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[0]), -extremeLin, extremeLin, 0.1,0.5,"min x limit");
+ uiBlockEndAlign(block);
+
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, 1, B_CONSTRAINT_TEST, "LinMaxX", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum x limit");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth), 18, &(data->maxLimit[0]), -extremeLin, extremeLin, 0.1,0.5,"max x limit");
-
+ uiDefButBitS(block, TOG, 1, B_CONSTRAINT_TEST, "LinMaxX", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum x limit");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth), 18, &(data->maxLimit[0]), -extremeLin, extremeLin, 0.1,0.5,"max x limit");
+ uiBlockEndAlign(block);
+
offsetY += 20;
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, 2, B_CONSTRAINT_TEST, "LinMinY", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y limit");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[1]), -extremeLin, extremeLin, 0.1,0.5,"min y limit");
-
+ uiDefButBitS(block, TOG, 2, B_CONSTRAINT_TEST, "LinMinY", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y limit");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[1]), -extremeLin, extremeLin, 0.1,0.5,"min y limit");
+ uiBlockEndAlign(block);
+
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, 2, B_CONSTRAINT_TEST, "LinMaxY", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum y limit");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth), 18, &(data->maxLimit[1]), -extremeLin, extremeLin, 0.1,0.5,"max y limit");
-
+ uiDefButBitS(block, TOG, 2, B_CONSTRAINT_TEST, "LinMaxY", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum y limit");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth), 18, &(data->maxLimit[1]), -extremeLin, extremeLin, 0.1,0.5,"max y limit");
+ uiBlockEndAlign(block);
+
offsetY += 20;
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, 4, B_CONSTRAINT_TEST, "LinMinZ", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum z limit");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[2]), -extremeLin, extremeLin, 0.1,0.5,"min z limit");
-
+ uiDefButBitS(block, TOG, 4, B_CONSTRAINT_TEST, "LinMinZ", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum z limit");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[2]), -extremeLin, extremeLin, 0.1,0.5,"min z limit");
+ uiBlockEndAlign(block);
+
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, 4, B_CONSTRAINT_TEST, "LinMaxZ", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum z limit");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth), 18, &(data->maxLimit[2]), -extremeLin, extremeLin, 0.1,0.5,"max z limit");
+ uiDefButBitS(block, TOG, 4, B_CONSTRAINT_TEST, "LinMaxZ", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum z limit");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth), 18, &(data->maxLimit[2]), -extremeLin, extremeLin, 0.1,0.5,"max z limit");
+ uiBlockEndAlign(block);
offsetY += 20;
}
if ((data->type==CONSTRAINT_RB_GENERIC6DOF) || (data->type==CONSTRAINT_RB_CONETWIST)) {
/* Draw Pairs of LimitToggle+LimitValue */
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, 8, B_CONSTRAINT_TEST, "AngMinX", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x limit");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[3]), -extremeAngX, extremeAngX, 0.1,0.5,"min x limit");
+ uiDefButBitS(block, TOG, 8, B_CONSTRAINT_TEST, "AngMinX", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x limit");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[3]), -extremeAngX, extremeAngX, 0.1,0.5,"min x limit");
+ uiBlockEndAlign(block);
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, 8, B_CONSTRAINT_TEST, "AngMaxX", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum x limit");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth), 18, &(data->maxLimit[3]), -extremeAngX, extremeAngX, 0.1,0.5,"max x limit");
-
+ uiDefButBitS(block, TOG, 8, B_CONSTRAINT_TEST, "AngMaxX", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum x limit");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth), 18, &(data->maxLimit[3]), -extremeAngX, extremeAngX, 0.1,0.5,"max x limit");
+ uiBlockEndAlign(block);
+
offsetY += 20;
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, 16, B_CONSTRAINT_TEST, "AngMinY", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y limit");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[4]), -extremeAngY, extremeAngY, 0.1,0.5,"min y limit");
-
+ uiDefButBitS(block, TOG, 16, B_CONSTRAINT_TEST, "AngMinY", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y limit");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[4]), -extremeAngY, extremeAngY, 0.1,0.5,"min y limit");
+ uiBlockEndAlign(block);
+
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, 16, B_CONSTRAINT_TEST, "AngMaxY", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum y limit");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth), 18, &(data->maxLimit[4]), -extremeAngY, extremeAngY, 0.1,0.5,"max y limit");
-
+ uiDefButBitS(block, TOG, 16, B_CONSTRAINT_TEST, "AngMaxY", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum y limit");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth), 18, &(data->maxLimit[4]), -extremeAngY, extremeAngY, 0.1,0.5,"max y limit");
+ uiBlockEndAlign(block);
+
offsetY += 20;
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, 32, B_CONSTRAINT_TEST, "AngMinZ", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum z limit");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[5]), -extremeAngZ, extremeAngZ, 0.1,0.5,"min z limit");
-
+ uiDefButBitS(block, TOG, 32, B_CONSTRAINT_TEST, "AngMinZ", *xco, *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum z limit");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-offsetY, (textButWidth-5), 18, &(data->minLimit[5]), -extremeAngZ, extremeAngZ, 0.1,0.5,"min z limit");
+ uiBlockEndAlign(block);
+
uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, 32, B_CONSTRAINT_TEST, "AngMaxZ", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum z limit");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth), 18, &(data->maxLimit[5]), -extremeAngZ, extremeAngZ, 0.1,0.5,"max z limit");
+ uiDefButBitS(block, TOG, 32, B_CONSTRAINT_TEST, "AngMaxZ", *xco+(width-(textButWidth-5)-togButWidth), *yco-offsetY, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use maximum z limit");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-offsetY, (textButWidth), 18, &(data->maxLimit[5]), -extremeAngZ, extremeAngZ, 0.1,0.5,"max z limit");
uiBlockEndAlign(block);
}
}
@@ -1419,17 +1390,17 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
/* Draw XYZ toggles */
uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Main Axis:", *xco, *yco-64, 90, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
- uiDefButI(block, ROW, B_CONSTRAINT_TEST, "Auto", *xco+100, *yco-64, 50, 18, &data->flag, 12.0, CLAMPTO_AUTO, 0, 0, "Automatically determine main-axis of movement");
- uiDefButI(block, ROW, B_CONSTRAINT_TEST, "X", *xco+150, *yco-64, 32, 18, &data->flag, 12.0, CLAMPTO_X, 0, 0, "Main axis of movement is x-axis");
- uiDefButI(block, ROW, B_CONSTRAINT_TEST, "Y", *xco+182, *yco-64, 32, 18, &data->flag, 12.0, CLAMPTO_Y, 0, 0, "Main axis of movement is y-axis");
- uiDefButI(block, ROW, B_CONSTRAINT_TEST, "Z", *xco+214, *yco-64, 32, 18, &data->flag, 12.0, CLAMPTO_Z, 0, 0, "Main axis of movement is z-axis");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Main Axis:", *xco, *yco-64, 90, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST, "Auto", *xco+100, *yco-64, 50, 18, &data->flag, 12.0, CLAMPTO_AUTO, 0, 0, "Automatically determine main-axis of movement");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST, "X", *xco+150, *yco-64, 32, 18, &data->flag, 12.0, CLAMPTO_X, 0, 0, "Main axis of movement is x-axis");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST, "Y", *xco+182, *yco-64, 32, 18, &data->flag, 12.0, CLAMPTO_Y, 0, 0, "Main axis of movement is y-axis");
+ uiDefButI(block, ROW, B_CONSTRAINT_TEST, "Z", *xco+214, *yco-64, 32, 18, &data->flag, 12.0, CLAMPTO_Z, 0, 0, "Main axis of movement is z-axis");
uiBlockEndAlign(block);
/* Extra Options Controlling Behaviour */
uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Options:", *xco, *yco-86, 90, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
- uiDefButBitI(block, TOG, CLAMPTO_CYCLIC, B_CONSTRAINT_TEST, "Cyclic", *xco+((width/2)), *yco-86,60,19, &data->flag2, 0, 0, 0, 0, "Treat curve as cyclic curve (no clamping to curve bounding box)");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Options:", *xco, *yco-86, 90, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ uiDefButBitI(block, TOG, CLAMPTO_CYCLIC, B_CONSTRAINT_TEST, "Cyclic", *xco+((width/2)), *yco-86,60,19, &data->flag2, 0, 0, 0, 0, "Treat curve as cyclic curve (no clamping to curve bounding box)");
uiBlockEndAlign(block);
}
break;
@@ -1446,20 +1417,19 @@ 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-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 if (is_geom_target) {
- but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-66,150,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
- uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
- }
- else {
- strcpy(data->subtarget, "");
- }
-
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object to use as Parent");
+
+ if (is_armature_target(data->tar)) {
+ 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 if (is_geom_target(data->tar)) {
+ but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-66,150,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
+ }
+ else {
+ strcpy(data->subtarget, "");
+ }
uiBlockEndAlign(block);
/* Extrapolate Ranges? */
@@ -1470,9 +1440,9 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
/* draw Loc/Rot/Size toggles */
uiBlockBeginAlign(block);
- uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Loc", *xco-5, *yco-82, 45, 18, &data->from, 12.0, 0, 0, 0, "Use Location transform channels from Target");
- uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Rot", *xco+40, *yco-82, 45, 18, &data->from, 12.0, 1, 0, 0, "Use Rotation transform channels from Target");
- uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Scale", *xco+85, *yco-82, 45, 18, &data->from, 12.0, 2, 0, 0, "Use Scale transform channels from Target");
+ uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Loc", *xco-5, *yco-82, 45, 18, &data->from, 12.0, 0, 0, 0, "Use Location transform channels from Target");
+ uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Rot", *xco+40, *yco-82, 45, 18, &data->from, 12.0, 1, 0, 0, "Use Rotation transform channels from Target");
+ uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Scale", *xco+85, *yco-82, 45, 18, &data->from, 12.0, 2, 0, 0, "Use Scale transform channels from Target");
uiBlockEndAlign(block);
/* Draw Pairs of Axis: Min/Max Value*/
@@ -1490,21 +1460,21 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
}
uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "X:", *xco-10, *yco-107, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+20, *yco-107, 55, 18, &data->from_min[0], fmin, fmax, 0, 0, "Bottom of range of x-axis source motion for source->target mapping");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+75, *yco-107, 55, 18, &data->from_max[0], fmin, fmax, 0, 0, "Top of range of x-axis source motion for source->target mapping");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "X:", *xco-10, *yco-107, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+20, *yco-107, 55, 18, &data->from_min[0], fmin, fmax, 0, 0, "Bottom of range of x-axis source motion for source->target mapping");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+75, *yco-107, 55, 18, &data->from_max[0], fmin, fmax, 0, 0, "Top of range of x-axis source motion for source->target mapping");
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Y:", *xco-10, *yco-127, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+20, *yco-127, 55, 18, &data->from_min[1], fmin, fmax, 0, 0, "Bottom of range of y-axis source motion for source->target mapping");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+75, *yco-127, 55, 18, &data->from_max[1], fmin, fmax, 0, 0, "Top of range of y-axis source motion for source->target mapping");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Y:", *xco-10, *yco-127, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+20, *yco-127, 55, 18, &data->from_min[1], fmin, fmax, 0, 0, "Bottom of range of y-axis source motion for source->target mapping");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+75, *yco-127, 55, 18, &data->from_max[1], fmin, fmax, 0, 0, "Top of range of y-axis source motion for source->target mapping");
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
- uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Z:", *xco-10, *yco-147, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+20, *yco-147, 55, 18, &data->from_min[2], fmin, fmax, 0, 0, "Bottom of range of z-axis source motion for source->target mapping");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+75, *yco-147, 55, 18, &data->from_max[2], fmin, fmax, 0, 0, "Top of range of z-axis source motion for source->target mapping");
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Z:", *xco-10, *yco-147, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+20, *yco-147, 55, 18, &data->from_min[2], fmin, fmax, 0, 0, "Bottom of range of z-axis source motion for source->target mapping");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+75, *yco-147, 55, 18, &data->from_max[2], fmin, fmax, 0, 0, "Top of range of z-axis source motion for source->target mapping");
uiBlockEndAlign(block);
@@ -1513,9 +1483,9 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
/* draw Loc/Rot/Size toggles */
uiBlockBeginAlign(block);
- uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Loc", *xco+150, *yco-82, 45, 18, &data->to, 12.0, 0, 0, 0, "Use as Location transform");
- uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Rot", *xco+195, *yco-82, 45, 18, &data->to, 12.0, 1, 0, 0, "Use as Rotation transform");
- uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Scale", *xco+245, *yco-82, 45, 18, &data->to, 12.0, 2, 0, 0, "Use as Scale transform");
+ uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Loc", *xco+150, *yco-82, 45, 18, &data->to, 12.0, 0, 0, 0, "Use as Location transform");
+ uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Rot", *xco+195, *yco-82, 45, 18, &data->to, 12.0, 1, 0, 0, "Use as Rotation transform");
+ uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Scale", *xco+245, *yco-82, 45, 18, &data->to, 12.0, 2, 0, 0, "Use as Scale transform");
uiBlockEndAlign(block);
/* Draw Pairs of Source-Axis: Min/Max Value*/
@@ -1533,25 +1503,25 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
}
uiBlockBeginAlign(block);
- uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Axis Mapping%t|X->X%x0|Y->X%x1|Z->X%x2", *xco+150, *yco-107, 40, 18, &data->map[0], 0, 24, 0, 0, "Specify which source axis the x-axis destination uses");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+175, *yco-107, 50, 18, &data->to_min[0], tmin, tmax, 0, 0, "Bottom of range of x-axis destination motion for source->target mapping");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+240, *yco-107, 50, 18, &data->to_max[0], tmin, tmax, 0, 0, "Top of range of x-axis destination motion for source->target mapping");
+ uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Axis Mapping%t|X->X%x0|Y->X%x1|Z->X%x2", *xco+150, *yco-107, 40, 18, &data->map[0], 0, 24, 0, 0, "Specify which source axis the x-axis destination uses");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+175, *yco-107, 50, 18, &data->to_min[0], tmin, tmax, 0, 0, "Bottom of range of x-axis destination motion for source->target mapping");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+240, *yco-107, 50, 18, &data->to_max[0], tmin, tmax, 0, 0, "Top of range of x-axis destination motion for source->target mapping");
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
- uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Axis Mapping%t|X->Y%x0|Y->Y%x1|Z->Y%x2", *xco+150, *yco-127, 40, 18, &data->map[1], 0, 24, 0, 0, "Specify which source axis the y-axis destination uses");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+175, *yco-127, 50, 18, &data->to_min[1], tmin, tmax, 0, 0, "Bottom of range of y-axis destination motion for source->target mapping");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+240, *yco-127, 50, 18, &data->to_max[1], tmin, tmax, 0, 0, "Top of range of y-axis destination motion for source->target mapping");
+ uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Axis Mapping%t|X->Y%x0|Y->Y%x1|Z->Y%x2", *xco+150, *yco-127, 40, 18, &data->map[1], 0, 24, 0, 0, "Specify which source axis the y-axis destination uses");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+175, *yco-127, 50, 18, &data->to_min[1], tmin, tmax, 0, 0, "Bottom of range of y-axis destination motion for source->target mapping");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+240, *yco-127, 50, 18, &data->to_max[1], tmin, tmax, 0, 0, "Top of range of y-axis destination motion for source->target mapping");
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
- uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Axis Mapping%t|X->Z%x0|Y->Z%x1|Z->Z%x2", *xco+150, *yco-147, 40, 18, &data->map[2], 0, 24, 0, 0, "Specify which source axis the z-axis destination uses");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+175, *yco-147, 50, 18, &data->to_min[2], tmin, tmax, 0, 0, "Bottom of range of z-axis destination motion for source->target mapping");
- uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+240, *yco-147, 50, 18, &data->to_max[2], tmin, tmax, 0, 0, "Top of range of z-axis destination motion for source->target mapping");
+ uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Axis Mapping%t|X->Z%x0|Y->Z%x1|Z->Z%x2", *xco+150, *yco-147, 40, 18, &data->map[2], 0, 24, 0, 0, "Specify which source axis the z-axis destination uses");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+175, *yco-147, 50, 18, &data->to_min[2], tmin, tmax, 0, 0, "Bottom of range of z-axis destination motion for source->target mapping");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+240, *yco-147, 50, 18, &data->to_max[2], tmin, tmax, 0, 0, "Top of range of z-axis destination motion for source->target mapping");
uiBlockEndAlign(block);
/* constraint space settings */
- draw_constraint_spaceselect(block, con, *xco, *yco-170, is_armature_owner, is_armature_target);
+ draw_constraint_spaceselect(block, con, *xco, *yco-170, is_armature_owner(ob), is_armature_target(data->tar));
}
break;
case CONSTRAINT_TYPE_NULL:
@@ -1564,11 +1534,11 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
height = 0;
break;
}
-
+
(*yco)-=(24+height);
}
- if ((con->type != CONSTRAINT_TYPE_NULL) && (con->type!=CONSTRAINT_TYPE_RIGIDBODYJOINT)) {
+ if (ELEM(con->type, CONSTRAINT_TYPE_NULL, CONSTRAINT_TYPE_RIGIDBODYJOINT)==0) {
uiBlockBeginAlign(block);
uiDefButF(block, NUMSLI, B_CONSTRAINT_INF, "Influence ", *xco, *yco, 197, 20, &(con->enforce), 0.0, 1.0, 0.0, 0.0, "Amount of influence this constraint will have on the final solution");
but = uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Show", *xco+200, *yco, 45, 20, 0, 0.0, 1.0, 0.0, 0.0, "Show constraint's ipo in the Ipo window, adds a channel if not there");
diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c
index f637734fa34..b65a34c9972 100644
--- a/source/blender/src/drawobject.c
+++ b/source/blender/src/drawobject.c
@@ -4285,10 +4285,10 @@ void draw_object(Base *base, int flag)
/* not for sets, duplicators or picking */
if(flag==0 && (!(G.vd->flag & V3D_HIDE_HELPLINES))) {
ListBase *list;
-
+
/* draw hook center and offset line */
if(ob!=G.obedit) draw_hooks(ob);
-
+
/* help lines and so */
if(ob!=G.obedit && ob->parent && (ob->parent->lay & G.vd->lay)) {
setlinestyle(3);
@@ -4301,29 +4301,46 @@ void draw_object(Base *base, int flag)
/* Drawing the constraint lines */
list = &ob->constraints;
- if (list){
- /*
- extern void make_axis_color(char *col, char *col2, char axis); // drawview.c
- */
+ if (list) {
bConstraint *curcon;
- float tmat[4][4];
+ bConstraintOb *cob;
char col[4], col2[4];
-
+
BIF_GetThemeColor3ubv(TH_GRID, col);
make_axis_color(col, col2, 'z');
glColor3ubv((GLubyte *)col2);
-
- 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, bsystem_time(ob, (float)(G.scene->r.cfra), ob->sf));
- setlinestyle(3);
- glBegin(GL_LINES);
- glVertex3fv(tmat[3]);
- glVertex3fv(ob->obmat[3]);
- glEnd();
- setlinestyle(0);
+
+ cob= constraints_make_evalob(ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+
+ for (curcon = list->first; curcon; curcon=curcon->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+
+ if ((curcon->flag & CONSTRAINT_EXPAND) && (cti->get_constraint_targets)) {
+ cti->get_constraint_targets(curcon, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ /* calculate target's matrix */
+ if (cti->get_target_matrix)
+ cti->get_target_matrix(curcon, cob, ct, bsystem_time(ob, (float)(G.scene->r.cfra), ob->sf));
+ else
+ Mat4One(ct->matrix);
+
+ setlinestyle(3);
+ glBegin(GL_LINES);
+ glVertex3fv(ct->matrix[3]);
+ glVertex3fv(ob->obmat[3]);
+ glEnd();
+ setlinestyle(0);
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(curcon, &targets, 1);
}
}
+
+ constraints_clear_evalob(cob);
}
}
diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c
index 81467b95297..2e7da10d8ca 100644
--- a/source/blender/src/editarmature.c
+++ b/source/blender/src/editarmature.c
@@ -451,16 +451,28 @@ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChann
pose= ob->pose;
for (pchant= pose->chanbase.first; pchant; pchant= pchant->next) {
for (con= pchant->constraints.first; con; con= con->next) {
- Object *conOb;
- char *subtarget;
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
/* constraint targets */
- conOb= get_constraint_target(con, &subtarget);
- if (conOb == srcArm) {
- if (strcmp(subtarget, "")==0)
- set_constraint_target(con, tarArm, "");
- else if (strcmp(pchan->name, subtarget)==0)
- set_constraint_target(con, tarArm, curbone->name);
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ if (ct->tar == srcArm) {
+ if (strcmp(ct->subtarget, "")==0) {
+ ct->tar = tarArm;
+ }
+ else if (strcmp(ct->subtarget, pchan->name)==0) {
+ ct->tar = tarArm;
+ strcpy(ct->subtarget, curbone->name);
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
}
/* action constraint? */
@@ -486,15 +498,28 @@ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChann
/* fix object-level constraints */
if (ob != srcArm) {
for (con= ob->constraints.first; con; con= con->next) {
- Object *conOb;
- char *subtarget;
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
- conOb= get_constraint_target(con, &subtarget);
- if (conOb == srcArm) {
- if (strcmp(subtarget, "")==0)
- set_constraint_target(con, tarArm, "");
- else if (strcmp(pchan->name, subtarget)==0)
- set_constraint_target(con, tarArm, curbone->name);
+ /* constraint targets */
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ if (ct->tar == srcArm) {
+ if (strcmp(ct->subtarget, "")==0) {
+ ct->tar = tarArm;
+ }
+ else if (strcmp(ct->subtarget, pchan->name)==0) {
+ ct->tar = tarArm;
+ strcpy(ct->subtarget, curbone->name);
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
}
}
}
diff --git a/source/blender/src/editconstraint.c b/source/blender/src/editconstraint.c
index 5da083ee9a2..c0bc964c07a 100644
--- a/source/blender/src/editconstraint.c
+++ b/source/blender/src/editconstraint.c
@@ -156,10 +156,10 @@ bConstraint *get_active_constraint(Object *ob)
{
ListBase *lb= get_active_constraints(ob);
- if(lb) {
+ if (lb) {
bConstraint *con;
- for(con= lb->first; con; con=con->next)
- if(con->flag & CONSTRAINT_ACTIVE)
+ for (con= lb->first; con; con=con->next)
+ if (con->flag & CONSTRAINT_ACTIVE)
return con;
}
return NULL;
@@ -176,15 +176,15 @@ bConstraintChannel *get_active_constraint_channel(Object *ob)
bPoseChannel *pchan;
pchan = get_active_posechannel(ob);
- if(pchan) {
- for(con= pchan->constraints.first; con; con= con->next)
- if(con->flag & CONSTRAINT_ACTIVE)
+ if (pchan) {
+ for (con= pchan->constraints.first; con; con= con->next)
+ if (con->flag & CONSTRAINT_ACTIVE)
break;
- if(con) {
+ if (con) {
bActionChannel *achan = get_action_channel(ob->action, pchan->name);
- if(achan) {
- for(chan= achan->constraintChannels.first; chan; chan= chan->next)
- if(!strcmp(chan->name, con->name))
+ if (achan) {
+ for (chan= achan->constraintChannels.first; chan; chan= chan->next)
+ if (!strcmp(chan->name, con->name))
break;
return chan;
}
@@ -215,16 +215,26 @@ bConstraintChannel *get_active_constraint_channel(Object *ob)
bConstraint *add_new_constraint(short type)
{
bConstraint *con;
+ bConstraintTypeInfo *cti;
con = MEM_callocN(sizeof(bConstraint), "constraint");
-
+
/* Set up a generic constraint datablock */
con->type = type;
con->flag |= CONSTRAINT_EXPAND;
- con->enforce=1.0F;
- /* Load the data for it */
- con->data = new_constraint_data(con->type);
+ con->enforce = 1.0F;
strcpy (con->name, "Const");
+
+ /* Load the data for it */
+ cti = constraint_get_typeinfo(con);
+ if (cti) {
+ con->data = MEM_callocN(cti->size, cti->structName);
+
+ /* only constraints that change any settings need this */
+ if (cti->new_data)
+ cti->new_data(con->data);
+ }
+
return con;
}
@@ -246,24 +256,51 @@ void add_constraint_to_object(bConstraint *con, Object *ob)
char *get_con_subtarget_name(bConstraint *con, Object *target)
{
- /*
- * If the target for this constraint is target, return a pointer
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+ static char subtarget[32];
+
+ /* If the target for this constraint is target, return a pointer
* to the name for this constraints subtarget ... NULL otherwise
*/
+ if (target == NULL)
+ return NULL;
- if (constraint_has_target(con)) {
- Object *tar;
- char *subtarget;
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
- tar = get_constraint_target(con, &subtarget);
- if (tar==target) return subtarget;
+ for (ct= targets.first; ct; ct= ct->next) {
+ if (ct->tar == target) {
+ if (ct->flag & CONSTRAINT_TAR_TEMP) {
+ /* as temporary targets were created, we can't point to thier subtarget,
+ * a local copy is made here... this should be ok as long as this function
+ * is not called twice with expectations that the string will stay the same
+ */
+ strcpy(subtarget, ct->subtarget);
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 1);
+
+ return &(subtarget[0]);
+ }
+ else {
+ /* not temporary, so we can return a direct pointer to it */
+ return &(ct->subtarget[0]);
+ }
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
}
return NULL;
}
/* checks validity of object pointers, and NULLs,
- if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag */
+ * if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag
+ */
static void test_constraints (Object *owner, const char* substring)
{
@@ -279,29 +316,29 @@ static void test_constraints (Object *owner, const char* substring)
if (strlen (substring)) {
switch (owner->type) {
case OB_ARMATURE:
- type = TARGET_BONE;
+ type = CONSTRAINT_OBTYPE_BONE;
break;
default:
- type = TARGET_OBJECT;
+ type = CONSTRAINT_OBTYPE_OBJECT;
break;
}
}
else
- type = TARGET_OBJECT;
+ type = CONSTRAINT_OBTYPE_OBJECT;
switch (type) {
- case TARGET_OBJECT:
+ case CONSTRAINT_OBTYPE_OBJECT:
conlist = &owner->constraints;
break;
- case TARGET_BONE:
+ case CONSTRAINT_OBTYPE_BONE:
{
Bone *bone;
bPoseChannel *chan;
- bone = get_named_bone(((bArmature*)owner->data), substring);
- chan = get_pose_channel (owner->pose, substring);
- if (bone && chan){
+ bone = get_named_bone( ((bArmature *)owner->data ), substring );
+ chan = get_pose_channel(owner->pose, substring);
+ if (bone && chan) {
conlist = &chan->constraints;
}
}
@@ -317,7 +354,6 @@ static void test_constraints (Object *owner, const char* substring)
case CONSTRAINT_TYPE_PYTHON:
{
bPythonConstraint *data = curcon->data;
- float dummy_matrix[4][4];
/* is there are valid script? */
if (!data->text) {
@@ -328,35 +364,9 @@ static void test_constraints (Object *owner, const char* substring)
curcon->flag |= CONSTRAINT_DISABLE;
break;
}
- data->flag &= ~PYCON_SCRIPTERROR;
-
- /* does the constraint require target input? */
- if (BPY_pyconstraint_targets(data, dummy_matrix))
- data->flag |= PYCON_USETARGETS;
- else
- data->flag &= ~PYCON_USETARGETS;
- /* check whether we have a valid target */
- if (data->flag & PYCON_USETARGETS) {
- /* validate target */
- if (!exist_object(data->tar)) {
- data->tar = NULL;
- curcon->flag |= CONSTRAINT_DISABLE;
- break;
- }
-
- if ( (data->tar == owner) &&
- (!get_named_bone(get_armature(owner),
- data->subtarget))) {
- curcon->flag |= CONSTRAINT_DISABLE;
- break;
- }
- }
- else {
- /* don't hold onto target */
- data->tar = NULL;
- BLI_strncpy(data->subtarget, "", 32);
- }
+ /* does the constraint require target input... also validates targets */
+ BPY_pyconstraint_update(owner, curcon);
}
break;
case CONSTRAINT_TYPE_ACTION:
@@ -630,6 +640,41 @@ void object_test_constraints (Object *owner)
}
+/* helper function for add_constriant - sets the last target for the active constraint */
+static void set_constraint_nth_target(bConstraint *con, Object *target, char subtarget[], int index)
+{
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+ int num_targets, i;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+ num_targets= BLI_countlist(&targets);
+
+ if (index < 0) {
+ if (abs(index) < num_targets)
+ index= num_targets - abs(index);
+ else
+ index= num_targets - 1;
+ }
+ else if (index >= num_targets) {
+ index= num_targets - 1;
+ }
+
+ for (ct=targets.first, i=0; ct; ct= ct->next, i++) {
+ if (i == index) {
+ ct->tar= target;
+ strcpy(ct->subtarget, subtarget);
+ break;
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
+}
+
/* context: active object in posemode, active channel, optional selected channel */
void add_constraint(int only_IK)
{
@@ -768,11 +813,10 @@ void add_constraint(int only_IK)
}
else if (nr==18) {
char *menustr;
- int scriptint= 0, dummy_int=0;
- float dummy_matrix[4][4];
+ int scriptint= 0;
/* popup a list of usable scripts */
- menustr = buildmenu_pyconstraints(NULL, &dummy_int);
+ menustr = buildmenu_pyconstraints(NULL, &scriptint);
scriptint = pupmenu(menustr);
MEM_freeN(menustr);
@@ -783,11 +827,7 @@ void add_constraint(int only_IK)
validate_pyconstraint_cb(con->data, &scriptint);
/* make sure target allowance is set correctly */
- dummy_int = BPY_pyconstraint_targets(con->data, dummy_matrix);
- if (dummy_int) {
- bPythonConstraint *pycon= (bPythonConstraint *)con->data;
- pycon->flag |= PYCON_USETARGETS;
- }
+ BPY_pyconstraint_update(ob, con);
}
}
else if (nr==19) {
@@ -818,10 +858,10 @@ void add_constraint(int only_IK)
/* set the target */
if (pchansel) {
- set_constraint_target(con, ob, pchansel->name);
+ set_constraint_nth_target(con, ob, pchansel->name, 0);
}
else if(obsel) {
- set_constraint_target(con, obsel, NULL);
+ set_constraint_nth_target(con, obsel, NULL, 0);
}
else if (ELEM4(nr, 11, 13, 14, 15)==0) { /* add new empty as target */
Base *base= BASACT, *newbase;
@@ -843,7 +883,7 @@ void add_constraint(int only_IK)
else
VECCOPY(obt->loc, ob->obmat[3]);
- set_constraint_target(con, obt, NULL);
+ set_constraint_nth_target(con, obt, NULL, 0);
/* restore, add_object sets active */
BASACT= base;
@@ -1011,6 +1051,16 @@ char *buildmenu_pyconstraints(Text *con_text, int *pyconindex)
return menustr;
}
+/* this callback gets called when the 'refresh' button of a pyconstraint gets pressed */
+void update_pyconstraint_cb(void *arg1, void *arg2)
+{
+ Object *owner= (Object *)arg1;
+ bConstraint *con= (bConstraint *)arg2;
+
+ if (owner && con)
+ BPY_pyconstraint_update(owner, con);
+}
+
/* ------------- Child-Of Constraint ------------------ */
/* ChildOf Constraint - set inverse callback */
@@ -1047,7 +1097,7 @@ void childof_const_setinv (void *conv, void *unused)
/* do constraint solving on pose-matrix containing no transforms
* N.B. code is copied from armature.c (where_is_pose_bone)
*/
- cob= constraints_make_evalob(ob, pchan, TARGET_BONE);
+ cob= constraints_make_evalob(ob, pchan, CONSTRAINT_OBTYPE_BONE);
solve_constraints(&pchan->constraints, cob, ctime);
constraints_clear_evalob(cob);
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index 593d9ecdcdc..1c9cf15bc7e 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -1378,9 +1378,6 @@ void make_parent(void)
}
}
else if(par->type == OB_CURVE){
- bConstraint *con;
- bFollowPathConstraint *data;
-
mode= pupmenu("Make Parent %t|Normal Parent %x1|Follow Path %x2|Curve Deform %x3|Path Constraint %x4");
if(mode<=0){
return;
@@ -1402,24 +1399,26 @@ void make_parent(void)
mode= PARSKEL;
}
else if(mode==4) {
-
+ bConstraint *con;
+ bFollowPathConstraint *data;
+
base= FIRSTBASE;
while(base) {
if TESTBASELIB(base) {
if(base!=BASACT) {
float cmat[4][4], vec[3];
-
+
con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
strcpy (con->name, "AutoPath");
-
+
data = con->data;
data->tar = BASACT->object;
-
+
add_constraint_to_object(con, base->object);
-
- get_constraint_target_matrix(con, TARGET_OBJECT, NULL, cmat, G.scene->r.cfra - base->object->sf);
+
+ get_constraint_target_matrix(con, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, G.scene->r.cfra - base->object->sf);
VecSubf(vec, base->object->obmat[3], cmat[3]);
-
+
base->object->loc[0] = vec[0];
base->object->loc[1] = vec[1];
base->object->loc[2] = vec[2];
diff --git a/source/blender/src/header_text.c b/source/blender/src/header_text.c
index 32268c35210..04c354fb2b1 100644
--- a/source/blender/src/header_text.c
+++ b/source/blender/src/header_text.c
@@ -286,7 +286,7 @@ static void do_text_filemenu(void *arg, int event)
case 1:
st->text= add_empty_text( "Text" );
st->top=0;
-
+
allqueue(REDRAWTEXT, 0);
allqueue(REDRAWHEADERS, 0);
break;
@@ -313,36 +313,36 @@ static void do_text_filemenu(void *arg, int event)
break;
case 7:
{
- Object *obt;
+ Object *ob;
bConstraint *con;
short update;
/* check all pyconstraints */
- for (obt=G.main->object.first; obt; obt=obt->id.next) {
+ for (ob= G.main->object.first; ob; ob= ob->id.next) {
update = 0;
- if(obt->type==OB_ARMATURE && obt->pose) {
+ if (ob->type==OB_ARMATURE && ob->pose) {
bPoseChannel *pchan;
- for(pchan= obt->pose->chanbase.first; pchan; pchan= pchan->next) {
- for (con = pchan->constraints.first; con; con=con->next) {
+ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ for (con = pchan->constraints.first; con; con= con->next) {
if (con->type==CONSTRAINT_TYPE_PYTHON) {
bPythonConstraint *data = con->data;
- if (data->text==text) data->flag = 0;
+ if (data->text==text) BPY_pyconstraint_update(ob, con);
update = 1;
}
}
}
}
- for (con = obt->constraints.first; con; con=con->next) {
+ for (con = ob->constraints.first; con; con= con->next) {
if (con->type==CONSTRAINT_TYPE_PYTHON) {
bPythonConstraint *data = con->data;
- if (data->text==text) data->flag = 0;
+ if (data->text==text) BPY_pyconstraint_update(ob, con);
update = 1;
}
}
if (update) {
- DAG_object_flush_update(G.scene, obt, OB_RECALC_DATA);
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
}
}
}
diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c
index 37d25e4f100..0ed50c75ad4 100644
--- a/source/blender/src/outliner.c
+++ b/source/blender/src/outliner.c
@@ -600,10 +600,13 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
tenla1->name= "Constraints";
for(con= pchan->constraints.first; con; con= con->next, const_index++) {
ten1= outliner_add_element(soops, &tenla1->subtree, ob, tenla1, TSE_CONSTRAINT, const_index);
+#if 0 /* disabled as it needs to be reworked for recoded constraints system */
target= get_constraint_target(con, &str);
if(str && str[0]) ten1->name= str;
else if(target) ten1->name= target->id.name+2;
else ten1->name= con->name;
+#endif
+ ten1->name= con->name;
ten1->directdata= con;
/* possible add all other types links? */
}
@@ -651,10 +654,13 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
tenla->name= "Constraints";
for(con= ob->constraints.first; con; con= con->next, a++) {
ten= outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, a);
+#if 0 /* disabled due to constraints system targets recode... code here needs review */
target= get_constraint_target(con, &str);
if(str && str[0]) ten->name= str;
else if(target) ten->name= target->id.name+2;
else ten->name= con->name;
+#endif
+ ten->name= con->name;
ten->directdata= con;
/* possible add all other types links? */
}
diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c
index 5e78abd8b41..faae6bd0da4 100644
--- a/source/blender/src/poseobject.c
+++ b/source/blender/src/poseobject.c
@@ -329,23 +329,30 @@ void pose_select_constraint_target(void)
bConstraint *con;
/* paranoia checks */
- if(!ob && !ob->pose) return;
- if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
+ if (!ob && !ob->pose) return;
+ if (ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- if(arm->layer & pchan->bone->layer) {
- if(pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) {
-
- for(con= pchan->constraints.first; con; con= con->next) {
- char *subtarget;
- Object *target= get_constraint_target(con, &subtarget);
+ if (arm->layer & pchan->bone->layer) {
+ if (pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) {
+ for (con= pchan->constraints.first; con; con= con->next) {
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
- if(ob==target) {
- if(subtarget) {
- bPoseChannel *pchanc= get_pose_channel(ob->pose, subtarget);
- if(pchanc)
- pchanc->bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ for (ct= targets.first; ct; ct= ct->next) {
+ if ((ct->tar == ob) && (ct->subtarget[0])) {
+ bPoseChannel *pchanc= get_pose_channel(ob->pose, ct->subtarget);
+ if(pchanc)
+ pchanc->bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
+ }
}
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 1);
}
}
}