diff options
author | Ken Hughes <khughes@pacific.edu> | 2006-05-07 18:57:58 +0400 |
---|---|---|
committer | Ken Hughes <khughes@pacific.edu> | 2006-05-07 18:57:58 +0400 |
commit | cd3af13a1b1aaada000322373394c02cc6b773fb (patch) | |
tree | c03c4422ae0c652e4a98c83e0e7e5c8a55b90a0d /source/blender/python/api2_2x/Constraint.c | |
parent | 8255bdce574283df7f04ccb24c607c1e45d956e9 (diff) |
===Python API===
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.
Diffstat (limited to 'source/blender/python/api2_2x/Constraint.c')
-rw-r--r-- | source/blender/python/api2_2x/Constraint.c | 1657 |
1 files changed, 1657 insertions, 0 deletions
diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c new file mode 100644 index 00000000000..5572411ea85 --- /dev/null +++ b/source/blender/python/api2_2x/Constraint.c @@ -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; +} |