From 8001a8b409833c3ff4e1dce36e9bebc36fb3e859 Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Sun, 23 Apr 2006 02:34:50 +0000 Subject: [PATCH] ===Python API=== Initial commit for new Modifier API. Probably does about 70-75% of what it should, but it's a start. --- source/blender/include/butspace.h | 4 + source/blender/python/api2_2x/Modifier.c | 1171 +++++++++++++++++ source/blender/python/api2_2x/Modifier.h | 70 + source/blender/python/api2_2x/Object.c | 3 + source/blender/python/api2_2x/Types.c | 8 + .../blender/python/api2_2x/doc/API_intro.py | 7 +- source/blender/python/api2_2x/doc/Modifier.py | 122 ++ source/blender/src/buttons_editing.c | 36 +- 8 files changed, 1406 insertions(+), 15 deletions(-) create mode 100644 source/blender/python/api2_2x/Modifier.c create mode 100644 source/blender/python/api2_2x/Modifier.h create mode 100644 source/blender/python/api2_2x/doc/Modifier.py diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index b5b0e5ac39e..d23b38fe69e 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -75,6 +75,10 @@ extern void autocomplete_vgroup(char *str, void *arg_v); extern void effects_panels(void); extern void do_effects_panels(unsigned short event); +/* modifiers */ +extern int mod_moveUp(void *ob_v, void *md_v); +extern int mod_moveDown(void *ob_v, void *md_v); + /* editing */ extern void editing_panels(void); extern void do_common_editbuts(unsigned short event); 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 "." */ + "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 "." */ + "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; +} diff --git a/source/blender/python/api2_2x/Modifier.h b/source/blender/python/api2_2x/Modifier.h new file mode 100644 index 00000000000..15b2c93f1df --- /dev/null +++ b/source/blender/python/api2_2x/Modifier.h @@ -0,0 +1,70 @@ +/* + * $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 ***** +*/ + +#ifndef EXPP_MODIFIER_H +#define EXPP_MODIFIER_H + +#include +#include "DNA_object_types.h" +#include "DNA_modifier_types.h" +#include "DNA_listBase.h" + +/*****************************************************************************/ +/* Python BPy_Modifier structure definition: */ +/*****************************************************************************/ +typedef struct { + PyObject_HEAD /* required macro */ + Object *obj; + ModifierData *md; +} BPy_Modifier; + +extern PyTypeObject Modifier_Type; + +#define BPy_Modifier_Check(v) ((v)->ob_type == &Modifier_Type) /* for type checking */ + +/* + * prototypes + */ + +PyObject *Modifier_CreatePyObject( Object *obj, ModifierData *md ); +ModifierData *Modifier_FromPyObject( PyObject * py_obj ); +int Modifier_CheckPyObject( PyObject * py_obj ); + +typedef struct { + PyObject_HEAD /* required macro */ + Object *obj; + ModifierData *iter; +} BPy_ModSeq; + +PyObject *ModSeq_CreatePyObject( Object *obj ); + +#endif /* EXPP_MODIFIER_H */ diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index ad29508f908..5fe26d91f14 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -108,6 +108,7 @@ struct rctf; #include "Effect.h" #include "Pose.h" #include "Group.h" +#include "Modifier.h" #include "gen_utils.h" #include "BIF_editkey.h" @@ -3513,6 +3514,8 @@ static PyObject *Object_getAttr( BPy_Object * obj, char *name ) return Object_getDupliNoSpeed( obj ); if( StringEqual( name, "drawSize" ) ) return ( PyFloat_FromDouble( object->empty_drawsize ) ); + if( StringEqual( name, "modifiers" ) ) + return ModSeq_CreatePyObject( obj->object ); /* not an attribute, search the methods table */ return Py_FindMethod( BPy_Object_methods, ( PyObject * ) obj, name ); diff --git a/source/blender/python/api2_2x/Types.c b/source/blender/python/api2_2x/Types.c index 3bec07ece19..858e733fb61 100644 --- a/source/blender/python/api2_2x/Types.c +++ b/source/blender/python/api2_2x/Types.c @@ -59,6 +59,7 @@ extern PyTypeObject property_Type; extern PyTypeObject buffer_Type, constant_Type, euler_Type; extern PyTypeObject matrix_Type, quaternion_Type, rgbTuple_Type, vector_Type; extern PyTypeObject point_Type; +extern PyTypeObject Modifier_Type, ModSeq_Type; char M_Types_doc[] = "The Blender Types module\n\n\ This module is a dictionary of all Blender Python types"; @@ -121,6 +122,9 @@ void types_InitAll( void ) vector_Type.ob_type = &PyType_Type; property_Type.ob_type = &PyType_Type; point_Type.ob_type = &PyType_Type; + PyType_Ready( &Modifier_Type ); + PyType_Ready( &ModSeq_Type ); + } /*****************************************************************************/ @@ -223,6 +227,10 @@ PyObject *Types_Init( void ) ( PyObject * ) &property_Type ); PyDict_SetItemString( dict, "pointType", ( PyObject * ) &point_Type ); + PyDict_SetItemString( dict, "ModifierType", + ( PyObject * ) &Modifier_Type ); + PyDict_SetItemString( dict, "ModSeqType", + ( PyObject * ) &ModSeq_Type ); return submodule; } diff --git a/source/blender/python/api2_2x/doc/API_intro.py b/source/blender/python/api2_2x/doc/API_intro.py index 60d4b79c573..e255a58dd1f 100644 --- a/source/blender/python/api2_2x/doc/API_intro.py +++ b/source/blender/python/api2_2x/doc/API_intro.py @@ -15,7 +15,7 @@ The Blender Python API Reference ----------- - L{Armature} - L{NLA} - - L{BezTriple} + - L{BezTriple} (*) - L{BGL} - L{Camera} - L{Curve} @@ -23,8 +23,8 @@ The Blender Python API Reference - L{Effect} - L{Group} (*) - L{Image} - - L{Ipo} - - L{IpoCurve} + - L{Ipo} (*) + - L{IpoCurve} (*) - L{Key} (*) - L{Lamp} - L{Lattice} @@ -33,6 +33,7 @@ The Blender Python API Reference - L{Mathutils} (*) - L{Mesh} (*) - L{Metaball} + - L{Modifier} (*) - L{NMesh} (*) - L{Noise} - L{Object} (*) diff --git a/source/blender/python/api2_2x/doc/Modifier.py b/source/blender/python/api2_2x/doc/Modifier.py new file mode 100644 index 00000000000..54f50a7b034 --- /dev/null +++ b/source/blender/python/api2_2x/doc/Modifier.py @@ -0,0 +1,122 @@ +# Blender.Modifier module and the Modifier PyType object + +""" +The Blender.Modifier submodule + +B{New}: + - provides access to Blender's modifier stack + +This module provides access to the Modifier Data in Blender. + +Example:: + from Blender import * + + ob = Object.Get('Cube') # retrieve an object + mods = ob.modifiers # get the object's modifiers + for mod in mods: + print mod,mod.name # print each modifier and its name + mod = mods.append(mod.SUBSURF) # add a new subsurf modifier + mod[mod.keys().LEVELS] = 3 # set subsurf subdivision levels to 3 +""" + + +class ModSeq: + """ + The ModSeq object + ================= + This object provides access to list of modifiers for a particular object. + """ + + def __getitem__(index): + """ + This operator returns one of the object's modifiers. + @type index: int + @return: an Modifier object + @rtype: Modifier + @raise KeyError: index was out of range + """ + + def __len__(): + """ + Returns the number of modifiers in the object's modifier stack. + @return: number of Modifiers + @rtype: int + """ + + def append(type): + """ + Appends a new modifier to the end of the object's modifier stack. + @type type: a constant specifying the type of modifier to create + @rtype: Modifier + @return: the new Modifier + """ + +class Modifier: + """ + The Modifier object + =================== + This object provides access to a modifier for a particular object. + """ + + def __getitem__(key): + """ + This operator returns one of the modifier's data attributes. + @type key: value from modifier's L{key()} constant + @return: the requested data + @rtype: varies + @raise KeyError: the key does not exist for the modifier + """ + + def __setitem__(key): + """ + This operator modifiers one of the modifier's data attributes. + @type key: value from modifier's L{key()} constant + @raise KeyError: the key does not exist for the modifier + """ + + def up(): + """ + Moves the modifier up in the object's modifier stack. + @rtype: PyNone + @raise RuntimeError: request to move above another modifier requiring + original data + """ + + def down(): + """ + Moves the modifier down in the object's modifier stack. + @rtype: PyNone + @raise RuntimeError: request to move modifier beyond a non-deforming + modifier + """ + + def keys(): + """ + Get the sequence of keys for the modifier. + For example, a subsurf modifier can be accessed by:: + from Blender import * + + ob = Object.Get('Cube') # retrieve an object + mod = ob.modifiers[0] # get the object's modifiers + mod[mod.keys().LEVELS] = 3 # set subsurf subdivision levels to 3 + + The valid keys are: + - Common keys (all modifiers contain these keys): RENDER, REALTIME, + EDITMODE, ONCAGE + - Armature keys: ENVELOPES, OBJECT, VERTGROUPS + - Boolean keys: OBJECT, OPERATION + - Build keys: START, LENGTH, SEED, RANDOMIZE + - Curve keys: OBJECT, VERTGROUP + - Decimate keys: RATIO, FACE_COUNT + - Lattice keys: OBJECT, VERTGROUP + - Mirror keys: LIMIT, FLAG, AXIS + - Subsurf keys: TYPE, LEVELS, RENDER_LEVELS, OPTIMAL, UV + - Wave keys: START_X, START_Y, HEIGHT, WIDTH, NARROW, SPEED, DAMP, + LIFETIME, TIME_OFFS, FLAG + + @rtype: PyConstant + @return: the keys for the modifier + @raise RuntimeError: request to move modifier beyond a non-deforming + modifier + """ + diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 69085ad1c9b..f96954786dc 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -812,7 +812,7 @@ static void modifiers_del(void *ob_v, void *md_v) BIF_undo_push("Del modifier"); } -static void modifiers_moveUp(void *ob_v, void *md_v) +int mod_moveUp(void *ob_v, void *md_v) { Object *ob = ob_v; ModifierData *md = md_v; @@ -823,20 +823,26 @@ static void modifiers_moveUp(void *ob_v, void *md_v) if (mti->type!=eModifierTypeType_OnlyDeform) { ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type); - if (nmti->flags&eModifierTypeFlag_RequiresOriginalData) { - error("Cannot move above a modifier requiring original data."); - return; - } + if (nmti->flags&eModifierTypeFlag_RequiresOriginalData) + return -1; } BLI_remlink(&ob->modifiers, md); BLI_insertlink(&ob->modifiers, md->prev->prev, md); } - BIF_undo_push("Move modifier"); + return 0; } -static void modifiers_moveDown(void *ob_v, void *md_v) +static void modifiers_moveUp(void *ob_v, void *md_v) +{ + if( mod_moveUp( ob_v, md_v ) ) + error("Cannot move above a modifier requiring original data."); + else + BIF_undo_push("Move modifier"); +} + +int mod_moveDown(void *ob_v, void *md_v) { Object *ob = ob_v; ModifierData *md = md_v; @@ -847,17 +853,23 @@ static void modifiers_moveDown(void *ob_v, void *md_v) if (mti->flags&eModifierTypeFlag_RequiresOriginalData) { ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type); - if (nmti->type!=eModifierTypeType_OnlyDeform) { - error("Cannot move beyond a non-deforming modifier."); - return; - } + if (nmti->type!=eModifierTypeType_OnlyDeform) + return -1; } BLI_remlink(&ob->modifiers, md); BLI_insertlink(&ob->modifiers, md->next, md); } - BIF_undo_push("Move modifier"); + return 0; +} + +static void modifiers_moveDown(void *ob_v, void *md_v) +{ + if( mod_moveDown( ob_v, md_v ) ) + error("Cannot move beyond a non-deforming modifier."); + else + BIF_undo_push("Move modifier"); } static void modifier_testLatticeObj(char *name, ID **idpp)