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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Hughes <khughes@pacific.edu>2006-04-23 06:34:50 +0400
committerKen Hughes <khughes@pacific.edu>2006-04-23 06:34:50 +0400
commit8001a8b409833c3ff4e1dce36e9bebc36fb3e859 (patch)
tree35f3811a49bb45fc8cbed35a34a27e80c7a4bec1 /source/blender/python/api2_2x/Modifier.c
parenta7863efb8abf60f35407c6d66127d65db089f33d (diff)
===Python API===
Initial commit for new Modifier API. Probably does about 70-75% of what it should, but it's a start.
Diffstat (limited to 'source/blender/python/api2_2x/Modifier.c')
-rw-r--r--source/blender/python/api2_2x/Modifier.c1171
1 files changed, 1171 insertions, 0 deletions
diff --git a/source/blender/python/api2_2x/Modifier.c b/source/blender/python/api2_2x/Modifier.c
new file mode 100644
index 00000000000..ad03dbcaed8
--- /dev/null
+++ b/source/blender/python/api2_2x/Modifier.c
@@ -0,0 +1,1171 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Ken Hughes
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "Modifier.h" /*This must come first*/
+
+#include "DNA_object_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_vec_types.h"
+
+#include "BKE_main.h"
+#include "BKE_global.h"
+#include "BKE_modifier.h"
+#include "BKE_library.h"
+#include "BLI_blenlib.h"
+#include "MEM_guardedalloc.h"
+#include "butspace.h"
+#include "blendef.h"
+#include "mydevice.h"
+
+#include "Object.h"
+#include "gen_utils.h"
+
+enum mod_constants {
+ EXPP_MOD_RENDER = 0,
+ EXPP_MOD_REALTIME,
+ EXPP_MOD_EDITMODE,
+ EXPP_MOD_ONCAGE,
+
+ EXPP_MOD_SUBSURF_TYPES,
+ EXPP_MOD_SUBSURF_LEVELS,
+ EXPP_MOD_SUBSURF_RENDLEVELS,
+ EXPP_MOD_SUBSURF_OPTIMAL,
+ EXPP_MOD_SUBSURF_UV,
+
+ EXPP_MOD_ARMATURE_OBJECT,
+ EXPP_MOD_ARMATURE_VERTGROUPS,
+ EXPP_MOD_ARMATURE_ENVELOPES,
+
+ EXPP_MOD_LATTICE_OBJECT,
+ EXPP_MOD_LATTICE_VERTGROUP,
+
+ EXPP_MOD_CURVE_OBJECT,
+ EXPP_MOD_CURVE_VERTGROUP,
+
+ EXPP_MOD_BUILD_START,
+ EXPP_MOD_BUILD_LENGTH,
+ EXPP_MOD_BUILD_SEED,
+ EXPP_MOD_BUILD_RANDOMIZE,
+
+ EXPP_MOD_MIRROR_LIMIT,
+ EXPP_MOD_MIRROR_FLAG,
+ EXPP_MOD_MIRROR_AXIS,
+
+ EXPP_MOD_DECIMATE_RATIO,
+ EXPP_MOD_DECIMATE_COUNT,
+
+ EXPP_MOD_WAVE_STARTX,
+ EXPP_MOD_WAVE_STARTY,
+ EXPP_MOD_WAVE_HEIGHT,
+ EXPP_MOD_WAVE_WIDTH,
+ EXPP_MOD_WAVE_NARROW,
+ EXPP_MOD_WAVE_SPEED,
+ EXPP_MOD_WAVE_DAMP,
+ EXPP_MOD_WAVE_LIFETIME,
+ EXPP_MOD_WAVE_TIMEOFFS,
+ EXPP_MOD_WAVE_FLAG,
+
+ EXPP_MOD_BOOLEAN_OPERATION,
+ EXPP_MOD_BOOLEAN_OBJECT,
+
+ /* yet to be implemented */
+ /* EXPP_MOD_HOOK_,
+ EXPP_MOD_ARRAY_, */
+};
+
+/*****************************************************************************/
+/* Python BPy_Modifier methods declarations: */
+/*****************************************************************************/
+static PyObject *Modifier_getName( BPy_Modifier * self );
+static int Modifier_setName( BPy_Modifier * self, PyObject *arg );
+
+static PyObject *Modifier_getKeys( BPy_Modifier * self );
+static PyObject *Modifier_moveUp( BPy_Modifier * self );
+static PyObject *Modifier_moveDown( BPy_Modifier * self );
+
+static PyObject *Modifier_getData( BPy_Modifier * self, PyObject * key );
+static int Modifier_setData( BPy_Modifier * self, PyObject * key,
+ PyObject * value );
+
+/*****************************************************************************/
+/* Python BPy_Modifier methods table: */
+/*****************************************************************************/
+static PyMethodDef BPy_Modifier_methods[] = {
+ /* name, method, flags, doc */
+ {"up", ( PyCFunction ) Modifier_moveUp, METH_NOARGS,
+ "Move modifier up in stack"},
+ {"down", ( PyCFunction ) Modifier_moveDown, METH_NOARGS,
+ "Move modifier down in stack"},
+ {"keys", ( PyCFunction )Modifier_getKeys, METH_NOARGS,
+ "Modifier keys"},
+ {NULL, NULL, 0, NULL}
+};
+
+/*****************************************************************************/
+/* Python BPy_Modifier attributes get/set structure: */
+/*****************************************************************************/
+static PyGetSetDef BPy_Modifier_getseters[] = {
+ {"name",
+ (getter)Modifier_getName, (setter)Modifier_setName,
+ "Modifier name", NULL},
+ {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
+};
+
+/*****************************************************************************/
+/* Python Modifier_Type Mapping Methods table: */
+/*****************************************************************************/
+static PyMappingMethods Modifier_as_mapping = {
+ NULL, /* mp_length */
+ ( binaryfunc ) Modifier_getData, /* mp_subscript */
+ ( objobjargproc ) Modifier_setData, /* mp_ass_subscript */
+};
+
+/*****************************************************************************/
+/* Python Modifier_Type callback function prototypes: */
+/*****************************************************************************/
+static PyObject *Modifier_repr( BPy_Modifier * self );
+
+/*****************************************************************************/
+/* Python Modifier_Type structure definition: */
+/*****************************************************************************/
+PyTypeObject Modifier_Type = {
+ PyObject_HEAD_INIT( NULL ) /* required py macro */
+ 0, /* ob_size */
+ /* For printing, in format "<module>.<name>" */
+ "Blender Modifier", /* char *tp_name; */
+ sizeof( BPy_Modifier ), /* int tp_basicsize; */
+ 0, /* tp_itemsize; For allocation */
+
+ /* Methods to implement standard operations */
+
+ ( destructor ) PyObject_Del,/* destructor tp_dealloc; */
+ NULL, /* printfunc tp_print; */
+ NULL, /* getattrfunc tp_getattr; */
+ NULL, /* setattrfunc tp_setattr; */
+ NULL, /* cmpfunc tp_compare; */
+ ( reprfunc ) Modifier_repr, /* reprfunc tp_repr; */
+
+ /* Method suites for standard classes */
+
+ NULL, /* PyNumberMethods *tp_as_number; */
+ NULL, /* PySequenceMethods *tp_as_sequence; */
+ &Modifier_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_Modifier_methods, /* struct PyMethodDef *tp_methods; */
+ NULL, /* struct PyMemberDef *tp_members; */
+ BPy_Modifier_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_Modifier methods: */
+/*****************************************************************************/
+
+/*
+ * return the name of this modifier
+ */
+
+static PyObject *Modifier_getName( BPy_Modifier * self )
+{
+ return PyString_FromString( self->md->name );
+}
+
+/*
+ * set the name of this modifier
+ */
+
+static int Modifier_setName( BPy_Modifier * self, PyObject * attr )
+{
+ char *name = PyString_AsString( attr );
+ if( !name )
+ return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" );
+
+ BLI_strncpy( self->md->name, name, sizeof( self->md->name ) );
+
+ return 0;
+}
+
+/*
+ * move the modifier up in the stack
+ */
+
+static PyObject *Modifier_moveUp( BPy_Modifier * self )
+{
+ if( mod_moveUp( self->obj, self->md ) )
+ return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+ "cannot move above a modifier requiring original data" );
+
+ Py_RETURN_NONE;
+}
+
+/*
+ * move the modifier down in the stack
+ */
+
+static PyObject *Modifier_moveDown( BPy_Modifier * self )
+{
+ if( mod_moveDown( self->obj, self->md ) )
+ return EXPP_ReturnPyObjError( PyExc_RuntimeError,
+ "cannot move beyond a non-deforming modifier" );
+
+ Py_RETURN_NONE;
+}
+
+/*
+ * return a constant object which contains all the data attributes which
+ * can be accessed for each modifier type
+ */
+
+static PyObject *Modifier_getKeys( BPy_Modifier * self )
+{
+ BPy_constant *attr = (BPy_constant *)PyConstant_New();
+
+ PyConstant_Insert( attr, "RENDER", PyInt_FromLong( EXPP_MOD_RENDER ) );
+ PyConstant_Insert( attr, "REALTIME", PyInt_FromLong( EXPP_MOD_REALTIME ) );
+ PyConstant_Insert( attr, "EDITMODE", PyInt_FromLong( EXPP_MOD_EDITMODE ) );
+ PyConstant_Insert( attr, "ONCAGE", PyInt_FromLong( EXPP_MOD_ONCAGE ) );
+ switch( self->md->type ) {
+ case eModifierType_Subsurf:
+ PyConstant_Insert( attr, "TYPE",
+ PyInt_FromLong( EXPP_MOD_SUBSURF_TYPES ) );
+ PyConstant_Insert( attr, "LEVELS",
+ PyInt_FromLong( EXPP_MOD_SUBSURF_LEVELS ) );
+ PyConstant_Insert( attr, "RENDER_LEVELS",
+ PyInt_FromLong( EXPP_MOD_SUBSURF_RENDLEVELS ) );
+ PyConstant_Insert( attr, "OPTIMAL",
+ PyInt_FromLong( EXPP_MOD_SUBSURF_OPTIMAL ) );
+ PyConstant_Insert( attr, "UV",
+ PyInt_FromLong( EXPP_MOD_SUBSURF_UV ) );
+ break;
+
+ case eModifierType_Armature:
+ PyConstant_Insert( attr, "OBJECT",
+ PyInt_FromLong( EXPP_MOD_ARMATURE_OBJECT ) );
+ PyConstant_Insert( attr, "VERTGROUPS",
+ PyInt_FromLong( EXPP_MOD_ARMATURE_VERTGROUPS ) );
+ PyConstant_Insert( attr, "ENVELOPES",
+ PyInt_FromLong( EXPP_MOD_ARMATURE_ENVELOPES ) );
+ break;
+
+ case eModifierType_Lattice:
+ PyConstant_Insert( attr, "OBJECT",
+ PyInt_FromLong( EXPP_MOD_LATTICE_OBJECT) );
+ PyConstant_Insert( attr, "VERTGROUP",
+ PyInt_FromLong( EXPP_MOD_LATTICE_VERTGROUP) );
+ break;
+
+ case eModifierType_Curve:
+ PyConstant_Insert( attr, "OBJECT",
+ PyInt_FromLong( EXPP_MOD_CURVE_OBJECT ) );
+ PyConstant_Insert( attr, "VERTGROUP",
+ PyInt_FromLong( EXPP_MOD_CURVE_VERTGROUP ) );
+ break;
+
+ case eModifierType_Build:
+ PyConstant_Insert( attr, "START",
+ PyInt_FromLong( EXPP_MOD_BUILD_START ) );
+ PyConstant_Insert( attr, "LENGTH",
+ PyInt_FromLong( EXPP_MOD_BUILD_LENGTH ) );
+ PyConstant_Insert( attr, "SEED",
+ PyInt_FromLong( EXPP_MOD_BUILD_SEED ) );
+ PyConstant_Insert( attr, "RANDOMIZE",
+ PyInt_FromLong( EXPP_MOD_BUILD_RANDOMIZE ) );
+ break;
+
+ case eModifierType_Mirror:
+ PyConstant_Insert( attr, "LIMIT",
+ PyInt_FromLong( EXPP_MOD_MIRROR_LIMIT ) );
+ PyConstant_Insert( attr, "FLAG",
+ PyInt_FromLong( EXPP_MOD_MIRROR_FLAG ) );
+ PyConstant_Insert( attr, "AXIS",
+ PyInt_FromLong( EXPP_MOD_MIRROR_AXIS ) );
+ break;
+
+ case eModifierType_Decimate:
+ PyConstant_Insert( attr, "RATIO",
+ PyInt_FromLong( EXPP_MOD_DECIMATE_RATIO ) );
+ PyConstant_Insert( attr, "FACE_COUNT",
+ PyInt_FromLong( EXPP_MOD_DECIMATE_COUNT ) );
+ break;
+
+ case eModifierType_Wave:
+ PyConstant_Insert( attr, "START_X",
+ PyInt_FromLong( EXPP_MOD_WAVE_STARTX ) );
+ PyConstant_Insert( attr, "START_Y",
+ PyInt_FromLong( EXPP_MOD_WAVE_STARTY ) );
+ PyConstant_Insert( attr, "HEIGHT",
+ PyInt_FromLong( EXPP_MOD_WAVE_HEIGHT ) );
+ PyConstant_Insert( attr, "WIDTH",
+ PyInt_FromLong( EXPP_MOD_WAVE_WIDTH ) );
+ PyConstant_Insert( attr, "NARROW",
+ PyInt_FromLong( EXPP_MOD_WAVE_NARROW ) );
+ PyConstant_Insert( attr, "SPEED",
+ PyInt_FromLong( EXPP_MOD_WAVE_SPEED ) );
+ PyConstant_Insert( attr, "DAMP",
+ PyInt_FromLong( EXPP_MOD_WAVE_DAMP ) );
+ PyConstant_Insert( attr, "LIFETIME",
+ PyInt_FromLong( EXPP_MOD_WAVE_LIFETIME ) );
+ PyConstant_Insert( attr, "TIME_OFFS",
+ PyInt_FromLong( EXPP_MOD_WAVE_TIMEOFFS ) );
+ PyConstant_Insert( attr, "FLAG",
+ PyInt_FromLong( EXPP_MOD_WAVE_FLAG ) );
+ break;
+
+ case eModifierType_Boolean:
+ PyConstant_Insert( attr, "OPERATION",
+ PyInt_FromLong( EXPP_MOD_BOOLEAN_OPERATION ) );
+ PyConstant_Insert( attr, "OBJECT",
+ PyInt_FromLong( EXPP_MOD_BOOLEAN_OBJECT ) );
+
+ default:
+ break;
+ }
+
+ return (PyObject *)attr;
+}
+
+static PyObject *subsurf_getter( ModifierData *ptr, int type )
+{
+ SubsurfModifierData *md = ( SubsurfModifierData *)ptr;
+
+ switch( type ) {
+ case EXPP_MOD_SUBSURF_TYPES:
+ return PyInt_FromLong( ( long )md->subdivType );
+ case EXPP_MOD_SUBSURF_LEVELS:
+ return PyInt_FromLong( ( long )md->levels );
+ case EXPP_MOD_SUBSURF_RENDLEVELS:
+ return PyInt_FromLong( ( long )md->renderLevels );
+ case EXPP_MOD_SUBSURF_OPTIMAL:
+ return PyBool_FromLong( ( long )
+ ( md->flags & eSubsurfModifierFlag_ControlEdges ) ) ;
+ case EXPP_MOD_SUBSURF_UV:
+ return PyBool_FromLong( ( long )
+ ( md->flags & eSubsurfModifierFlag_SubsurfUv ) ) ;
+ default:
+ return EXPP_ReturnPyObjError( PyExc_KeyError,
+ "key not found" );
+ }
+}
+
+static int subsurf_setter( ModifierData *ptr, int type,
+ PyObject *value )
+{
+ SubsurfModifierData *md = (SubsurfModifierData *)ptr;
+
+ switch( type ) {
+ case EXPP_MOD_SUBSURF_TYPES:
+ return EXPP_setIValueRange( value, &md->subdivType, 0, 1, 'h' );
+ case EXPP_MOD_SUBSURF_LEVELS:
+ return EXPP_setIValueClamped( value, &md->levels, 1, 6, 'h' );
+ case EXPP_MOD_SUBSURF_RENDLEVELS:
+ return EXPP_setIValueClamped( value, &md->renderLevels, 1, 6, 'h' );
+ case EXPP_MOD_SUBSURF_OPTIMAL:
+ return EXPP_setBitfield( value, &md->flags,
+ eSubsurfModifierFlag_ControlEdges, 'h' );
+ case EXPP_MOD_SUBSURF_UV:
+ return EXPP_setBitfield( value, &md->flags,
+ eSubsurfModifierFlag_SubsurfUv, 'h' );
+ default:
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static PyObject *armature_getter( ModifierData *ptr, int type )
+{
+ ArmatureModifierData *md = (ArmatureModifierData *)ptr;
+
+ switch( type ) {
+ case EXPP_MOD_ARMATURE_OBJECT:
+ return Object_CreatePyObject( md->object );
+ case EXPP_MOD_ARMATURE_VERTGROUPS:
+ return PyBool_FromLong( ( long )( md->deformflag & 1 ) ) ;
+ case EXPP_MOD_ARMATURE_ENVELOPES:
+ return PyBool_FromLong( ( long )( md->deformflag & 2 ) ) ;
+ default:
+ return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static int armature_setter( ModifierData *ptr, int type, PyObject *value )
+{
+ ArmatureModifierData *md = (ArmatureModifierData *)ptr;
+
+ switch( type ) {
+ case EXPP_MOD_ARMATURE_OBJECT: {
+ Object *obj = (( BPy_Object * )value)->object;
+ if( !BPy_Object_Check( value ) || obj->type != OB_ARMATURE )
+ return EXPP_ReturnIntError( PyExc_TypeError,
+ "expected BPy armature object argument" );
+ md->object = obj;
+ return 0;
+ }
+ case EXPP_MOD_ARMATURE_VERTGROUPS:
+ return EXPP_setBitfield( value, &md->deformflag, 1, 'h' );
+ case EXPP_MOD_ARMATURE_ENVELOPES:
+ return EXPP_setBitfield( value, &md->deformflag, 2, 'h' );
+ default:
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static PyObject *lattice_getter( ModifierData *ptr, int type )
+{
+ LatticeModifierData *md = (LatticeModifierData *)ptr;
+
+ switch( type ) {
+ case EXPP_MOD_LATTICE_OBJECT:
+ return Object_CreatePyObject( md->object );
+ case EXPP_MOD_LATTICE_VERTGROUP:
+ return PyString_FromString( md->name ) ;
+ default:
+ return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static int lattice_setter( ModifierData *ptr, int type, PyObject *value )
+{
+ LatticeModifierData *md = (LatticeModifierData *)ptr;
+
+ switch( type ) {
+ case EXPP_MOD_LATTICE_OBJECT: {
+ Object *obj = (( BPy_Object * )value)->object;
+ if( !BPy_Object_Check( value ) || obj->type != OB_LATTICE )
+ return EXPP_ReturnIntError( PyExc_TypeError,
+ "expected BPy lattice object argument" );
+ md->object = obj;
+ break;
+ }
+ case EXPP_MOD_LATTICE_VERTGROUP: {
+ char *name = PyString_AsString( value );
+ if( !name )
+ return EXPP_ReturnIntError( PyExc_TypeError,
+ "expected string arg" );
+ BLI_strncpy( md->name, name, sizeof( md->name ) );
+ break;
+ }
+ default:
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+ }
+ return 0;
+}
+
+static PyObject *curve_getter( ModifierData *ptr, int type )
+{
+ CurveModifierData *md = (CurveModifierData *)ptr;
+
+ switch( type ) {
+ case EXPP_MOD_CURVE_OBJECT:
+ return Object_CreatePyObject( md->object );
+ case EXPP_MOD_CURVE_VERTGROUP:
+ return PyString_FromString( md->name ) ;
+ default:
+ return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static int curve_setter( ModifierData *ptr, int type, PyObject *value )
+{
+ CurveModifierData *md = (CurveModifierData *)ptr;
+
+ switch( type ) {
+ case EXPP_MOD_CURVE_OBJECT: {
+ Object *obj = (( BPy_Object * )value)->object;
+ if( !BPy_Object_Check( value ) || obj->type != OB_CURVE )
+ return EXPP_ReturnIntError( PyExc_TypeError,
+ "expected BPy lattice object argument" );
+ md->object = obj;
+ break;
+ }
+ case EXPP_MOD_CURVE_VERTGROUP: {
+ char *name = PyString_AsString( value );
+ if( !name )
+ return EXPP_ReturnIntError( PyExc_TypeError,
+ "expected string arg" );
+ BLI_strncpy( md->name, name, sizeof( md->name ) );
+ break;
+ }
+ default:
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+ }
+ return 0;
+}
+
+static PyObject *build_getter( ModifierData *ptr, int type )
+{
+ BuildModifierData *md = (BuildModifierData *)ptr;
+
+ switch( type ) {
+ case EXPP_MOD_BUILD_START:
+ return PyFloat_FromDouble( ( float )md->start );
+ case EXPP_MOD_BUILD_LENGTH:
+ return PyFloat_FromDouble( ( float )md->length );
+ case EXPP_MOD_BUILD_SEED:
+ return PyInt_FromLong( ( long )md->seed );
+ case EXPP_MOD_BUILD_RANDOMIZE:
+ return PyBool_FromLong( ( long )md->randomize ) ;
+ default:
+ return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static int build_setter( ModifierData *ptr, int type, PyObject *value )
+{
+ BuildModifierData *md = (BuildModifierData *)ptr;
+
+ switch( type ) {
+ case EXPP_MOD_BUILD_START:
+ return EXPP_setFloatClamped( value, &md->start, 1.0, MAXFRAMEF );
+ case EXPP_MOD_BUILD_LENGTH:
+ return EXPP_setFloatClamped( value, &md->length, 1.0, MAXFRAMEF );
+ case EXPP_MOD_BUILD_SEED:
+ return EXPP_setIValueClamped( value, &md->seed, 1, MAXFRAME, 'i' );
+ case EXPP_MOD_BUILD_RANDOMIZE:
+ return EXPP_setBitfield( value, &md->randomize, 1, 'i' );
+ default:
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static PyObject *mirror_getter( ModifierData *ptr, int type )
+{
+ MirrorModifierData *md = (MirrorModifierData *)ptr;
+
+ switch( type ) {
+ case EXPP_MOD_MIRROR_LIMIT:
+ return PyFloat_FromDouble( (double)md->tolerance );
+ case EXPP_MOD_MIRROR_FLAG:
+ return PyBool_FromLong( (long)( md->flag & MOD_MIR_CLIPPING ) ) ;
+ case EXPP_MOD_MIRROR_AXIS:
+ return PyInt_FromLong( (long)md->axis );
+ default:
+ return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static int mirror_setter( ModifierData *ptr, int type, PyObject *value )
+{
+ MirrorModifierData *md = (MirrorModifierData *)ptr;
+
+ switch( type ) {
+ case EXPP_MOD_MIRROR_LIMIT:
+ return EXPP_setFloatClamped( value, &md->tolerance, 0.0, 1.0 );
+ case EXPP_MOD_MIRROR_FLAG:
+ return EXPP_setBitfield( value, &md->flag, MOD_MIR_CLIPPING, 'i' );
+ case EXPP_MOD_MIRROR_AXIS:
+ return EXPP_setIValueRange( value, &md->axis, 0, 2, 'h' );
+ default:
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static PyObject *decimate_getter( ModifierData *ptr, int type )
+{
+ DecimateModifierData *md = (DecimateModifierData *)ptr;
+
+ if( type == EXPP_MOD_DECIMATE_RATIO )
+ return PyFloat_FromDouble( (double)md->percent );
+ else if( type == EXPP_MOD_DECIMATE_COUNT )
+ return PyInt_FromLong( (long)md->faceCount );
+ return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+}
+
+static int decimate_setter( ModifierData *ptr, int type, PyObject *value )
+{
+ DecimateModifierData *md = (DecimateModifierData *)ptr;
+
+ if( type == EXPP_MOD_DECIMATE_RATIO )
+ return EXPP_setFloatClamped( value, &md->percent, 0.0, 1.0 );
+ else if( type == EXPP_MOD_DECIMATE_COUNT )
+ return EXPP_ReturnIntError( PyExc_AttributeError,
+ "value is read-only" );
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+}
+
+static PyObject *wave_getter( ModifierData *ptr, int type )
+{
+ WaveModifierData *md = (WaveModifierData *)ptr;
+
+ switch( type ) {
+ case EXPP_MOD_WAVE_STARTX:
+ return PyFloat_FromDouble( (double)md->startx );
+ case EXPP_MOD_WAVE_STARTY:
+ return PyFloat_FromDouble( (double)md->starty );
+ case EXPP_MOD_WAVE_HEIGHT:
+ return PyFloat_FromDouble( (double)md->height );
+ case EXPP_MOD_WAVE_WIDTH:
+ return PyFloat_FromDouble( (double)md->width );
+ case EXPP_MOD_WAVE_NARROW:
+ return PyFloat_FromDouble( (double)md->narrow );
+ case EXPP_MOD_WAVE_SPEED:
+ return PyFloat_FromDouble( (double)md->speed );
+ case EXPP_MOD_WAVE_DAMP:
+ return PyFloat_FromDouble( (double)md->damp );
+ case EXPP_MOD_WAVE_LIFETIME:
+ return PyFloat_FromDouble( (double)md->lifetime );
+ case EXPP_MOD_WAVE_TIMEOFFS:
+ return PyFloat_FromDouble( (double)md->timeoffs );
+ case EXPP_MOD_WAVE_FLAG:
+ return PyInt_FromLong( (long)md->flag );
+ default:
+ return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static int wave_setter( ModifierData *ptr, int type, PyObject *value )
+{
+ WaveModifierData *md = (WaveModifierData *)ptr;
+
+ switch( type ) {
+ case EXPP_MOD_WAVE_STARTX:
+ return EXPP_setFloatClamped( value, &md->startx, -100.0, 100.0 );
+ case EXPP_MOD_WAVE_STARTY:
+ return EXPP_setFloatClamped( value, &md->starty, -100.0, 100.0 );
+ case EXPP_MOD_WAVE_HEIGHT:
+ return EXPP_setFloatClamped( value, &md->height, -2.0, 2.0 );
+ case EXPP_MOD_WAVE_WIDTH:
+ return EXPP_setFloatClamped( value, &md->width, 0.0, 5.0 );
+ case EXPP_MOD_WAVE_NARROW:
+ return EXPP_setFloatClamped( value, &md->width, 0.0, 5.0 );
+ case EXPP_MOD_WAVE_SPEED:
+ return EXPP_setFloatClamped( value, &md->speed, -2.0, 2.0 );
+ case EXPP_MOD_WAVE_DAMP:
+ return EXPP_setFloatClamped( value, &md->damp, -1000.0, 1000.0 );
+ case EXPP_MOD_WAVE_LIFETIME:
+ return EXPP_setFloatClamped( value, &md->lifetime, -1000.0, 1000.0 );
+ case EXPP_MOD_WAVE_TIMEOFFS:
+ return EXPP_setFloatClamped( value, &md->timeoffs, -1000.0, 1000.0 );
+ case EXPP_MOD_WAVE_FLAG:
+ return EXPP_setIValueRange( value, &md->flag, 0,
+ WAV_X+WAV_Y+WAV_CYCL, 'h' );
+ default:
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static PyObject *boolean_getter( ModifierData *ptr, int type )
+{
+ BooleanModifierData *md = (BooleanModifierData *)ptr;
+
+ if( type == EXPP_MOD_BOOLEAN_OBJECT )
+ return Object_CreatePyObject( md->object );
+ else if( type == EXPP_MOD_BOOLEAN_OPERATION )
+ return PyInt_FromLong( ( long )md->operation ) ;
+
+ return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+}
+
+static int boolean_setter( ModifierData *ptr, int type, PyObject *value )
+{
+ BooleanModifierData *md = (BooleanModifierData *)ptr;
+
+ if( type == EXPP_MOD_BOOLEAN_OBJECT ) {
+ Object *obj = (( BPy_Object * )value)->object;
+ if( !BPy_Object_Check( value ) || obj->type != OB_MESH )
+ return EXPP_ReturnIntError( PyExc_TypeError,
+ "expected BPy mesh object argument" );
+ md->object = obj;
+ return 0;
+ } else if( type == EXPP_MOD_BOOLEAN_OPERATION )
+ return EXPP_setIValueRange( value, &md->operation,
+ eBooleanModifierOp_Intersect, eBooleanModifierOp_Difference,
+ 'h' );
+
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+}
+
+static PyObject *hook_getter( ModifierData *ptr, int type )
+{
+ Py_RETURN_NONE;
+}
+
+static int hook_setter( ModifierData *ptr, int type, PyObject *value )
+{
+ return 0;
+}
+
+static PyObject *softbody_getter( ModifierData *ptr, int type )
+{
+ Py_RETURN_NONE;
+}
+
+static int softbody_setter( ModifierData *ptr, int type, PyObject *value )
+{
+ return 0;
+}
+
+static PyObject *array_getter( ModifierData *ptr, int type )
+{
+ Py_RETURN_NONE;
+}
+
+static int array_setter( ModifierData *ptr, int type, PyObject *value )
+{
+ return 0;
+}
+
+static PyObject *Modifier_getData( BPy_Modifier * self, PyObject * key )
+{
+ int type;
+
+ if( !PyInt_CheckExact( key ) )
+ return EXPP_ReturnPyObjError( PyExc_TypeError,
+ "expected string arg" );
+
+ type = PyInt_AsLong( key );
+ switch( type ) {
+ case EXPP_MOD_RENDER:
+ return EXPP_getBitfield( &self->md->mode, eModifierMode_Render, 'h' );
+ case EXPP_MOD_REALTIME:
+ return EXPP_getBitfield( &self->md->mode, eModifierMode_Realtime, 'h' );
+ case EXPP_MOD_EDITMODE:
+ return EXPP_getBitfield( &self->md->mode, eModifierMode_Editmode, 'h' );
+ case EXPP_MOD_ONCAGE:
+ return EXPP_getBitfield( &self->md->mode, eModifierMode_OnCage, 'h' );
+ default:
+ switch( self->md->type ) {
+ case eModifierType_Subsurf:
+ return subsurf_getter( self->md, type );
+ case eModifierType_Armature:
+ return armature_getter( self->md, type );
+ case eModifierType_Lattice:
+ return lattice_getter( self->md, type );
+ case eModifierType_Curve:
+ return curve_getter( self->md, type );
+ case eModifierType_Build:
+ return build_getter( self->md, type );
+ case eModifierType_Mirror:
+ return mirror_getter( self->md, type );
+ case eModifierType_Decimate:
+ return decimate_getter( self->md, type );
+ case eModifierType_Wave:
+ return wave_getter( self->md, type );
+ case eModifierType_Hook:
+ return hook_getter( self->md, type );
+ case eModifierType_Softbody:
+ return softbody_getter( self->md, type );
+ case eModifierType_Boolean:
+ return boolean_getter( self->md, type );
+ case eModifierType_Array:
+ return array_getter( self->md, type );
+ case eModifierType_None:
+ Py_RETURN_NONE;
+ }
+ }
+ return EXPP_ReturnPyObjError( PyExc_KeyError,
+ "unknown key or modifier type" );
+}
+
+static int Modifier_setData( BPy_Modifier * self, PyObject * key,
+ PyObject * arg )
+{
+ int type;
+
+ if( !PyNumber_Check( key ) )
+ return EXPP_ReturnIntError( PyExc_TypeError,
+ "expected string arg" );
+
+ type = PyInt_AsLong( key );
+ switch( self->md->type ) {
+ case eModifierType_Subsurf:
+ return subsurf_setter( self->md, type, arg );
+ case eModifierType_Armature:
+ return armature_setter( self->md, type, arg );
+ case eModifierType_Lattice:
+ return lattice_setter( self->md, type, arg );
+ case eModifierType_Curve:
+ return curve_setter( self->md, type, arg );
+ case eModifierType_Build:
+ return build_setter( self->md, type, arg );
+ case eModifierType_Mirror:
+ return mirror_setter( self->md, type, arg );
+ case eModifierType_Decimate:
+ return decimate_setter( self->md, type, arg );
+ case eModifierType_Wave:
+ return wave_setter( self->md, type, arg );
+ case eModifierType_Hook:
+ return hook_setter( self->md, type, arg );
+ case eModifierType_Softbody:
+ return softbody_setter( self->md, type, arg );
+ case eModifierType_Boolean:
+ return boolean_setter( self->md, type, arg );
+ case eModifierType_Array:
+ return array_setter( self->md, type, arg );
+ case eModifierType_None:
+ return 0;
+ }
+ return EXPP_ReturnIntError( PyExc_RuntimeError,
+ "unsupported modifier type" );
+}
+
+/*****************************************************************************/
+/* Function: Modifier_repr */
+/* Description: This is a callback function for the BPy_Modifier type. It */
+/* builds a meaningful string to represent modifier objects. */
+/*****************************************************************************/
+static PyObject *Modifier_repr( BPy_Modifier * self )
+{
+ ModifierTypeInfo *mti = modifierType_getInfo(self->md->type);
+ return PyString_FromFormat( "[Modifier \"%s\"]", mti->name );
+}
+
+/* Three Python Modifier_Type helper functions needed by the Object module: */
+
+/*****************************************************************************/
+/* Function: Modifier_CreatePyObject */
+/* Description: This function will create a new BPy_Modifier from an */
+/* existing Blender modifier structure. */
+/*****************************************************************************/
+PyObject *Modifier_CreatePyObject( Object *obj, ModifierData * md )
+{
+ BPy_Modifier *pymod;
+ pymod = ( BPy_Modifier * ) PyObject_NEW( BPy_Modifier, &Modifier_Type );
+ if( !pymod )
+ return EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "couldn't create BPy_Modifier object" );
+ pymod->md = md;
+ pymod->obj = obj;
+ return ( PyObject * ) pymod;
+}
+
+/*****************************************************************************/
+/* Function: Modifier_CheckPyObject */
+/* Description: This function returns true when the given PyObject is of the */
+/* type Modifier. Otherwise it will return false. */
+/*****************************************************************************/
+int Modifier_CheckPyObject( PyObject * pyobj )
+{
+ return ( pyobj->ob_type == &Modifier_Type );
+}
+
+/*****************************************************************************/
+/* Function: Modifier_FromPyObject */
+/* Description: This function returns the Blender modifier from the given */
+/* PyObject. */
+/*****************************************************************************/
+ModifierData *Modifier_FromPyObject( PyObject * pyobj )
+{
+ return ( ( BPy_Modifier * ) pyobj )->md;
+}
+
+/*****************************************************************************/
+/* Modifier Sequence wrapper */
+/*****************************************************************************/
+
+/*
+ * Initialize the interator
+ */
+
+static PyObject *ModSeq_getIter( BPy_ModSeq * self )
+{
+ self->iter = (ModifierData *)self->obj->modifiers.first;
+ return EXPP_incr_ret ( (PyObject *) self );
+}
+
+/*
+ * Get the next Modifier
+ */
+
+static PyObject *ModSeq_nextIter( BPy_ModSeq * self )
+{
+ ModifierData *this = self->iter;
+ if( this ) {
+ self->iter = this->next;
+ return Modifier_CreatePyObject( self->obj, this );
+ }
+
+ return EXPP_ReturnPyObjError( PyExc_StopIteration,
+ "iterator at end" );
+}
+
+/* return the number of modifiers */
+
+static int ModSeq_length( BPy_ModSeq * self )
+{
+ return BLI_countlist( &self->obj->modifiers );
+}
+
+/* return a modifier */
+
+static PyObject *ModSeq_item( BPy_ModSeq * self, int i )
+{
+ ModifierData *md = NULL;
+
+ /* if index is negative, start counting from the end of the list */
+ if( i < 0 )
+ i += ModSeq_length( self );
+
+ /* skip through the list until we get the modifier or end of list */
+
+ for( md = self->obj->modifiers.first; i && md; --i ) md = md->next;
+
+ if( md )
+ return Modifier_CreatePyObject( self->obj, md );
+ else
+ return EXPP_ReturnPyObjError( PyExc_IndexError,
+ "array index out of range" );
+}
+
+/*****************************************************************************/
+/* Python BPy_ModSeq sequence table: */
+/*****************************************************************************/
+static PySequenceMethods ModSeq_as_sequence = {
+ ( inquiry ) ModSeq_length, /* sq_length */
+ ( binaryfunc ) 0, /* sq_concat */
+ ( intargfunc ) 0, /* sq_repeat */
+ ( intargfunc ) ModSeq_item, /* sq_item */
+ ( intintargfunc ) 0, /* sq_slice */
+ ( intobjargproc ) 0, /* sq_ass_item */
+ ( intintobjargproc ) 0, /* sq_ass_slice */
+ ( objobjproc ) 0, /* sq_contains */
+ ( binaryfunc ) 0, /* sq_inplace_concat */
+ ( intargfunc ) 0, /* sq_inplace_repeat */
+};
+
+/* create a new modifier at the end of the list */
+
+static PyObject *ModSeq_append( BPy_ModSeq *self, PyObject *args )
+{
+ int type;
+
+ if( !PyArg_ParseTuple( args, "i", &type ) )
+ EXPP_ReturnPyObjError( PyExc_TypeError, "expected int argument" );
+
+ BLI_addtail(&self->obj->modifiers, modifier_new(type));
+ return Modifier_CreatePyObject( self->obj, self->obj->modifiers.last );
+}
+
+/*
+ * simple method to implement pseudo module constants
+ */
+
+static PyObject *ModSeq_typeConst( BPy_Modifier *self_unused, void *type )
+{
+ return PyInt_FromLong( (long)type );
+}
+
+/*****************************************************************************/
+/* Python BPy_ModSeq attributes get/set structure: */
+/*****************************************************************************/
+static PyGetSetDef BPy_ModSeq_getseters[] = {
+ {"SUBSURF",
+ (getter)ModSeq_typeConst, (setter)NULL,
+ NULL, (void *)eModifierType_Subsurf},
+ {"ARMATURE",
+ (getter)ModSeq_typeConst, (setter)NULL,
+ NULL, (void *)eModifierType_Armature},
+ {"LATTICE",
+ (getter)ModSeq_typeConst, (setter)NULL,
+ NULL, (void *)eModifierType_Lattice},
+ {"CURVE",
+ (getter)ModSeq_typeConst, (setter)NULL,
+ NULL, (void *)eModifierType_Curve},
+ {"BUILD",
+ (getter)ModSeq_typeConst, (setter)NULL,
+ NULL, (void *)eModifierType_Build},
+ {"MIRROR",
+ (getter)ModSeq_typeConst, (setter)NULL,
+ NULL, (void *)eModifierType_Mirror},
+ {"DECIMATE",
+ (getter)ModSeq_typeConst, (setter)NULL,
+ NULL, (void *)eModifierType_Decimate},
+ {"WAVE",
+ (getter)ModSeq_typeConst, (setter)NULL,
+ NULL, (void *)eModifierType_Wave},
+ {"BOOLEAN",
+ (getter)ModSeq_typeConst, (setter)NULL,
+ NULL, (void *)eModifierType_Boolean},
+ {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
+};
+
+/*****************************************************************************/
+/* Python BPy_ModSeq methods table: */
+/*****************************************************************************/
+static PyMethodDef BPy_ModSeq_methods[] = {
+ /* name, method, flags, doc */
+ {"append", ( PyCFunction ) ModSeq_append, METH_VARARGS,
+ "add a new modifier"},
+ {NULL, NULL, 0, NULL}
+};
+
+/*****************************************************************************/
+/* Python ModSeq_Type structure definition: */
+/*****************************************************************************/
+PyTypeObject ModSeq_Type = {
+ PyObject_HEAD_INIT( NULL ) /* required py macro */
+ 0, /* ob_size */
+ /* For printing, in format "<module>.<name>" */
+ "Blender Modifier Sequence",/* char *tp_name; */
+ sizeof( BPy_ModSeq ), /* int tp_basicsize; */
+ 0, /* tp_itemsize; For allocation */
+
+ /* Methods to implement standard operations */
+
+ ( destructor ) PyObject_Del,/* 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; */
+ &ModSeq_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 )ModSeq_getIter, /* getiterfunc tp_iter; */
+ ( iternextfunc )ModSeq_nextIter, /* iternextfunc tp_iternext; */
+
+ /*** Attribute descriptor and subclassing stuff ***/
+ BPy_ModSeq_methods, /* struct PyMethodDef *tp_methods; */
+ NULL, /* struct PyMemberDef *tp_members; */
+ BPy_ModSeq_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
+};
+
+/*****************************************************************************/
+/* Function: ModSeq_CreatePyObject */
+/* Description: This function will create a new BPy_ModSeq from an existing */
+/* ListBase structure. */
+/*****************************************************************************/
+PyObject *ModSeq_CreatePyObject( Object *obj )
+{
+ BPy_ModSeq *pymod;
+ pymod = ( BPy_ModSeq * ) PyObject_NEW( BPy_ModSeq, &ModSeq_Type );
+ if( !pymod )
+ return EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "couldn't create BPy_ModSeq object" );
+ pymod->obj = obj;
+ return ( PyObject * ) pymod;
+}