Index: source/blender/python/api2_2x/Actuator.c =================================================================== --- source/blender/python/api2_2x/Actuator.c (revision 0) +++ source/blender/python/api2_2x/Actuator.c (revision 0) @@ -0,0 +1,2002 @@ +/* + * ***** 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. + * + * This is a new part of Blender. + * + * Contributor(s): Matthieu Delanoë + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "Actuator.h" /*This must come first*/ + +#include "DNA_object_types.h" + +#include "BLI_blenlib.h" +#include "MEM_guardedalloc.h" + +#include "BKE_sca.h" +#include "NLA.h" +#include "Object.h" +#include "Scene.h" +#include "Mesh.h" +#include "Sound.h" +#include "Text.h" +#include "gen_utils.h" +#include "gen_library.h" + + +/* checks for the actuator being removed */ +#define ACTUATOR_DEL_CHECK_PY(bpy_actuator) if (!(bpy_actuator->act)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "Actuator has been removed" ) ) +#define ACTUATOR_DEL_CHECK_INT(bpy_actuator) if (!(bpy_actuator->act)) return ( EXPP_ReturnIntError( PyExc_RuntimeError, "Actuator has been removed" ) ) + + +enum actuator_constants { + // For Motion actuator + EXPP_ACT_DLOC=0, + EXPP_ACT_DROT, + EXPP_ACT_FORCE, // also for IPO + EXPP_ACT_TORQUE, + EXPP_ACT_LINV, // also for Edit Object + EXPP_ACT_ANGV, + EXPP_ACT_ADDLINV, + + // For IPO actuator + EXPP_ACT_PROPERTY, // also for Property, Random, Action + EXPP_ACT_START, // also Action + EXPP_ACT_END, // also Action + EXPP_ACT_TYPE, // also for Property, Constraint, Scene, Edit Object, Random, Message, CD, Game, Action, Visibility, Sound, 2D filter + EXPP_ACT_CHILD, + EXPP_ACT_FORCE_LOCAL, + + // For camera actuator + EXPP_ACT_HEIGHT, + EXPP_ACT_MIN, // also for Constraint + EXPP_ACT_MAX, // also for Constraint + EXPP_ACT_OBJECT, // also for Property, Edit Object + EXPP_ACT_AXIS, + + // For Property actuator + EXPP_ACT_VALUE, // also for 2D filter + + // For Constraint actuator + EXPP_ACT_DAMP, + + // For Scene actuator + EXPP_ACT_CAMERA, + EXPP_ACT_SCENE, + + // For Edit Object actuator + EXPP_ACT_TIME, + EXPP_ACT_3D, + EXPP_ACT_MESH, + + // For random actuator + EXPP_ACT_SEED, + EXPP_ACT_FLOAT1, + EXPP_ACT_FLOAT2, + EXPP_ACT_INT1, + EXPP_ACT_INT2, + + // For Message actuator + EXPP_ACT_TO, + EXPP_ACT_SUBJECT, + EXPP_ACT_BODY, + + // For CD actuator + EXPP_ACT_TRACK, + EXPP_ACT_VOLUME, + + // For Game actuator + EXPP_ACT_FILE, + + // For Action actuator + EXPP_ACT_BLENDIN, + EXPP_ACT_PRIORITY, + EXPP_ACT_ACTION, + + // For Sound actuator + EXPP_ACT_SOUND, + + // For 2D Filter + EXPP_ACT_PASS, + EXPP_ACT_DISABLED, + EXPP_ACT_SCRIPT, + +}; + + +/*****************************************************************************/ +/* Python BPy_Actuator methods declarations: */ +/*****************************************************************************/ +static PyObject *Actuator_getName( BPy_Actuator * self ); +static int Actuator_setName( BPy_Actuator * self, PyObject *arg ); +static PyObject *Actuator_getType( BPy_Actuator * self ); +//static PyObject *Actuator_reset( BPy_Actuator * self ); + +static PyObject *Actuator_getData( BPy_Actuator * self, PyObject * key ); +static int Actuator_setData( BPy_Actuator * self, PyObject * key, PyObject * arg ); + +/*****************************************************************************/ +/* Python BPy_Actuator methods table: */ +/*****************************************************************************/ +//static PyMethodDef BPy_Actuator_methods[] = { +// /* name, method, flags, doc */ +// {"reset", (PyCFunction)Actuator_reset, METH_NOARGS, "resets a hook actuator location"}, +// {NULL, NULL, 0, NULL} +//}; + +/*****************************************************************************/ +/* Python BPy_Actuator attributes get/set structure: */ +/*****************************************************************************/ +static PyGetSetDef BPy_Actuator_getseters[] = { + {"name", (getter)Actuator_getName, (setter)Actuator_setName, "Actuator name", NULL}, + {"type", (getter)Actuator_getType, (setter)NULL, "Actuator type (read only)", NULL}, + {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ +}; + +/*****************************************************************************/ +/* Python Actuator_Type Mapping Methods table: */ +/*****************************************************************************/ +static PyMappingMethods Actuator_as_mapping = { + NULL, /* act_length */ + ( binaryfunc ) Actuator_getData, /* act_subscript */ + ( objobjargproc ) Actuator_setData, /* act_ass_subscript */ +}; + +/*****************************************************************************/ +/* Python Actuator_Type callback function prototypes: */ +/*****************************************************************************/ +static PyObject *Actuator_repr( BPy_Actuator * self ); + +/*****************************************************************************/ +/* Python Actuator_Type structure definition: */ +/*****************************************************************************/ +PyTypeObject Actuator_Type = { + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ + /* For printing, in format "." */ + "Blender Actuator", /* char *tp_name; */ + sizeof( BPy_Actuator ), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ + + /* Methods to implement standard operations */ + + NULL, /* destructor tp_dealloc; */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* cmpfunc tp_compare; */ + ( reprfunc ) Actuator_repr, /* reprfunc tp_repr; */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + &Actuator_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_Actuator_methods*/NULL, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + BPy_Actuator_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_Actuator methods: */ +/*****************************************************************************/ + +/* + * return the name of this actuator + */ + +static PyObject *Actuator_getName( BPy_Actuator * self ) +{ + ACTUATOR_DEL_CHECK_PY(self); + return PyString_FromString( self->act->name ); +} + +/* + * set the name of this actuator + */ + +static int Actuator_setName( BPy_Actuator * self, PyObject * attr ) +{ + char *name = PyString_AsString( attr ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + + ACTUATOR_DEL_CHECK_INT(self); + + BLI_strncpy( self->act->name, name, sizeof( self->act->name ) ); + + return 0; +} + +/* + * return the type of this actuator + */ + +static PyObject *Actuator_getType( BPy_Actuator * self ) +{ + ACTUATOR_DEL_CHECK_PY(self); + + return PyInt_FromLong( self->act->type ); +} + + + + + + +/*****************************************************************************/ +/* BPy_Actuator getsetters */ +/*****************************************************************************/ + +/* + * Object actuator getter + */ +static PyObject *object_getter( BPy_Actuator * self, int type ) +{ + bObjectActuator *act = self->act->data; + switch (type) { + case EXPP_ACT_DLOC: + return Py_BuildValue("(fffO)", act->dloc[0], act->dloc[1], act->dloc[2], + ((act->flag & ACT_DLOC_LOCAL) !=0)?PyBool_FromLong(1) : PyBool_FromLong(0) ); + case EXPP_ACT_DROT: + return Py_BuildValue("(fffO)", act->drot[0], act->drot[1], act->drot[2], + ((act->flag & ACT_DROT_LOCAL) !=0)?PyBool_FromLong(1) : PyBool_FromLong(0) ); + case EXPP_ACT_FORCE: + return Py_BuildValue("(fffO)", act->forceloc[0], act->forceloc[1], act->forceloc[2], + ((act->flag & ACT_FORCE_LOCAL) !=0)?PyBool_FromLong(1) : PyBool_FromLong(0) ); + case EXPP_ACT_TORQUE: + return Py_BuildValue("(fffO)", act->forcerot[0], act->forcerot[1], act->forcerot[2], + ((act->flag & ACT_TORQUE_LOCAL) !=0)?PyBool_FromLong(1) : PyBool_FromLong(0) ); + case EXPP_ACT_LINV: + return Py_BuildValue("(fffO)", act->linearvelocity[0], act->linearvelocity[1], act->linearvelocity[2], + ((act->flag & ACT_LIN_VEL_LOCAL) !=0)?PyBool_FromLong(1) : PyBool_FromLong(0) ); + case EXPP_ACT_ANGV: + return Py_BuildValue("(fffO)", act->angularvelocity[0], act->angularvelocity[1], act->angularvelocity[2], + ((act->flag & ACT_ANG_VEL_LOCAL) !=0)?PyBool_FromLong(1) : PyBool_FromLong(0) ); + case EXPP_ACT_ADDLINV: + return ((act->flag & ACT_ADD_LIN_VEL) !=0)?PyBool_FromLong(1) : PyBool_FromLong(0); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + +#define OBJECT_VECTOR_SETTER(PARAM, LOCAL, FLAG)\ + float f1;\ + float f2;\ + float f3;\ + short local=1;\ + int st;\ + if ( PyObject_Length( value ) == 4 )\ + st = PyArg_ParseTuple( value, "fffh", &f1, &f2, &f3, &local );\ + else if( PyObject_Length( value ) == 3 )\ + st = PyArg_ParseTuple( value, "fff", &f1, &f2, &f3 );\ + else if ( PyObject_Length( value ) == 2 )\ + st = PyArg_ParseTuple( value, "(fff)h", &f1, &f2, &f3, &local );\ + else{\ + st = PyArg_ParseTuple( value, "(fffh)", &f1, &f2, &f3, &local );\ + if( !st )\ + st = PyArg_ParseTuple( value, "(fff)", &f1, &f2, &f3 );\ + }\ + if( !st )\ + return EXPP_ReturnIntError( PyExc_TypeError, "expected list argument of 3 floats and a bool" );\ + act->PARAM[0] = f1;\ + act->PARAM[1] = f2;\ + act->PARAM[2] = f3;\ + if ( local == 1 ) act->LOCAL |= FLAG;\ + else act->LOCAL &= ~FLAG;\ + return 0; + + +/* + * Object actuator setter + */ +static int object_setter( BPy_Actuator *self, int type, PyObject *value ) +{ + bObjectActuator *act = self->act->data; + + switch (type) { + case EXPP_ACT_DLOC: + { + OBJECT_VECTOR_SETTER (dloc, flag, ACT_DLOC_LOCAL) + } + case EXPP_ACT_DROT: + { + OBJECT_VECTOR_SETTER (drot, flag, ACT_DROT_LOCAL) + } + case EXPP_ACT_FORCE: + { + OBJECT_VECTOR_SETTER (forceloc, flag, ACT_FORCE_LOCAL) + } + case EXPP_ACT_TORQUE: + { + OBJECT_VECTOR_SETTER (forcerot, flag, ACT_TORQUE_LOCAL) + } + case EXPP_ACT_LINV: + { + OBJECT_VECTOR_SETTER (linearvelocity, flag, ACT_LIN_VEL_LOCAL) + } + case EXPP_ACT_ANGV: + { + OBJECT_VECTOR_SETTER (angularvelocity, flag, ACT_ANG_VEL_LOCAL) + } + case EXPP_ACT_ADDLINV: + { + return EXPP_setBitfield( value, &act->flag, ACT_ADD_LIN_VEL, 'h' ); + } + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + +/* + * Ipo actuator getter + */ +static PyObject *ipo_getter( BPy_Actuator * self, int type ) +{ + bIpoActuator *act = self->act->data; + switch (type) { + case EXPP_ACT_PROPERTY: + return PyString_FromString (act->name); + case EXPP_ACT_START: + return PyInt_FromLong( ( long )act->sta ); + case EXPP_ACT_END: + return PyInt_FromLong( ( long )act->end ); + case EXPP_ACT_TYPE: + return PyInt_FromLong( ( long )act->type ); + case EXPP_ACT_CHILD: + return ((act->flag & ACT_IPOCHILD) !=0)?PyBool_FromLong(1) : PyBool_FromLong(0); + case EXPP_ACT_FORCE: + return ((act->flag & ACT_IPOFORCE) !=0)?PyBool_FromLong(1) : PyBool_FromLong(0); + case EXPP_ACT_FORCE_LOCAL: + return ((act->flag & ACT_IPOFORCE_LOCAL) !=0)?PyBool_FromLong(1) : PyBool_FromLong(0); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + + +/* + * ipo actuator setter + */ +static int ipo_setter( BPy_Actuator *self, int type, PyObject *value ) +{ + bIpoActuator *act = self->act->data; + + switch (type) { + case EXPP_ACT_PROPERTY: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( act->name, name, sizeof( act->name ) ); + break; + } + case EXPP_ACT_START: + return EXPP_setIValueRange( value, &act->sta, 0, 300000, 'i' ); + case EXPP_ACT_END: + return EXPP_setIValueRange( value, &act->end, 0, 300000, 'i' ); + case EXPP_ACT_TYPE: + return EXPP_setIValueRange( value, &act->type, ACT_IPO_PLAY, ACT_IPO_FROM_PROP, 'h' ); + case EXPP_ACT_CHILD: + return EXPP_setBitfield( value, &act->flag, ACT_IPOCHILD, 'h' ); + case EXPP_ACT_FORCE: + return EXPP_setBitfield( value, &act->flag, ACT_IPOFORCE, 'h' ); + case EXPP_ACT_FORCE_LOCAL: + return EXPP_setBitfield( value, &act->flag, ACT_IPOFORCE_LOCAL, 'h' ); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + +/* + * Camera actuator getter + */ +static PyObject *camera_getter( BPy_Actuator * self, int type ) +{ + bCameraActuator *act = self->act->data; + switch (type) { + case EXPP_ACT_HEIGHT: + return PyFloat_FromDouble( (double)act->height ); + case EXPP_ACT_MIN: + return PyFloat_FromDouble( (double)act->min ); + case EXPP_ACT_MAX: + return PyFloat_FromDouble( (double)act->max ); + case EXPP_ACT_OBJECT: + return Object_CreatePyObject( act->ob ); + case EXPP_ACT_AXIS: + return PyInt_FromLong( (long )act->axis ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + + +/* + * Camera actuator setter + */ +static int camera_setter( BPy_Actuator *self, int type, PyObject *value ) +{ + bCameraActuator *act = self->act->data; + + switch (type) { + case EXPP_ACT_HEIGHT: + return EXPP_setFloatClamped( value, &act->height, 0.0, 20.0 ); + case EXPP_ACT_MIN: + return EXPP_setFloatClamped( value, &act->min, 0.0, 20.0 ); + case EXPP_ACT_MAX: + return EXPP_setFloatClamped( value, &act->max, 0.0, 20.0 ); + case EXPP_ACT_OBJECT: + return GenericLib_assignData(value, (void **) &act->ob, (void **) &self->object, 0, ID_OB, 0); + case EXPP_ACT_AXIS: + { + short v = (short)(PyInt_AsLong(value)); + if ((v != (short)'x') && (v != (short)'y')) + return EXPP_ReturnIntError( PyExc_TypeError, "expected int arg as in Blender.Actuator.Values.CAMERA_" ); + act->axis = v; + return 0; + } + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + +/* + * Property actuator getter + */ +static PyObject *property_getter( BPy_Actuator * self, int type ) +{ + bPropertyActuator *act = self->act->data; + switch (type) { + case EXPP_ACT_OBJECT: + return Object_CreatePyObject( act->ob ); + case EXPP_ACT_PROPERTY: + return PyString_FromString (act->name); + case EXPP_ACT_VALUE: + return PyString_FromString (act->value); + case EXPP_ACT_TYPE: + return PyInt_FromLong( ( long )act->type ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + + +/* + * Property actuator setter + */ +static int property_setter( BPy_Actuator *self, int type, PyObject *value ) +{ + bPropertyActuator *act = self->act->data; + + switch (type) { + case EXPP_ACT_OBJECT: + return GenericLib_assignData(value, (void **) &act->ob, 0, 0, ID_OB, 0); + case EXPP_ACT_PROPERTY: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( act->name, name, sizeof( act->name ) ); + break; + } + case EXPP_ACT_VALUE: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( act->value, name, sizeof( act->value ) ); + break; + } + case EXPP_ACT_TYPE: + return EXPP_setIValueRange( value, &act->type, ACT_PROP_ASSIGN, ACT_PROP_COPY, 'h' ); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + +/* + * Constraint actuator getter + */ +static PyObject *constraint_getter( BPy_Actuator * self, int type ) +{ + bConstraintActuator *act = self->act->data; + switch (type) { + case EXPP_ACT_TYPE: + return PyInt_FromLong( ( long )act->flag ); + case EXPP_ACT_DAMP: + return PyInt_FromLong( ( long )act->damp ); + case EXPP_ACT_MIN: + return Py_BuildValue("(fff)", act->minloc[0], act->minloc[1], act->minloc[2]); + case EXPP_ACT_MAX: + return Py_BuildValue("(fff)", act->maxloc[0], act->maxloc[1], act->maxloc[2]); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + +#define CONSTRAINT_VECTOR_GETTER(PARAM)\ + float f1;\ + float f2;\ + float f3;\ + int st;\ + if( PyObject_Length( value ) == 3 )\ + st = PyArg_ParseTuple( value, "fff", &f1, &f2, &f3 );\ + else\ + st = PyArg_ParseTuple( value, "(fff)", &f1, &f2, &f3 );\ + if( !st )\ + return EXPP_ReturnIntError( PyExc_TypeError, "expected list argument of 3 floats" );\ + act->PARAM[0] = (f1<-20000)?-20000:((f1>20000)?20000:f1);\ + act->PARAM[1] = (f2<-20000)?-20000:((f2>20000)?20000:f2);\ + act->PARAM[2] = (f3<-20000)?-20000:((f3>20000)?20000:f3);\ + return 0; + + +/* + * Constraint actuator setter + */ +static int constraint_setter( BPy_Actuator *self, int type, PyObject *value ) +{ + bConstraintActuator *act = self->act->data; + + switch (type) { + case EXPP_ACT_TYPE: + return EXPP_setIValueRange( value, &act->flag, 0, ACT_CONST_LOCZ, 'h' ); + case EXPP_ACT_DAMP: + return EXPP_setIValueRange( value, &act->damp, 0, 100, 'i' ); + case EXPP_ACT_MIN: + { + CONSTRAINT_VECTOR_GETTER(minloc) + } + case EXPP_ACT_MAX: + { + CONSTRAINT_VECTOR_GETTER(maxloc) + } + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + +/* + * Scene actuator getter + */ +static PyObject *scene_getter( BPy_Actuator * self, int type ) +{ + bSceneActuator *act = self->act->data; + switch (type) { + case EXPP_ACT_TYPE: + return PyInt_FromLong( ( long )act->type ); + case EXPP_ACT_CAMERA: + return Object_CreatePyObject( act->camera ); + case EXPP_ACT_SCENE: + return Scene_CreatePyObject( act->scene ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + + +/* + * Scene actuator setter + */ +static int scene_setter( BPy_Actuator *self, int type, PyObject *value ) +{ + bSceneActuator *act = self->act->data; + + switch (type) { + case EXPP_ACT_TYPE: + return EXPP_setIValueRange( value, &act->type, ACT_SCENE_RESTART, ACT_SCENE_RESUME, 'h' ); + case EXPP_ACT_CAMERA: + return GenericLib_assignData(value, (void **) &act->camera, (void **) &self->object, 0, ID_OB, 0); + case EXPP_ACT_SCENE: + return GenericLib_assignData(value, (void **) &act->scene, 0, 0, ID_SCE, 0); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + +/* + * Edit Object actuator getter + */ +static PyObject *editObject_getter( BPy_Actuator * self, int type ) +{ + bEditObjectActuator *act = self->act->data; + switch (type) { + case EXPP_ACT_TYPE: + return PyInt_FromLong( ( long )act->type ); + case EXPP_ACT_TIME: + return PyInt_FromLong( ( long )act->time ); + case EXPP_ACT_OBJECT: + return Object_CreatePyObject( act->ob ); + case EXPP_ACT_3D: + return PyInt_FromLong( ( long )act->flag ); + case EXPP_ACT_MESH: + { + if (act->me) + return Mesh_CreatePyObject( act->me, NULL ); + else + Py_RETURN_NONE; + } + case EXPP_ACT_LINV: + return Py_BuildValue("(fffO)", act->linVelocity[0], act->linVelocity[1], act->linVelocity[2], + (act->localflag == 2)?PyBool_FromLong(1) : PyBool_FromLong(0) ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + + +/* + * Edit Object actuator setter + */ +static int editObject_setter( BPy_Actuator *self, int type, PyObject *value ) +{ + bEditObjectActuator *act = self->act->data; + + switch (type) { + case EXPP_ACT_TYPE: + return EXPP_setIValueRange( value, &act->type, ACT_EDOB_ADD_OBJECT, ACT_EDOB_TRACK_TO, 'h' ); + case EXPP_ACT_TIME: + return EXPP_setIValueRange( value, &act->time, 0, 2000, 'i' ); + case EXPP_ACT_OBJECT: + return GenericLib_assignData(value, (void **) &act->ob, 0, 0, ID_OB, 0); + case EXPP_ACT_3D: + return EXPP_setBitfield( value, &act->flag, ACT_TRACK_3D, 'h' ); + case EXPP_ACT_MESH: + return GenericLib_assignData(value, (void **) &act->me, 0, 0, ID_ME, 0); + case EXPP_ACT_LINV: + { + OBJECT_VECTOR_SETTER (linVelocity, localflag, 2) + } + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + +/* + * Random actuator getter + */ +static PyObject *random_getter( BPy_Actuator * self, int type ) +{ + bRandomActuator *act = self->act->data; + switch (type) { + case EXPP_ACT_TYPE: + return PyInt_FromLong( ( long )act->distribution ); + case EXPP_ACT_SEED: + return PyInt_FromLong( ( long )act->seed ); + case EXPP_ACT_PROPERTY: + return PyString_FromString (act->propname); + case EXPP_ACT_FLOAT1: + return PyFloat_FromDouble( (double)act->float_arg_1 ); + case EXPP_ACT_FLOAT2: + return PyFloat_FromDouble( (double)act->float_arg_2 ); + case EXPP_ACT_INT1: + return PyInt_FromLong( ( long )act->int_arg_1 ); + case EXPP_ACT_INT2: + return PyInt_FromLong( ( long )act->int_arg_2 ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + + +/* + * Random actuator setter + */ +static int random_setter( BPy_Actuator *self, int type, PyObject *value ) +{ + bRandomActuator *act = self->act->data; + + switch (type) { + case EXPP_ACT_TYPE: + return EXPP_setIValueRange( value, &act->distribution, ACT_RANDOM_BOOL_CONST, ACT_RANDOM_FLOAT_NEGATIVE_EXPONENTIAL, 'i' ); + case EXPP_ACT_SEED: + return EXPP_setIValueRange( value, &act->seed, 0, 1000, 'i' ); + case EXPP_ACT_PROPERTY: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( act->propname, name, sizeof( act->propname ) ); + break; + } + case EXPP_ACT_FLOAT1: + return EXPP_setFloatClamped( value, &act->float_arg_1, -10000.0, 10000.0 ); + case EXPP_ACT_FLOAT2: + return EXPP_setFloatClamped( value, &act->float_arg_2, -10000.0, 10000.0 ); + case EXPP_ACT_INT1: + return EXPP_setIValueClamped( value, &act->int_arg_1, -1000, 1000, 'i' ); + case EXPP_ACT_INT2: + return EXPP_setIValueClamped( value, &act->int_arg_2, -1000, 1000, 'i' ); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + +/* + * Message actuator getter + */ +static PyObject *message_getter( BPy_Actuator * self, int type ) +{ + bMessageActuator *act = self->act->data; + switch (type) { + case EXPP_ACT_TYPE: + return PyInt_FromLong( ( long )act->bodyType ); + case EXPP_ACT_TO: + return PyString_FromString (act->toPropName); + case EXPP_ACT_SUBJECT: + return PyString_FromString (act->subject); + case EXPP_ACT_BODY: + return PyString_FromString (act->body); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + + +/* + * Message actuator setter + */ +static int message_setter( BPy_Actuator *self, int type, PyObject *value ) +{ + bMessageActuator *act = self->act->data; + + switch (type) { + case EXPP_ACT_TYPE: + return EXPP_setIValueRange( value, &act->bodyType, 0, 1, 'h' ); + case EXPP_ACT_TO: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( act->toPropName, name, sizeof( act->toPropName ) ); + break; + } + case EXPP_ACT_SUBJECT: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( act->subject, name, sizeof( act->subject ) ); + break; + } + case EXPP_ACT_BODY: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( act->body, name, sizeof( act->body ) ); + break; + } + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + +/* + * CD actuator getter + */ +static PyObject *cd_getter( BPy_Actuator * self, int type ) +{ + bCDActuator *act = self->act->data; + switch (type) { + case EXPP_ACT_TYPE: + return PyInt_FromLong( ( long )act->type ); + case EXPP_ACT_TRACK: + return PyInt_FromLong( ( long )act->track ); + case EXPP_ACT_VOLUME: + return PyFloat_FromDouble( (double)act->volume ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + + +/* + * CD actuator setter + */ +static int cd_setter( BPy_Actuator *self, int type, PyObject *value ) +{ + bCDActuator *act = self->act->data; + + switch (type) { + case EXPP_ACT_TYPE: + return EXPP_setIValueRange( value, &act->type, ACT_CD_PLAY_ALL, ACT_CD_RESUME, 'h' ); + case EXPP_ACT_TRACK: + return EXPP_setIValueRange( value, &act->track, 0, 99, 'h' ); + case EXPP_ACT_VOLUME: + return EXPP_setFloatClamped( value, &act->volume, 0, 1.0); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + +/* + * Game actuator getter + */ +static PyObject *game_getter( BPy_Actuator * self, int type ) +{ + bGameActuator *act = self->act->data; + switch (type) { + case EXPP_ACT_TYPE: + return PyInt_FromLong( ( long )act->type ); + case EXPP_ACT_FILE: + return PyString_FromString (act->filename); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + + +/* + * Game actuator setter + */ +static int game_setter( BPy_Actuator *self, int type, PyObject *value ) +{ + bGameActuator *act = self->act->data; + + switch (type) { + case EXPP_ACT_TYPE: + return EXPP_setIValueRange( value, &act->type, ACT_GAME_LOAD, ACT_GAME_QUIT, 'h' ); + case EXPP_ACT_FILE: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( act->filename, name, sizeof( act->filename ) ); + break; + } + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + +/* + * Visibility actuator getter + */ +static PyObject *visibility_getter( BPy_Actuator * self, int type ) +{ + bVisibilityActuator *act = self->act->data; + switch (type) { + case EXPP_ACT_TYPE: + return PyInt_FromLong( ( long )act->flag ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + + +/* + * Visibility actuator setter + */ +static int visibility_setter( BPy_Actuator *self, int type, PyObject *value ) +{ + bVisibilityActuator *act = self->act->data; + + switch (type) { + case EXPP_ACT_TYPE: + return EXPP_setIValueRange( value, &act->flag, 0, 1, 'h' ); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + +/* + * Action actuator getter + */ +static PyObject *action_getter( BPy_Actuator * self, int type ) +{ + bActionActuator *act = self->act->data; + switch (type) { + case EXPP_ACT_TYPE: + return PyInt_FromLong( ( long )act->type ); + case EXPP_ACT_PROPERTY: + return PyString_FromString (act->name); + case EXPP_ACT_START: + return PyInt_FromLong( ( long )act->sta ); + case EXPP_ACT_END: + return PyInt_FromLong( ( long )act->end ); + case EXPP_ACT_BLENDIN: + return PyInt_FromLong( ( long )act->blendin ); + case EXPP_ACT_PRIORITY: + return PyInt_FromLong( ( long )act->priority ); + case EXPP_ACT_ACTION: + return Action_CreatePyObject( act->act ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + + +/* + * Action actuator setter + */ +static int action_setter( BPy_Actuator *self, int type, PyObject *value ) +{ + bActionActuator *act = self->act->data; + + switch (type) { + case EXPP_ACT_TYPE: + { + short v = (short)(PyInt_AsLong(value)); + if (v != ACT_ACTION_PLAY && v != ACT_ACTION_FLIPPER + && v != ACT_ACTION_LOOP_STOP && v != ACT_ACTION_LOOP_END + && v != ACT_ACTION_FROM_PROP) + return EXPP_ReturnIntError( PyExc_TypeError, "expected int arg as in Blender.Sensor.Values" ); + + act->type = v; + break; + } + case EXPP_ACT_PROPERTY: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( act->name, name, sizeof( act->name ) ); + break; + } + case EXPP_ACT_START: + return EXPP_setIValueRange( value, &act->sta, 0, 300000, 'i' ); + case EXPP_ACT_END: + return EXPP_setIValueRange( value, &act->end, 0, 300000, 'i' ); + case EXPP_ACT_BLENDIN: + return EXPP_setIValueRange( value, &act->blendin, 0, 300000, 'i' ); + case EXPP_ACT_PRIORITY: + return EXPP_setIValueRange( value, &act->priority, 0, 100, 'h' ); + case EXPP_ACT_ACTION: + return GenericLib_assignData(value, (void **) &act->act, 0, 0, ID_AC, 0); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + + +/* + * Sound actuator getter + */ +static PyObject *sound_getter( BPy_Actuator * self, int type ) +{ + bSoundActuator *act = self->act->data; + switch (type) { + case EXPP_ACT_TYPE: + return PyInt_FromLong( ( long )act->type ); + case EXPP_ACT_SOUND: + { + if (act->sound) + return Sound_CreatePyObject( act->sound ); + else + Py_RETURN_NONE; + } + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + + +/* + * Sound actuator setter + */ +static int sound_setter( BPy_Actuator *self, int type, PyObject *value ) +{ + bSoundActuator *act = self->act->data; + + switch (type) { + case EXPP_ACT_TYPE: + return EXPP_setIValueRange( value, &act->type, ACT_SND_PLAY_STOP_SOUND, ACT_SND_LOOP_BIDIRECTIONAL_STOP_SOUND, 'h' ); + case EXPP_ACT_SOUND: + return GenericLib_assignData(value, (void **) &act->sound, 0, 0, ID_SO, 0); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + + +/* + * 2D Filter actuator getter + */ +static PyObject *filter2d_getter( BPy_Actuator * self, int type ) +{ + bTwoDFilterActuator *act = self->act->data; + switch (type) { + case EXPP_ACT_TYPE: + return PyInt_FromLong( ( long )act->type ); + case EXPP_ACT_VALUE: + return PyFloat_FromDouble( (double)act->float_arg ); + case EXPP_ACT_PASS: + return PyInt_FromLong( ( long )act->int_arg ); + case EXPP_ACT_DISABLED: + return ((act->flag & 1) !=0)?PyBool_FromLong(1) : PyBool_FromLong(0); + case EXPP_ACT_SCRIPT: + if (act->text) + return Text_CreatePyObject (act->text); + else + Py_RETURN_NONE; + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + + +/* + * 2D Filter actuator setter + */ +static int filter2d_setter( BPy_Actuator *self, int type, PyObject *value ) +{ + bTwoDFilterActuator *act = self->act->data; + + switch (type) { + case EXPP_ACT_TYPE: + return EXPP_setIValueRange( value, &act->type, ACT_2DFILTER_ENABLED, ACT_2DFILTER_CUSTOMFILTER, 'h' ); + case EXPP_ACT_VALUE: + return EXPP_setFloatClamped( value, &act->float_arg, 0.0, 1.0 ); + case EXPP_ACT_PASS: + return EXPP_setIValueRange( value, &act->int_arg, 0, 99, 'i' ); + case EXPP_ACT_DISABLED: + return EXPP_setBitfield( value, &act->flag, 1, 'h' ); + case EXPP_ACT_SCRIPT: + return GenericLib_assignData(value, (void **) &act->text, 0, 0, ID_TXT, 0); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + + + + + + + + + + + + + +/* + * get data from a actuator + */ + +static PyObject *Actuator_getData( BPy_Actuator * self, PyObject * key ) +{ + int setting; + + if( !PyInt_Check( key ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected an int arg as stored in Blender.Actuator.Settings" ); + + ACTUATOR_DEL_CHECK_PY(self); + + setting = PyInt_AsLong( key ); + + switch (self->act->type) { + case ACT_OBJECT: + return object_getter( self, setting); + case ACT_IPO: + return ipo_getter( self, setting); + case ACT_CAMERA: + return camera_getter( self, setting); + case ACT_PROPERTY: + return property_getter( self, setting); + case ACT_CONSTRAINT: + return constraint_getter( self, setting); + case ACT_SCENE: + return scene_getter( self, setting); + case ACT_EDIT_OBJECT: + return editObject_getter( self, setting); + case ACT_RANDOM: + return random_getter( self, setting); + case ACT_MESSAGE: + return message_getter( self, setting); + case ACT_CD: + return cd_getter( self, setting); + case ACT_GAME: + return game_getter( self, setting); + case ACT_VISIBILITY: + return visibility_getter( self, setting); + case ACT_ACTION: + return action_getter( self, setting); + case ACT_SOUND: + return sound_getter( self, setting); + case ACT_2DFILTER: + return filter2d_getter( self, setting); + default: + Py_RETURN_NONE; + } + return EXPP_ReturnPyObjError( PyExc_KeyError, + "unknown key or actuator type" ); +} + + +/* + * set data to a actuator + */ + +static int Actuator_setData( BPy_Actuator * self, PyObject * key, PyObject * arg ) +{ + int key_int; + + if( !PyNumber_Check( key ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected an int arg as stored in Blender.Actuator.Settings" ); + + ACTUATOR_DEL_CHECK_INT(self); + + key_int = PyInt_AsLong( key ); + + switch (self->act->type) { + case ACT_OBJECT: + return object_setter( self, key_int, arg); + case ACT_IPO: + return ipo_setter( self, key_int, arg); + case ACT_CAMERA: + return camera_setter( self, key_int, arg); + case ACT_PROPERTY: + return property_setter( self, key_int, arg); + case ACT_CONSTRAINT: + return constraint_setter( self, key_int, arg); + case ACT_SCENE: + return scene_setter( self, key_int, arg); + case ACT_EDIT_OBJECT: + return editObject_setter( self, key_int, arg); + case ACT_RANDOM: + return random_setter( self, key_int, arg); + case ACT_MESSAGE: + return message_setter( self, key_int, arg); + case ACT_CD: + return cd_setter( self, key_int, arg); + case ACT_GAME: + return game_setter( self, key_int, arg); + case ACT_VISIBILITY: + return visibility_setter( self, key_int, arg); + case ACT_ACTION: + return action_setter( self, key_int, arg); + case ACT_SOUND: + return sound_setter( self, key_int, arg); + case ACT_2DFILTER: + return filter2d_setter( self, key_int, arg); + default: + return 0; + } + return EXPP_ReturnIntError( PyExc_RuntimeError, + "unsupported actuator setting" ); +} + + + + + + + + +/*****************************************************************************/ +/* Function: Actuator_repr */ +/* Description: This is a callback function for the BPy_Actuator type. It */ +/* builds a meaningful string to represent actuator objects. */ +/*****************************************************************************/ + +// return actuator's name from its type (copy from buttons_logic.c) +static char *actuator_name(int type) +{ + switch (type) { + case ACT_ACTION: + return "Action"; + case ACT_OBJECT: + return "Motion"; + case ACT_IPO: + return "Ipo"; + case ACT_LAMP: + return "Lamp"; + case ACT_CAMERA: + return "Camera"; + case ACT_MATERIAL: + return "Material"; + case ACT_SOUND: + return "Sound"; + case ACT_CD: + return "CD"; + case ACT_PROPERTY: + return "Property"; + case ACT_EDIT_OBJECT: + return "Edit Object"; + case ACT_CONSTRAINT: + return "Constraint"; + case ACT_SCENE: + return "Scene"; + case ACT_GROUP: + return "Group"; + case ACT_RANDOM: + return "Random"; + case ACT_MESSAGE: + return "Message"; + case ACT_GAME: + return "Game"; + case ACT_VISIBILITY: + return "Visibility"; + case ACT_2DFILTER: + return "2D Filter"; + } + return "unknown"; +} + +static PyObject *Actuator_repr( BPy_Actuator * self ) +{ + if (self->act==NULL) + return PyString_FromString( "[Actuator - Removed"); + + return PyString_FromFormat( "[Actuator \"%s\", Type \"%s\"]", self->act->name, actuator_name(self->act->type)); +} + +/* Three Python Actuator_Type helper functions needed by the Object module: */ + +/*****************************************************************************/ +/* Function: Actuator_CreatePyObject */ +/* Description: This function will create a new BPy_Actuator from an */ +/* existing Blender actuator structure. */ +/*****************************************************************************/ +PyObject *Actuator_CreatePyObject( Object *ob, bActuator * act ) +{ + BPy_Actuator *pyact; + pyact = ( BPy_Actuator * ) PyObject_NEW( BPy_Actuator, &Actuator_Type ); + if( !pyact ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, + "couldn't create BPy_Actuator object" ); + pyact->act = act; + pyact->object = ob; + return ( PyObject * ) pyact; +} + +/*****************************************************************************/ +/* Function: Actuator_FromPyObject */ +/* Description: This function returns the Blender actuator from the given */ +/* PyObject. */ +/*****************************************************************************/ +bActuator *Actuator_FromPyObject( PyObject * pyobj ) +{ + return ( ( BPy_Actuator * ) pyobj )->act; +} + + + + + + + + + + + + + + +/*****************************************************************************/ +/* Actuator Sequence wrapper */ +/*****************************************************************************/ + +/* + * Initialize the interator + */ + +static PyObject *ActuatorSeq_getIter( BPy_ActuatorSeq * self ) +{ + if (!self->iter) { + self->iter = (bActuator *)self->object->actuators.first; + return EXPP_incr_ret ( (PyObject *) self ); + } else { + return ActuatorSeq_CreatePyObject(self->object, (bActuator *)self->object->actuators.first); + } +} + +/* + * Get the next Actuator + */ + +static PyObject *ActuatorSeq_nextIter( BPy_ActuatorSeq * self ) +{ + bActuator *iter = self->iter; + if( iter ) { + self->iter = iter->next; + return Actuator_CreatePyObject( self->object, iter ); + } + + self->iter= NULL; /* mark as not iterating */ + return EXPP_ReturnPyObjError( PyExc_StopIteration, + "iterator at end" ); +} + +/* return the number of actuators */ + +static int ActuatorSeq_length( BPy_ActuatorSeq * self ) +{ + return BLI_countlist( &self->object->actuators ); +} + +/* return a actuator */ + +static PyObject *ActuatorSeq_item( BPy_ActuatorSeq * self, int i ) +{ + bActuator *act = NULL; + + /* if index is negative, start counting from the end of the list */ + if( i < 0 ) + i += ActuatorSeq_length( self ); + + /* skip through the list until we get the actuator or end of list */ + + for( act = self->object->actuators.first; i && act; --i ) act = act->next; + + if( act ) + return Actuator_CreatePyObject( self->object, act ); + else + return EXPP_ReturnPyObjError( PyExc_IndexError, + "array index out of range" ); +} + + + +/*****************************************************************************/ +/* Python BPy_ActuatorSeq sequence table: */ +/*****************************************************************************/ +static PySequenceMethods ActuatorSeq_as_sequence = { + ( inquiry ) ActuatorSeq_length, /* sq_length */ + ( binaryfunc ) 0, /* sq_concat */ + ( intargfunc ) 0, /* sq_repeat */ + ( intargfunc ) ActuatorSeq_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 */ +}; + +/* + * helper function to check for a valid actuator argument + */ + +static bActuator *locate_actuator( BPy_ActuatorSeq *self, BPy_Actuator * value ) +{ + bActuator *act; + + /* check that argument is a actuator */ + if( !BPy_Actuator_Check(value) ) + return (bActuator *)EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a actuator as an argument" ); + + /* check whether actuator has been removed */ + if( !value->act ) + return (bActuator *)EXPP_ReturnPyObjError( PyExc_RuntimeError, + "This actuator has been removed!" ); + + /* find the actuator in the object's list */ + for( act = self->object->actuators.first; act; act = act->next ) + if( act == value->act ) + return act; + + /* return exception if we can't find the actuator */ + return (bActuator *)EXPP_ReturnPyObjError( PyExc_AttributeError, + "This actuator is not in the object's stack" ); +} + +/* create a new actuator at the end of the list */ + +static PyObject *ActuatorSeq_append( BPy_ActuatorSeq *self, PyObject *value ) +{ + int type = PyInt_AsLong(value); + + if( type < ACT_OBJECT || type > ACT_2DFILTER ) + return EXPP_ReturnPyObjError( PyExc_ValueError, + "Not an int or argument out of range, expected an int from Blender.Actuator.Type" ); + + if ((self->object->type != OB_ARMATURE) && (type == ACT_ACTION)) + return EXPP_ReturnPyObjError( PyExc_ValueError, + "Only Armature objects can handle an action actuator" ); + + BLI_addtail( &self->object->actuators, new_actuator( type ) ); + return Actuator_CreatePyObject( self->object, self->object->actuators.last ); +} + +/* remove an existing actuator */ + +static PyObject *ActuatorSeq_remove( BPy_ActuatorSeq *self, BPy_Actuator *value ) +{ + bActuator *act = locate_actuator( self, value ); + + /* if we can't locate the actuator, return (exception already set) */ + if( !act ) + return (PyObject *)NULL; + + /* do the actual removal */ + BLI_remlink( &self->object->actuators, act ); + free_actuator( act ); + + /* erase the link to the actuator */ + value->act = NULL; + + Py_RETURN_NONE; +} + + +/*****************************************************************************/ +/* Python BPy_ActuatorSeq methods table: */ +/*****************************************************************************/ +static PyMethodDef BPy_ActuatorSeq_methods[] = { + /* name, method, flags, doc */ + {"append", ( PyCFunction ) ActuatorSeq_append, METH_O, + "(type) - add a new actuator, where type is the type of actuator"}, + {"remove", ( PyCFunction ) ActuatorSeq_remove, METH_O, + "(actuator) - remove an existing actuator, where actuator is a actuator from this object."}, + {NULL, NULL, 0, NULL} +}; + +/*****************************************************************************/ +/* Python ActuatorSeq_Type structure definition: */ +/*****************************************************************************/ +PyTypeObject ActuatorSeq_Type = { + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ + /* For printing, in format "." */ + "Blender.Actuators", /* char *tp_name; */ + sizeof( BPy_ActuatorSeq ), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ + + /* Methods to implement standard operations */ + + NULL, /* 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; */ + &ActuatorSeq_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 )ActuatorSeq_getIter, /* getiterfunc tp_iter; */ + ( iternextfunc )ActuatorSeq_nextIter, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + BPy_ActuatorSeq_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: ActuatorSeq_CreatePyObject */ +/* Description: This function will create a new BPy_ActuatorSeq from an */ +/* existing ListBase structure. */ +/*****************************************************************************/ +PyObject *ActuatorSeq_CreatePyObject( Object *ob, bActuator *iter ) +{ + BPy_ActuatorSeq *pyact; + pyact = ( BPy_ActuatorSeq * ) PyObject_NEW( BPy_ActuatorSeq, &ActuatorSeq_Type ); + if( !pyact ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, + "couldn't create BPy_ActuatorSeq object" ); + pyact->object = ob; + pyact->iter = iter; + return ( PyObject * ) pyact; +} + + + + +static PyObject *M_Actuator_TypeDict( void ) +{ + PyObject *S = PyConstant_New( ); + + if( S ) { + BPy_constant *d = ( BPy_constant * ) S; + + PyConstant_Insert( d, "MOTION", + PyInt_FromLong( ACT_OBJECT ) ); + PyConstant_Insert( d, "IPO", + PyInt_FromLong( ACT_IPO ) ); + PyConstant_Insert( d, "CAMERA", + PyInt_FromLong( ACT_CAMERA ) ); + PyConstant_Insert( d, "SOUND", + PyInt_FromLong( ACT_SOUND ) ); + PyConstant_Insert( d, "PROPERTY", + PyInt_FromLong( ACT_PROPERTY ) ); + PyConstant_Insert( d, "CONSTRAINT", + PyInt_FromLong( ACT_CONSTRAINT ) ); + PyConstant_Insert( d, "EDIT_OBJECT", + PyInt_FromLong( ACT_EDIT_OBJECT ) ); + PyConstant_Insert( d, "SCENE", + PyInt_FromLong( ACT_SCENE ) ); + PyConstant_Insert( d, "RANDOM", + PyInt_FromLong( ACT_RANDOM ) ); + PyConstant_Insert( d, "MESSAGE", + PyInt_FromLong( ACT_MESSAGE ) ); + PyConstant_Insert( d, "ACTION", + PyInt_FromLong( ACT_ACTION ) ); + PyConstant_Insert( d, "CD", + PyInt_FromLong( ACT_CD ) ); + PyConstant_Insert( d, "GAME", + PyInt_FromLong( ACT_GAME ) ); + PyConstant_Insert( d, "VISIBILITY", + PyInt_FromLong( ACT_VISIBILITY ) ); + PyConstant_Insert( d, "FILTER2D", + PyInt_FromLong( ACT_2DFILTER ) ); + } + return S; +} + + +static PyObject *M_Actuator_ValuesDict( void ) +{ + PyObject *S = PyConstant_New( ); + + if( S ) { + BPy_constant *d = ( BPy_constant * ) S; + + // IPO constants + PyConstant_Insert( d, "IPO_PLAY", + PyInt_FromLong( ACT_IPO_PLAY ) ); + PyConstant_Insert( d, "IPO_PINGPONG", + PyInt_FromLong( ACT_IPO_PINGPONG ) ); + PyConstant_Insert( d, "IPO_FLIPPER", + PyInt_FromLong( ACT_IPO_FLIPPER ) ); + PyConstant_Insert( d, "IPO_LOOP_STOP", + PyInt_FromLong( ACT_IPO_LOOP_STOP ) ); + PyConstant_Insert( d, "IPO_LOOP_END", + PyInt_FromLong( ACT_IPO_LOOP_END ) ); + PyConstant_Insert( d, "IPO_PROPERTY", + PyInt_FromLong( ACT_IPO_FROM_PROP ) ); + + // Camera constants + PyConstant_Insert( d, "CAMERA_X", + PyInt_FromLong( (long)'x' ) ); + PyConstant_Insert( d, "CAMERA_Y", + PyInt_FromLong( (long)'y' ) ); + + // Property constants + PyConstant_Insert( d, "PROP_ASSIGN", + PyInt_FromLong( ACT_PROP_ASSIGN ) ); + PyConstant_Insert( d, "PROP_ADD", + PyInt_FromLong( ACT_PROP_ADD ) ); + PyConstant_Insert( d, "PROP_COPY", + PyInt_FromLong( ACT_PROP_COPY ) ); + + // Scene constants + PyConstant_Insert( d, "SCENE_RESTART", + PyInt_FromLong( ACT_SCENE_RESTART ) ); + PyConstant_Insert( d, "SCENE_SET", + PyInt_FromLong( ACT_SCENE_SET ) ); + PyConstant_Insert( d, "SCENE_CAMERA", + PyInt_FromLong( ACT_SCENE_CAMERA ) ); + PyConstant_Insert( d, "SCENE_ADD_FRONT", + PyInt_FromLong( ACT_SCENE_ADD_FRONT ) ); + PyConstant_Insert( d, "SCENE_ADD_BACK", + PyInt_FromLong( ACT_SCENE_ADD_BACK ) ); + PyConstant_Insert( d, "SCENE_REMOVE", + PyInt_FromLong( ACT_SCENE_REMOVE ) ); + PyConstant_Insert( d, "SCENE_SUSPEND", + PyInt_FromLong( ACT_SCENE_SUSPEND ) ); + PyConstant_Insert( d, "SCENE_RESUME", + PyInt_FromLong( ACT_SCENE_RESUME ) ); + + // Edit Object constants + PyConstant_Insert( d, "EDIT_ADD", + PyInt_FromLong( ACT_EDOB_ADD_OBJECT ) ); + PyConstant_Insert( d, "EDIT_END", + PyInt_FromLong( ACT_EDOB_END_OBJECT ) ); + PyConstant_Insert( d, "EDIT_REPLACE", + PyInt_FromLong( ACT_EDOB_REPLACE_MESH ) ); + PyConstant_Insert( d, "EDIT_TRACK", + PyInt_FromLong( ACT_EDOB_TRACK_TO ) ); + + // Random constants + PyConstant_Insert( d, "RANDOM_BOOL_CONST", + PyInt_FromLong( ACT_RANDOM_BOOL_CONST ) ); + PyConstant_Insert( d, "RANDOM_BOOL_UNIFORM", + PyInt_FromLong( ACT_RANDOM_BOOL_UNIFORM ) ); + PyConstant_Insert( d, "RANDOM_BOOL_BERNOUILLI", + PyInt_FromLong( ACT_RANDOM_BOOL_BERNOUILLI ) ); + PyConstant_Insert( d, "RANDOM_INT_CONST", + PyInt_FromLong( ACT_RANDOM_INT_CONST ) ); + PyConstant_Insert( d, "RANDOM_INT_UNIFORM", + PyInt_FromLong( ACT_RANDOM_INT_UNIFORM ) ); + PyConstant_Insert( d, "RANDOM_INT_POISSON", + PyInt_FromLong( ACT_RANDOM_INT_POISSON ) ); + PyConstant_Insert( d, "RANDOM_FLOAT_CONST", + PyInt_FromLong( ACT_RANDOM_FLOAT_CONST ) ); + PyConstant_Insert( d, "RANDOM_FLOAT_UNIFORM", + PyInt_FromLong( ACT_RANDOM_FLOAT_UNIFORM ) ); + PyConstant_Insert( d, "RANDOM_FLOAT_NORMAL", + PyInt_FromLong( ACT_RANDOM_FLOAT_NORMAL ) ); + PyConstant_Insert( d, "RANDOM_FLOAT_NEGATIVE_EXPONENTIAL", + PyInt_FromLong( ACT_RANDOM_FLOAT_NEGATIVE_EXPONENTIAL ) ); + + // Message constants + PyConstant_Insert( d, "MESSAGE_TEXT", + PyInt_FromLong( ACT_MESG_MESG ) ); + PyConstant_Insert( d, "MESSAGE_PROP", + PyInt_FromLong( ACT_MESG_PROP ) ); + + // CD constants + PyConstant_Insert( d, "CD_PLAY_ALL", + PyInt_FromLong( ACT_CD_PLAY_ALL ) ); + PyConstant_Insert( d, "CD_PLAY_TRACK", + PyInt_FromLong( ACT_CD_PLAY_TRACK ) ); + PyConstant_Insert( d, "CD_VOLUME", + PyInt_FromLong( ACT_CD_VOLUME ) ); + PyConstant_Insert( d, "CD_STOP", + PyInt_FromLong( ACT_CD_STOP ) ); + PyConstant_Insert( d, "CD_PAUSE", + PyInt_FromLong( ACT_CD_PAUSE ) ); + PyConstant_Insert( d, "CD_RESUME", + PyInt_FromLong( ACT_CD_RESUME ) ); + + // Game constants + PyConstant_Insert( d, "GAME_LOAD", + PyInt_FromLong( ACT_GAME_LOAD ) ); + PyConstant_Insert( d, "GAME_RESTART", + PyInt_FromLong( ACT_GAME_RESTART ) ); + PyConstant_Insert( d, "GAME_QUIT", + PyInt_FromLong( ACT_GAME_QUIT ) ); + + // Action constants + PyConstant_Insert( d, "ACTION_PLAY", + PyInt_FromLong( ACT_ACTION_PLAY ) ); + PyConstant_Insert( d, "ACTION_FLIPPER", + PyInt_FromLong( ACT_ACTION_FLIPPER ) ); + PyConstant_Insert( d, "ACTION_LOOP_STOP", + PyInt_FromLong( ACT_ACTION_LOOP_STOP ) ); + PyConstant_Insert( d, "ACTION_LOOP_END", + PyInt_FromLong( ACT_ACTION_LOOP_END ) ); + PyConstant_Insert( d, "ACTION_PROPERTY", + PyInt_FromLong( ACT_ACTION_FROM_PROP ) ); + + // Constraint constants + PyConstant_Insert( d, "CONST_NONE", + PyInt_FromLong( 0 ) ); + PyConstant_Insert( d, "CONST_LOCX", + PyInt_FromLong( ACT_CONST_LOCX ) ); + PyConstant_Insert( d, "CONST_LOCY", + PyInt_FromLong( ACT_CONST_LOCY ) ); + PyConstant_Insert( d, "CONST_LOCZ", + PyInt_FromLong( ACT_CONST_LOCZ ) ); + + // Sound constants + PyConstant_Insert( d, "SOUND_PLAY_STOP", + PyInt_FromLong( ACT_SND_PLAY_STOP_SOUND ) ); + PyConstant_Insert( d, "SOUND_PLAY_END", + PyInt_FromLong( ACT_SND_PLAY_END_SOUND ) ); + PyConstant_Insert( d, "SOUND_LOOP_STOP", + PyInt_FromLong( ACT_SND_LOOP_STOP_SOUND ) ); + PyConstant_Insert( d, "SOUND_LOOP_END", + PyInt_FromLong( ACT_SND_LOOP_END_SOUND ) ); + PyConstant_Insert( d, "SOUND_LOOP_PING_PONG", + PyInt_FromLong( ACT_SND_LOOP_BIDIRECTIONAL_SOUND ) ); + PyConstant_Insert( d, "SOUND_LOOP_PING_PONG_STOP", + PyInt_FromLong( ACT_SND_LOOP_BIDIRECTIONAL_STOP_SOUND ) ); + + // 2D Filters constants + PyConstant_Insert( d, "F2D_ENABLED", + PyInt_FromLong( ACT_2DFILTER_ENABLED ) ); + PyConstant_Insert( d, "F2D_DISABLED", + PyInt_FromLong( ACT_2DFILTER_DISABLED ) ); + PyConstant_Insert( d, "F2D_NOFILTER", + PyInt_FromLong( ACT_2DFILTER_NOFILTER ) ); + PyConstant_Insert( d, "F2D_MOTIONBLUR", + PyInt_FromLong( ACT_2DFILTER_MOTIONBLUR ) ); + PyConstant_Insert( d, "F2D_BLUR", + PyInt_FromLong( ACT_2DFILTER_BLUR ) ); + PyConstant_Insert( d, "F2D_SHARPEN", + PyInt_FromLong( ACT_2DFILTER_SHARPEN ) ); + PyConstant_Insert( d, "F2D_DILATION", + PyInt_FromLong( ACT_2DFILTER_DILATION ) ); + PyConstant_Insert( d, "F2D_EROSION", + PyInt_FromLong( ACT_2DFILTER_EROSION ) ); + PyConstant_Insert( d, "F2D_LAPLACIAN", + PyInt_FromLong( ACT_2DFILTER_LAPLACIAN ) ); + PyConstant_Insert( d, "F2D_SOBEL", + PyInt_FromLong( ACT_2DFILTER_SOBEL ) ); + PyConstant_Insert( d, "F2D_PREWITT", + PyInt_FromLong( ACT_2DFILTER_PREWITT ) ); + PyConstant_Insert( d, "F2D_GRAYSCALE", + PyInt_FromLong( ACT_2DFILTER_GRAYSCALE ) ); + PyConstant_Insert( d, "F2D_SEPIA", + PyInt_FromLong( ACT_2DFILTER_SEPIA ) ); + PyConstant_Insert( d, "F2D_INVERT", + PyInt_FromLong( ACT_2DFILTER_INVERT ) ); + PyConstant_Insert( d, "F2D_CUSTOMFILTER", + PyInt_FromLong( ACT_2DFILTER_CUSTOMFILTER ) ); + + } + return S; +} + + + +static PyObject *M_Actuator_SettingsDict( void ) +{ + PyObject *S = PyConstant_New( ); + + if( S ) { + BPy_constant *d = ( BPy_constant * ) S; + + PyConstant_Insert( d, "DLOC", + PyInt_FromLong( EXPP_ACT_DLOC ) ); + PyConstant_Insert( d, "DROT", + PyInt_FromLong( EXPP_ACT_DROT ) ); + PyConstant_Insert( d, "FORCE", + PyInt_FromLong( EXPP_ACT_FORCE ) ); + PyConstant_Insert( d, "TORQUE", + PyInt_FromLong( EXPP_ACT_TORQUE ) ); + PyConstant_Insert( d, "LINV", + PyInt_FromLong( EXPP_ACT_LINV ) ); + PyConstant_Insert( d, "ANGV", + PyInt_FromLong( EXPP_ACT_ANGV ) ); + PyConstant_Insert( d, "ADDLINV", + PyInt_FromLong( EXPP_ACT_ADDLINV ) ); + PyConstant_Insert( d, "PROPERTY", + PyInt_FromLong( EXPP_ACT_PROPERTY ) ); + PyConstant_Insert( d, "START", + PyInt_FromLong( EXPP_ACT_START ) ); + PyConstant_Insert( d, "END", + PyInt_FromLong( EXPP_ACT_END ) ); + PyConstant_Insert( d, "TYPE", + PyInt_FromLong( EXPP_ACT_TYPE ) ); + PyConstant_Insert( d, "CHILD", + PyInt_FromLong( EXPP_ACT_CHILD ) ); + PyConstant_Insert( d, "FORCE_LOCAL", + PyInt_FromLong( EXPP_ACT_FORCE_LOCAL ) ); + PyConstant_Insert( d, "HEIGHT", + PyInt_FromLong( EXPP_ACT_HEIGHT ) ); + PyConstant_Insert( d, "MIN", + PyInt_FromLong( EXPP_ACT_MIN ) ); + PyConstant_Insert( d, "MAX", + PyInt_FromLong( EXPP_ACT_MAX ) ); + PyConstant_Insert( d, "OBJECT", + PyInt_FromLong( EXPP_ACT_OBJECT ) ); + PyConstant_Insert( d, "AXIS", + PyInt_FromLong( EXPP_ACT_AXIS ) ); + PyConstant_Insert( d, "VALUE", + PyInt_FromLong( EXPP_ACT_VALUE ) ); + PyConstant_Insert( d, "DAMP", + PyInt_FromLong( EXPP_ACT_DAMP ) ); + PyConstant_Insert( d, "CAMERA", + PyInt_FromLong( EXPP_ACT_CAMERA ) ); + PyConstant_Insert( d, "SCENE", + PyInt_FromLong( EXPP_ACT_SCENE ) ); + PyConstant_Insert( d, "TIME", + PyInt_FromLong( EXPP_ACT_TIME ) ); + PyConstant_Insert( d, "TRACK_3D", + PyInt_FromLong( EXPP_ACT_3D ) ); + PyConstant_Insert( d, "MESH", + PyInt_FromLong( EXPP_ACT_MESH ) ); + PyConstant_Insert( d, "SEED", + PyInt_FromLong( EXPP_ACT_SEED ) ); + PyConstant_Insert( d, "FLOAT1", + PyInt_FromLong( EXPP_ACT_FLOAT1 ) ); + PyConstant_Insert( d, "FLOAT2", + PyInt_FromLong( EXPP_ACT_FLOAT2 ) ); + PyConstant_Insert( d, "INT1", + PyInt_FromLong( EXPP_ACT_INT1 ) ); + PyConstant_Insert( d, "INT2", + PyInt_FromLong( EXPP_ACT_INT2 ) ); + PyConstant_Insert( d, "TO", + PyInt_FromLong( EXPP_ACT_TO ) ); + PyConstant_Insert( d, "SUBJECT", + PyInt_FromLong( EXPP_ACT_SUBJECT ) ); + PyConstant_Insert( d, "BODY", + PyInt_FromLong( EXPP_ACT_BODY ) ); + PyConstant_Insert( d, "TRACK", + PyInt_FromLong( EXPP_ACT_TRACK ) ); + PyConstant_Insert( d, "VOLUME", + PyInt_FromLong( EXPP_ACT_VOLUME ) ); + PyConstant_Insert( d, "FILE", + PyInt_FromLong( EXPP_ACT_FILE ) ); + PyConstant_Insert( d, "BLENDIN", + PyInt_FromLong( EXPP_ACT_BLENDIN ) ); + PyConstant_Insert( d, "PRIORITY", + PyInt_FromLong( EXPP_ACT_PRIORITY ) ); + PyConstant_Insert( d, "ACTION", + PyInt_FromLong( EXPP_ACT_ACTION ) ); + PyConstant_Insert( d, "SOUND", + PyInt_FromLong( EXPP_ACT_SOUND ) ); + PyConstant_Insert( d, "PASS", + PyInt_FromLong( EXPP_ACT_PASS ) ); + PyConstant_Insert( d, "DISABLED", + PyInt_FromLong( EXPP_ACT_DISABLED ) ); + PyConstant_Insert( d, "SCRIPT", + PyInt_FromLong( EXPP_ACT_SCRIPT ) ); + } + return S; +} + + + + +/*****************************************************************************/ +/* Function: Actuator_Init */ +/*****************************************************************************/ +PyObject *Actuator_Init( void ) +{ + PyObject *submodule; + PyObject *TypeDict = M_Actuator_TypeDict( ); + PyObject *SettingsDict = M_Actuator_SettingsDict( ); + PyObject *ValuesDict = M_Actuator_ValuesDict( ); + + if( PyType_Ready( &ActuatorSeq_Type ) < 0 || + PyType_Ready( &Actuator_Type ) < 0 ) + return NULL; + + submodule = Py_InitModule3( "Blender.Actuator", NULL, + "Actuator module for accessing and creating object actuator data" ); + + if( TypeDict ) { + PyModule_AddObject( submodule, "Type", TypeDict ); /* deprecated */ + /* since PyModule_AddObject() steals a reference, we need to + incref TypeDict to use it again */ + Py_INCREF( TypeDict); + PyModule_AddObject( submodule, "Types", TypeDict ); + } + + if( SettingsDict ) + PyModule_AddObject( submodule, "Settings", SettingsDict ); + + if( ValuesDict ) + PyModule_AddObject( submodule, "Values", ValuesDict ); + + return submodule; +} Index: source/blender/python/api2_2x/Actuator.h =================================================================== --- source/blender/python/api2_2x/Actuator.h (revision 0) +++ source/blender/python/api2_2x/Actuator.h (revision 0) @@ -0,0 +1,70 @@ +/* + * ***** 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. + * + * This is a new part of Blender. + * + * Contributor(s): Matthieu Delanoë + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef EXPP_ACTUATOR_H +#define EXPP_ACTUATOR_H + +#include +#include "DNA_object_types.h" +#include "DNA_actuator_types.h" +#include "DNA_listBase.h" + +/*****************************************************************************/ +/* Python BPy_Actuator and BPy_ActuatorSeq structure definition: */ +/*****************************************************************************/ + +typedef struct { + PyObject_HEAD /* required macro */ + Object *object; + bActuator *iter; +} BPy_ActuatorSeq; + +typedef struct { + PyObject_HEAD /* required macro */ + Object *object; + /* if act is null, the actuator has been removed and we need to raise + an error when its data is accessed */ + bActuator *act; +} BPy_Actuator; + +extern PyTypeObject ActuatorSeq_Type; +extern PyTypeObject Actuator_Type; +#define BPy_ActuatorSeq_Check(v) ((v)->ob_type == &ActuatorSeq_Type) +#define BPy_Actuator_Check(v) ((v)->ob_type == &Actuator_Type) + + + +/* + * prototypes + */ + +PyObject *Actuator_Init( void ); +PyObject *ActuatorSeq_CreatePyObject( Object *obj, bActuator *iter ); +PyObject *Actuator_CreatePyObject( Object *obj, bActuator *sens ); +bActuator *Actuator_FromPyObject( PyObject * py_obj ); + +#endif /* EXPP_ACTUATOR_H */ Index: source/blender/python/api2_2x/Blender.c =================================================================== --- source/blender/python/api2_2x/Blender.c (revision 13588) +++ source/blender/python/api2_2x/Blender.c (working copy) @@ -89,6 +89,10 @@ #include "Group.h" #include "Registry.h" #include "Scene.h" +#include "Sensor.h" +#include "Actuator.h" +#include "Controller.h" + #include "Sound.h" #include "SurfNurb.h" #include "Sys.h" @@ -1024,11 +1028,13 @@ EXPP_dict_set_item_str(dict, "event", PyString_FromString("")); EXPP_dict_set_item_str(dict, "mode", smode); + PyDict_SetItemString(dict, "Actuator", Actuator_Init()); PyDict_SetItemString(dict, "Armature", Armature_Init()); 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, "Controller", Controller_Init()); PyDict_SetItemString(dict, "Curve", Curve_Init()); PyDict_SetItemString(dict, "Camera", Camera_Init()); PyDict_SetItemString(dict, "Draw", Draw_Init()); @@ -1052,6 +1058,7 @@ PyDict_SetItemString(dict, "Group", Group_Init()); PyDict_SetItemString(dict, "Registry", Registry_Init()); PyDict_SetItemString(dict, "Scene", Scene_Init()); + PyDict_SetItemString(dict, "Sensor", Sensor_Init()); PyDict_SetItemString(dict, "Sound", Sound_Init()); PyDict_SetItemString(dict, "SurfNurb", SurfNurb_Init()); PyDict_SetItemString(dict, "sys", sys_Init()); Index: source/blender/python/api2_2x/Controller.c =================================================================== --- source/blender/python/api2_2x/Controller.c (revision 0) +++ source/blender/python/api2_2x/Controller.c (revision 0) @@ -0,0 +1,919 @@ +/* + * ***** 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. + * + * This is a new part of Blender. + * + * Contributor(s): Matthieu Delanoë + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "Controller.h" /*This must come first*/ + +#include "DNA_object_types.h" + +#include "BLI_blenlib.h" +#include "MEM_guardedalloc.h" + +#include "BKE_sca.h" +#include "Object.h" +#include "Text.h" +#include "gen_utils.h" +#include "gen_library.h" + +#include "Actuator.h" + + +/* checks for the controller being removed */ +#define CONTROLLER_DEL_CHECK_PY(bpy_controller) if (!(bpy_controller->cont)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "Controller has been removed" ) ) +#define CONTROLLER_DEL_CHECK_INT(bpy_controller) if (!(bpy_controller->cont)) return ( EXPP_ReturnIntError( PyExc_RuntimeError, "Controller has been removed" ) ) + + +enum controller_constants { + // For Expression controller + EXPP_CONT_EXP=0, + + // For Python controller + EXPP_CONT_SCRIPT, + +}; + + + +/*****************************************************************************/ +/* Python BPy_Controller methods declarations: */ +/*****************************************************************************/ +static PyObject *Controller_getName( BPy_Controller * self ); +static int Controller_setName( BPy_Controller * self, PyObject *arg ); +static PyObject *Controller_getType( BPy_Controller * self ); + +static PyObject *Controller_linkActuator( BPy_Controller * self, PyObject *arg ); +static PyObject *Controller_unlinkActuator( BPy_Controller * self, PyObject *arg ); +static PyObject *Controller_unlinkAllActuators( BPy_Controller * self ); +static PyObject *Controller_getLinkedActuator( BPy_Controller * self, PyObject *arg ); +static PyObject *Controller_getActuatorsCount( BPy_Controller * self ); + +static PyObject *Controller_getData( BPy_Controller * self, PyObject * key ); +static int Controller_setData( BPy_Controller * self, PyObject * key, PyObject * arg ); + +/*****************************************************************************/ +/* Python BPy_Controller methods table: */ +/*****************************************************************************/ +static PyMethodDef BPy_Controller_methods[] = { + /* name, method, flags, doc */ + {"linkActuator", (PyCFunction)Controller_linkActuator, METH_VARARGS, "link an actuator to this controller"}, + {"unlinkActuator", (PyCFunction)Controller_unlinkActuator, METH_VARARGS, "unlink an actuator from this controller"}, + {"unlinkAllActuators", (PyCFunction)Controller_unlinkAllActuators, METH_NOARGS, "unlink all actuators from this controller"}, + {"getLinkedActuator", (PyCFunction)Controller_getLinkedActuator, METH_VARARGS, "get an actuator linked to this controller"}, + {"getActuatorsCount", (PyCFunction)Controller_getActuatorsCount, METH_NOARGS, "number of actuators linked to this controller"}, + {NULL, NULL, 0, NULL} +}; + +/*****************************************************************************/ +/* Python BPy_Controller attributes get/set structure: */ +/*****************************************************************************/ +static PyGetSetDef BPy_Controller_getseters[] = { + {"name", (getter)Controller_getName, (setter)Controller_setName, "Controller name", NULL}, + {"type", (getter)Controller_getType, (setter)NULL, "Controller type (read only)", NULL}, + {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ +}; + +/*****************************************************************************/ +/* Python Controller_Type Mapping Methods table: */ +/*****************************************************************************/ +static PyMappingMethods Controller_as_mapping = { + NULL, /* act_length */ + ( binaryfunc ) Controller_getData, /* act_subscript */ + ( objobjargproc ) Controller_setData, /* act_ass_subscript */ +}; + +/*****************************************************************************/ +/* Python Controller_Type callback function prototypes: */ +/*****************************************************************************/ +static PyObject *Controller_repr( BPy_Controller * self ); + +/*****************************************************************************/ +/* Python Controller_Type structure definition: */ +/*****************************************************************************/ +PyTypeObject Controller_Type = { + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ + /* For printing, in format "." */ + "Blender Controller", /* char *tp_name; */ + sizeof( BPy_Controller ), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ + + /* Methods to implement standard operations */ + + NULL, /* destructor tp_dealloc; */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* cmpfunc tp_compare; */ + ( reprfunc ) Controller_repr, /* reprfunc tp_repr; */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + &Controller_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_Controller_methods /*NULL*/, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + BPy_Controller_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_Controller getsetters: */ +/*****************************************************************************/ + +/* + * return the name of this controller + */ + +static PyObject *Controller_getName( BPy_Controller * self ) +{ + CONTROLLER_DEL_CHECK_PY(self); + return PyString_FromString( self->cont->name ); +} + +/* + * set the name of this controller + */ + +static int Controller_setName( BPy_Controller * self, PyObject * attr ) +{ + char *name = PyString_AsString( attr ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + + CONTROLLER_DEL_CHECK_INT(self); + + BLI_strncpy( self->cont->name, name, sizeof( self->cont->name ) ); + + return 0; +} + +/* + * return the type of this controller + */ + +static PyObject *Controller_getType( BPy_Controller * self ) +{ + CONTROLLER_DEL_CHECK_PY(self); + + return PyInt_FromLong( self->cont->type ); +} + + + + + + + +/*****************************************************************************/ +/* BPy_Controller methods */ +/*****************************************************************************/ + +/* + * link an actuator to this controller + */ + +static PyObject *Controller_linkActuator( BPy_Controller * self, PyObject *arg ) +{ + BPy_Actuator *act; + int idx; + bActuator **oldlinks; + + if (!PyArg_ParseTuple(arg, "O!", &Actuator_Type, &act)) + return EXPP_ReturnPyObjError( PyExc_TypeError, "expected an actuator as argument" ); + + for (idx = 0; idx < self->cont->totlinks; ++idx) + if (self->cont->links[idx] == act->act) + return Py_BuildValue("h", 0); + + oldlinks = self->cont->links; + ++self->cont->totlinks; + self->cont->links = MEM_callocN( (self->cont->totlinks)*sizeof(void *), "new link"); + + for(idx=0; idxcont->totlinks-1; idx++) + self->cont->links[idx] = oldlinks[idx]; + self->cont->links[idx] = act->act; + + if (oldlinks != NULL) MEM_freeN(oldlinks); + + return Py_BuildValue("h", 1); +} + + +/* + * unlink an actuator from this controller + */ + +static PyObject *Controller_unlinkActuator( BPy_Controller * self, PyObject *arg ) +{ + BPy_Actuator *act; + short idx; + + if (!PyArg_ParseTuple(arg, "O!", &Actuator_Type, &act)) + return EXPP_ReturnPyObjError( PyExc_TypeError, "expected an actuator as argument" ); + + for (idx = 0; idx < self->cont->totlinks; ++idx) + if (self->cont->links[idx] == act->act) + break; + + if (idx == self->cont->totlinks) + return Py_BuildValue("h", 1); + + self->cont->totlinks--; + for (; idx < self->cont->totlinks ; idx++) + self->cont->links[idx] = self->cont->links[idx + 1]; + + if (self->cont->totlinks == 0) + { + MEM_freeN(self->cont->links); + self->cont->links = NULL; + } + + return Py_BuildValue("h", 1); +} + + +/* + * unlink all actuators from this controller + */ + +static PyObject *Controller_unlinkAllActuators( BPy_Controller * self ) +{ + if (self->cont->totlinks > 0) + { + self->cont->totlinks = 0; + MEM_freeN(self->cont->links); + self->cont->links = NULL; + } + return Py_BuildValue("h", 1); +} + + +/* + * get an actuator linked to this controller + */ + +static PyObject *Controller_getLinkedActuator( BPy_Controller * self, PyObject *arg ) +{ + short index; + + if (PyArg_ParseTuple(arg, "h", &index)) + { + if (index < 0 || index >= self->cont->totlinks) + return EXPP_ReturnPyObjError( PyExc_TypeError, "Index is out of range" ); + + return Actuator_CreatePyObject(NULL, self->cont->links[index]); + } + + return Py_BuildValue("h", 1); +} + + +/* + * get the number of actuators linked to this controller + */ + +static PyObject *Controller_getActuatorsCount( BPy_Controller * self ) +{ + return Py_BuildValue("h", self->cont->totlinks); +} + + + + + + + +/*****************************************************************************/ +/* BPy_Controller mapping getsetters */ +/*****************************************************************************/ + + +/* + * Expression controller getter + */ +static PyObject *expression_getter( BPy_Controller * self, int type ) +{ + bExpressionCont *cont = self->cont->data; + + switch (type) { + case EXPP_CONT_EXP: + return PyString_FromString (cont->str); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + + +/* + * Expression controller setter + */ +static int expression_setter( BPy_Controller *self, int type, PyObject *value ) +{ + bExpressionCont *cont = self->cont->data; + + switch (type) { + case EXPP_CONT_EXP: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( cont->str, name, sizeof( cont->str ) ); + break; + } + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + + +/* + * Python controller getter + */ +static PyObject *python_getter( BPy_Controller * self, int type ) +{ + bPythonCont *cont = self->cont->data; + + switch (type) { + case EXPP_CONT_SCRIPT: + if (cont->text) + return Text_CreatePyObject (cont->text); + else + Py_RETURN_NONE; + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + + +/* + * Python controller setter + */ +static int python_setter( BPy_Controller *self, int type, PyObject *value ) +{ + bPythonCont *cont = self->cont->data; + + switch (type) { + case EXPP_CONT_SCRIPT: + return GenericLib_assignData(value, (void **) &cont->text, 0, 0, ID_TXT, 0); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + + + + + + + + + +/* + * get data from a controller + */ + +static PyObject *Controller_getData( BPy_Controller * self, PyObject * key ) +{ + int setting; + + if( !PyInt_Check( key ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected an int arg as stored in Blender.Controller.Settings" ); + + CONTROLLER_DEL_CHECK_PY(self); + + setting = PyInt_AsLong( key ); + + switch (self->cont->type) { + case CONT_EXPRESSION: + return expression_getter( self, setting); + case CONT_PYTHON: + return python_getter( self, setting); + default: + Py_RETURN_NONE; + } + return EXPP_ReturnPyObjError( PyExc_KeyError, + "unknown key or controller type" ); +} + + +/* + * set data to a controller + */ + +static int Controller_setData( BPy_Controller * self, PyObject * key, PyObject * arg ) +{ + int key_int; + + if( !PyNumber_Check( key ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected an int arg as stored in Blender.Controller.Settings" ); + + CONTROLLER_DEL_CHECK_INT(self); + + key_int = PyInt_AsLong( key ); + + switch (self->cont->type) { + case CONT_EXPRESSION: + return expression_setter( self, key_int, arg); + case CONT_PYTHON: + return python_setter( self, key_int, arg); + default: + return 0; + } + return EXPP_ReturnIntError( PyExc_RuntimeError, + "unsupported controller setting" ); +} + + + + + + + + +/*****************************************************************************/ +/* Function: Controller_repr */ +/* Description: This is a callback function for the BPy_Controller type. It */ +/* builds a meaningful string to represent controller objects. */ +/*****************************************************************************/ + +// Return controller's name from its type (copy from buttons_logic.c) +static char *controller_name(int type) +{ + switch (type) { + case CONT_LOGIC_AND: + return "AND"; + case CONT_LOGIC_OR: + return "OR"; + case CONT_EXPRESSION: + return "Expression"; + case CONT_PYTHON: + return "Python"; + } + return "unknown"; +} + +static PyObject *Controller_repr( BPy_Controller * self ) +{ + if (self->cont==NULL) + return PyString_FromString( "[Controller - Removed"); + + return PyString_FromFormat( "[Controller \"%s\", Type \"%s\"]", self->cont->name, controller_name(self->cont->type) ); +} + +/* Three Python Controller_Type helper functions needed by the Object module: */ + +/*****************************************************************************/ +/* Function: Controller_CreatePyObject */ +/* Description: This function will create a new BPy_Controller from an */ +/* existing Blender controller structure. */ +/*****************************************************************************/ +PyObject *Controller_CreatePyObject( Object *ob, bController * cont ) +{ + BPy_Controller *pycont; + pycont = ( BPy_Controller * ) PyObject_NEW( BPy_Controller, &Controller_Type ); + if( !pycont ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, + "couldn't create BPy_Controller object" ); + pycont->cont = cont; + pycont->object = ob; + return ( PyObject * ) pycont; +} + +/*****************************************************************************/ +/* Function: Controller_FromPyObject */ +/* Description: This function returns the Blender controller from the given */ +/* PyObject. */ +/*****************************************************************************/ +bController *Controller_FromPyObject( PyObject * pyobj ) +{ + return ( ( BPy_Controller * ) pyobj )->cont; +} + + + + + + + + + + + + + + +/*****************************************************************************/ +/* Controller Sequence wrapper */ +/*****************************************************************************/ + +/* + * Initialize the interator + */ + +static PyObject *ControllerSeq_getIter( BPy_ControllerSeq * self ) +{ + if (!self->iter) { + self->iter = (bController *)self->object->controllers.first; + return EXPP_incr_ret ( (PyObject *) self ); + } else { + return ControllerSeq_CreatePyObject(self->object, (bController *)self->object->controllers.first); + } +} + +/* + * Get the next Controller + */ + +static PyObject *ControllerSeq_nextIter( BPy_ControllerSeq * self ) +{ + bController *iter = self->iter; + if( iter ) { + self->iter = iter->next; + return Controller_CreatePyObject( self->object, iter ); + } + + self->iter= NULL; /* mark as not iterating */ + return EXPP_ReturnPyObjError( PyExc_StopIteration, + "iterator at end" ); +} + +/* return the number of controllers */ + +static int ControllerSeq_length( BPy_ControllerSeq * self ) +{ + return BLI_countlist( &self->object->controllers ); +} + +/* return a controller */ + +static PyObject *ControllerSeq_item( BPy_ControllerSeq * self, int i ) +{ + bController *cont = NULL; + + /* if index is negative, start counting from the end of the list */ + if( i < 0 ) + i += ControllerSeq_length( self ); + + /* skip through the list until we get the controller or end of list */ + + for( cont = self->object->controllers.first; i && cont; --i ) cont = cont->next; + + if( cont ) + return Controller_CreatePyObject( self->object, cont ); + else + return EXPP_ReturnPyObjError( PyExc_IndexError, + "array index out of range" ); +} + + + +/*****************************************************************************/ +/* Python BPy_ControllerSeq sequence table: */ +/*****************************************************************************/ +static PySequenceMethods ControllerSeq_as_sequence = { + ( inquiry ) ControllerSeq_length, /* sq_length */ + ( binaryfunc ) 0, /* sq_concat */ + ( intargfunc ) 0, /* sq_repeat */ + ( intargfunc ) ControllerSeq_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 */ +}; + +/* + * helper function to check for a valid controller argument + */ + +static bController *locate_controller( BPy_ControllerSeq *self, BPy_Controller * value ) +{ + bController *cont; + + /* check that argument is a controller */ + if( !BPy_Controller_Check(value) ) + return (bController *)EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a controller as an argument" ); + + /* check whether controller has been removed */ + if( !value->cont ) + return (bController *)EXPP_ReturnPyObjError( PyExc_RuntimeError, + "This controller has been removed!" ); + + /* find the controller in the object's list */ + for( cont = self->object->controllers.first; cont; cont = cont->next ) + if( cont == value->cont ) + return cont; + + /* return exception if we can't find the controller */ + return (bController *)EXPP_ReturnPyObjError( PyExc_AttributeError, + "This controller is not in the object's stack" ); +} + +/* create a new controller at the end of the list */ + +static PyObject *ControllerSeq_append( BPy_ControllerSeq *self, PyObject *value ) +{ + int type = PyInt_AsLong(value); + + if( type < CONT_LOGIC_AND || type > CONT_PYTHON ) + return EXPP_ReturnPyObjError( PyExc_ValueError, + "Not an int or argument out of range, expected an int from Blender.Controller.Type" ); + + BLI_addtail( &self->object->controllers, new_controller( type ) ); + return Controller_CreatePyObject( self->object, self->object->controllers.last ); +} + +/* remove an existing controller */ + +static PyObject *ControllerSeq_remove( BPy_ControllerSeq *self, BPy_Controller *value ) +{ + bController *cont = locate_controller( self, value ); + + /* if we can't locate the controller, return (exception already set) */ + if( !cont ) + return (PyObject *)NULL; + + /* do the actual removal */ + BLI_remlink( &self->object->controllers, cont ); + free_controller( cont ); + + /* erase the link to the controller */ + value->cont = NULL; + + Py_RETURN_NONE; +} + + +/*****************************************************************************/ +/* Python BPy_ControllerSeq methods table: */ +/*****************************************************************************/ +static PyMethodDef BPy_ControllerSeq_methods[] = { + /* name, method, flags, doc */ + {"append", ( PyCFunction ) ControllerSeq_append, METH_O, + "(type) - add a new controller, where type is the type of controller"}, + {"remove", ( PyCFunction ) ControllerSeq_remove, METH_O, + "(controller) - remove an existing controller, where controller is a controller from this object."}, + {NULL, NULL, 0, NULL} +}; + +/*****************************************************************************/ +/* Python ControllerSeq_Type structure definition: */ +/*****************************************************************************/ +PyTypeObject ControllerSeq_Type = { + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ + /* For printing, in format "." */ + "Blender.Controllers", /* char *tp_name; */ + sizeof( BPy_ControllerSeq ), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ + + /* Methods to implement standard operations */ + + NULL, /* 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; */ + &ControllerSeq_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 )ControllerSeq_getIter, /* getiterfunc tp_iter; */ + ( iternextfunc )ControllerSeq_nextIter, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + BPy_ControllerSeq_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: ControllerSeq_CreatePyObject */ +/* Description: This function will create a new BPy_ControllerSeq from an */ +/* existing ListBase structure. */ +/*****************************************************************************/ +PyObject *ControllerSeq_CreatePyObject( Object *ob, bController *iter ) +{ + BPy_ControllerSeq *pycont; + pycont = ( BPy_ControllerSeq * ) PyObject_NEW( BPy_ControllerSeq, &ControllerSeq_Type ); + if( !pycont ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, + "couldn't create BPy_ControllerSeq object" ); + pycont->object = ob; + pycont->iter = iter; + return ( PyObject * ) pycont; +} + + + + +static PyObject *M_Controller_TypeDict( void ) +{ + PyObject *S = PyConstant_New( ); + + if( S ) { + BPy_constant *d = ( BPy_constant * ) S; + + PyConstant_Insert( d, "AND", + PyInt_FromLong( CONT_LOGIC_AND ) ); + PyConstant_Insert( d, "OR", + PyInt_FromLong( CONT_LOGIC_OR ) ); + PyConstant_Insert( d, "EXPRESSION", + PyInt_FromLong( CONT_EXPRESSION ) ); + PyConstant_Insert( d, "PYTHON", + PyInt_FromLong( CONT_PYTHON ) ); + } + return S; +} + + + +static PyObject *M_Controller_SettingsDict( void ) +{ + PyObject *S = PyConstant_New( ); + + if( S ) { + BPy_constant *d = ( BPy_constant * ) S; + + PyConstant_Insert( d, "EXP", + PyInt_FromLong( EXPP_CONT_EXP ) ); + PyConstant_Insert( d, "SCRIPT", + PyInt_FromLong( EXPP_CONT_SCRIPT ) ); + } + return S; +} + + + + +/*****************************************************************************/ +/* Function: Controller_Init */ +/*****************************************************************************/ +PyObject *Controller_Init( void ) +{ + PyObject *submodule; + PyObject *TypeDict = M_Controller_TypeDict( ); + PyObject *SettingsDict = M_Controller_SettingsDict( ); + + if( PyType_Ready( &ControllerSeq_Type ) < 0 || + PyType_Ready( &Controller_Type ) < 0 ) + return NULL; + + submodule = Py_InitModule3( "Blender.Controller", NULL, + "Controller module for accessing and creating object controller data" ); + + if( TypeDict ) { + PyModule_AddObject( submodule, "Type", TypeDict ); /* deprecated */ + /* since PyModule_AddObject() steals a reference, we need to + incref TypeDict to use it again */ + Py_INCREF( TypeDict); + PyModule_AddObject( submodule, "Types", TypeDict ); + } + + if( SettingsDict ) + PyModule_AddObject( submodule, "Settings", SettingsDict ); + + return submodule; +} Index: source/blender/python/api2_2x/Controller.h =================================================================== --- source/blender/python/api2_2x/Controller.h (revision 0) +++ source/blender/python/api2_2x/Controller.h (revision 0) @@ -0,0 +1,70 @@ +/* + * ***** 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. + * + * This is a new part of Blender. + * + * Contributor(s): Matthieu Delanoë + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef EXPP_CONTROLLER_H +#define EXPP_CONTROLLER_H + +#include +#include "DNA_object_types.h" +#include "DNA_controller_types.h" +#include "DNA_listBase.h" + +/*****************************************************************************/ +/* Python BPy_Controller and BPy_ControllerSeq structure definition: */ +/*****************************************************************************/ + +typedef struct { + PyObject_HEAD /* required macro */ + Object *object; + bController *iter; +} BPy_ControllerSeq; + +typedef struct { + PyObject_HEAD /* required macro */ + Object *object; + /* if act is null, the controller has been removed and we need to raise + an error when its data is accessed */ + bController *cont; +} BPy_Controller; + +extern PyTypeObject ControllerSeq_Type; +extern PyTypeObject Controller_Type; +#define BPy_ControllerSeq_Check(v) ((v)->ob_type == &ControllerSeq_Type) +#define BPy_Controller_Check(v) ((v)->ob_type == &Controller_Type) + + + +/* + * prototypes + */ + +PyObject *Controller_Init( void ); +PyObject *ControllerSeq_CreatePyObject( Object *obj, bController *iter ); +PyObject *Controller_CreatePyObject( Object *obj, bController *cont ); +bController *Controller_FromPyObject( PyObject * py_obj ); + +#endif /* EXPP_CONTROLLER_H */ Index: source/blender/python/api2_2x/doc/Actuator.py =================================================================== --- source/blender/python/api2_2x/doc/Actuator.py (revision 0) +++ source/blender/python/api2_2x/doc/Actuator.py (revision 0) @@ -0,0 +1,312 @@ +# Blender.Actuator module and the Actuator PyType object + +""" +The Blender.Actuator submodule + +This module provides access to the Actuators Data in Blender. + +Example:: + from Blender import * + + ob = Object.GetSelected()[0] # retrieve an object + act = obj.actuators.append(Actuator.Types.MESSAGE) # add an actuator + # set settings: + act[Actuator.Settings.TYPE] = Actuator.Values.MESSAGE_PROP + act[Actuator.Settings.SUBJECT] = "sub" + act[Actuator.Settings.BODY] = "prop" + + +Example:: + # Remove all actuators from an object: + from Blender import * + + ob = Object.GetSelected()[0] # retrieve an object + acts = obj.actuators # get actuators list + for act in acts : + print act + objs.actuators.remove(act) # remove actuator + + + +@type Types: readonly dictionary +@var Types: Constant Actuator dict used for L{ActuatorSeq.append} to a + actuator sequence and comparing with L{Actuator.type}: + - ACTION - type value for Action actuators + - CAMERA - type value for Camera actuators + - CD - type value for Cd actuators + - CONSTRAINT - type value for Constraint actuators + - EDIT_OBJECT - type value for Edit Object actuators + - FILTER2D - type value for 2D Filter actuators + - GAME - type value for Game actuators + - IPO - type value for IPO actuators + - MESSAGE - type value for Message actuators + - MOTION - type value for Motion actuators + - PROPERTY - type value for Property actuators + - RANDOM - type value for Random actuators + - SCENE - type value for Scene actuators + - SOUND - type value for Sound actuators + - VISIBILITY - type value for Visibility actuators + + +@type Values: readonly dictionary +@var Values: Constant Actuator dict used as values for settings: + - 2D Filter types: + - F2D_ENABLED + - F2D_DISABLED + - F2D_NOFILTER + - F2D_MOTIONBLUR + - F2D_BLUR + - F2D_SHARPEN + - F2D_DILATION + - F2D_EROSION + - F2D_LAPLACIAN + - F2D_SOBEL + - F2D_PREWITT + - F2D_GRAYSCALE + - F2D_SEPIA + - F2D_INVERT + - F2D_CUSTOMFILTER + + - Action types: + - ACTION_PLAY + - ACTION_FLIPPER + - ACTION_LOOP_STOP + - ACTION_LOOP_END + - ACTION_PROPERTY + + - Camera axis: + - CAMERA_X + - CAMERA_Y + + - Constraint types: + - CONST_NONE + - CONST_LOCX + - CONST_LOCY + - CONST_LOCZ + + - Edit Object types: + - EDIT_ADD + - EDIT_END + - EDIT_REPLACE + - EDIT_TRACK + + - Game types: + - GAME_LOAD + - GAME_RESTART + - GAME_QUIT + + - IPO types: + - IPO_PLAY + - IPO_PINGPONG + - IPO_FLIPPER + - IPO_LOOP_STOP + - IPO_LOOP_END + - IPO_PROPERTY + + - Message types: + - MESSAGE_TEXT + - MESSAGE_PROP + + - Property types: + - PROP_ASSIGN + - PROP_ADD + - PROP_COPY + + - Random types: + - RANDOM_BOOL_CONST + - RANDOM_BOOL_UNIFORM + - RANDOM_BOOL_BERNOUILLI + - RANDOM_INT_CONST + - RANDOM_INT_UNIFORM + - RANDOM_INT_POISSON + - RANDOM_FLOAT_CONST + - RANDOM_FLOAT_UNIFORM + - RANDOM_FLOAT_NORMAL + - RANDOM_FLOAT_NEGATIVE_EXPONENTIAL + + - Scene types: + - SCENE_RESTART + - SCENE_SET + - SCENE_CAMERA + - SCENE_ADD_FRONT + - SCENE_ADD_BACK + - SCENE_REMOVE + - SCENE_SUSPEND + - SCENE_RESUME + + - Sound types: + - SOUND_PLAY_STOP + - SOUND_PLAY_END + - SOUND_LOOP_STOP + - SOUND_LOOP_END + - SOUND_LOOP_PING_PONG + - SOUND_LOOP_PING_PONG_STOP + + + +@type Settings: readonly dictionary +@var Settings: Constant Actuator dict used for changing actuator settings. + - Used by 2D Filter actuators: + - DISABLED (bool): used for Motion Blur filters + - PASS (int): clamped to [0 : 99] + - SCRIPT (Text object) + - TYPE (int): see L{Values} in 2D Filter section for possible values + - VALUE (float): used for Motion Blur filters ; clamped to [0.0 : 1.0] + + - Used by Action actuators: + - ACTION (action object) + - BLENDIN (int): clamped to [0 : 300000] + - PRIORITY (int): clamped to [0 : 100] + - PROPERTY (string): 31 characters + - TYPE (int): see L{Values} in Action section for possible values + + - Used by Camera actuators: + - AXIS (int): see L{Values} in Camera section for possible values + - HEIGHT (float): clamped to [0.0 : 20.0] + - OBJECT (object) + - MAX (float): clamped to [0.0 : 20.0] + - MIN (float): clamped to [0.0 : 20.0] + + - Used by CD actuators: + - TRACK (int): clamped to [0 : 99] + - TYPE (int): see L{Values} in CD section for possible values + - VOLUME (float): clamped to [0.0 : 1.0] + + _ Used by Constraint actuators: + - DAMP (int): clamped to [0 : 100] + - MAX (tuple of 3 floats) + - MIN (tuple of 3 floats) + - TYPE (int): see L{Values} in Constraint section for possible values + + - Used by Edit Object actuators: + - LINV (tuple of 3 floats and a bool): 3 floats for vector values and a bool for the local flag + - MESH (Mesh data) + - OBJECT (Object) + - TIME (int): clamped to [0 : 2000] + - TRACK_3D (int): 0 or 1 + - TYPE (int): see L{Values} in Edit Object section for possible values + + - Used by Game actuators: + - FILE (string): 63 characters + - TYPE (int): see L{Values} in Game section for possible values + + - Used by IPO actuators: + - CHILD (bool) + - END (int): clamped to [0 : 300000] + - FORCE (bool) + - FORCE_LOCAL (bool) + - PROPERTY (string): 31 characters + - START (int): clamped to [0 : 300000] + - TYPE (int): see L{Values} in IPO section for possible values + + - Used by Message actuators: + - BODY (string): 31 characters + - SUBJECT (string): 31 characters + - TO (string): 31 characters + - TYPE (int): see L{Values} in Message section for possible values + + - Used by Motion actuators: + - ADDLINV (bool) + - ANGV (tuple of 3 floats and a bool): 3 floats for vector values and a bool for the local flag + - DLOC (tuple of 3 floats and a bool): 3 floats for vector values and a bool for the local flag + - DROT (tuple of 3 floats and a bool): 3 floats for vector values and a bool for the local flag + - FORCE (tuple of 3 floats and a bool): 3 floats for vector values and a bool for the local flag + - LINV (tuple of 3 floats and a bool): 3 floats for vector values and a bool for the local flag + - TORQUE (tuple of 3 floats and a bool): 3 floats for vector values and a bool for the local flag + + - Used by Property actuators: + - OBJECT (object) + - PROPERTY (string): 31 characters + - TYPE (int): see L{Values} in Property section for possible values + - VALUE (string): 31 characters + + - Used by Random actuators: + - FLOAT1 (float): used for HALF-LIFE, MEAN, MIN, VALUE, CHANCE ; clamped to [-10000.0 : 10000.0] + - FLOAT2 (float): used for SEED, MAX ; clamped to [-10000.0 : 10000.0] + - INT1 (int): used for MIN, VALUE, ALWAYS ; clamped to [-1000 : 1000] + - INT2 (int): used for MAX ; clamped to [-1000 : 1000] + - PROPERTY (string): 31 characters + - SEED (int): clamped to [0 : 1000] + - TYPE (int): see L{Values} in Random section for possible values + + - Used by Scene actuators: + - CAMERA (object) + - SCENE (scene) + - TYPE (int): see L{Values} in Scene section for possible values + + - Used by Sound actuators: + - SOUND (Sound object) + - TYPE (int): see L{Values} in Sound section for possible values + + - Used by Visibility actuators: + - TYPE (int): 0 or 1 +""" + +class ActuatorSeq: + """ + The ActuatorSeq object + ====================== + This object provides access to list of L{actuators} for a particular object. + Only accessed from L{Object.Object.actuators}. + """ + + def __getitem__(index): + """ + This operator returns one of the object's actuators. + @type index: int + @return: an Actuator object + @rtype: Actuator + @raise KeyError: index was out of range + """ + + def __len__(): + """ + Returns the number of actuators in the object's actuator stack. + @return: number of Actuators + @rtype: int + """ + + def append(type): + """ + Appends a new actuator to the end of the object's actuator stack. + @type type: a constant specifying the type of actuator to create. as from L{Types} + @rtype: Actuator + @return: the new Actuator + """ + + def remove(actuator): + """ + Remove a actuator from this objects actuator sequence. + @type actuator: a actuator from this sequence to remove. + @note: Accessing attributes of the actuator after removing will raise an error. + """ + +class Actuator: + """ + The Actuator object + =================== + This object provides access to a actuator for a particular object accessed + from L{ActuatorSeq}. + @ivar name: The name of this actuator. 31 chars max. + @type name: string + @ivar type: The type of this actuator. Read-only. The returned value + matches the types in L{Types}. + @type type: int + """ + + def __getitem__(key): + """ + This operator returns one of the actuator's data attributes. + @type key: value from actuator's L{Actuator.Settings} constant + @return: the requested data + @rtype: varies + @raise KeyError: the key does not exist for the actuator + """ + + def __setitem__(key): + """ + This operator changes one of the actuator's data attributes. + @type key: value from actuator's L{Actuator.Settings} constant + @raise KeyError: the key does not exist for the actuator + """ + Index: source/blender/python/api2_2x/doc/API_intro.py =================================================================== --- source/blender/python/api2_2x/doc/API_intro.py (revision 13588) +++ source/blender/python/api2_2x/doc/API_intro.py (working copy) @@ -46,6 +46,9 @@ - L{Pose} (*) - L{Constraint} (*) - L{ActionStrips} (*) + - L{Sensor} (*) + - L{Controller} (*) + - L{Actuator} (*) - L{Registry} - L{Scene} (*) - L{Radio} Index: source/blender/python/api2_2x/doc/Controller.py =================================================================== --- source/blender/python/api2_2x/doc/Controller.py (revision 0) +++ source/blender/python/api2_2x/doc/Controller.py (revision 0) @@ -0,0 +1,159 @@ +# Blender.Controller module and the Controller PyType object + +""" +The Blender.Controller submodule + +This module provides access to the Controllers Data in Blender. + +Example:: + from Blender import * + + ob = Object.GetSelected()[0] # retrieve an object + cont = obj.controllers.append(Controller.Types.EXPRESSION) # add a controller + # set settings: + cont[Controller.Settings.EXP] = "sens and sens < 5" + + +Example:: + # Remove all controllers from an object: + from Blender import * + + ob = Object.GetSelected()[0] # retrieve an object + conts = obj.controllers # get controllers list + for cont in conts : + print cont + objs.controllers.remove(cont) # remove controller + +Example:: + # Link an actuator to a controller: + from Blender import * + + ob = Object.GetSelected()[0] # retrieve an object + cont = obj.controllers[0] # retrieve a controller + act = obj.actuators[3] # retrieve an actuator + cont.linkActuator (act) # link actuator to controller + + + +@type Types: readonly dictionary +@var Types: Constant Controller dict used for L{ControllerSeq.append} to a + controller sequence and comparing with L{Controller.type}: + - AND - type value for And controllers + - OR - type value for Or controllers + - EXPRESSION - type value for Expression controllers + - PYTHON - type value for Python controllers + + + +@type Settings: readonly dictionary +@var Settings: Constant Controller dict used for changing controller settings. + - Used by Expression controller: + - EXP (string): 127 characters + + - Used by Python controller: + - SCRIPT (Text object) + + + +""" + +class ControllerSeq: + """ + The ControllerSeq object + ======================== + This object provides access to list of L{controllers} for a particular object. + Only accessed from L{Object.Object.controllers}. + """ + + def __getitem__(index): + """ + This operator returns one of the object's controllers. + @type index: int + @return: a Controller object + @rtype: Controller + @raise KeyError: index was out of range + """ + + def __len__(): + """ + Returns the number of controllers in the object's controller stack. + @return: number of Controllers + @rtype: int + """ + + def append(type): + """ + Appends a new controller to the end of the object's controller stack. + @type type: a constant specifying the type of controller to create. as from L{Types} + @rtype: Controller + @return: the new Controller + """ + + def remove(controller): + """ + Remove a controller from this objects controller sequence. + @type controller: a controller from this sequence to remove. + @note: Accessing attributes of the controller after removing will raise an error. + """ + +class Controller: + """ + The Controller object + ===================== + This object provides access to a controller for a particular object accessed + from L{ControllerSeq}. + @ivar name: The name of this controller. 31 chars max. + @type name: string + @ivar type: The type of this controller. Read-only. The returned value + matches the types in L{Types}. + @type type: int + """ + + def __getitem__(key): + """ + This operator returns one of the controller's data attributes. + @type key: value from controller's L{Controller.Settings} constant + @return: the requested data + @rtype: varies + @raise KeyError: the key does not exist for the controller + """ + + def __setitem__(key): + """ + This operator changes one of the controller's data attributes. + @type key: value from controller's L{Controller.Settings} constant + @raise KeyError: the key does not exist for the controller + """ + + def getActuatorsCount(): + """ + Return the number of actuators linked to this controller. + @return: number of actuators + @rtype: int + """ + + def getLinkedActuator(index): + """ + Return one of the actuators linked to this controller. + @type index: int + @return: an actuator object + @rtype: Actuator + @raise KeyError: index is out of range + """ + + def linkActuator(act): + """ + Link an actuator to this controller. + @type act: Actuator + """ + + def unlinkActuator(act): + """ + Unlink an actuator from this controller. + @type act: Actuator + """ + + def unlinkAllActuators(): + """ + Unlink all actuators from this controller. + """ Index: source/blender/python/api2_2x/doc/Object.py =================================================================== --- source/blender/python/api2_2x/doc/Object.py (revision 13588) +++ source/blender/python/api2_2x/doc/Object.py (working copy) @@ -636,6 +636,12 @@ @ivar rbShapeBoundType: Rigid body shape bound type. See L{RBShapes} const dict for values. @type rbShapeBoundType: int + @ivar actuators: The actuators associated with the object. + @type actuators: L{Actuator Sequence} + @ivar sensors: The sensors associated with the object. + @type sensors: L{Sensor Sequence} + @ivar controllers: The controllers associated with the object. + @type controllers: L{Controller Sequence} """ def buildParts(): Index: source/blender/python/api2_2x/doc/Sensor.py =================================================================== --- source/blender/python/api2_2x/doc/Sensor.py (revision 0) +++ source/blender/python/api2_2x/doc/Sensor.py (revision 0) @@ -0,0 +1,270 @@ +# Blender.Sensor module and the Sensor PyType object + +""" +The Blender.Sensor submodule + +This module provides access to the Sensors Data in Blender. + +Example:: + from Blender import * + + ob = Object.GetSelected()[0] # retrieve an object + sens = obj.sensors.append(Sensor.Types.KEYBOARD) # add a sensor + # set settings: + sens[Sensor.Settings.KEY] = (Draw.AKEY, Draw.FKEY) + sens[Sensor.Settings.TARGET] = "tar" + sens[Sensor.Settings.ALLKEYS] = False + + +Example:: + # Remove all sensors from an object: + from Blender import * + + ob = Object.GetSelected()[0] # retrieve an object + sens = obj.sensors # get sensors list + for sen in sens : + print sen + objs.sensors.remove(sen) # remove sensor + +Example:: + # Build a logic chain: + from Blender import * + + sens = obj.sensors.append(Sensor.Types.KEYBOARD) # add a sensor + cont = obj.controllers.append(Controller.Types.ADD) # add a controller + act = obj.actuators.append(Actuator.Types.MESSAGE) # add an actuator + + sens.linkController (cont) # link controller to sensor + cont.linkActuator (act) # link actuator to controller + + + +@type Types: readonly dictionary +@var Types: Constant Sensor dict used for L{SensorSeq.append} to a + sensor sequence and comparing with L{Sensor.type}: + - COLLISION - type value for Collision sensors + - JOYSTICK - type value for Joystick sensors + - KEYBOARD - type value for Keyboard sensors + - MESSAGE - type value for Message sensors + - MOUSE - type value for Mouse sensors + - NEAR - type value for Near sensors + - PROPERTY - type value for Property sensors + - RADAR - type value for Radar sensors + - RANDOM - type value for Random sensors + - RAY - type value for Ray sensors + - TOUCH - type value for Touch sensors + + + +@type Values: readonly dictionary +@var Values: Constant Sensor dict used as values for settings: + - Joystick types: + - JOY_BUTTON + - JOY_PRESSED + - JOY_RELEASED + - JOY_AXIS + - JOY_X_AXIS + - JOY_Y_AXIS + - JOY_NEG_X_AXIS + - JOY_NEG_Y_AXIS + - JOY_HAT + + - Mouse types: + - MOUSE_LEFT_BUTTON + - MOUSE_MIDDLE_BUTTON + - MOUSE_RIGHT_BUTTON + - MOUSE_WHEEL_UP + - MOUSE_WHEEL_DOWN + - MOUSE_MOVEMENT + - MOUSE_MOUSEOVER + - MOUSE_MOUSEOVER_ANY + + - Property types: + - PROP_EQUAL + - PROP_NEQUAL + - PROP_INTERVAL + - PROP_CHANGED + + - Radar types: + - RADAR_X_AXIS + - RADAR_Y_AXIS + - RADAR_Z_AXIS + + - Ray types: + - RAY_X_AXIS + - RAY_Y_AXIS + - RAY_Z_AXIS + - RAY_NEG_X_AXIS + - RAY_NEG_Y_AXIS + - RAY_NEG_Z_AXIS + + + +@type Settings: readonly dictionary +@var Settings: Constant Sensor dict used for changing sensor settings. + - Used by all sensors: + - INVERT (bool) + - FREQ (int): clamped to [0 : 10000] + - TRUE_PULSE (bool) + - FALSE_PULSE (bool) + - + + - Used by Collision sensor: + - MATERIAL (string): 31 characters + - PROPERTY (string): 31 characters + - TYPE (int): 0 for Property, 1 for Material + + - Used by Joystick sensor: + - AXIS (int): see L{Values} in Joystick section for possible values + - BUTTON (int): see L{Values} in Joystick section for possible values + - DIRECTION (int): clamped to [0 : 12] + - NUM_AXIS (int): 1 or 2 + - NUM_BUTTON (int): clamped to [0 : 18] + - NUM_HAT (int): 1 or 2 + - THRESHOLD (int): clamped to [0 : 32768] + - TYPE (int): see L{Values} in Joystick section for possible values + + - Used by Keyboard sensors: + - ALLKEYS (bool) + - KEY (tuple of 1, 2, or 3 int): (Key, Hold1, Hold2) from L{Draw} + - LOGTOGGLE (string): 31 characters + - TARGET (string): 31 characters + + - Used by Message sensors: + - SUBJECT (string): 31 characters + + - Used by Mouse sensors: + - TYPE (int): see L{Values} in Mouse section for possible values + + - Used by Near sensors: + - DIST (float): clamped to [0.0 : 1000.0] + - PROPERTY (string): 31 characters + - RESET (float): clamped to [0.0 : 1000.0] + + - Used by Property sensors: + - MAX (string): 31 characters + - PROPERTY (string): 31 characters + - TYPE (int): see L{Values} in Property section for possible values + - VALUE (string): used for VALUE and MIN ; 31 characters + + - Used by Radar sensors: + - ANGLE (float): clamped to [0.0 : 179.9] + - AXIS (int): see L{Values} in Radar section for possible values + - DIST (float): clamped to [0.0 : 10000.0] + - PROPERTY (string): 31 characters + + - Used by Random sensors: + - SEED (int): clamped to [0 : 1000] + + - Used by Ray sensors: + - AXIS (int): see L{Values} in Ray section for possible values + - MATERIAL (string): 31 characters + - PROPERTY (string): 31 characters + - RANGE (float): clamped to [0.0 : 10000.0] + - TYPE (int): 0 for Property, 1 for Material + + - Used for Touch sensors: + - MATERIAL (L{Material} data) + +""" + +class SensorSeq: + """ + The SensorSeq object + ==================== + This object provides access to list of L{sensors} for a particular object. + Only accessed from L{Object.Object.sensors}. + """ + + def __getitem__(index): + """ + This operator returns one of the object's sensors. + @type index: int + @return: a Sensor object + @rtype: Sensor + @raise KeyError: index was out of range + """ + + def __len__(): + """ + Returns the number of sensors in the object's sensor stack. + @return: number of Sensors + @rtype: int + """ + + def append(type): + """ + Appends a new sensor to the end of the object's sensor stack. + @type type: a constant specifying the type of sensor to create. as from L{Types} + @rtype: Sensor + @return: the new Sensor + """ + + def remove(sensor): + """ + Remove a sensor from this objects sensor sequence. + @type sensor: a sensor from this sequence to remove. + @note: Accessing attributes of the sensor after removing will raise an error. + """ + +class Sensor: + """ + The Sensor object + ================= + This object provides access to a sensor for a particular object accessed + from L{SensorSeq}. + @ivar name: The name of this sensor. 31 chars max. + @type name: string + @ivar type: The type of this sensor. Read-only. The returned value + matches the types in L{Types}. + @type type: int + """ + + def __getitem__(key): + """ + This operator returns one of the sensor's data attributes. + @type key: value from sensor's L{Sensor.Settings} constant + @return: the requested data + @rtype: varies + @raise KeyError: the key does not exist for the sensor + """ + + def __setitem__(key): + """ + This operator changes one of the sensor's data attributes. + @type key: value from sensor's L{Sensor.Settings} constant + @raise KeyError: the key does not exist for the sensor + """ + + def getControllersCount(): + """ + Return the number of controllers linked to this sensor. + @return: number of controllers + @rtype: int + """ + + def getLinkedController(index): + """ + Return one of the controllers linked to this sensor. + @type index: int + @return: a controller object + @rtype: Controller + @raise KeyError: index is out of range + """ + + def linkController(cont): + """ + Link a controller to this sensor. + @type cont: Controller + """ + + def unlinkController(cont): + """ + Unlink a controller from this sensor. + @type cont: Controller + """ + + def unlinkAllControllers(): + """ + Unlink all controllers from this sensor. + """ Index: source/blender/python/api2_2x/gen_library.c =================================================================== --- source/blender/python/api2_2x/gen_library.c (revision 13588) +++ source/blender/python/api2_2x/gen_library.c (working copy) @@ -31,6 +31,7 @@ #include "Ipo.h" #include "DNA_object_types.h" #include "DNA_ipo_types.h" +#include "Material.h" /* Generic get/set attrs */ @@ -163,12 +164,12 @@ */ short GenericLib_getType(PyObject * pydata) { - //~ if (BPy_Scene_Check(pydata)) return ID_SCE; + if (BPy_Scene_Check(pydata)) return ID_SCE; if (BPy_Object_Check(pydata)) return ID_OB; if (BPy_Mesh_Check(pydata)) return ID_ME; //~ if (BPy_Curve_Check(pydata)) return ID_CU; //~ if (BPy_Metaball_Check(pydata)) return ID_MB; - //~ if (BPy_Material_Check(pydata)) return ID_MA; + if (BPy_Material_Check(pydata)) return ID_MA; if (BPy_Texture_Check(pydata)) return ID_TE; //~ if (BPy_Image_Check(pydata)) return ID_IM; //~ //if (BPy_Lattice_Check(pydata)) return ID_LT; @@ -177,8 +178,8 @@ if (BPy_Ipo_Check(pydata)) return ID_IP; if (BPy_World_Check(pydata)) return ID_WO; //~ //if (BPy_Font_Check(pydata)) return ID_VF; - //~ if (BPy_Text_Check(pydata)) return ID_TXT; - //~ if (BPy_Sound_Check(pydata)) return ID_SO; + if (BPy_Text_Check(pydata)) return ID_TXT; + if (BPy_Sound_Check(pydata)) return ID_SO; if (BPy_Group_Check(pydata)) return ID_GR; //~ if (BPy_Armature_Check(pydata)) return ID_AR; if (BPy_Action_Check(pydata)) return ID_AC; Index: source/blender/python/api2_2x/Object.c =================================================================== --- source/blender/python/api2_2x/Object.c (revision 13588) +++ source/blender/python/api2_2x/Object.c (working copy) @@ -120,6 +120,9 @@ #include "EXPP_interface.h" #include "BIF_editkey.h" #include "IDProp.h" +#include "Sensor.h" +#include "Actuator.h" +#include "Controller.h" /* Defines for insertIpoKey */ @@ -3072,6 +3075,21 @@ return ModSeq_CreatePyObject( self->object, NULL ); } +static PyObject *Object_getSensors( BPy_Object * self ) +{ + return SensorSeq_CreatePyObject( self->object, NULL ); +} + +static PyObject *Object_getActuators( BPy_Object * self ) +{ + return ActuatorSeq_CreatePyObject( self->object, NULL ); +} + +static PyObject *Object_getControllers( BPy_Object * self ) +{ + return ControllerSeq_CreatePyObject( self->object, NULL ); +} + static int Object_setModifiers( BPy_Object * self, PyObject * value ) { BPy_ModSeq *pymodseq; @@ -5045,6 +5063,18 @@ (getter)Object_getModifiers, (setter)Object_setModifiers, "The modifiers associated with the object", NULL}, + {"sensors", + (getter)Object_getSensors, (setter)NULL, + "The sensors associated with the object", + NULL}, + {"actuators", + (getter)Object_getActuators, (setter)NULL, + "The actuators associated with the object", + NULL}, + {"controllers", + (getter)Object_getControllers, (setter)NULL, + "The controllers associated with the object", + NULL}, {"protectFlags", (getter)Object_getProtectFlags, (setter)Object_setProtectFlags, "The \"transform locking\" bitfield for the object", Index: source/blender/python/api2_2x/Sensor.c =================================================================== --- source/blender/python/api2_2x/Sensor.c (revision 0) +++ source/blender/python/api2_2x/Sensor.c (revision 0) @@ -0,0 +1,1667 @@ +/* + * ***** 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. + * + * This is a new part of Blender. + * + * Contributor(s): Matthieu Delanoë + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + + +#include "Sensor.h" /*This must come first*/ + +#include "DNA_object_types.h" + +#include "BLI_blenlib.h" +#include "MEM_guardedalloc.h" + +#include "BKE_sca.h" +#include "Object.h" +#include "gen_utils.h" +#include "gen_library.h" + +#include "Material.h" + +#include "Controller.h" + + +/* checks for the sensor being removed */ +#define SENSOR_DEL_CHECK_PY(bpy_sensor) if (!(bpy_sensor->sens)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "Sensor has been removed" ) ) +#define SENSOR_DEL_CHECK_INT(bpy_sensor) if (!(bpy_sensor->sens)) return ( EXPP_ReturnIntError( PyExc_RuntimeError, "Sensor has been removed" ) ) + + +enum sensor_constants { + // For all sensors + EXPP_SENS_INVERT=0, + EXPP_SENS_FREQ, + EXPP_SENS_TRUE_PULSE, + EXPP_SENS_FALSE_PULSE, + + EXPP_SENS_ALL_COMMON, + + // For Touch sensor + EXPP_SENS_MATERIAL, // also for Ray + + // For Near sensor + EXPP_SENS_PROPERTY, // also for Radar, Ray, Property, Near, Collision + EXPP_SENS_DIST, // also for Radar, + EXPP_SENS_RESET, + + // For Keyboard sensor + EXPP_SENS_KEY, + EXPP_SENS_LOGTOGGLE, + EXPP_SENS_TARGET, + EXPP_SENS_ALLKEYS, + + // For Property sensor + EXPP_SENS_TYPE, // also for Collision, Mouse, Joystick + EXPP_SENS_VALUE, + EXPP_SENS_MAX, + + // For radar sensor + EXPP_SENS_ANGLE, + EXPP_SENS_AXIS, // also for Ray, Joystick + + // For Random sensor + EXPP_SENS_SEED, + + // For Ray sensor + EXPP_SENS_RANGE, + + // For Message sensor + EXPP_SENS_SUBJECT, + + // For Joystick sensor + EXPP_SENS_BUTTON, + EXPP_SENS_NUM_AXIS, + EXPP_SENS_NUM_HAT, + EXPP_SENS_NUM_BUTTON, + EXPP_SENS_THRESHOLD, + EXPP_SENS_DIRECTION +}; + + +/*****************************************************************************/ +/* Python BPy_Sensor methods declarations: */ +/*****************************************************************************/ +static PyObject *Sensor_getName( BPy_Sensor * self ); +static int Sensor_setName( BPy_Sensor * self, PyObject *arg ); +static PyObject *Sensor_getType( BPy_Sensor * self ); + +static PyObject *Sensor_linkController( BPy_Sensor * self, PyObject *arg ); +static PyObject *Sensor_unlinkController( BPy_Sensor * self, PyObject *arg ); +static PyObject *Sensor_unlinkAllControllers( BPy_Sensor * self ); +static PyObject *Sensor_getLinkedController( BPy_Sensor * self, PyObject *arg ); +static PyObject *Sensor_getControllersCount( BPy_Sensor * self ); + +static PyObject *Sensor_getData( BPy_Sensor * self, PyObject * key ); +static int Sensor_setData( BPy_Sensor * self, PyObject * key, PyObject * arg ); + +/*****************************************************************************/ +/* Python BPy_Sensor methods table: */ +/*****************************************************************************/ +static PyMethodDef BPy_Sensor_methods[] = { + /* name, method, flags, doc */ + {"linkController", (PyCFunction)Sensor_linkController, METH_VARARGS, "link a controller to this sensor"}, + {"unlinkController", (PyCFunction)Sensor_unlinkController, METH_VARARGS, "unlink a controller from this sensor"}, + {"unlinkAllControllers", (PyCFunction)Sensor_unlinkAllControllers, METH_NOARGS, "unlink all controllers from this sensor"}, + {"getLinkedController", (PyCFunction)Sensor_getLinkedController, METH_VARARGS, "get a controller linked to this sensor"}, + {"getControllersCount", (PyCFunction)Sensor_getControllersCount, METH_NOARGS, "number of controllers linked to this sensor"}, + {NULL, NULL, 0, NULL} +}; + +/*****************************************************************************/ +/* Python BPy_Sensor attributes get/set structure: */ +/*****************************************************************************/ +static PyGetSetDef BPy_Sensor_getseters[] = { + {"name", (getter)Sensor_getName, (setter)Sensor_setName, "Sensor name", NULL}, + {"type", (getter)Sensor_getType, (setter)NULL, "Sensor type (read only)", NULL}, + {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ +}; + +/*****************************************************************************/ +/* Python Sensor_Type Mapping Methods table: */ +/*****************************************************************************/ +static PyMappingMethods Sensor_as_mapping = { + NULL, /* sens_length */ + ( binaryfunc ) Sensor_getData, /* sens_subscript */ + ( objobjargproc ) Sensor_setData, /* sens_ass_subscript */ +}; + +/*****************************************************************************/ +/* Python Sensor_Type callback function prototypes: */ +/*****************************************************************************/ +static PyObject *Sensor_repr( BPy_Sensor * self ); + +/*****************************************************************************/ +/* Python Sensor_Type structure definition: */ +/*****************************************************************************/ +PyTypeObject Sensor_Type = { + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ + /* For printing, in format "." */ + "Blender Sensor", /* char *tp_name; */ + sizeof( BPy_Sensor ), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ + + /* Methods to implement standard operations */ + + NULL, /* destructor tp_dealloc; */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* cmpfunc tp_compare; */ + ( reprfunc ) Sensor_repr, /* reprfunc tp_repr; */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + &Sensor_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_Sensor_methods/*NULL*/, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + BPy_Sensor_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_Sensor getsetters: */ +/*****************************************************************************/ + +/* + * return the name of this sensor + */ + +static PyObject *Sensor_getName( BPy_Sensor * self ) +{ + SENSOR_DEL_CHECK_PY(self); + return PyString_FromString( self->sens->name ); +} + +/* + * set the name of this sensor + */ + +static int Sensor_setName( BPy_Sensor * self, PyObject * attr ) +{ + char *name = PyString_AsString( attr ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + + SENSOR_DEL_CHECK_INT(self); + + BLI_strncpy( self->sens->name, name, sizeof( self->sens->name ) ); + + return 0; +} + +/* + * return the type of this sensor + */ + +static PyObject *Sensor_getType( BPy_Sensor * self ) +{ + SENSOR_DEL_CHECK_PY(self); + + return PyInt_FromLong( self->sens->type ); +} + + + + + + + + +/*****************************************************************************/ +/* BPy_Sensor methods */ +/*****************************************************************************/ + +/* + * link a controller to this sensor + */ + +static PyObject *Sensor_linkController( BPy_Sensor * self, PyObject *arg ) +{ + BPy_Controller *cont; + int idx; + bController **oldlinks; + + if (!PyArg_ParseTuple(arg, "O!", &Controller_Type, &cont)) + return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a controller as argument" ); + + for (idx = 0; idx < self->sens->totlinks; ++idx) + if (self->sens->links[idx] == cont->cont) + return Py_BuildValue("h", 0); + + oldlinks = self->sens->links; + ++self->sens->totlinks; + self->sens->links = MEM_callocN( (self->sens->totlinks)*sizeof(void *), "new link"); + + for(idx=0; idxsens->totlinks-1; idx++) + self->sens->links[idx] = oldlinks[idx]; + self->sens->links[idx] = cont->cont; + + if (oldlinks != NULL) MEM_freeN(oldlinks); + + return Py_BuildValue("h", 1); +} + + +/* + * unlink a controller from this sensor + */ + +static PyObject *Sensor_unlinkController( BPy_Sensor * self, PyObject *arg ) +{ + BPy_Controller *cont; + short idx; + + if (!PyArg_ParseTuple(arg, "O!", &Controller_Type, &cont)) + return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a controller as argument" ); + + for (idx = 0; idx < self->sens->totlinks; ++idx) + if (self->sens->links[idx] == cont->cont) + break; + + if (idx == self->sens->totlinks) + return Py_BuildValue("h", 1); + + self->sens->totlinks--; + for (; idx < self->sens->totlinks ; idx++) + self->sens->links[idx] = self->sens->links[idx + 1]; + + if (self->sens->totlinks == 0) + { + MEM_freeN(self->sens->links); + self->sens->links = NULL; + } + + return Py_BuildValue("h", 1); +} + + +/* + * unlink all controllers from this sensor + */ + +static PyObject *Sensor_unlinkAllControllers( BPy_Sensor * self ) +{ + if (self->sens->totlinks > 0) + { + self->sens->totlinks = 0; + MEM_freeN(self->sens->links); + self->sens->links = NULL; + } + return Py_BuildValue("h", 1); +} + + +/* + * get a controller linked to this sensor + */ + +static PyObject *Sensor_getLinkedController( BPy_Sensor * self, PyObject *arg ) +{ + short index; + + if (PyArg_ParseTuple(arg, "h", &index)) + { + if (index < 0 || index >= self->sens->totlinks) + return EXPP_ReturnPyObjError( PyExc_IndexError, "index is out of range" ); + + return Controller_CreatePyObject(NULL, self->sens->links[index]); + } + return Py_BuildValue("h", 1); +} + + +/* + * return the number of controllers linked to this sensor + */ + +static PyObject *Sensor_getControllersCount( BPy_Sensor * self ) +{ + return Py_BuildValue("h", self->sens->totlinks); +} + + +/*****************************************************************************/ +/* BPy_Sensor mapping getsetters */ +/*****************************************************************************/ + +/* + * Touch sensor getter + */ +static PyObject *touch_getter( BPy_Sensor * self, int type ) +{ + bTouchSensor *sens = self->sens->data; + switch (type) { + case EXPP_SENS_MATERIAL: + if (sens->ma) return Material_CreatePyObject(sens->ma); + else Py_RETURN_NONE; + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + +/* + * Touch sensor setter + */ +static int touch_setter( BPy_Sensor *self, int type, PyObject *value ) +{ + bTouchSensor *sens = self->sens->data; + + switch (type) { + case EXPP_SENS_MATERIAL: + return GenericLib_assignData(value, (void **) &sens->ma, 0, 1, ID_MA, 0); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + +/* + * Near sensor getter + */ +static PyObject *near_getter( BPy_Sensor * self, int type ) +{ + bNearSensor *sens = self->sens->data; + switch (type) { + case EXPP_SENS_PROPERTY: + return PyString_FromString (sens->name); + case EXPP_SENS_DIST: + return PyFloat_FromDouble( (double)sens->dist ); + case EXPP_SENS_RESET: + return PyFloat_FromDouble( (double)sens->resetdist ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + +/* + * Near sensor setter + */ +static int near_setter( BPy_Sensor *self, int type, PyObject *value ) +{ + bNearSensor *sens = self->sens->data; + + switch (type) { + case EXPP_SENS_PROPERTY: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( sens->name, name, sizeof( sens->name ) ); + break; + } + case EXPP_SENS_DIST: + return EXPP_setFloatClamped( value, &sens->dist, 0.0, 1000.0 ); + case EXPP_SENS_RESET: + return EXPP_setFloatClamped( value, &sens->resetdist, 0.0, 1000.0 ); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + +/* + * Keyboard sensor getter + */ +static PyObject *keyboard_getter( BPy_Sensor * self, int type ) +{ + bKeyboardSensor *sens = self->sens->data; + switch (type) { + case EXPP_SENS_KEY: + return Py_BuildValue("(hhh)", sens->key, sens->qual, sens->qual2); + case EXPP_SENS_LOGTOGGLE: + return PyString_FromString (sens->toggleName); + case EXPP_SENS_TARGET: + return PyString_FromString (sens->targetName); + case EXPP_SENS_ALLKEYS: + return PyBool_FromLong((long)sens->type) ; + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + +/* + * Keyboard sensor setter + */ +static int keyboard_setter( BPy_Sensor *self, int type, PyObject *value ) +{ + bKeyboardSensor *sens = self->sens->data; + + switch (type) { + case EXPP_SENS_KEY: + { + short key=0; + short qual=0; + short qual2=0; + + if( PyInt_Check( value ) ) + key = PyInt_AS_LONG( value ); + else if (!PyArg_ParseTuple( value, "h|hh", &key, &qual, &qual2 )) + return EXPP_ReturnIntError( PyExc_TypeError, "1-3 ints expected (1)" ); + + sens->key = key; + sens->qual = qual; + sens->qual2 = qual2; + return 0; + + } + case EXPP_SENS_LOGTOGGLE: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( sens->toggleName, name, sizeof( sens->toggleName ) ); + break; + } + case EXPP_SENS_TARGET: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( sens->targetName, name, sizeof( sens->targetName ) ); + break; + } + case EXPP_SENS_ALLKEYS: + return EXPP_setBitfield( value, &sens->type, 1<<0, 'h' ); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + +/* + * Property sensor getter + */ +static PyObject *property_getter( BPy_Sensor * self, int type ) +{ + bPropertySensor *sens = self->sens->data; + switch (type) { + case EXPP_SENS_TYPE: + return PyInt_FromLong( ( long )sens->type ); + case EXPP_SENS_PROPERTY: + return PyString_FromString (sens->name); + case EXPP_SENS_VALUE: + return PyString_FromString (sens->value); + case EXPP_SENS_MAX: + return PyString_FromString (sens->maxvalue); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + +/* + * Property sensor setter + */ +static int property_setter( BPy_Sensor *self, int type, PyObject *value ) +{ + bPropertySensor *sens = self->sens->data; + + switch (type) { + case EXPP_SENS_TYPE: + return EXPP_setIValueRange( value, &sens->type, SENS_PROP_EQUAL, SENS_PROP_CHANGED, 'i' ); + case EXPP_SENS_PROPERTY: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( sens->name, name, sizeof( sens->name ) ); + break; + } + case EXPP_SENS_VALUE: + { + char *str = PyString_AsString( value ); + if( !str ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( sens->value, str, sizeof( sens->value ) ); + break; + } + case EXPP_SENS_MAX: + { + char *str = PyString_AsString( value ); + if( !str ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( sens->maxvalue, str, sizeof( sens->maxvalue ) ); + break; + } + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + +/* + * Mouse sensor getter + */ +static PyObject *mouse_getter( BPy_Sensor * self, int type ) +{ + bMouseSensor *sens = self->sens->data; + switch (type) { + case EXPP_SENS_TYPE: + return PyInt_FromLong( ( long )sens->type ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + +/* + * Mouse sensor setter + */ +static int mouse_setter( BPy_Sensor *self, int type, PyObject *value ) +{ + bMouseSensor *sens = self->sens->data; + + switch (type) { + case EXPP_SENS_TYPE: + { + short v = (short)(PyInt_AsLong(value)); + if (v != BL_SENS_MOUSE_LEFT_BUTTON && v != BL_SENS_MOUSE_MIDDLE_BUTTON + && v != BL_SENS_MOUSE_RIGHT_BUTTON && v != BL_SENS_MOUSE_WHEEL_UP + && v != BL_SENS_MOUSE_WHEEL_DOWN && v != BL_SENS_MOUSE_MOVEMENT + && v != BL_SENS_MOUSE_MOUSEOVER && v != BL_SENS_MOUSE_MOUSEOVER_ANY) + return EXPP_ReturnIntError( PyExc_TypeError, "expected int arg as in Blender.Sensor.Values" ); + + sens->type = v; + break; + } + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + +/* + * Collision sensor getter + */ +static PyObject *collision_getter( BPy_Sensor * self, int type ) +{ + bCollisionSensor *sens = self->sens->data; + switch (type) { + case EXPP_SENS_PROPERTY: + return PyString_FromString (sens->name); + case EXPP_SENS_MATERIAL: + return PyString_FromString (sens->materialName); + case EXPP_SENS_TYPE: + return PyInt_FromLong( ( long )sens->mode ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + +/* + * Collision sensor setter + */ +static int collision_setter( BPy_Sensor *self, int type, PyObject *value ) +{ + bCollisionSensor *sens = self->sens->data; + + switch (type) { + case EXPP_SENS_PROPERTY: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( sens->name, name, sizeof( sens->name ) ); + break; + } + case EXPP_SENS_MATERIAL: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( sens->materialName, name, sizeof( sens->materialName ) ); + break; + } + case EXPP_SENS_TYPE: + return EXPP_setIValueRange( value, &sens->mode, 0, 1, 'h' ); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + +/* + * Radar sensor getter + */ +static PyObject *radar_getter( BPy_Sensor * self, int type ) +{ + bRadarSensor *sens = self->sens->data; + switch (type) { + case EXPP_SENS_PROPERTY: + return PyString_FromString (sens->name); + case EXPP_SENS_DIST: + return PyFloat_FromDouble( (double)sens->range ); + case EXPP_SENS_ANGLE: + return PyFloat_FromDouble( (double)sens->angle ); + case EXPP_SENS_AXIS: + return PyInt_FromLong( ( long )sens->axis ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + +/* + * Radar sensor setter + */ +static int radar_setter( BPy_Sensor *self, int type, PyObject *value ) +{ + bRadarSensor *sens = self->sens->data; + + switch (type) { + case EXPP_SENS_PROPERTY: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( sens->name, name, sizeof( sens->name ) ); + break; + } + case EXPP_SENS_DIST: + return EXPP_setFloatClamped( value, &sens->range, 0.0, 10000.0 ); + case EXPP_SENS_ANGLE: + return EXPP_setFloatClamped( value, &sens->angle, 0.0, 179.9 ); + case EXPP_SENS_AXIS: + return EXPP_setIValueRange( value, &sens->axis, 0, 2, 'h' ); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + +/* + * Random sensor getter + */ +static PyObject *random_getter( BPy_Sensor * self, int type ) +{ + bRandomSensor *sens = self->sens->data; + switch (type) { + case EXPP_SENS_SEED: + return PyInt_FromLong( ( long )sens->seed ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + +/* + * Random sensor setter + */ +static int random_setter( BPy_Sensor *self, int type, PyObject *value ) +{ + bRandomSensor *sens = self->sens->data; + + switch (type) { + case EXPP_SENS_SEED: + return EXPP_setIValueRange( value, &sens->seed, 0, 1000, 'i' ); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + +/* + * Ray sensor getter + */ +static PyObject *ray_getter( BPy_Sensor * self, int type ) +{ + bRaySensor *sens = self->sens->data; + switch (type) { + case EXPP_SENS_PROPERTY: + return PyString_FromString (sens->propname); + case EXPP_SENS_MATERIAL: + return PyString_FromString (sens->matname); + case EXPP_SENS_RANGE: + return PyFloat_FromDouble( (double)sens->range ); + case EXPP_SENS_TYPE: + return PyInt_FromLong( ( long )sens->mode ); + case EXPP_SENS_AXIS: + return PyInt_FromLong( ( long )sens->axisflag ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + +/* + * Ray sensor setter + */ +static int ray_setter( BPy_Sensor *self, int type, PyObject *value ) +{ + bRaySensor *sens = self->sens->data; + + switch (type) { + case EXPP_SENS_PROPERTY: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( sens->propname, name, sizeof( sens->propname ) ); + break; + } + case EXPP_SENS_MATERIAL: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( sens->matname, name, sizeof( sens->matname ) ); + break; + } + case EXPP_SENS_TYPE: + return EXPP_setIValueRange( value, &sens->mode, 0, 1, 'h' ); + case EXPP_SENS_RANGE: + return EXPP_setFloatClamped( value, &sens->range, 0.0, 10000.0 ); + case EXPP_SENS_AXIS: + return EXPP_setIValueRange( value, &sens->axisflag, SENS_RAY_Y_AXIS, SENS_RAY_NEG_Z_AXIS, 'i' ); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + +/* + * Message sensor getter + */ +static PyObject *message_getter( BPy_Sensor * self, int type ) +{ + bMessageSensor *sens = self->sens->data; + + switch (type) { + case EXPP_SENS_SUBJECT: + return PyString_FromString (sens->subject); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + +/* + * Message sensor setter + */ +static int message_setter( BPy_Sensor *self, int type, PyObject *value ) +{ + bMessageSensor *sens = self->sens->data; + + switch (type) { + case EXPP_SENS_SUBJECT: + { + char *name = PyString_AsString( value ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" ); + BLI_strncpy( sens->subject, name, sizeof( sens->subject ) ); + break; + } + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + +/* + * Joystick sensor getter + */ +static PyObject *joystick_getter( BPy_Sensor * self, int type ) +{ + bJoystickSensor *sens = self->sens->data; + + switch (type) { + case EXPP_SENS_TYPE: + return PyInt_FromLong( ( long )sens->type ); + case EXPP_SENS_BUTTON: + return PyInt_FromLong( ( long )sens->buttonf ); + case EXPP_SENS_AXIS: + return PyInt_FromLong( ( long )sens->axisf ); + case EXPP_SENS_THRESHOLD: + return PyInt_FromLong( ( long )sens->precision ); + case EXPP_SENS_DIRECTION: + return PyInt_FromLong( ( long )sens->hatf ); + case EXPP_SENS_NUM_AXIS: + return PyInt_FromLong( ( long )sens->axis ); + case EXPP_SENS_NUM_HAT: + return PyInt_FromLong( ( long )sens->hat ); + case EXPP_SENS_NUM_BUTTON: + return PyInt_FromLong( ( long )sens->button ); + default: + return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); + } +} + +/* + * Joystick sensor setter + */ +static int joystick_setter( BPy_Sensor *self, int type, PyObject *value ) +{ + bJoystickSensor *sens = self->sens->data; + + switch (type) { + case EXPP_SENS_TYPE: + return EXPP_setIValueRange( value, &sens->type, SENS_JOY_BUTTON, SENS_JOY_HAT, 'h' ); + case EXPP_SENS_BUTTON: + return EXPP_setIValueRange( value, &sens->buttonf, SENS_JOY_BUTTON_PRESSED, SENS_JOY_BUTTON_RELEASED, 'i' ); + case EXPP_SENS_AXIS: + return EXPP_setIValueRange( value, &sens->axisf, SENS_JOY_X_AXIS, SENS_JOY_NEG_Y_AXIS, 'i' ); + case EXPP_SENS_THRESHOLD: + return EXPP_setIValueRange( value, &sens->precision, 0, 32768, 'i' ); + case EXPP_SENS_DIRECTION: + return EXPP_setIValueRange( value, &sens->hatf, 0, 12, 'i' ); + case EXPP_SENS_NUM_AXIS: + return EXPP_setIValueRange( value, &sens->axis, 1, 2, 'i' ); + case EXPP_SENS_NUM_HAT: + return EXPP_setIValueRange( value, &sens->hat, 1, 2, 'i' ); + case EXPP_SENS_NUM_BUTTON: + return EXPP_setIValueRange( value, &sens->button, 0, 18, 'i' ); + default: + return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); + } + return 0; +} + + + + + + +/* + * get data from a sensor + */ + +static PyObject *Sensor_getData( BPy_Sensor * self, PyObject * key ) +{ + int setting; + + if( !PyInt_Check( key ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected an int arg as stored in Blender.Sensor.Settings" ); + + SENSOR_DEL_CHECK_PY(self); + + setting = PyInt_AsLong( key ); + + switch (setting) { + case EXPP_SENS_ALL_COMMON: + return Py_BuildValue("(hhhh)", + (short)((self->sens->pulse & (1<<0))?1:0), + (short)((self->sens->pulse & (1<<2))?1:0), + self->sens->freq, + self->sens->invert); + + case EXPP_SENS_INVERT: + return PyInt_FromLong( ( long )self->sens->invert ); + case EXPP_SENS_FREQ: + return PyInt_FromLong( ( long )self->sens->freq ); + case EXPP_SENS_TRUE_PULSE: + return EXPP_getBitfield( &self->sens->pulse, (1<<0), 'h' ); + case EXPP_SENS_FALSE_PULSE: + return EXPP_getBitfield( &self->sens->pulse, (1<<2), 'h' ); + } + + switch (self->sens->type) { + //case SENS_ALWAYS: + // return always_getter( self, setting); + case SENS_TOUCH: + return touch_getter( self, setting); + case SENS_NEAR: + return near_getter( self, setting); + case SENS_KEYBOARD: + return keyboard_getter( self, setting); + case SENS_PROPERTY: + return property_getter( self, setting); + case SENS_MOUSE: + return mouse_getter( self, setting); + case SENS_COLLISION: + return collision_getter( self, setting); + case SENS_RADAR: + return radar_getter( self, setting); + case SENS_RANDOM: + return random_getter( self, setting); + case SENS_RAY: + return ray_getter( self, setting); + case SENS_MESSAGE: + return message_getter( self, setting); + case SENS_JOYSTICK: + return joystick_getter( self, setting); + default: + Py_RETURN_NONE; + } + return EXPP_ReturnPyObjError( PyExc_KeyError, + "unknown key or sensor type" ); +} + + +/* + * set data to a sensor + */ + +static int Sensor_setData( BPy_Sensor * self, PyObject * key, PyObject * arg ) +{ + int key_int; + + if( !PyNumber_Check( key ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected an int arg as stored in Blender.Sensor.Settings" ); + + SENSOR_DEL_CHECK_INT(self); + + key_int = PyInt_AsLong( key ); + + switch (key_int) { + case EXPP_SENS_ALL_COMMON: + { + short truepulse=0; + short falsepulse=0; + short freq=0; + short invert=0; + int st; + st = PyArg_ParseTuple( arg, "hhhh", &truepulse, &falsepulse, &freq, &invert ); + if (!st) + return EXPP_ReturnIntError( PyExc_TypeError, "expected a for int tuple" ); + + self->sens->invert = invert; + self->sens->freq = freq; + self->sens->pulse = (truepulse<<0) | (falsepulse<<2); + return 0; + } + case EXPP_SENS_INVERT: + return EXPP_setIValueRange( arg, &self->sens->invert, 0, 1, 'h' ); + case EXPP_SENS_FREQ: + return EXPP_setIValueClamped( arg, &self->sens->freq, 0, 10000, 'h' ); + case EXPP_SENS_TRUE_PULSE: + return EXPP_setBitfield( arg, &self->sens->pulse, 1<<0, 'h' ); + case EXPP_SENS_FALSE_PULSE: + return EXPP_setBitfield( arg, &self->sens->pulse, 1<<2, 'h' ); + } + + switch (self->sens->type) { + //case SENS_ALWAYS: + // return always_setter( self, key_int, arg); + case SENS_TOUCH: + return touch_setter( self, key_int, arg); + case SENS_NEAR: + return near_setter( self, key_int, arg); + case SENS_KEYBOARD: + return keyboard_setter( self, key_int, arg); + case SENS_PROPERTY: + return property_setter( self, key_int, arg); + case SENS_MOUSE: + return mouse_setter( self, key_int, arg); + case SENS_COLLISION: + return collision_setter( self, key_int, arg); + case SENS_RADAR: + return radar_setter( self, key_int, arg); + case SENS_RANDOM: + return random_setter( self, key_int, arg); + case SENS_RAY: + return ray_setter( self, key_int, arg); + case SENS_MESSAGE: + return message_setter( self, key_int, arg); + case SENS_JOYSTICK: + return joystick_setter( self, key_int, arg); + default: + return 0; + } + return EXPP_ReturnIntError( PyExc_RuntimeError, + "unsupported sensor setting" ); +} + + + + + + + + +/*****************************************************************************/ +/* Function: Sensor_repr */ +/* Description: This is a callback function for the BPy_Sensor type. It */ +/* builds a meaningful string to represent sensor objects. */ +/*****************************************************************************/ + +// Return sensor's name from its type (copy from buttons_logic.c) +static char *sensor_name(int type) +{ + switch (type) { + case SENS_ALWAYS: + return "Always"; + case SENS_TOUCH: + return "Touch"; + case SENS_NEAR: + return "Near"; + case SENS_KEYBOARD: + return "Keyboard"; + case SENS_PROPERTY: + return "Property"; + case SENS_MOUSE: + return "Mouse"; + case SENS_COLLISION: + return "Collision"; + case SENS_RADAR: + return "Radar"; + case SENS_RANDOM: + return "Random"; + case SENS_RAY: + return "Ray"; + case SENS_MESSAGE: + return "Message"; + case SENS_JOYSTICK: + return "Joystick"; + } + return "unknown"; +} + + +static PyObject *Sensor_repr( BPy_Sensor * self ) +{ + if (self->sens==NULL) + return PyString_FromString( "[Sensor - Removed"); + + return PyString_FromFormat( "[Sensor \"%s\", Type \"%s\"]", self->sens->name, sensor_name(self->sens->type) ); +} + +/* Three Python Sensor_Type helper functions needed by the Object module: */ + +/*****************************************************************************/ +/* Function: Sensor_CreatePyObject */ +/* Description: This function will create a new BPy_Sensor from an */ +/* existing Blender sensor structure. */ +/*****************************************************************************/ +PyObject *Sensor_CreatePyObject( Object *ob, bSensor * sens ) +{ + BPy_Sensor *pysens; + pysens = ( BPy_Sensor * ) PyObject_NEW( BPy_Sensor, &Sensor_Type ); + if( !pysens ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, + "couldn't create BPy_Sensor object" ); + pysens->sens = sens; + pysens->object = ob; + return ( PyObject * ) pysens; +} + +/*****************************************************************************/ +/* Function: Sensor_FromPyObject */ +/* Description: This function returns the Blender sensor from the given */ +/* PyObject. */ +/*****************************************************************************/ +bSensor *Sensor_FromPyObject( PyObject * pyobj ) +{ + return ( ( BPy_Sensor * ) pyobj )->sens; +} + + + + + + + + + + + + + + +/*****************************************************************************/ +/* Sensor Sequence wrapper */ +/*****************************************************************************/ + +/* + * Initialize the interator + */ + +static PyObject *SensorSeq_getIter( BPy_SensorSeq * self ) +{ + if (!self->iter) { + self->iter = (bSensor *)self->object->sensors.first; + return EXPP_incr_ret ( (PyObject *) self ); + } else { + return SensorSeq_CreatePyObject(self->object, (bSensor *)self->object->sensors.first); + } +} + +/* + * Get the next Sensor + */ + +static PyObject *SensorSeq_nextIter( BPy_SensorSeq * self ) +{ + bSensor *iter = self->iter; + if( iter ) { + self->iter = iter->next; + return Sensor_CreatePyObject( self->object, iter ); + } + + self->iter= NULL; /* mark as not iterating */ + return EXPP_ReturnPyObjError( PyExc_StopIteration, + "iterator at end" ); +} + +/* return the number of sensors */ + +static int SensorSeq_length( BPy_SensorSeq * self ) +{ + return BLI_countlist( &self->object->sensors ); +} + +/* return a sensor */ + +static PyObject *SensorSeq_item( BPy_SensorSeq * self, int i ) +{ + bSensor *sens = NULL; + + /* if index is negative, start counting from the end of the list */ + if( i < 0 ) + i += SensorSeq_length( self ); + + /* skip through the list until we get the sensor or end of list */ + + for( sens = self->object->sensors.first; i && sens; --i ) sens = sens->next; + + if( sens ) + return Sensor_CreatePyObject( self->object, sens ); + else + return EXPP_ReturnPyObjError( PyExc_IndexError, + "array index out of range" ); +} + + + +/*****************************************************************************/ +/* Python BPy_SensorSeq sequence table: */ +/*****************************************************************************/ +static PySequenceMethods SensorSeq_as_sequence = { + ( inquiry ) SensorSeq_length, /* sq_length */ + ( binaryfunc ) 0, /* sq_concat */ + ( intargfunc ) 0, /* sq_repeat */ + ( intargfunc ) SensorSeq_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 */ +}; + +/* + * helper function to check for a valid sensor argument + */ + +static bSensor *locate_sensor( BPy_SensorSeq *self, BPy_Sensor * value ) +{ + bSensor *sens; + + /* check that argument is a sensor */ + if( !BPy_Sensor_Check(value) ) + return (bSensor *)EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a sensor as an argument" ); + + /* check whether sensor has been removed */ + if( !value->sens ) + return (bSensor *)EXPP_ReturnPyObjError( PyExc_RuntimeError, + "This sensor has been removed!" ); + + /* find the sensor in the object's list */ + for( sens = self->object->sensors.first; sens; sens = sens->next ) + if( sens == value->sens ) + return sens; + + /* return exception if we can't find the sensor */ + return (bSensor *)EXPP_ReturnPyObjError( PyExc_AttributeError, + "This sensor is not in the object's stack" ); +} + +/* create a new sensor at the end of the list */ + +static PyObject *SensorSeq_append( BPy_SensorSeq *self, PyObject *value ) +{ + int type = PyInt_AsLong(value); + + if( type < SENS_ALWAYS || type > SENS_JOYSTICK ) + return EXPP_ReturnPyObjError( PyExc_ValueError, + "Not an int or argument out of range, expected an int from Blender.Sensor.Type" ); + + BLI_addtail( &self->object->sensors, new_sensor( type ) ); + return Sensor_CreatePyObject( self->object, self->object->sensors.last ); +} + +/* remove an existing sensor */ + +static PyObject *SensorSeq_remove( BPy_SensorSeq *self, BPy_Sensor *value ) +{ + bSensor *sens = locate_sensor( self, value ); + + /* if we can't locate the sensor, return (exception already set) */ + if( !sens ) + return (PyObject *)NULL; + + /* do the actual removal */ + BLI_remlink( &self->object->sensors, sens ); + free_sensor( sens ); + + /* erase the link to the sensor */ + value->sens = NULL; + + Py_RETURN_NONE; +} + + +/*****************************************************************************/ +/* Python BPy_SensorSeq methods table: */ +/*****************************************************************************/ +static PyMethodDef BPy_SensorSeq_methods[] = { + /* name, method, flags, doc */ + {"append", ( PyCFunction ) SensorSeq_append, METH_O, + "(type) - add a new sensor, where type is the type of sensor"}, + {"remove", ( PyCFunction ) SensorSeq_remove, METH_O, + "(sensor) - remove an existing sensor, where sensor is a sensor from this object."}, + {NULL, NULL, 0, NULL} +}; + +/*****************************************************************************/ +/* Python SensorSeq_Type structure definition: */ +/*****************************************************************************/ +PyTypeObject SensorSeq_Type = { + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ + /* For printing, in format "." */ + "Blender.Sensors", /* char *tp_name; */ + sizeof( BPy_SensorSeq ), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ + + /* Methods to implement standard operations */ + + NULL, /* 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; */ + &SensorSeq_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 )SensorSeq_getIter, /* getiterfunc tp_iter; */ + ( iternextfunc )SensorSeq_nextIter, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + BPy_SensorSeq_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: SensorSeq_CreatePyObject */ +/* Description: This function will create a new BPy_SensorSeq from an */ +/* existing ListBase structure. */ +/*****************************************************************************/ +PyObject *SensorSeq_CreatePyObject( Object *ob, bSensor *iter ) +{ + BPy_SensorSeq *pysens; + pysens = ( BPy_SensorSeq * ) PyObject_NEW( BPy_SensorSeq, &SensorSeq_Type ); + if( !pysens ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, + "couldn't create BPy_SensorSeq object" ); + pysens->object = ob; + pysens->iter = iter; + return ( PyObject * ) pysens; +} + + + + + + + + + + + + + + +static PyObject *M_Sensor_TypeDict( void ) +{ + PyObject *S = PyConstant_New( ); + + if( S ) { + BPy_constant *d = ( BPy_constant * ) S; + + PyConstant_Insert( d, "ALWAYS", + PyInt_FromLong( SENS_ALWAYS ) ); + PyConstant_Insert( d, "TOUCH", + PyInt_FromLong( SENS_TOUCH ) ); + PyConstant_Insert( d, "NEAR", + PyInt_FromLong( SENS_NEAR ) ); + PyConstant_Insert( d, "KEYBOARD", + PyInt_FromLong( SENS_KEYBOARD ) ); + PyConstant_Insert( d, "PROPERTY", + PyInt_FromLong( SENS_PROPERTY ) ); + PyConstant_Insert( d, "MOUSE", + PyInt_FromLong( SENS_MOUSE ) ); + PyConstant_Insert( d, "COLLISION", + PyInt_FromLong( SENS_COLLISION ) ); + PyConstant_Insert( d, "RADAR", + PyInt_FromLong( SENS_RADAR ) ); + PyConstant_Insert( d, "RANDOM", + PyInt_FromLong( SENS_RANDOM ) ); + PyConstant_Insert( d, "RAY", + PyInt_FromLong( SENS_RAY ) ); + PyConstant_Insert( d, "MESSAGE", + PyInt_FromLong( SENS_MESSAGE ) ); + PyConstant_Insert( d, "JOYSTICK", + PyInt_FromLong( SENS_JOYSTICK ) ); + } + return S; +} + + +static PyObject *M_Sensor_ValuesDict( void ) +{ + PyObject *S = PyConstant_New( ); + + if( S ) { + BPy_constant *d = ( BPy_constant * ) S; + + // Mouse constants + PyConstant_Insert( d, "MOUSE_LEFT_BUTTON", + PyInt_FromLong( BL_SENS_MOUSE_LEFT_BUTTON ) ); + PyConstant_Insert( d, "MOUSE_MIDDLE_BUTTON", + PyInt_FromLong( BL_SENS_MOUSE_MIDDLE_BUTTON ) ); + PyConstant_Insert( d, "MOUSE_RIGHT_BUTTON", + PyInt_FromLong( BL_SENS_MOUSE_RIGHT_BUTTON ) ); + PyConstant_Insert( d, "MOUSE_WHEEL_UP", + PyInt_FromLong( BL_SENS_MOUSE_WHEEL_UP ) ); + PyConstant_Insert( d, "MOUSE_WHEEL_DOWN", + PyInt_FromLong( BL_SENS_MOUSE_WHEEL_DOWN ) ); + PyConstant_Insert( d, "MOUSE_MOVEMENT", + PyInt_FromLong( BL_SENS_MOUSE_MOVEMENT ) ); + PyConstant_Insert( d, "MOUSE_MOUSEOVER", + PyInt_FromLong( BL_SENS_MOUSE_MOUSEOVER ) ); + PyConstant_Insert( d, "MOUSE_MOUSEOVER_ANY", + PyInt_FromLong( BL_SENS_MOUSE_MOUSEOVER_ANY ) ); + + // Property constants + PyConstant_Insert( d, "PROP_EQUAL", + PyInt_FromLong( SENS_PROP_EQUAL ) ); + PyConstant_Insert( d, "PROP_NEQUAL", + PyInt_FromLong( SENS_PROP_NEQUAL ) ); + PyConstant_Insert( d, "PROP_INTERVAL", + PyInt_FromLong( SENS_PROP_INTERVAL ) ); + PyConstant_Insert( d, "PROP_CHANGED", + PyInt_FromLong( SENS_PROP_CHANGED ) ); + + // Ray constants + PyConstant_Insert( d, "RAY_X_AXIS", + PyInt_FromLong( SENS_RAY_X_AXIS ) ); + PyConstant_Insert( d, "RAY_Y_AXIS", + PyInt_FromLong( SENS_RAY_Y_AXIS ) ); + PyConstant_Insert( d, "RAY_Z_AXIS", + PyInt_FromLong( SENS_RAY_Z_AXIS ) ); + PyConstant_Insert( d, "RAY_NEG_X_AXIS", + PyInt_FromLong( SENS_RAY_NEG_X_AXIS ) ); + PyConstant_Insert( d, "RAY_NEG_Y_AXIS", + PyInt_FromLong( SENS_RAY_NEG_Y_AXIS ) ); + PyConstant_Insert( d, "RAY_NEG_Z_AXIS", + PyInt_FromLong( SENS_RAY_NEG_Z_AXIS ) ); + + // Joystick constants + PyConstant_Insert( d, "JOY_BUTTON", + PyInt_FromLong( SENS_JOY_BUTTON ) ); + PyConstant_Insert( d, "JOY_AXIS", + PyInt_FromLong( SENS_JOY_AXIS ) ); + PyConstant_Insert( d, "JOY_HAT", + PyInt_FromLong( SENS_JOY_HAT ) ); + PyConstant_Insert( d, "JOY_PRESSED", + PyInt_FromLong( SENS_JOY_BUTTON_PRESSED ) ); + PyConstant_Insert( d, "JOY_RELEASED", + PyInt_FromLong( SENS_JOY_BUTTON_RELEASED ) ); + PyConstant_Insert( d, "JOY_X_AXIS", + PyInt_FromLong( SENS_JOY_X_AXIS ) ); + PyConstant_Insert( d, "JOY_Y_AXIS", + PyInt_FromLong( SENS_JOY_Y_AXIS ) ); + PyConstant_Insert( d, "JOY_NEG_X_AXIS", + PyInt_FromLong( SENS_JOY_NEG_X_AXIS ) ); + PyConstant_Insert( d, "JOY_NEG_Y_AXIS", + PyInt_FromLong( SENS_JOY_NEG_Y_AXIS ) ); + + // Radar constants + PyConstant_Insert( d, "RADAR_X_AXIS", + PyInt_FromLong( 0 ) ); + PyConstant_Insert( d, "RADAR_Y_AXIS", + PyInt_FromLong( 1 ) ); + PyConstant_Insert( d, "RADAR_Z_AXIS", + PyInt_FromLong( 2 ) ); + + + } + return S; +} + + +static PyObject *M_Sensor_SettingsDict( void ) +{ + PyObject *S = PyConstant_New( ); + + if( S ) { + BPy_constant *d = ( BPy_constant * ) S; + + PyConstant_Insert( d, "INVERT", + PyInt_FromLong( EXPP_SENS_INVERT ) ); + PyConstant_Insert( d, "FREQ", + PyInt_FromLong( EXPP_SENS_FREQ ) ); + PyConstant_Insert( d, "TRUE_PULSE", + PyInt_FromLong( EXPP_SENS_TRUE_PULSE ) ); + PyConstant_Insert( d, "FALSE_PULSE", + PyInt_FromLong( EXPP_SENS_FALSE_PULSE ) ); + PyConstant_Insert( d, "MATERIAL", + PyInt_FromLong( EXPP_SENS_MATERIAL ) ); + PyConstant_Insert( d, "PROPERTY", + PyInt_FromLong( EXPP_SENS_PROPERTY ) ); + PyConstant_Insert( d, "DIST", + PyInt_FromLong( EXPP_SENS_DIST ) ); + PyConstant_Insert( d, "RESET", + PyInt_FromLong( EXPP_SENS_RESET ) ); + PyConstant_Insert( d, "KEY", + PyInt_FromLong( EXPP_SENS_KEY ) ); + PyConstant_Insert( d, "LOGTOGGLE", + PyInt_FromLong( EXPP_SENS_LOGTOGGLE ) ); + PyConstant_Insert( d, "TARGET", + PyInt_FromLong( EXPP_SENS_TARGET ) ); + PyConstant_Insert( d, "ALLKEYS", + PyInt_FromLong( EXPP_SENS_ALLKEYS ) ); + PyConstant_Insert( d, "TYPE", + PyInt_FromLong( EXPP_SENS_TYPE ) ); + PyConstant_Insert( d, "VALUE", + PyInt_FromLong( EXPP_SENS_VALUE ) ); + PyConstant_Insert( d, "MAX", + PyInt_FromLong( EXPP_SENS_MAX ) ); + PyConstant_Insert( d, "ANGLE", + PyInt_FromLong( EXPP_SENS_ANGLE ) ); + PyConstant_Insert( d, "AXIS", + PyInt_FromLong( EXPP_SENS_AXIS ) ); + PyConstant_Insert( d, "SEED", + PyInt_FromLong( EXPP_SENS_SEED ) ); + PyConstant_Insert( d, "RANGE", + PyInt_FromLong( EXPP_SENS_RANGE ) ); + PyConstant_Insert( d, "SUBJECT", + PyInt_FromLong( EXPP_SENS_SUBJECT ) ); + PyConstant_Insert( d, "BUTTON", + PyInt_FromLong( EXPP_SENS_BUTTON ) ); + PyConstant_Insert( d, "NUM_AXIS", + PyInt_FromLong( EXPP_SENS_NUM_AXIS ) ); + PyConstant_Insert( d, "NUM_HAT", + PyInt_FromLong( EXPP_SENS_NUM_HAT ) ); + PyConstant_Insert( d, "NUM_BUTTON", + PyInt_FromLong( EXPP_SENS_NUM_BUTTON ) ); + PyConstant_Insert( d, "THRESHOLD", + PyInt_FromLong( EXPP_SENS_THRESHOLD ) ); + PyConstant_Insert( d, "DIRECTION", + PyInt_FromLong( EXPP_SENS_DIRECTION ) ); + PyConstant_Insert( d, "ALL_COMMON", + PyInt_FromLong( EXPP_SENS_ALL_COMMON ) ); + } + return S; +} + + + + + +/*****************************************************************************/ +/* Function: Sensor_Init */ +/*****************************************************************************/ +PyObject *Sensor_Init( void ) +{ + PyObject *submodule; + PyObject *TypeDict = M_Sensor_TypeDict( ); + PyObject *SettingsDict = M_Sensor_SettingsDict( ); + PyObject *ValuesDict = M_Sensor_ValuesDict( ); + + if( PyType_Ready( &SensorSeq_Type ) < 0 || + PyType_Ready( &Sensor_Type ) < 0 ) + return NULL; + + submodule = Py_InitModule3( "Blender.Sensor", NULL, + "Sensor module for accessing and creating object sensor data" ); + + if( TypeDict ) { + PyModule_AddObject( submodule, "Type", TypeDict ); /* deprecated */ + /* since PyModule_AddObject() steals a reference, we need to + incref TypeDict to use it again */ + Py_INCREF( TypeDict); + PyModule_AddObject( submodule, "Types", TypeDict ); + } + + if( SettingsDict ) + PyModule_AddObject( submodule, "Settings", SettingsDict ); + + if( ValuesDict ) + PyModule_AddObject( submodule, "Values", ValuesDict ); + + return submodule; +} Index: source/blender/python/api2_2x/Sensor.h =================================================================== --- source/blender/python/api2_2x/Sensor.h (revision 0) +++ source/blender/python/api2_2x/Sensor.h (revision 0) @@ -0,0 +1,70 @@ +/* + * ***** 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. + * + * This is a new part of Blender. + * + * Contributor(s): Matthieu Delanoë + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef EXPP_SENSOR_H +#define EXPP_SENSOR_H + +#include +#include "DNA_object_types.h" +#include "DNA_sensor_types.h" +#include "DNA_listBase.h" + +/*****************************************************************************/ +/* Python BPy_Sensor and BPy_SensorSeq structure definition: */ +/*****************************************************************************/ + +typedef struct { + PyObject_HEAD /* required macro */ + Object *object; + bSensor *iter; +} BPy_SensorSeq; + +typedef struct { + PyObject_HEAD /* required macro */ + Object *object; + /* if sens is null, the sensor has been removed and we need to raise + an error when its data is accessed */ + bSensor *sens; +} BPy_Sensor; + +extern PyTypeObject SensorSeq_Type; +extern PyTypeObject Sensor_Type; +#define BPy_SensorSeq_Check(v) ((v)->ob_type == &SensorSeq_Type) +#define BPy_Sensor_Check(v) ((v)->ob_type == &Sensor_Type) + + + +/* + * prototypes + */ + +PyObject *Sensor_Init( void ); +PyObject *SensorSeq_CreatePyObject( Object *obj, bSensor *iter ); +PyObject *Sensor_CreatePyObject( Object *obj, bSensor *sens ); +bSensor *Sensor_FromPyObject( PyObject * py_obj ); + +#endif /* EXPP_SENSOR_H */