===Python API===
authorKen Hughes <khughes@pacific.edu>
Sun, 7 May 2006 14:57:58 +0000 (14:57 +0000)
committerKen Hughes <khughes@pacific.edu>
Sun, 7 May 2006 14:57:58 +0000 (14:57 +0000)
New Constraint API.  Constraints are accessible through a "constraints"
attribute in poses and objects.  Would be REALLY NICE for armature users to
pound on this code.

source/blender/include/butspace.h
source/blender/python/api2_2x/Blender.c
source/blender/python/api2_2x/Constraint.c [new file with mode: 0644]
source/blender/python/api2_2x/Constraint.h [new file with mode: 0644]
source/blender/python/api2_2x/Object.c
source/blender/python/api2_2x/Pose.c
source/blender/python/api2_2x/doc/API_intro.py
source/blender/python/api2_2x/doc/Constraint.py [new file with mode: 0644]
source/blender/python/api2_2x/doc/Object.py
source/blender/python/api2_2x/doc/Pose.py
source/blender/src/buttons_object.c

index d23b38fe69ea18e7acd41d6ae645db36dd26cb79..d0961f804e3ad01fbb94cf7a9c26c30e7dc177d3 100644 (file)
@@ -79,6 +79,13 @@ extern void do_effects_panels(unsigned short event);
 extern int mod_moveUp(void *ob_v, void *md_v);
 extern int mod_moveDown(void *ob_v, void *md_v);
 
+/* constraint */
+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 */
 extern void editing_panels(void);
 extern void do_common_editbuts(unsigned short event);
index 164ec5d426bdfb5fb5e2cfda06258c1cfedaa8d9..8f89989e0c8b9fc23def6c1b7b759f6135f1911b 100644 (file)
@@ -64,6 +64,7 @@ struct ID; /*keep me up here */
 #include "Armature.h"
 #include "BezTriple.h"
 #include "Camera.h"
+#include "Constraint.h"
 #include "Curve.h"
 #include "CurNurb.h"
 #include "Draw.h"
@@ -928,6 +929,7 @@ void M_Blender_Init(void)
        PyDict_SetItemString(dict, "BezTriple", BezTriple_Init());
        PyDict_SetItemString(dict, "BGL", BGL_Init());
        PyDict_SetItemString(dict, "CurNurb", CurNurb_Init());
+       PyDict_SetItemString(dict, "Constraint", Constraint_Init());
        PyDict_SetItemString(dict, "Curve", Curve_Init());
        PyDict_SetItemString(dict, "Camera", Camera_Init());
        PyDict_SetItemString(dict, "Draw", Draw_Init());
diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c
new file mode 100644 (file)
index 0000000..5572411
--- /dev/null
@@ -0,0 +1,1657 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Joseph Gilbert, Ken Hughes
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "Constraint.h" /*This must come first*/
+
+#include "DNA_object_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_vec_types.h"
+#include "DNA_curve_types.h"
+
+#include "BKE_main.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_action.h"
+#include "BLI_blenlib.h"
+#include "BIF_editconstraint.h"
+#include "BSE_editipo.h"
+#include "MEM_guardedalloc.h"
+#include "butspace.h"
+#include "blendef.h"
+#include "mydevice.h"
+
+#include "Object.h"
+#include "NLA.h"
+#include "gen_utils.h"
+
+enum constraint_constants {
+       EXPP_CONSTR_XROT = 0,
+       EXPP_CONSTR_YROT = 1,
+       EXPP_CONSTR_ZROT = 2,
+
+       EXPP_CONSTR_MAXX = TRACK_X,
+       EXPP_CONSTR_MAXY = TRACK_Y,
+       EXPP_CONSTR_MAXZ = TRACK_Z,
+       EXPP_CONSTR_MINX = TRACK_nX,
+       EXPP_CONSTR_MINY = TRACK_nY,
+       EXPP_CONSTR_MINZ = TRACK_nZ,
+
+       EXPP_CONSTR_TARGET = 100,
+       EXPP_CONSTR_TOLERANCE,
+       EXPP_CONSTR_ITERATIONS,
+       EXPP_CONSTR_BONE,
+       EXPP_CONSTR_CHAINLEN,
+       EXPP_CONSTR_POSWEIGHT,
+       EXPP_CONSTR_ROTWEIGHT,
+       EXPP_CONSTR_ROTATE,
+       EXPP_CONSTR_USETIP,
+
+       EXPP_CONSTR_ACTION,
+       EXPP_CONSTR_LOCAL,
+       EXPP_CONSTR_START,
+       EXPP_CONSTR_END,
+       EXPP_CONSTR_MIN,
+       EXPP_CONSTR_MAX,
+       EXPP_CONSTR_KEYON,
+
+       EXPP_CONSTR_TRACK,
+       EXPP_CONSTR_UP,
+
+       EXPP_CONSTR_RESTLENGTH,
+       EXPP_CONSTR_VOLVARIATION,
+       EXPP_CONSTR_VOLUMEMODE,
+       EXPP_CONSTR_PLANE,
+
+       EXPP_CONSTR_FOLLOW,
+       EXPP_CONSTR_OFFSET,
+       EXPP_CONSTR_FORWARD,
+
+       EXPP_CONSTR_LOCK,
+
+       EXPP_CONSTR_MINMAX,
+       EXPP_CONSTR_STICKY,
+
+       EXPP_CONSTR_COPY,
+};
+
+/*****************************************************************************/
+/* Python BPy_Constraint methods declarations:                               */
+/*****************************************************************************/
+static PyObject *Constraint_getName( BPy_Constraint * self );
+static int Constraint_setName( BPy_Constraint * self, PyObject *arg );
+static PyObject *Constraint_getType( BPy_Constraint * self );
+static PyObject *Constraint_getInfluence( BPy_Constraint * self );
+static int Constraint_setInfluence( BPy_Constraint * self, PyObject * arg );
+
+static PyObject *Constraint_moveUp( BPy_Constraint * self );
+static PyObject *Constraint_moveDown( BPy_Constraint * self );
+static PyObject *Constraint_insertKey( BPy_Constraint * self, PyObject * arg );
+
+static PyObject *Constraint_getData( BPy_Constraint * self, PyObject * key );
+static int Constraint_setData( BPy_Constraint * self, PyObject * key, 
+               PyObject * value );
+
+/*****************************************************************************/
+/* Python BPy_Constraint methods table:                                      */
+/*****************************************************************************/
+static PyMethodDef BPy_Constraint_methods[] = {
+       /* name, method, flags, doc */
+       {"up", ( PyCFunction ) Constraint_moveUp, METH_NOARGS,
+        "Move constraint up in stack"},
+       {"down", ( PyCFunction ) Constraint_moveDown, METH_NOARGS,
+        "Move constraint down in stack"},
+       {"insertKey", ( PyCFunction ) Constraint_insertKey, METH_VARARGS,
+        "Insert influence keyframe for constraint"},
+       {NULL, NULL, 0, NULL}
+};
+
+/*****************************************************************************/
+/* Python BPy_Constraint attributes get/set structure:                       */
+/*****************************************************************************/
+static PyGetSetDef BPy_Constraint_getseters[] = {
+       {"name",
+       (getter)Constraint_getName, (setter)Constraint_setName,
+        "Constraint name", NULL},
+       {"type",
+       (getter)Constraint_getType, (setter)NULL,
+        "Constraint type (read only)", NULL},
+       {"influence",
+       (getter)Constraint_getInfluence, (setter)Constraint_setInfluence,
+        "Constraint influence", NULL},
+       {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
+};
+
+/*****************************************************************************/
+/* Python Constraint_Type Mapping Methods table:                             */
+/*****************************************************************************/
+static PyMappingMethods Constraint_as_mapping = {
+       NULL,                               /* mp_length        */
+       ( binaryfunc ) Constraint_getData,      /* mp_subscript     */
+       ( objobjargproc ) Constraint_setData,   /* mp_ass_subscript */
+};
+
+/*****************************************************************************/
+/* Python Constraint_Type callback function prototypes:                      */
+/*****************************************************************************/
+static void Constraint_dealloc( BPy_Constraint * self );
+static PyObject *Constraint_repr( BPy_Constraint * self );
+
+/*****************************************************************************/
+/* Python Constraint_Type structure definition:                              */
+/*****************************************************************************/
+PyTypeObject Constraint_Type = {
+       PyObject_HEAD_INIT( NULL )  /* required py macro */
+       0,                          /* ob_size */
+       /*  For printing, in format "<module>.<name>" */
+       "Blender Constraint",         /* char *tp_name; */
+       sizeof( BPy_Constraint ),     /* int tp_basicsize; */
+       0,                          /* tp_itemsize;  For allocation */
+
+       /* Methods to implement standard operations */
+
+       ( destructor ) Constraint_dealloc,/* destructor tp_dealloc; */
+       NULL,                       /* printfunc tp_print; */
+       NULL,                       /* getattrfunc tp_getattr; */
+       NULL,                       /* setattrfunc tp_setattr; */
+       NULL,                       /* cmpfunc tp_compare; */
+       ( reprfunc ) Constraint_repr, /* reprfunc tp_repr; */
+
+       /* Method suites for standard classes */
+
+       NULL,                       /* PyNumberMethods *tp_as_number; */
+       NULL,                       /* PySequenceMethods *tp_as_sequence; */
+       &Constraint_as_mapping,       /* PyMappingMethods *tp_as_mapping; */
+
+       /* More standard operations (here for binary compatibility) */
+
+       NULL,                       /* hashfunc tp_hash; */
+       NULL,                       /* ternaryfunc tp_call; */
+       NULL,                       /* reprfunc tp_str; */
+       NULL,                       /* getattrofunc tp_getattro; */
+       NULL,                       /* setattrofunc tp_setattro; */
+
+       /* Functions to access object as input/output buffer */
+       NULL,                       /* PyBufferProcs *tp_as_buffer; */
+
+  /*** Flags to define presence of optional/expanded features ***/
+       Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
+
+       NULL,                       /*  char *tp_doc;  Documentation string */
+  /*** Assigned meaning in release 2.0 ***/
+       /* call function for all accessible objects */
+       NULL,                       /* traverseproc tp_traverse; */
+
+       /* delete references to contained objects */
+       NULL,                       /* inquiry tp_clear; */
+
+  /***  Assigned meaning in release 2.1 ***/
+  /*** rich comparisons ***/
+       NULL,                       /* richcmpfunc tp_richcompare; */
+
+  /***  weak reference enabler ***/
+       0,                          /* long tp_weaklistoffset; */
+
+  /*** Added in release 2.2 ***/
+       /*   Iterators */
+       NULL,                       /* getiterfunc tp_iter; */
+       NULL,                       /* iternextfunc tp_iternext; */
+
+  /*** Attribute descriptor and subclassing stuff ***/
+       BPy_Constraint_methods,       /* struct PyMethodDef *tp_methods; */
+       NULL,                       /* struct PyMemberDef *tp_members; */
+       BPy_Constraint_getseters,     /* struct PyGetSetDef *tp_getset; */
+       NULL,                       /* struct _typeobject *tp_base; */
+       NULL,                       /* PyObject *tp_dict; */
+       NULL,                       /* descrgetfunc tp_descr_get; */
+       NULL,                       /* descrsetfunc tp_descr_set; */
+       0,                          /* long tp_dictoffset; */
+       NULL,                       /* initproc tp_init; */
+       NULL,                       /* allocfunc tp_alloc; */
+       NULL,                       /* newfunc tp_new; */
+       /*  Low-level free-memory routine */
+       NULL,                       /* freefunc tp_free;  */
+       /* For PyObject_IS_GC */
+       NULL,                       /* inquiry tp_is_gc;  */
+       NULL,                       /* PyObject *tp_bases; */
+       /* method resolution order */
+       NULL,                       /* PyObject *tp_mro;  */
+       NULL,                       /* PyObject *tp_cache; */
+       NULL,                       /* PyObject *tp_subclasses; */
+       NULL,                       /* PyObject *tp_weaklist; */
+       NULL
+};
+
+/*****************************************************************************/
+/* Python BPy_Constraint methods:                                            */
+/*****************************************************************************/
+
+/*
+ * return the name of this constraint
+ */
+
+static PyObject *Constraint_getName( BPy_Constraint * self )
+{
+       if( !self->con )
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               "This constraint has been removed!" );
+       
+       return PyString_FromString( self->con->name );
+}
+
+/*
+ * set the name of this constraint
+ */
+
+static int Constraint_setName( BPy_Constraint * self, PyObject * attr )
+{
+       char *name = PyString_AsString( attr );
+       if( !name )
+               return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" );
+
+       if( !self->con )
+               return EXPP_ReturnIntError( PyExc_RuntimeError,
+                               "This constraint has been removed!" );
+       
+       BLI_strncpy( self->con->name, name, sizeof( self->con->name ) );
+
+       return 0;
+}
+
+/*
+ * return the influence of this constraint
+ */
+
+static PyObject *Constraint_getInfluence( BPy_Constraint * self )
+{
+       if( !self->con )
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               "This constraint has been removed!" );
+       
+       return PyFloat_FromDouble( (double)self->con->enforce );
+}
+
+/*
+ * set the influence of this constraint
+ */
+
+static int Constraint_setInfluence( BPy_Constraint * self, PyObject * value )
+{
+       if( !self->con )
+               return EXPP_ReturnIntError( PyExc_RuntimeError,
+                               "This constraint has been removed!" );
+
+       return EXPP_setFloatClamped( value, &self->con->enforce, 0.0, 1.0 );
+}
+
+/*
+ * return the type of this constraint
+ */
+
+static PyObject *Constraint_getType( BPy_Constraint * self )
+{
+       if( !self->con )
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               "This constraint has been removed!" );
+       
+       return PyInt_FromLong( self->con->type );
+}
+
+/*
+ * move the constraint up in the stack
+ */
+
+
+static PyObject *Constraint_moveUp( BPy_Constraint * self )
+{
+       if( !self->con )
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               "This constraint has been removed!" );
+       
+       const_moveUp( self->obj, self->con );
+       Py_RETURN_NONE;
+}
+
+/*
+ * move the constraint down in the stack
+ */
+
+static PyObject *Constraint_moveDown( BPy_Constraint * self )
+{
+       if( !self->con )
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               "This constraint has been removed!" );
+
+       const_moveDown( self->obj, self->con );
+       Py_RETURN_NONE;
+}
+
+/*
+ * add keyframe for influence
+       base on code in add_influence_key_to_constraint_func()
+ */
+
+static PyObject *Constraint_insertKey( BPy_Constraint * self, PyObject * arg )
+{
+       IpoCurve *icu;
+       float cfra;
+       char actname[32] = "";
+       Object *ob = self->obj;
+       bConstraint *con = self->con;
+
+       if( !self->con )
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               "This constraint has been removed!" );
+
+       /* get frame for inserting key */
+       if( !PyArg_ParseTuple( arg, "f", &cfra ) )
+               return EXPP_ReturnPyObjError( PyExc_TypeError,
+                               "expected a float argument" );
+
+       // constraint_active_func(ob_v, con_v);
+       get_constraint_ipo_context( ob, actname );
+       icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, CO_ENFORCE);
+
+       if( ob->action )
+               insert_vert_ipo( icu, get_action_frame(ob, cfra), con->enforce);
+       else
+               insert_vert_ipo( icu, cfra, con->enforce);
+
+       Py_RETURN_NONE;
+}
+
+/*****************************************************************************/
+/* Specific constraint get/set procedures                                    */
+/*****************************************************************************/
+
+static PyObject *kinematic_getter( BPy_Constraint * self, int type )
+{
+       bKinematicConstraint *con = (bKinematicConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET:
+               return Object_CreatePyObject( con->tar );
+       case EXPP_CONSTR_BONE:
+               return PyString_FromString( con->subtarget );
+       case EXPP_CONSTR_TOLERANCE:
+               return PyFloat_FromDouble( (double)con->tolerance );
+       case EXPP_CONSTR_ITERATIONS:
+               return PyInt_FromLong( (long)con->iterations );
+       case EXPP_CONSTR_CHAINLEN:
+               return PyInt_FromLong( (long)con->rootbone );
+       case EXPP_CONSTR_POSWEIGHT:
+               return PyFloat_FromDouble( (double)con->weight );
+       case EXPP_CONSTR_ROTWEIGHT:
+               return PyFloat_FromDouble( (double)con->orientweight );
+       case EXPP_CONSTR_ROTATE:
+               return PyBool_FromLong( (long)( con->flag & CONSTRAINT_IK_ROT ) ) ;
+       case EXPP_CONSTR_USETIP:
+               return PyBool_FromLong( (long)( con->flag & CONSTRAINT_IK_TIP ) ) ;
+       default:
+               return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static int kinematic_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+       bKinematicConstraint *con = (bKinematicConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET: {
+               Object *obj = (( BPy_Object * )value)->object;
+               if( !BPy_Object_Check( value ) )
+                       return EXPP_ReturnIntError( PyExc_TypeError, 
+                                       "expected BPy object argument" );
+               con->tar = obj;
+               return 0;
+               }
+       case EXPP_CONSTR_BONE: {
+               char *name = PyString_AsString( value );
+               if( !name )
+                       return EXPP_ReturnIntError( PyExc_TypeError,
+                                       "expected string arg" );
+
+               BLI_strncpy( con->subtarget, name, sizeof( con->subtarget ) );
+
+               return 0;
+               }
+       case EXPP_CONSTR_TOLERANCE:
+               return EXPP_setFloatClamped( value, &con->tolerance, 0.0001, 1.0 );
+       case EXPP_CONSTR_ITERATIONS:
+               return EXPP_setIValueClamped( value, &con->iterations, 1, 10000, 'h' );
+       case EXPP_CONSTR_CHAINLEN:
+               return EXPP_setIValueClamped( value, &con->rootbone, 0, 255, 'i' );
+       case EXPP_CONSTR_POSWEIGHT:
+               return EXPP_setFloatClamped( value, &con->weight, 0.01, 1.0 );
+       case EXPP_CONSTR_ROTWEIGHT:
+               return EXPP_setFloatClamped( value, &con->orientweight, 0.01, 1.0 );
+       case EXPP_CONSTR_ROTATE:
+               return EXPP_setBitfield( value, &con->flag, CONSTRAINT_IK_ROT, 'h' );
+       case EXPP_CONSTR_USETIP:
+               return EXPP_setBitfield( value, &con->flag, CONSTRAINT_IK_TIP, 'h' );
+       default:
+               return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static PyObject *action_getter( BPy_Constraint * self, int type )
+{
+       bActionConstraint *con = (bActionConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET:
+               return Object_CreatePyObject( con->tar );
+       case EXPP_CONSTR_BONE:
+               return PyString_FromString( con->subtarget );
+       case EXPP_CONSTR_ACTION:
+               return Action_CreatePyObject( con->act );
+       case EXPP_CONSTR_LOCAL:
+               return PyBool_FromLong( (long)( con->local & SELECT ) );
+       case EXPP_CONSTR_START:
+               return PyInt_FromLong( (long)con->start );
+       case EXPP_CONSTR_END:
+               return PyInt_FromLong( (long)con->end );
+       case EXPP_CONSTR_MIN:
+               return PyFloat_FromDouble( (double)con->min );
+       case EXPP_CONSTR_MAX:
+               return PyFloat_FromDouble( (double)con->max );
+       case EXPP_CONSTR_KEYON:
+               return PyInt_FromLong( (long)con->type );
+       default:
+               return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static int action_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+       bActionConstraint *con = (bActionConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET: {
+               Object *obj = (( BPy_Object * )value)->object;
+               if( !BPy_Object_Check( value ) )
+                       return EXPP_ReturnIntError( PyExc_TypeError, 
+                                       "expected BPy object argument" );
+               con->tar = obj;
+               return 0;
+               }
+       case EXPP_CONSTR_BONE: {
+               char *name = PyString_AsString( value );
+               if( !name )
+                       return EXPP_ReturnIntError( PyExc_TypeError,
+                                       "expected string arg" );
+
+               BLI_strncpy( con->subtarget, name, sizeof( con->subtarget ) );
+
+               return 0;
+               }
+       case EXPP_CONSTR_ACTION: {
+               bAction *act = (( BPy_Action * )value)->action;
+               if( !Action_CheckPyObject( value ) )
+                       return EXPP_ReturnIntError( PyExc_TypeError, 
+                                       "expected BPy action argument" );
+               con->act = act;
+               return 0;
+               }
+       case EXPP_CONSTR_LOCAL:
+               return EXPP_setBitfield( value, &con->local, SELECT, 'h' );
+       case EXPP_CONSTR_START:
+               return EXPP_setIValueClamped( value, &con->start, 1, MAXFRAME, 'h' );
+       case EXPP_CONSTR_END:
+               return EXPP_setIValueClamped( value, &con->end, 1, MAXFRAME, 'h' );
+       case EXPP_CONSTR_MIN:
+               return EXPP_setFloatClamped( value, &con->min, -180.0, 180.0 );
+       case EXPP_CONSTR_MAX:
+               return EXPP_setFloatClamped( value, &con->max, -180.0, 180.0 );
+       case EXPP_CONSTR_KEYON:
+               return EXPP_setIValueRange( value, &con->type,
+                               EXPP_CONSTR_XROT, EXPP_CONSTR_ZROT, 'h' );
+       default:
+               return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static PyObject *trackto_getter( BPy_Constraint * self, int type )
+{
+       bTrackToConstraint *con = (bTrackToConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET:
+               return Object_CreatePyObject( con->tar );
+       case EXPP_CONSTR_BONE:
+               return PyString_FromString( con->subtarget );
+       case EXPP_CONSTR_TRACK:
+               return PyInt_FromLong( (long)con->reserved1 );
+       case EXPP_CONSTR_UP:
+               return PyInt_FromLong( (long)con->reserved2 );
+       default:
+               return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static int trackto_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+       bTrackToConstraint *con = (bTrackToConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET: {
+               Object *obj = (( BPy_Object * )value)->object;
+               if( !BPy_Object_Check( value ) )
+                       return EXPP_ReturnIntError( PyExc_TypeError, 
+                                       "expected BPy object argument" );
+               con->tar = obj;
+               return 0;
+               }
+       case EXPP_CONSTR_BONE: {
+               char *name = PyString_AsString( value );
+               if( !name )
+                       return EXPP_ReturnIntError( PyExc_TypeError,
+                                       "expected string arg" );
+
+               BLI_strncpy( con->subtarget, name, sizeof( con->subtarget ) );
+
+               return 0;
+               }
+       case EXPP_CONSTR_TRACK:
+               return EXPP_setIValueRange( value, &con->reserved1,
+                               TRACK_X, TRACK_nZ, 'i' );
+       case EXPP_CONSTR_UP:
+               return EXPP_setIValueRange( value, &con->reserved2,
+                               UP_X, UP_Z, 'i' );
+       default:
+               return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static PyObject *stretchto_getter( BPy_Constraint * self, int type )
+{
+       bStretchToConstraint *con = (bStretchToConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET:
+               return Object_CreatePyObject( con->tar );
+       case EXPP_CONSTR_BONE:
+               return PyString_FromString( con->subtarget );
+       case EXPP_CONSTR_RESTLENGTH:
+               return PyFloat_FromDouble( (double)con->orglength );
+       case EXPP_CONSTR_VOLVARIATION:
+               return PyFloat_FromDouble( (double)con->bulge );
+       case EXPP_CONSTR_VOLUMEMODE:
+               return PyInt_FromLong( (long)con->volmode );
+       case EXPP_CONSTR_PLANE:
+               return PyInt_FromLong( (long)con->plane );
+       default:
+               return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static int stretchto_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+       bStretchToConstraint *con = (bStretchToConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET: {
+               Object *obj = (( BPy_Object * )value)->object;
+               if( !BPy_Object_Check( value ) )
+                       return EXPP_ReturnIntError( PyExc_TypeError, 
+                                       "expected BPy object argument" );
+               con->tar = obj;
+               return 0;
+               }
+       case EXPP_CONSTR_BONE: {
+               char *name = PyString_AsString( value );
+               if( !name )
+                       return EXPP_ReturnIntError( PyExc_TypeError,
+                                       "expected string arg" );
+
+               BLI_strncpy( con->subtarget, name, sizeof( con->subtarget ) );
+
+               return 0;
+               }
+       case EXPP_CONSTR_RESTLENGTH:
+               return EXPP_setFloatClamped( value, &con->orglength, 0.0, 100.0 );
+       case EXPP_CONSTR_VOLVARIATION:
+               return EXPP_setFloatClamped( value, &con->bulge, 0.0, 100.0 );
+       case EXPP_CONSTR_VOLUMEMODE:
+               return EXPP_setIValueRange( value, &con->volmode,
+                               VOLUME_XZ, NO_VOLUME, 'h' );
+       case EXPP_CONSTR_PLANE: {
+               int status, oldcode = con->plane;
+               status = EXPP_setIValueRange( value, &con->plane,
+                               PLANE_X, PLANE_Z, 'h' );
+               if( !status && con->plane == PLANE_Y ) {
+                       con->plane = oldcode;
+                       return EXPP_ReturnIntError( PyExc_ValueError,
+                                       "value must be either PLANEX or PLANEZ" );
+               }
+               return status;
+               }
+       default:
+               return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static PyObject *followpath_getter( BPy_Constraint * self, int type )
+{
+       bFollowPathConstraint *con = (bFollowPathConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET:
+               return Object_CreatePyObject( con->tar );
+       case EXPP_CONSTR_FOLLOW:
+               return PyBool_FromLong( (long)( con->followflag & SELECT ) );
+       case EXPP_CONSTR_OFFSET:
+               return PyFloat_FromDouble( (double)con->offset );
+       case EXPP_CONSTR_FORWARD:
+               return PyInt_FromLong( (long)con->trackflag );
+       case EXPP_CONSTR_UP:
+               return PyInt_FromLong( (long)con->upflag );
+       default:
+               return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static int followpath_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+       bFollowPathConstraint *con = (bFollowPathConstraint *)(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_FOLLOW:
+               return EXPP_setBitfield( value, &con->followflag, SELECT, 'i' );
+       case EXPP_CONSTR_OFFSET:
+               return EXPP_setFloatClamped( value, &con->offset,
+                               -MAXFRAMEF, MAXFRAMEF );
+       case EXPP_CONSTR_FORWARD:
+               return EXPP_setIValueRange( value, &con->trackflag,
+                               TRACK_X, TRACK_nZ, 'i' );
+       case EXPP_CONSTR_UP:
+               return EXPP_setIValueRange( value, &con->upflag,
+                               UP_X, UP_Z, 'i' );
+       default:
+               return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static PyObject *locktrack_getter( BPy_Constraint * self, int type )
+{
+       bLockTrackConstraint *con = (bLockTrackConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET:
+               return Object_CreatePyObject( con->tar );
+       case EXPP_CONSTR_BONE:
+               return PyString_FromString( con->subtarget );
+       case EXPP_CONSTR_TRACK:
+               return PyInt_FromLong( (long)con->trackflag );
+       case EXPP_CONSTR_LOCK:
+               return PyInt_FromLong( (long)con->lockflag );
+       default:
+               return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static int locktrack_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+       bLockTrackConstraint *con = (bLockTrackConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET: {
+               Object *obj = (( BPy_Object * )value)->object;
+               if( !BPy_Object_Check( value ) )
+                       return EXPP_ReturnIntError( PyExc_TypeError, 
+                                       "expected BPy object argument" );
+               con->tar = obj;
+               return 0;
+               }
+       case EXPP_CONSTR_BONE: {
+               char *name = PyString_AsString( value );
+               if( !name )
+                       return EXPP_ReturnIntError( PyExc_TypeError,
+                                       "expected string arg" );
+
+               BLI_strncpy( con->subtarget, name, sizeof( con->subtarget ) );
+
+               return 0;
+               }
+       case EXPP_CONSTR_TRACK:
+               return EXPP_setIValueRange( value, &con->trackflag,
+                               TRACK_X, TRACK_nZ, 'i' );
+       case EXPP_CONSTR_LOCK:
+               return EXPP_setIValueRange( value, &con->lockflag,
+                               LOCK_X, LOCK_Z, 'i' );
+       default:
+               return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static PyObject *floor_getter( BPy_Constraint * self, int type )
+{
+       bMinMaxConstraint *con = (bMinMaxConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET:
+               return Object_CreatePyObject( con->tar );
+       case EXPP_CONSTR_BONE:
+               return PyString_FromString( con->subtarget );
+       case EXPP_CONSTR_MINMAX:
+               return PyInt_FromLong( (long)con->minmaxflag );
+       case EXPP_CONSTR_OFFSET:
+               return PyFloat_FromDouble( (double)con->offset );
+       case EXPP_CONSTR_STICKY:
+               return PyBool_FromLong( (long)( con->sticky & SELECT ) ) ;
+       default:
+               return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static int floor_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+       bMinMaxConstraint *con = (bMinMaxConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET: {
+               Object *obj = (( BPy_Object * )value)->object;
+               if( !BPy_Object_Check( value ) )
+                       return EXPP_ReturnIntError( PyExc_TypeError, 
+                                       "expected BPy object argument" );
+               con->tar = obj;
+               return 0;
+               }
+       case EXPP_CONSTR_BONE: {
+               char *name = PyString_AsString( value );
+               if( !name )
+                       return EXPP_ReturnIntError( PyExc_TypeError,
+                                       "expected string arg" );
+
+               BLI_strncpy( con->subtarget, name, sizeof( con->subtarget ) );
+
+               return 0;
+               }
+       case EXPP_CONSTR_MINMAX:
+               return EXPP_setIValueRange( value, &con->minmaxflag,
+                               EXPP_CONSTR_MAXX, EXPP_CONSTR_MINZ, 'i' );
+       case EXPP_CONSTR_OFFSET:
+               return EXPP_setFloatClamped( value, &con->offset, -100.0, 100.0 );
+       case EXPP_CONSTR_STICKY:
+               return EXPP_setBitfield( value, &con->sticky, SELECT, 'h' );
+       default:
+               return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static PyObject *locatelike_getter( BPy_Constraint * self, int type )
+{
+       bLocateLikeConstraint *con = (bLocateLikeConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET:
+               return Object_CreatePyObject( con->tar );
+       case EXPP_CONSTR_BONE:
+               return PyString_FromString( con->subtarget );
+       case EXPP_CONSTR_COPY:
+               return PyInt_FromLong( (long)con->flag );
+       default:
+               return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static int locatelike_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+       bLocateLikeConstraint *con = (bLocateLikeConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET: {
+               Object *obj = (( BPy_Object * )value)->object;
+               if( !BPy_Object_Check( value ) )
+                       return EXPP_ReturnIntError( PyExc_TypeError, 
+                                       "expected BPy object argument" );
+               con->tar = obj;
+               return 0;
+               }
+       case EXPP_CONSTR_BONE: {
+               char *name = PyString_AsString( value );
+               if( !name )
+                       return EXPP_ReturnIntError( PyExc_TypeError,
+                                       "expected string arg" );
+
+               BLI_strncpy( con->subtarget, name, sizeof( con->subtarget ) );
+
+               return 0;
+               }
+       case EXPP_CONSTR_COPY:
+               return EXPP_setIValueRange( value, &con->flag,
+                               0, LOCLIKE_X | LOCLIKE_Y | LOCLIKE_Z, 'i' );
+       default:
+               return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static PyObject *rotatelike_getter( BPy_Constraint * self, int type )
+{
+       bRotateLikeConstraint *con = (bRotateLikeConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET:
+               return Object_CreatePyObject( con->tar );
+       case EXPP_CONSTR_BONE:
+               return PyString_FromString( con->subtarget );
+       case EXPP_CONSTR_COPY:
+               return PyInt_FromLong( (long)con->flag );
+       default:
+               return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static int rotatelike_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+       bRotateLikeConstraint *con = (bRotateLikeConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET: {
+               Object *obj = (( BPy_Object * )value)->object;
+               if( !BPy_Object_Check( value ) )
+                       return EXPP_ReturnIntError( PyExc_TypeError, 
+                                       "expected BPy object argument" );
+               con->tar = obj;
+               return 0;
+               }
+       case EXPP_CONSTR_BONE: {
+               char *name = PyString_AsString( value );
+               if( !name )
+                       return EXPP_ReturnIntError( PyExc_TypeError,
+                                       "expected string arg" );
+
+               BLI_strncpy( con->subtarget, name, sizeof( con->subtarget ) );
+
+               return 0;
+               }
+       case EXPP_CONSTR_COPY:
+               return EXPP_setIValueRange( value, &con->flag,
+                               0, LOCLIKE_X | LOCLIKE_Y | LOCLIKE_Z, 'i' );
+       default:
+               return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static PyObject *sizelike_getter( BPy_Constraint * self, int type )
+{
+       bSizeLikeConstraint *con = (bSizeLikeConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET:
+               return Object_CreatePyObject( con->tar );
+       case EXPP_CONSTR_BONE:
+               return PyString_FromString( con->subtarget );
+       case EXPP_CONSTR_COPY:
+               return PyInt_FromLong( (long)con->flag );
+       default:
+               return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static int sizelike_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+       bSizeLikeConstraint *con = (bSizeLikeConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET: {
+               Object *obj = (( BPy_Object * )value)->object;
+               if( !BPy_Object_Check( value ) )
+                       return EXPP_ReturnIntError( PyExc_TypeError, 
+                                       "expected BPy object argument" );
+               con->tar = obj;
+               return 0;
+               }
+       case EXPP_CONSTR_BONE: {
+               char *name = PyString_AsString( value );
+               if( !name )
+                       return EXPP_ReturnIntError( PyExc_TypeError,
+                                       "expected string arg" );
+
+               BLI_strncpy( con->subtarget, name, sizeof( con->subtarget ) );
+
+               return 0;
+               }
+       case EXPP_CONSTR_COPY:
+               return EXPP_setIValueRange( value, &con->flag,
+                               0, LOCLIKE_X | LOCLIKE_Y | LOCLIKE_Z, 'i' );
+       default:
+               return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+       }
+}
+
+/*
+ * get data from a constraint
+ */
+
+static PyObject *Constraint_getData( BPy_Constraint * self, PyObject * key )
+{
+       int setting;
+
+       if( !PyInt_CheckExact( key ) )
+               return EXPP_ReturnPyObjError( PyExc_TypeError,
+                               "expected an int arg" );
+
+       if( !self->con )
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               "This constraint has been removed!" );
+       
+       setting = PyInt_AsLong( key );
+       switch( self->con->type ) {
+               case CONSTRAINT_TYPE_NULL:
+                       Py_RETURN_NONE;
+               case CONSTRAINT_TYPE_TRACKTO:
+                       return trackto_getter( self, setting );
+               case CONSTRAINT_TYPE_KINEMATIC:
+                       return kinematic_getter( self, setting );
+               case CONSTRAINT_TYPE_FOLLOWPATH:
+                       return followpath_getter( self, setting );
+               case CONSTRAINT_TYPE_ACTION:
+                       return action_getter( self, setting );
+               case CONSTRAINT_TYPE_LOCKTRACK:
+                       return locktrack_getter( self, setting );
+               case CONSTRAINT_TYPE_STRETCHTO:
+                       return stretchto_getter( self, setting );
+               case CONSTRAINT_TYPE_MINMAX:
+                       return floor_getter( self, setting );
+               case CONSTRAINT_TYPE_LOCLIKE:
+                       return locatelike_getter( self, setting );
+               case CONSTRAINT_TYPE_ROTLIKE:
+                       return rotatelike_getter( self, setting );
+               case CONSTRAINT_TYPE_SIZELIKE:
+                       return sizelike_getter( self, setting );
+
+               case CONSTRAINT_TYPE_CHILDOF:   /* Unimplemented */
+               case CONSTRAINT_TYPE_ROTLIMIT:
+               case CONSTRAINT_TYPE_LOCLIMIT:
+               case CONSTRAINT_TYPE_SIZELIMIT:
+               case CONSTRAINT_TYPE_PYTHON:
+               default:
+                       return EXPP_ReturnPyObjError( PyExc_KeyError,
+                                       "unknown constraint type" );
+       }
+}
+
+static int Constraint_setData( BPy_Constraint * self, PyObject * key, 
+               PyObject * arg )
+{
+       int key_int, result;
+
+       if( !PyNumber_Check( key ) )
+               return EXPP_ReturnIntError( PyExc_TypeError,
+                               "expected an int arg" );
+       if( !self->con )
+               return EXPP_ReturnIntError( PyExc_RuntimeError,
+                               "This constraint has been removed!" );
+       
+       key_int = PyInt_AsLong( key );
+       switch( self->con->type ) {
+       case CONSTRAINT_TYPE_KINEMATIC:
+               result = kinematic_setter( self, key_int, arg );
+               break;
+       case CONSTRAINT_TYPE_ACTION:
+               result = action_setter( self, key_int, arg );
+               break;
+       case CONSTRAINT_TYPE_TRACKTO:
+               result = trackto_setter( self, key_int, arg );
+               break;
+       case CONSTRAINT_TYPE_STRETCHTO:
+               result = stretchto_setter( self, key_int, arg );
+               break;
+       case CONSTRAINT_TYPE_FOLLOWPATH:
+               result = followpath_setter( self, key_int, arg );
+               break;
+       case CONSTRAINT_TYPE_LOCKTRACK:
+               result = locktrack_setter( self, key_int, arg );
+               break;
+       case CONSTRAINT_TYPE_MINMAX:
+               result = floor_setter( self, key_int, arg );
+               break;
+       case CONSTRAINT_TYPE_LOCLIKE:
+               result = locatelike_setter( self, key_int, arg );
+               break;
+       case CONSTRAINT_TYPE_ROTLIKE:
+               result = rotatelike_setter( self, key_int, arg );
+               break;
+       case CONSTRAINT_TYPE_SIZELIKE:
+               result = sizelike_setter( self, key_int, arg );
+               break;
+       case CONSTRAINT_TYPE_CHILDOF:   /* Unimplemented */
+       case CONSTRAINT_TYPE_ROTLIMIT:
+       case CONSTRAINT_TYPE_LOCLIMIT:
+       case CONSTRAINT_TYPE_SIZELIMIT:
+       case CONSTRAINT_TYPE_PYTHON:
+       default:
+               return EXPP_ReturnIntError( PyExc_RuntimeError,
+                               "unsupported constraint setting" );
+       }
+       if( !result && self->pchan )
+               update_pose_constraint_flags( self->obj->pose );
+       return result;
+}
+
+/*****************************************************************************/
+/* Function:    Constraint_dealloc                                           */
+/* Description: This is a callback function for the BPy_Constraint type. It  */
+/*              destroys data when the object is deleted.                    */
+/*****************************************************************************/
+static void Constraint_dealloc( BPy_Constraint * self )
+{
+       PyObject_DEL( self );
+}
+
+/*****************************************************************************/
+/* Function:    Constraint_repr                                              */
+/* Description: This is a callback function for the BPy_Constraint type. It  */
+/*              builds a meaningful string to represent constraint objects.  */
+/*****************************************************************************/
+
+static PyObject *Constraint_repr( BPy_Constraint * self )
+{
+       char type[32];
+
+       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 );
+}
+
+/* Three Python Constraint_Type helper functions needed by the Object module: */
+
+/*****************************************************************************/
+/* Function:    Constraint_CreatePyObject                                    */
+/* Description: This function will create a new BPy_Constraint from an       */
+/*              existing Blender constraint structure.                       */
+/*****************************************************************************/
+PyObject *Constraint_CreatePyObject( bPoseChannel *pchan, Object *obj,
+               bConstraint *con )
+{
+       BPy_Constraint *pycon;
+       pycon = ( BPy_Constraint * ) PyObject_NEW( BPy_Constraint,
+                       &Constraint_Type );
+       if( !pycon )
+               return EXPP_ReturnPyObjError( PyExc_MemoryError,
+                                             "couldn't create BPy_Constraint object" );
+
+       pycon->con = con;
+
+       /* one of these two will be NULL */
+       pycon->obj = obj;       
+       pycon->pchan = pchan;
+       return ( PyObject * ) pycon;
+}
+
+/*****************************************************************************/
+/* Function:    Constraint_CheckPyObject                                     */
+/* Description: This function returns true when the given PyObject is of the */
+/*              type Constraint. Otherwise it will return false.               */
+/*****************************************************************************/
+int Constraint_CheckPyObject( PyObject * pyobj )
+{
+       return ( pyobj->ob_type == &Constraint_Type );
+}
+
+/*****************************************************************************/
+/* Function:    Constraint_FromPyObject                                      */
+/* Description: This function returns the Blender constraint from the given  */
+/*              PyObject.                                                    */
+/*****************************************************************************/
+bConstraint *Constraint_FromPyObject( BPy_Constraint * self )
+{
+       return self->con;
+}
+
+/*****************************************************************************/
+/* Constraint Sequence wrapper                                               */
+/*****************************************************************************/
+
+/*
+ * Initialize the interator
+ */
+
+static PyObject *ConstraintSeq_getIter( BPy_ConstraintSeq * self )
+{
+       if( self->pchan )
+               self->iter = (bConstraint *)self->pchan->constraints.first;
+       else
+               self->iter = (bConstraint *)self->obj->constraints.first;
+       return EXPP_incr_ret ( (PyObject *) self );
+}
+
+/*
+ * Get the next Constraint
+ */
+
+static PyObject *ConstraintSeq_nextIter( BPy_ConstraintSeq * self )
+{
+       bConstraint *this = self->iter;
+       if( this ) {
+               self->iter = this->next;
+               return Constraint_CreatePyObject( self->pchan, self->obj, this );
+       }
+
+       return EXPP_ReturnPyObjError( PyExc_StopIteration,
+                       "iterator at end" );
+}
+
+/* return the number of constraints */
+
+static int ConstraintSeq_length( BPy_ConstraintSeq * self )
+{
+       return BLI_countlist( self->pchan ?
+               &self->pchan->constraints : &self->obj->constraints );
+}
+
+/* return a constraint */
+
+static PyObject *ConstraintSeq_item( BPy_ConstraintSeq * self, int i )
+{
+       bConstraint *con = NULL;
+
+       /* if index is negative, start counting from the end of the list */
+       if( i < 0 )
+               i += ConstraintSeq_length( self );
+
+       /* skip through the list until we get the constraint or end of list */
+
+       if( self->pchan )
+               con = self->pchan->constraints.first;
+       else
+               con = self->obj->constraints.first;
+
+       while( i && con ) {
+               --i;
+               con = con->next;
+       }
+
+       if( con )
+               return Constraint_CreatePyObject( self->pchan, self->obj, con );
+       else
+               return EXPP_ReturnPyObjError( PyExc_IndexError,
+                               "array index out of range" );
+}
+
+/*****************************************************************************/
+/* Python BPy_ConstraintSeq sequence table:                                  */
+/*****************************************************************************/
+static PySequenceMethods ConstraintSeq_as_sequence = {
+       ( inquiry ) ConstraintSeq_length,       /* sq_length */
+       ( binaryfunc ) 0,       /* sq_concat */
+       ( intargfunc ) 0,       /* sq_repeat */
+       ( intargfunc ) ConstraintSeq_item,      /* sq_item */
+       ( intintargfunc ) 0,    /* sq_slice */
+       ( intobjargproc ) 0,    /* sq_ass_item */
+       ( intintobjargproc ) 0, /* sq_ass_slice */
+       ( objobjproc ) 0,       /* sq_contains */
+       ( binaryfunc ) 0,               /* sq_inplace_concat */
+       ( intargfunc ) 0,               /* sq_inplace_repeat */
+};
+
+/* create a new constraint at the end of the list */
+
+static PyObject *ConstraintSeq_append( BPy_ConstraintSeq *self, PyObject *args )
+{
+       int type;
+       bConstraint *con;
+
+       if( !PyArg_ParseTuple( args, "i", &type ) )
+               EXPP_ReturnPyObjError( PyExc_TypeError, "expected int argument" );
+
+       /* type 0 is CONSTRAINT_TYPE_NULL, should we be able to add one of these? */
+       if( type <= CONSTRAINT_TYPE_NULL || type >= CONSTRAINT_TYPE_MINMAX ) 
+               return EXPP_ReturnPyObjError( PyExc_ValueError,
+                               "int argument out of range" );
+
+       con = add_new_constraint( type );
+       if( self->pchan ) {
+               BLI_addtail( &self->pchan->constraints, con );
+               update_pose_constraint_flags( self->obj->pose );
+       }
+       else
+               BLI_addtail( &self->obj->constraints, con );
+
+       return Constraint_CreatePyObject( self->pchan, self->obj, con );
+                               
+}
+
+/* remove an existing constraint */
+
+static PyObject *ConstraintSeq_remove( BPy_ConstraintSeq *self, PyObject *args )
+{
+       BPy_Constraint *pyobj;
+       Object *obj;
+       bConstraint *con;
+
+       /* check that argument is a constraint */
+       if( !PyArg_ParseTuple( args, "O!", &Constraint_Type, &pyobj ) )
+               return EXPP_ReturnPyObjError( PyExc_TypeError,
+                               "expected a constraint as an argument" );
+
+       /* 
+        * check that constraintseq and constraint refer to the same object
+        * (this is more for user sanity than anything else)
+        */
+
+       if( self->obj != pyobj->obj )
+               return EXPP_ReturnPyObjError( PyExc_AttributeError,
+                               "constraint does not belong to this object" );
+       obj = self->obj;
+
+       if( !pyobj->con )
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               "This constraint has already been removed!" );
+
+       /* verify the constraint is still exists in the stack */
+       if( self->pchan )
+               con = self->pchan->constraints.first;
+       else
+               con = obj->constraints.first;
+       while( con && con != pyobj->con )
+               con = con->next;
+       if( !con )
+               return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                               "This constraint is no longer in the object's stack" );
+
+       /* do the actual removal */
+       if( self->pchan )
+               BLI_remlink(&(self->pchan->constraints), con);
+       else
+               BLI_remlink(&(obj->constraints), con);
+       del_constr_func (obj, con);
+
+       pyobj->con = NULL;
+       Py_RETURN_NONE;
+}
+
+/*****************************************************************************/
+/* Function:    ConstraintSeq_dealloc                                        */
+/* Description: This is a callback function for the BPy_ConstraintSeq type.  */
+/*              It destroys data when the object is deleted.                 */
+/*****************************************************************************/
+static void ConstraintSeq_dealloc( BPy_Constraint * self )
+{
+       PyObject_DEL( self );
+}
+
+/*****************************************************************************/
+/* Python BPy_ConstraintSeq methods table:                                   */
+/*****************************************************************************/
+static PyMethodDef BPy_ConstraintSeq_methods[] = {
+       /* name, method, flags, doc */
+       {"append", ( PyCFunction ) ConstraintSeq_append, METH_VARARGS,
+        "(type) - add a new constraint, where type is the constraint type"},
+       {"remove", ( PyCFunction ) ConstraintSeq_remove, METH_VARARGS,
+        "(con) - remove an existing constraint, where con is a constraint from this object."},
+       {NULL, NULL, 0, NULL}
+};
+
+/*****************************************************************************/
+/* Python ConstraintSeq_Type structure definition:                           */
+/*****************************************************************************/
+PyTypeObject ConstraintSeq_Type = {
+       PyObject_HEAD_INIT( NULL )  /* required py macro */
+       0,                          /* ob_size */
+       /*  For printing, in format "<module>.<name>" */
+       "Blender Constraint Sequence",/* char *tp_name; */
+       sizeof( BPy_ConstraintSeq ),     /* int tp_basicsize; */
+       0,                          /* tp_itemsize;  For allocation */
+
+       /* Methods to implement standard operations */
+
+       ( destructor ) ConstraintSeq_dealloc,/* destructor tp_dealloc; */
+       NULL,                       /* printfunc tp_print; */
+       NULL,                       /* getattrfunc tp_getattr; */
+       NULL,                       /* setattrfunc tp_setattr; */
+       NULL,                       /* cmpfunc tp_compare; */
+       ( reprfunc ) NULL,          /* reprfunc tp_repr; */
+
+       /* Method suites for standard classes */
+
+       NULL,                       /* PyNumberMethods *tp_as_number; */
+       &ConstraintSeq_as_sequence,        /* PySequenceMethods *tp_as_sequence; */
+       NULL,                       /* PyMappingMethods *tp_as_mapping; */
+
+       /* More standard operations (here for binary compatibility) */
+
+       NULL,                       /* hashfunc tp_hash; */
+       NULL,                       /* ternaryfunc tp_call; */
+       NULL,                       /* reprfunc tp_str; */
+       NULL,                       /* getattrofunc tp_getattro; */
+       NULL,                       /* setattrofunc tp_setattro; */
+
+       /* Functions to access object as input/output buffer */
+       NULL,                       /* PyBufferProcs *tp_as_buffer; */
+
+  /*** Flags to define presence of optional/expanded features ***/
+       Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
+
+       NULL,                       /*  char *tp_doc;  Documentation string */
+  /*** Assigned meaning in release 2.0 ***/
+       /* call function for all accessible objects */
+       NULL,                       /* traverseproc tp_traverse; */
+
+       /* delete references to contained objects */
+       NULL,                       /* inquiry tp_clear; */
+
+  /***  Assigned meaning in release 2.1 ***/
+  /*** rich comparisons ***/
+       NULL,                       /* richcmpfunc tp_richcompare; */
+
+  /***  weak reference enabler ***/
+       0,                          /* long tp_weaklistoffset; */
+
+  /*** Added in release 2.2 ***/
+       /*   Iterators */
+       ( getiterfunc )ConstraintSeq_getIter, /* getiterfunc tp_iter; */
+    ( iternextfunc )ConstraintSeq_nextIter, /* iternextfunc tp_iternext; */
+
+  /*** Attribute descriptor and subclassing stuff ***/
+       BPy_ConstraintSeq_methods,         /* struct PyMethodDef *tp_methods; */
+       NULL,                       /* struct PyMemberDef *tp_members; */
+       NULL,                       /* struct PyGetSetDef *tp_getset; */
+       NULL,                       /* struct _typeobject *tp_base; */
+       NULL,                       /* PyObject *tp_dict; */
+       NULL,                       /* descrgetfunc tp_descr_get; */
+       NULL,                       /* descrsetfunc tp_descr_set; */
+       0,                          /* long tp_dictoffset; */
+       NULL,                       /* initproc tp_init; */
+       NULL,                       /* allocfunc tp_alloc; */
+       NULL,                       /* newfunc tp_new; */
+       /*  Low-level free-memory routine */
+       NULL,                       /* freefunc tp_free;  */
+       /* For PyObject_IS_GC */
+       NULL,                       /* inquiry tp_is_gc;  */
+       NULL,                       /* PyObject *tp_bases; */
+       /* method resolution order */
+       NULL,                       /* PyObject *tp_mro;  */
+       NULL,                       /* PyObject *tp_cache; */
+       NULL,                       /* PyObject *tp_subclasses; */
+       NULL,                       /* PyObject *tp_weaklist; */
+       NULL
+};
+
+/*****************************************************************************/
+/* Function:    PoseConstraintSeq_CreatePyObject                             */
+/* Description: This function will create a new BPy_ConstraintSeq from an    */
+/*              existing ListBase structure.                                 */
+/*****************************************************************************/
+PyObject *PoseConstraintSeq_CreatePyObject( bPoseChannel *pchan )
+{
+       BPy_ConstraintSeq *pyseq;
+       Object *ob;
+
+       for( ob = G.main->object.first; ob; ob = ob->id.next ) {
+               if( ob->type == OB_ARMATURE ) {
+                       bPoseChannel *p = ob->pose->chanbase.first;
+                       while( p ) {
+                               if( p == pchan ) {
+                                       pyseq = ( BPy_ConstraintSeq * ) PyObject_NEW( 
+                                                       BPy_ConstraintSeq, &ConstraintSeq_Type );
+                                       if( !pyseq )
+                                               return EXPP_ReturnPyObjError( PyExc_MemoryError,
+                                                               "couldn't create BPy_ConstraintSeq object" );
+                                       pyseq->pchan = pchan;
+                                       pyseq->obj = ob;
+                                       return ( PyObject * ) pyseq;
+                               } else
+                                       p = p->next;
+                       }
+               }
+       }
+       return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+                       "couldn't find ANY armature with the pose!" );
+
+}
+
+/*****************************************************************************/
+/* Function:    ObConstraintSeq_CreatePyObject                               */
+/* Description: This function will create a new BPy_ConstraintSeq from an    */
+/*              existing ListBase structure.                                 */
+/*****************************************************************************/
+PyObject *ObConstraintSeq_CreatePyObject( Object *obj )
+{
+       BPy_ConstraintSeq *pyseq;
+       pyseq = ( BPy_ConstraintSeq * ) PyObject_NEW( BPy_ConstraintSeq,
+                       &ConstraintSeq_Type );
+       if( !pyseq )
+               return EXPP_ReturnPyObjError( PyExc_MemoryError,
+                                             "couldn't create BPy_ConstraintSeq object" );
+       pyseq->obj = obj;
+       pyseq->pchan = NULL;
+       return ( PyObject * ) pyseq;
+}
+
+static PyObject *M_Constraint_TypeDict( void )
+{
+       PyObject *S = PyConstant_New(  );
+
+       if( S ) {
+               BPy_constant *d = ( BPy_constant * ) S;
+               PyConstant_Insert( d, "NULL", 
+                               PyInt_FromLong( CONSTRAINT_TYPE_NULL ) );
+               PyConstant_Insert( d, "TRACKTO",
+                               PyInt_FromLong( CONSTRAINT_TYPE_TRACKTO ) );
+               PyConstant_Insert( d, "IKSOLVER", 
+                               PyInt_FromLong( CONSTRAINT_TYPE_KINEMATIC ) );
+               PyConstant_Insert( d, "FOLLOWPATH", 
+                               PyInt_FromLong( CONSTRAINT_TYPE_FOLLOWPATH ) );
+               PyConstant_Insert( d, "COPYROT", 
+                               PyInt_FromLong( CONSTRAINT_TYPE_ROTLIKE ) );
+               PyConstant_Insert( d, "COPYLOC", 
+                               PyInt_FromLong( CONSTRAINT_TYPE_LOCLIKE ) );
+               PyConstant_Insert( d, "COPYSIZE", 
+                               PyInt_FromLong( CONSTRAINT_TYPE_SIZELIKE ) );
+               PyConstant_Insert( d, "ACTION", 
+                               PyInt_FromLong( CONSTRAINT_TYPE_ACTION ) );
+               PyConstant_Insert( d, "LOCKTRACK", 
+                               PyInt_FromLong( CONSTRAINT_TYPE_LOCKTRACK ) );
+               PyConstant_Insert( d, "STRETCHTO", 
+                               PyInt_FromLong( CONSTRAINT_TYPE_STRETCHTO ) );
+               PyConstant_Insert( d, "FLOOR", 
+                               PyInt_FromLong( CONSTRAINT_TYPE_MINMAX ) );
+       }
+       return S;
+}
+
+static PyObject *M_Constraint_SettingsDict( void )
+{
+       PyObject *S = PyConstant_New(  );
+       
+       if( S ) {
+               BPy_constant *d = ( BPy_constant * ) S;
+               PyConstant_Insert( d, "XROT",
+                               PyInt_FromLong( EXPP_CONSTR_XROT ) );
+               PyConstant_Insert( d, "YROT",
+                               PyInt_FromLong( EXPP_CONSTR_YROT ) );
+               PyConstant_Insert( d, "ZROT",
+                               PyInt_FromLong( EXPP_CONSTR_ZROT ) );
+
+               PyConstant_Insert( d, "UPX",
+                               PyInt_FromLong( UP_X ) );
+               PyConstant_Insert( d, "UPY",
+                               PyInt_FromLong( UP_Y ) );
+               PyConstant_Insert( d, "UPZ",
+                               PyInt_FromLong( UP_Z ) );
+
+               PyConstant_Insert( d, "TRACKX",
+                               PyInt_FromLong( TRACK_X ) );
+               PyConstant_Insert( d, "TRACKY",
+                               PyInt_FromLong( TRACK_Y ) );
+               PyConstant_Insert( d, "TRACKZ",
+                               PyInt_FromLong( TRACK_Z ) );
+               PyConstant_Insert( d, "TRACKNEGX",
+                               PyInt_FromLong( TRACK_nX ) );
+               PyConstant_Insert( d, "TRACKNEGY",
+                               PyInt_FromLong( TRACK_nY ) );
+               PyConstant_Insert( d, "TRACKNEGZ",
+                               PyInt_FromLong( TRACK_nZ ) );
+
+               PyConstant_Insert( d, "VOLUMEXZ",
+                               PyInt_FromLong( VOLUME_XZ ) );
+               PyConstant_Insert( d, "VOLUMEX",
+                               PyInt_FromLong( VOLUME_X ) );
+               PyConstant_Insert( d, "VOLUMEZ",
+                               PyInt_FromLong( VOLUME_Z ) );
+               PyConstant_Insert( d, "VOLUMENONE",
+                               PyInt_FromLong( NO_VOLUME ) );
+
+               PyConstant_Insert( d, "PLANEX",
+                               PyInt_FromLong( PLANE_X ) );
+               PyConstant_Insert( d, "PLANEY",
+                               PyInt_FromLong( PLANE_Y ) );
+               PyConstant_Insert( d, "PLANEZ",
+                               PyInt_FromLong( PLANE_Z ) );
+
+               PyConstant_Insert( d, "LOCKX",
+                               PyInt_FromLong( LOCK_X ) );
+               PyConstant_Insert( d, "LOCKY",
+                               PyInt_FromLong( LOCK_Y ) );
+               PyConstant_Insert( d, "LOCKZ",
+                               PyInt_FromLong( LOCK_Z ) );
+
+               PyConstant_Insert( d, "MAXX",
+                               PyInt_FromLong( EXPP_CONSTR_MAXX ) );
+               PyConstant_Insert( d, "MAXY",
+                               PyInt_FromLong( EXPP_CONSTR_MAXY ) );
+               PyConstant_Insert( d, "MAXZ",
+                               PyInt_FromLong( EXPP_CONSTR_MAXZ ) );
+               PyConstant_Insert( d, "MINX",
+                               PyInt_FromLong( EXPP_CONSTR_MINX ) );
+               PyConstant_Insert( d, "MINY",
+                               PyInt_FromLong( EXPP_CONSTR_MINY ) );
+               PyConstant_Insert( d, "MINZ",
+                               PyInt_FromLong( EXPP_CONSTR_MINZ ) );
+
+               PyConstant_Insert( d, "COPYX",
+                               PyInt_FromLong( LOCLIKE_X ) );
+               PyConstant_Insert( d, "COPYY",
+                               PyInt_FromLong( LOCLIKE_Y ) );
+               PyConstant_Insert( d, "COPYZ",
+                               PyInt_FromLong( LOCLIKE_Z ) );
+
+               PyConstant_Insert( d, "TARGET",
+                               PyInt_FromLong( EXPP_CONSTR_TARGET ) );
+               PyConstant_Insert( d, "TOLERANCE", 
+                               PyInt_FromLong( EXPP_CONSTR_TOLERANCE ) );
+               PyConstant_Insert( d, "ITERATIONS", 
+                               PyInt_FromLong( EXPP_CONSTR_ITERATIONS ) );
+               PyConstant_Insert( d, "BONE", 
+                               PyInt_FromLong( EXPP_CONSTR_BONE ) );
+               PyConstant_Insert( d, "CHAINLEN", 
+                               PyInt_FromLong( EXPP_CONSTR_CHAINLEN ) );
+               PyConstant_Insert( d, "POSWEIGHT", 
+                               PyInt_FromLong( EXPP_CONSTR_POSWEIGHT ) );
+               PyConstant_Insert( d, "ROTWEIGHT", 
+                               PyInt_FromLong( EXPP_CONSTR_ROTWEIGHT ) );
+               PyConstant_Insert( d, "ROTATE", 
+                               PyInt_FromLong( EXPP_CONSTR_ROTATE ) );
+               PyConstant_Insert( d, "USETIP", 
+                               PyInt_FromLong( EXPP_CONSTR_USETIP ) );
+
+               PyConstant_Insert( d, "ACTION", 
+                               PyInt_FromLong( EXPP_CONSTR_ACTION ) );
+               PyConstant_Insert( d, "LOCAL", 
+                               PyInt_FromLong( EXPP_CONSTR_LOCAL ) );
+               PyConstant_Insert( d, "START", 
+                               PyInt_FromLong( EXPP_CONSTR_START ) );
+               PyConstant_Insert( d, "END", 
+                               PyInt_FromLong( EXPP_CONSTR_END ) );
+               PyConstant_Insert( d, "MIN", 
+                               PyInt_FromLong( EXPP_CONSTR_MIN ) );
+               PyConstant_Insert( d, "MAX", 
+                               PyInt_FromLong( EXPP_CONSTR_MAX ) );
+               PyConstant_Insert( d, "KEYON", 
+                               PyInt_FromLong( EXPP_CONSTR_KEYON ) );
+
+               PyConstant_Insert( d, "TRACK", 
+                               PyInt_FromLong( EXPP_CONSTR_TRACK ) );
+               PyConstant_Insert( d, "UP", 
+                               PyInt_FromLong( EXPP_CONSTR_UP ) );
+
+               PyConstant_Insert( d, "RESTLENGTH",
+                               PyInt_FromLong( EXPP_CONSTR_RESTLENGTH ) );
+               PyConstant_Insert( d, "VOLVARIATION",
+                               PyInt_FromLong( EXPP_CONSTR_VOLVARIATION ) );
+               PyConstant_Insert( d, "VOLUMEMODE",
+                               PyInt_FromLong( EXPP_CONSTR_VOLUMEMODE ) );
+               PyConstant_Insert( d, "PLANE",
+                               PyInt_FromLong( EXPP_CONSTR_PLANE ) );
+
+               PyConstant_Insert( d, "FOLLOW",
+                               PyInt_FromLong( EXPP_CONSTR_FOLLOW ) );
+               PyConstant_Insert( d, "OFFSET",
+                               PyInt_FromLong( EXPP_CONSTR_OFFSET ) );
+               PyConstant_Insert( d, "FORWARD",
+                               PyInt_FromLong( EXPP_CONSTR_FORWARD ) );
+
+               PyConstant_Insert( d, "LOCK",
+                               PyInt_FromLong( EXPP_CONSTR_LOCK ) );
+
+               PyConstant_Insert( d, "COPY",
+                               PyInt_FromLong( EXPP_CONSTR_COPY ) );
+       }
+       return S;
+}
+
+/*****************************************************************************/
+/* Function:              Constraint_Init                                    */
+/*****************************************************************************/
+PyObject *Constraint_Init( void )
+{
+       PyObject *submodule;
+       PyObject *TypeDict = M_Constraint_TypeDict( );
+       PyObject *SettingsDict = M_Constraint_SettingsDict( );
+
+       if( PyType_Ready( &ConstraintSeq_Type ) < 0
+                       || PyType_Ready( &Constraint_Type ) < 0 )
+               return NULL;
+
+       submodule = Py_InitModule3( "Blender.Constraint", NULL,
+                       "Constraint module for accessing and creating constraint data" );
+
+       if( TypeDict )
+               PyModule_AddObject( submodule, "Type", TypeDict );
+       
+       if( SettingsDict )
+               PyModule_AddObject( submodule, "Settings", SettingsDict );
+       
+       return submodule;
+}
diff --git a/source/blender/python/api2_2x/Constraint.h b/source/blender/python/api2_2x/Constraint.h
new file mode 100644 (file)
index 0000000..c0b07a1
--- /dev/null
@@ -0,0 +1,77 @@
+/* 
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Joseph Gilbert, Ken Hughes
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+#ifndef EXPP_CONSTRAINT_H
+#define EXPP_CONSTRAINT_H
+
+#include <Python.h>
+#include "DNA_object_types.h"
+#include "DNA_action_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_listBase.h"
+
+/*****************************************************************************/
+/* Python BPy_Modifier structure definition:                                 */
+/*****************************************************************************/
+typedef struct {
+       PyObject_HEAD           /* required macro */
+       Object *obj;            /* "parent" object */
+       bPoseChannel *pchan;/* "parent" pose channel */
+       /* if con this is null, the constraint has been removed and we need to
+        * raise an error when its data is accessed */
+       bConstraint *con;
+} BPy_Constraint;
+
+extern PyTypeObject Constraint_Type;
+
+#define BPy_Constraint_Check(v)  ((v)->ob_type == &Constraint_Type)    /* for type checking */
+typedef struct {
+       PyObject_HEAD           /* required macro */
+       Object *obj;            /* "parent" object */
+       bPoseChannel *pchan;/* "parent" pose channel */
+       bConstraint *iter;
+} BPy_ConstraintSeq;
+
+/* 
+ *   prototypes
+ */
+
+PyObject *Constraint_Init( void );
+PyObject *Constraint_CreatePyObject( bPoseChannel *pchan, Object *obj,
+               bConstraint *con );
+bConstraint *Constraint_FromPyObject( BPy_Constraint * obj );
+int Constraint_CheckPyObject( PyObject * py_obj );
+
+PyObject *PoseConstraintSeq_CreatePyObject( bPoseChannel *pchan );
+PyObject *ObConstraintSeq_CreatePyObject( Object *obj );
+
+#endif                         /* EXPP_CONSTRAINT_H */
index fdad28838ca684c172ca326ac22a5820bf2c3752..1d9712c217c4e4e113fa5ca6c453a841d5698af3 100644 (file)
@@ -109,6 +109,7 @@ struct rctf;
 #include "Pose.h"
 #include "Group.h"
 #include "Modifier.h"
+#include "Constraint.h"
 #include "gen_utils.h"
 #include "EXPP_interface.h"
 #include "BIF_editkey.h"
@@ -3594,7 +3595,9 @@ static PyObject *Object_getAttr( BPy_Object * obj, char *name )
        if( StringEqual( name, "drawSize" ) )
                return ( PyFloat_FromDouble( object->empty_drawsize ) );
        if( StringEqual( name, "modifiers" ) )
-               return ModSeq_CreatePyObject( obj->object );
+               return ModSeq_CreatePyObject( object );
+       if( StringEqual( name, "constraints" ) )
+               return ObConstraintSeq_CreatePyObject( object );
        
        /* not an attribute, search the methods table */
        return Py_FindMethod( BPy_Object_methods, ( PyObject * ) obj, name );
index f19e7b366c6598dd16fc2b371ef99675dc666589..4a78208046c28c97fdc72f263ac0381ea9864721 100644 (file)
@@ -49,6 +49,7 @@
 #include "BLI_arithb.h"
 #include "Mathutils.h"
 #include "Object.h"
+#include "Constraint.h"
 #include "NLA.h"
 #include "gen_utils.h"
 
@@ -705,30 +706,12 @@ static int PoseBone_setPoseMatrix(BPy_PoseBone *self, PyObject *value, void *clo
        return EXPP_intError(PyExc_AttributeError, "%s%s%s",
                sPoseBoneError, ".poseMatrix: ", "not able to set this property");
 }
-////------------------------PoseBone.constraints (getter)
-////Gets the constraints list
-//static PyObject *PoseBone_getConstraints(BPy_PoseBone *self, void *closure)
-//{
-//     PyObject *list = NULL, *py_constraint = NULL;
-//     bConstraint *constraint = NULL;
-//
-//     list = PyList_New(0);
-//     for (constraint = self->posechannel->constraints.first; constraint; constraint = constraint->next){
-//             py_constraint = PyConstraint_FromConstraint(constraint);
-//             if (!py_constraint)
-//                     return NULL;
-//             if (PyList_Append(list, py_constraint) == -1){
-//                     Py_DECREF(py_constraint);
-//                     goto RuntimeError;
-//             }
-//             Py_DECREF(py_constraint);
-//     }
-//     return list;
-//
-//RuntimeError:
-//     return EXPP_objError(PyExc_RuntimeError, "%s%s%s",
-//             sPoseBoneError, ".constraints: ", "unable to build constraint list");
-//}
+//------------------------PoseBone.constraints (getter)
+//Gets the constraints sequence
+static PyObject *PoseBone_getConstraints(BPy_PoseBone *self, void *closure)
+{
+       return PoseConstraintSeq_CreatePyObject( self->posechannel );
+}
 ////------------------------PoseBone.constraints (setter)
 ////Sets the constraints list
 //static int PoseBone_setConstraints(BPy_PoseBone *self, PyObject *value, void *closure)
@@ -782,8 +765,8 @@ static PyGetSetDef BPy_PoseBone_getset[] = {
                "The pose bone's head positon", NULL},
        {"tail", (getter)PoseBone_getTail, (setter)PoseBone_setTail, 
                "The pose bone's tail positon", NULL},
-       //{"constraints", (getter)PoseBone_getConstraints, (setter)PoseBone_setConstraints
-       //      "The list of contraints that pertain to this pose bone", NULL},
+       {"constraints", (getter)PoseBone_getConstraints, (setter)NULL
+               "The list of contraints that pertain to this pose bone", NULL},
        {NULL, NULL, NULL, NULL, NULL}
 };
 //------------------------tp_dealloc
index b325db237c54479e7aad21de728fd4afac02dfc1..dd6ae59811722c99c9ef706d36b326d3b5b14255 100644 (file)
@@ -38,6 +38,7 @@ The Blender Python API Reference
   - L{Noise}
   - L{Object} (*)
      - L{Pose}
+     - L{Constraint} (*)
   - L{Registry}
   - L{Scene}
      - L{Radio}
diff --git a/source/blender/python/api2_2x/doc/Constraint.py b/source/blender/python/api2_2x/doc/Constraint.py
new file mode 100644 (file)
index 0000000..18ffbf3
--- /dev/null
@@ -0,0 +1,224 @@
+# Blender.Constraint module and the Constraint PyType object
+
+"""
+The Blender.Constraint submodule
+
+B{New}: 
+  -  provides access to Blender's constraint stack
+
+This module provides access to the Constraint Data in Blender.
+
+Examples::
+  from Blender import *
+
+  ob = Object.Get('Cube')
+  if len(ob.constraints) > 0:
+    const = ob.constraints[0]
+    if const.type == Constraint.Type.FLOOR:
+      offs = const[Constrint.Settings.OFFSET]
+  
+Or to print all the constraints attached to each bone in a pose::
+  from Blender import *
+  
+  ob = Object.Get('Armature')
+  for bonename in pose.bones.keys():
+    bone = pose.bones[bonename]
+    for const in bone.constraints:
+      print bone.name,'=>'const
+
+@type Type: readonly dictionary
+@var Type: Constant Constraint dict used by L{ConstraintSeq.append()} and 
+  for comparison with L{Constraint.type}.  Values are
+  TRACKTO, IKSOLVER, FOLLOWPATH, COPYROT, COPYLOC, COPYSIZE, ACTION,
+  LOCKTRACK, STRETCHTO, FLOOR
+
+@type Settings: readonly dictionary
+@var Settings: Constant dict used for changing constraint settings.
+  - Used for all constraints
+    - TARGET (Object)
+    - BONE (string): name of Bone subtarget (for armature targets) (Note: not
+      used by Stretch To (STRETCHTO))
+  - Used by IK Solver (IKSOLVER) constraint:
+    - TOLERANCE (float): clamped to [0.0001:1.0]
+    - ITERATIONS (int): clamped to [1,10000]
+    - CHAINLEN (int): clamped to [0,255]
+    - POSWEIGHT (float): clamped to [0.01,1.0]
+    - ROTWEIGHT (float): clamped to [0.01,1.0]
+    - ROTATE (bool)
+    - USETIP (bool)
+  - Used by Action (ACTION) constraint:
+    - ACTION (Action Object)
+    - LOCAL (bool)
+    - START (int): clamped to [1,maxframe]
+    - END (int): clamped to [1,maxframe]
+    - MIN (float): clamped to [-180.0,180.0]
+    - MAX (float): clamped to [-180.0,180.0]
+    - KEYON (int): values are XROT, YROT, ZROT
+  - Used by Track To (TRACKTO) constraint:
+    - TRACK (int): values are TRACKX, TRACKY, TRACKZ, TRACKNEGX,
+      TRACKNEGY, TRACKNEGZ
+    - UP (int): values are UPX, UPY, UPZ
+  - Used by Stretch To (STRETCHTO) constraint:
+    - RESTLENGTH (float): clamped to [0.0:100.0]
+    - VOLVARIATION (float): clamped to [0.0:100.0]
+    - VOLUMEMODE (int): values are VOLUMEXZ, VOLUMEX, VOLUMEZ,
+      VOLUMENONE
+    - PLANE (int): values are PLANEX, PLANEZ
+  - Used by Follow Path (FOLLOWPATH) constraint:
+    - FOLLOW (bool)
+    - OFFSET (float): clamped to [-maxframe:maxframe]
+    - FORWARD (int): values are TRACKX, TRACKY, TRACKZ, TRACKNEGX,
+      TRACKNEGY, TRACKNEGZ
+    - UP (int): values are UPX, UPY, UPZ
+  - Used by Lock Track (FOLLOWPATH) constraint:
+    - TRACK (int): values are TRACKX, TRACKY, TRACKZ, TRACKNEGX,
+      TRACKNEGY, TRACKNEGZ
+    - LOCK (int): values are LOCKX, LOCKY, LOCKZ
+  - Used by Floor (FLOOR) constraint:
+    - MINMAX (int): values are MINX, MINY, MINZ, MAXX, MAXY, MAXZ
+    - OFFSET (float): clamped to [-100.0,100.0]
+    - STICKY (bool)
+  - Used by Copy Location (COPYLOC), Copy Rotation (COPYROT), and Copy Size
+  (COPYSIZE) constraint:
+    - COPY (bitfield): any combination of COPYX, COPYY and COPYZ
+
+"""
+
+class ConstraintSeq:
+  """
+  The ConstraintSeq object
+  ========================
+  This object provides access to sequence of
+  L{constraints<Constraint.Constraint>} for a particular object.
+  They can be accessed from L{Object.constraints<Object.Object.constraints>}.
+  or L{PoseBone.constraints<Pose.PoseBone.constraints>}.
+  """
+
+  def __getitem__(index):
+    """
+    This operator returns one of the constraints in the stack.
+    @type index: int
+    @return: an Constraint object
+    @rtype: Constraint
+    @raise KeyError: index was out of range
+    """
+
+  def __len__():
+    """
+    Returns the number of constraints in the constraint stack.
+    @return: number of Constraints
+    @rtype: int
+    """
+
+  def append(type):
+    """
+    Appends a new constraint to the end of the constraint stack.
+    @type type: a constant specifying the type of constraint to create. as from L{Type}
+    @rtype: Constraint
+    @return: the new Constraint
+    """
+
+  def remove(constraint):
+    """
+    Remove a constraint from this objects constraint sequence.
+    @type constraint: a constraint from this sequence to remove.
+    @note: Accessing attributes of the constraint after it is removed will 
+    throw an exception.
+    """
+
+class Constraint:
+  """
+  The Constraint object
+  =====================
+  This object provides access to a constraint for a particular object
+  accessed from L{ConstraintSeq}.
+  @ivar name: The name of this constraint. 29 chars max.
+  @type name: string
+  @ivar type: The type of this constraint. Read-only.  The returned value
+  matches the types in L{Type}.
+  @type type: int
+  @ivar influence: The influence value of the constraint.  Valid values
+  are in the range [0.0,1.0].
+  @type influence: float
+  """
+
+  def __getitem__(key):
+    """
+    This operator returns one of the constraint's data attributes.
+    @type key: value from constraint's L{Constraint.Settings} constant
+    @return: the requested data
+    @rtype: varies
+    @raise KeyError: the key does not exist for the constraint
+    """
+
+  def __setitem__(key):
+    """
+    This operator changes one of the constraint's data attributes.
+    @type key: value from constraint's L{Constraint.Settings} constant
+    @raise KeyError: the key does not exist for the constraint
+    """
+
+  def up():
+    """
+    Moves the constraint up in the object's constraint stack.
+    @rtype: PyNone
+    """
+
+  def down():
+    """
+    Moves the constraint down in the object's constraint stack.
+    @rtype: PyNone
+    """
+
+  def insertKey(frame):
+    """
+    Adds an influence keyframe for the constraint Ipo.  
+    @rtype: PyNone
+    @type frame: float
+    @param frame: the frame number at which to insert the key.
+    """
+
+
+
+class ConstraintSeq:
+  """
+  The ConstraintSeq object
+  ========================
+  This object provides access to sequence of
+  L{constraints<Constraint.Constraint>} for a particular object.
+  They can be accessed from L{Object.constraints<Object.Object.constraints>}.
+  or L{PoseBone.constraints<Pose.PoseBone.constraints>}.
+  """
+
+  def __getitem__(index):
+    """
+    This operator returns one of the constraints in the stack.
+    @type index: int
+    @return: an Constraint object
+    @rtype: Constraint
+    @raise KeyError: index was out of range
+    """
+
+  def __len__():
+    """
+    Returns the number of constraints in the constraint stack.
+    @return: number of Constraints
+    @rtype: int
+    """
+
+  def append(type):
+    """
+    Appends a new constraint to the end of the constraint stack.
+    @type type: a constant specifying the type of constraint to create. as from L{Type}
+    @rtype: Constraint
+    @return: the new Constraint
+    """
+
+  def remove(constraint):
+    """
+    Remove a constraint from this objects constraint sequence.
+    @type constraint: a constraint from this sequence to remove.
+    @note: Accessing attributes of the constraint after removing will 
+    throw an exception.
+    """
+
index f1c91c56660e49d068b39992f6f5c44f9206f83b..4ead3eb01e9432a90e45df2c4f24aadd4e009907 100644 (file)
@@ -138,7 +138,6 @@ def Duplicate (mesh=0, surface=0, curve=0, text=0, metaball=0, armature=0, lamp=
   @param texture: When non-zero, texture data used by the object's materials will be duplicated with the objects.
   @type ipo: bool
   @param ipo: When non-zero, Ipo data linked to the object will be duplicated with the objects.
-  @return: None
 
   I{B{Example:}}
 
@@ -328,6 +327,9 @@ class Object:
     @type drawSize: float
     @ivar modifiers: The modifiers for this object.
     @type modifiers: ModSeq L{Modifier.ModSeq}
+    @type constraints: BPy_ConstraintSeq
+    @ivar constraints: a L{sequence<Constraint.ConstraintSeq>} of
+    L{constraints<Constraint.Constraint>} for the object.
   """
 
   def buildParts():
index 993658a00c3d5cf573239f5ee2f7d9a4e15bd1fa..740d794b94b0504cf2da0a2dc25bc3a7a96bfe03 100644 (file)
@@ -85,6 +85,9 @@ class PoseBone:
   @type localMatrix: Matrix object
   @ivar poseMatrix: The total transformation of this PoseBone including constraints. (not settable)
   @type poseMatrix: Matrix object
+  @type constraints: BPy_ConstraintSeq
+  @ivar constraints: a sequence of constraints for the object
+
   """
 
   def insertKey(parentObject, frameNumber, type):
index 93c58860f100e0166922b0e11ae63920da9270d4..e548176ad7d6bdd1ea9362433b48f62d3ba258cd 100644 (file)
@@ -197,8 +197,9 @@ static void add_constraint_to_active(Object *ob, bConstraint *con)
 
 /* returns base ID for Ipo, sets actname to channel if appropriate */
 /* should not make action... */
-static void get_constraint_ipo_context(Object *ob, char *actname)
+void get_constraint_ipo_context(void *ob_v, char *actname)
 {
+       Object *ob= ob_v;
        
        /* todo; check object if it has ob-level action ipo */
        
@@ -268,8 +269,7 @@ static void add_influence_key_to_constraint_func (void *ob_v, void *con_v)
        BIF_undo_push("Insert Influence Key");
 }
 
-
-static void del_constraint_func (void *ob_v, void *con_v)
+void del_constr_func (void *ob_v, void *con_v)
 {
        bConstraint *con= con_v;
        bConstraintChannel *chan;
@@ -290,11 +290,14 @@ static void del_constraint_func (void *ob_v, void *con_v)
        BLI_freelinkN(lb, con);
        
        constraint_active_func(ob_v, NULL);
+}
 
+static void del_constraint_func (void *ob_v, void *con_v)
+{
+       del_constr_func (ob_v, con_v);
        BIF_undo_push("Delete constraint");
        allqueue(REDRAWBUTSOBJECT, 0);
        allqueue(REDRAWIPO, 0); 
-
 }
 
 static void verify_constraint_name_func (void *ob_v, void *con_v)
@@ -311,8 +314,10 @@ static void verify_constraint_name_func (void *ob_v, void *con_v)
 
 }
 
-static void get_constraint_typestring (char *str, bConstraint *con)
+void get_constraint_typestring (char *str, void *con_v)
 {
+       bConstraint *con= con_v;
+
        switch (con->type){
        case CONSTRAINT_TYPE_CHILDOF:
                strcpy (str, "Child Of");
@@ -386,7 +391,7 @@ static int get_constraint_col(bConstraint *con)
        }
 }
 
-static void constraint_moveUp(void *ob_v, void *con_v)
+void const_moveUp(void *ob_v, void *con_v)
 {
        bConstraint *con, *constr= con_v;
        ListBase *conlist;
@@ -401,10 +406,15 @@ static void constraint_moveUp(void *ob_v, void *con_v)
                        }
                }
        }
+}
+
+static void constraint_moveUp(void *ob_v, void *con_v)
+{
+       const_moveUp(ob_v, con_v);
        BIF_undo_push("Move constraint");
 }
 
-static void constraint_moveDown(void *ob_v, void *con_v)
+void const_moveDown(void *ob_v, void *con_v)
 {
        bConstraint *con, *constr= con_v;
        ListBase *conlist;
@@ -419,6 +429,11 @@ static void constraint_moveDown(void *ob_v, void *con_v)
                        }
                }
        }
+}
+
+static void constraint_moveDown(void *ob_v, void *con_v)
+{
+       const_moveDown(ob_v, con_v);
        BIF_undo_push("Move constraint");
 }
 
@@ -948,8 +963,8 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
 
                                
                                uiBlockBeginAlign(block);
-                               uiDefButF(block,BUTM,B_CONSTRAINT_TEST,"R",*xco, *yco-60,20,18,&(data->orglength),0.0,0,0,0,"Recalculate RLenght");
-                               uiDefButF(block,NUM,B_CONSTRAINT_TEST,"Rest Length:",*xco+18, *yco-60,237,18,&(data->orglength),0.0,100,0.5,0.5,"Lenght 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");