1237 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1237 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* 
 | 
						|
 * $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): Jacques Guignot
 | 
						|
 *
 | 
						|
 * ***** END GPL/BL DUAL LICENSE BLOCK *****
 | 
						|
 */
 | 
						|
 | 
						|
#include "Metaball.h" /*This must come first*/
 | 
						|
 | 
						|
#include "BKE_main.h"
 | 
						|
#include "BKE_global.h"
 | 
						|
#include "BKE_mball.h"
 | 
						|
#include "BKE_library.h"
 | 
						|
#include "BLI_blenlib.h"
 | 
						|
#include "BLI_arithb.h" /* for quat normal */
 | 
						|
#include "DNA_object_types.h"
 | 
						|
#include "Mathutils.h"
 | 
						|
#include "Material.h"
 | 
						|
#include "gen_utils.h"
 | 
						|
 | 
						|
/* for dealing with materials */
 | 
						|
#include "MEM_guardedalloc.h"
 | 
						|
#include "BKE_material.h"
 | 
						|
 | 
						|
/* checks for the metaelement being removed */
 | 
						|
#define METAELEM_DEL_CHECK_PY(bpy_meta_elem) if (!(bpy_meta_elem->metaelem)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "Metaball has been removed" ) );
 | 
						|
#define METAELEM_DEL_CHECK_INT(bpy_meta_elem) if (!(bpy_meta_elem->metaelem)) return ( EXPP_ReturnIntError( PyExc_RuntimeError, "Metaball has been removed" ) );
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Python API function prototypes for the Metaball module.                   */
 | 
						|
/*****************************************************************************/
 | 
						|
static PyObject *M_Metaball_New( PyObject * self, PyObject * args );
 | 
						|
static PyObject *M_Metaball_Get( PyObject * self, PyObject * args );
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* The following string definitions are used for documentation strings.      */
 | 
						|
/* In Python these will be written to the console when doing a               */
 | 
						|
/* Blender.Metaball.__doc__                                                  */
 | 
						|
/*****************************************************************************/
 | 
						|
static char M_Metaball_doc[] =
 | 
						|
	"The Blender Metaball module\n\n\nMetaballs are primitive shapes\
 | 
						|
 such as balls, pipes, boxes and planes,\
 | 
						|
 that can join each other to create smooth,\
 | 
						|
 organic volumes\n. The shapes themseves are called\
 | 
						|
 'Metaelements' and can be accessed from the Metaball module.";
 | 
						|
 | 
						|
static char M_Metaball_New_doc[] = "Creates new metaball object data";
 | 
						|
 | 
						|
static char M_Metaball_Get_doc[] = "Retreives an existing metaball object data";
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Python method structure definition for Blender.Metaball module:           */
 | 
						|
/*****************************************************************************/
 | 
						|
struct PyMethodDef M_Metaball_methods[] = {
 | 
						|
	{"New", M_Metaball_New, METH_VARARGS, M_Metaball_New_doc},
 | 
						|
	{"Get", M_Metaball_Get, METH_VARARGS, M_Metaball_Get_doc},
 | 
						|
	{NULL, NULL, 0, NULL}
 | 
						|
};
 | 
						|
 | 
						|
static PyObject *M_MetaElem_TypesDict( void )
 | 
						|
{
 | 
						|
	PyObject *Types = PyConstant_New(  );
 | 
						|
 | 
						|
	if( Types ) {
 | 
						|
		BPy_constant *d = ( BPy_constant * ) Types;
 | 
						|
 | 
						|
		PyConstant_Insert( d, "BALL",	PyInt_FromLong( MB_BALL ) );
 | 
						|
		/* PyConstant_Insert( d, "TUBEX",	PyInt_FromLong( MB_TUBEX ) );  - DEPRICATED */
 | 
						|
		/* PyConstant_Insert( d, "TUBEY",	PyInt_FromLong( MB_TUBEY ) );  - DEPRICATED */
 | 
						|
		/* PyConstant_Insert( d, "TUBEZ",	PyInt_FromLong( MB_TUBEZ ) );  - DEPRICATED */
 | 
						|
		PyConstant_Insert( d, "TUBE",	PyInt_FromLong( MB_TUBE ) );
 | 
						|
		PyConstant_Insert( d, "PLANE",	PyInt_FromLong( MB_PLANE ) );
 | 
						|
		PyConstant_Insert( d, "ELIPSOID",PyInt_FromLong( MB_ELIPSOID ) );
 | 
						|
		PyConstant_Insert( d, "CUBE",	PyInt_FromLong( MB_CUBE ) );
 | 
						|
	}
 | 
						|
 | 
						|
	return Types;
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Python BPy_Metaball methods declarations:                                */
 | 
						|
/*****************************************************************************/
 | 
						|
static PyObject *Metaball_getElements( BPy_Metaball * self );
 | 
						|
static PyObject *Metaball_getName( BPy_Metaball * self );
 | 
						|
static int Metaball_setName( BPy_Metaball * self, PyObject * value );
 | 
						|
static PyObject *Metaball_getMaterials( BPy_Metaball * self );
 | 
						|
static int Metaball_setMaterials( BPy_Metaball * self, PyObject * value );
 | 
						|
static PyObject *Metaball_getWiresize( BPy_Metaball * self );
 | 
						|
static int Metaball_setWiresize( BPy_Metaball * self, PyObject * value );
 | 
						|
static PyObject *Metaball_getRendersize( BPy_Metaball * self );
 | 
						|
static int Metaball_setRendersize( BPy_Metaball * self, PyObject * value);
 | 
						|
static PyObject *Metaball_getThresh( BPy_Metaball * self );
 | 
						|
static int Metaball_setThresh( BPy_Metaball * self, PyObject * args );
 | 
						|
static PyObject *Metaball_copy( BPy_Metaball * self );
 | 
						|
static PyObject *Metaball_getUsers( BPy_Metaball * self );
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Python BPy_Metaball methods table:                                       */
 | 
						|
/*****************************************************************************/
 | 
						|
static PyMethodDef BPy_Metaball_methods[] = {
 | 
						|
	/* name, method, flags, doc */
 | 
						|
	{"__copy__", ( PyCFunction ) Metaball_copy,
 | 
						|
	 METH_NOARGS, "() - Return a copy of this metaball"},
 | 
						|
	{NULL, NULL, 0, NULL}
 | 
						|
};
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Python BPy_Metaelem methods table:                                        */
 | 
						|
/*****************************************************************************/
 | 
						|
static PyMethodDef BPy_Metaelem_methods[] = {
 | 
						|
	{NULL, NULL, 0, NULL}
 | 
						|
};
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Python Metaball_Type callback function prototypes:                       */
 | 
						|
/*****************************************************************************/
 | 
						|
static void Metaball_dealloc( BPy_Metaball * self );
 | 
						|
static PyObject *Metaball_repr( BPy_Metaball * self );
 | 
						|
static int Metaball_compare( BPy_Metaball * a, BPy_Metaball * b );
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Python Metaelem_Type callback function prototypes:                        */
 | 
						|
/*****************************************************************************/
 | 
						|
static void Metaelem_dealloc( BPy_Metaelem * self );
 | 
						|
static PyObject *Metaelem_repr( BPy_Metaelem * self );
 | 
						|
static int Metaelem_compare( BPy_Metaelem * a, BPy_Metaelem * b );
 | 
						|
 | 
						|
static PyObject *Metaelem_getType( BPy_Metaelem *self );
 | 
						|
static int Metaelem_setType( BPy_Metaelem * self,  PyObject * args );
 | 
						|
static PyObject *Metaelem_getCoord( BPy_Metaelem * self );
 | 
						|
static int Metaelem_setCoord( BPy_Metaelem * self,  VectorObject * value );
 | 
						|
static PyObject *Metaelem_getDims( BPy_Metaelem * self );
 | 
						|
static int Metaelem_setDims( BPy_Metaelem * self,  VectorObject * value );
 | 
						|
static PyObject *Metaelem_getQuat( BPy_Metaelem * self );
 | 
						|
static int Metaelem_setQuat( BPy_Metaelem * self,  QuaternionObject * value );
 | 
						|
static PyObject *Metaelem_getStiffness( BPy_Metaelem * self );
 | 
						|
static int Metaelem_setStiffness( BPy_Metaelem * self,  PyObject * value );
 | 
						|
static PyObject *Metaelem_getRadius( BPy_Metaelem * self );
 | 
						|
static int Metaelem_setRadius( BPy_Metaelem * self,  PyObject * value );
 | 
						|
 | 
						|
static PyObject *Metaelem_getMFlagBits( BPy_Metaelem * self, void * type );
 | 
						|
static int Metaelem_setMFlagBits( BPy_Metaelem * self, PyObject * value, void * type );
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Python attributes get/set structure:                                      */
 | 
						|
/*****************************************************************************/
 | 
						|
static PyGetSetDef BPy_Metaball_getseters[] = {
 | 
						|
	{"name",
 | 
						|
	 (getter)Metaball_getName, (setter)Metaball_setName,
 | 
						|
	 "Metaball name",
 | 
						|
	 NULL},
 | 
						|
	{"users",
 | 
						|
	 (getter)Metaball_getUsers, (setter)NULL,
 | 
						|
	 "Number of metaball users",
 | 
						|
	 NULL},
 | 
						|
	{"materials",
 | 
						|
	 (getter)Metaball_getMaterials, (setter)Metaball_setMaterials,
 | 
						|
	 "Number of metaball users",
 | 
						|
	 NULL},
 | 
						|
	{"elements",
 | 
						|
	 (getter)Metaball_getElements, (setter)NULL,
 | 
						|
	 "Elements in this metaball",
 | 
						|
	 NULL},
 | 
						|
	{"wiresize",
 | 
						|
	 (getter)Metaball_getWiresize, (setter)Metaball_setWiresize,
 | 
						|
	 "The density to draw the metaball in the 3D view",
 | 
						|
	 NULL},
 | 
						|
	{"rendersize",
 | 
						|
	 (getter)Metaball_getRendersize, (setter)Metaball_setRendersize,
 | 
						|
	 "The density to render wire",
 | 
						|
	 NULL},
 | 
						|
	{"thresh",
 | 
						|
	 (getter)Metaball_getThresh, (setter)Metaball_setThresh,
 | 
						|
	 "The density to render wire",
 | 
						|
	 NULL},
 | 
						|
	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Python TypeMetaball structure definition:                                     */
 | 
						|
/*****************************************************************************/
 | 
						|
PyTypeObject Metaball_Type = {
 | 
						|
	PyObject_HEAD_INIT( NULL )  /* required py macro */
 | 
						|
	0,                          /* ob_size */
 | 
						|
	/*  For printing, in format "<module>.<name>" */
 | 
						|
	"Blender Metaball",             /* char *tp_name; */
 | 
						|
	sizeof( BPy_Metaball ),         /* int tp_basicsize; */
 | 
						|
	0,                          /* tp_itemsize;  For allocation */
 | 
						|
 | 
						|
	/* Methods to implement standard operations */
 | 
						|
 | 
						|
	( destructor ) Metaball_dealloc,/* destructor tp_dealloc; */
 | 
						|
	NULL,                       /* printfunc tp_print; */
 | 
						|
	NULL,                       /* getattrfunc tp_getattr; */
 | 
						|
	NULL,                       /* setattrfunc tp_setattr; */
 | 
						|
	( cmpfunc ) Metaball_compare,   /* cmpfunc tp_compare; */
 | 
						|
	( reprfunc ) Metaball_repr,     /* reprfunc tp_repr; */
 | 
						|
 | 
						|
	/* Method suites for standard classes */
 | 
						|
 | 
						|
	NULL,                       /* PyNumberMethods *tp_as_number; */
 | 
						|
	NULL,                       /* 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 */
 | 
						|
	NULL,                       /* getiterfunc tp_iter; */
 | 
						|
	NULL,                       /* iternextfunc tp_iternext; */
 | 
						|
 | 
						|
  /*** Attribute descriptor and subclassing stuff ***/
 | 
						|
	BPy_Metaball_methods,           /* struct PyMethodDef *tp_methods; */
 | 
						|
	NULL,                       /* struct PyMemberDef *tp_members; */
 | 
						|
	BPy_Metaball_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
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
static PyGetSetDef BPy_Metaelem_getseters[] = {
 | 
						|
	{"type",
 | 
						|
	 (getter)Metaelem_getType, (setter)Metaelem_setType,
 | 
						|
	 "Metaelem Type",
 | 
						|
	 NULL},
 | 
						|
	{"co",
 | 
						|
	 (getter)Metaelem_getCoord, (setter)Metaelem_setCoord,
 | 
						|
	 "Metaelem Location",
 | 
						|
	 NULL},
 | 
						|
	{"quat",
 | 
						|
	 (getter)Metaelem_getQuat, (setter)Metaelem_setQuat,
 | 
						|
	 "Metaelem Rotation Quat",
 | 
						|
	 NULL},
 | 
						|
	{"dims",
 | 
						|
	 (getter)Metaelem_getDims, (setter)Metaelem_setDims,
 | 
						|
	 "Metaelem Dimensions",
 | 
						|
	 NULL},
 | 
						|
	{"stiffness",
 | 
						|
	 (getter)Metaelem_getStiffness, (setter)Metaelem_setStiffness,
 | 
						|
	 "MetaElem stiffness",
 | 
						|
	 NULL},
 | 
						|
	{"radius",
 | 
						|
	 (getter)Metaelem_getRadius, (setter)Metaelem_setRadius,
 | 
						|
	 "The radius of the MetaElem",
 | 
						|
	 NULL},
 | 
						|
	{"negative",
 | 
						|
	 (getter)Metaelem_getMFlagBits, (setter)Metaelem_setMFlagBits,
 | 
						|
	 "The density to render wire",
 | 
						|
	 (void *)MB_NEGATIVE},
 | 
						|
	{"hide",
 | 
						|
	 (getter)Metaelem_getMFlagBits, (setter)Metaelem_setMFlagBits,
 | 
						|
	 "The density to render wire",
 | 
						|
	 (void *)MB_HIDE},
 | 
						|
	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Python TypeMetaelem structure definition:                                     */
 | 
						|
/*****************************************************************************/
 | 
						|
PyTypeObject Metaelem_Type = {
 | 
						|
	PyObject_HEAD_INIT( NULL )  /* required py macro */
 | 
						|
	0,                          /* ob_size */
 | 
						|
	/*  For printing, in format "<module>.<name>" */
 | 
						|
	"Blender Metaelem",             /* char *tp_name; */
 | 
						|
	sizeof( BPy_Metaelem ),         /* int tp_basicsize; */
 | 
						|
	0,                          /* tp_itemsize;  For allocation */
 | 
						|
 | 
						|
	/* Methods to implement standard operations */
 | 
						|
 | 
						|
	( destructor ) Metaelem_dealloc,/* destructor tp_dealloc; */
 | 
						|
	NULL,                       /* printfunc tp_print; */
 | 
						|
	NULL,                       /* getattrfunc tp_getattr; */
 | 
						|
	NULL,                       /* setattrfunc tp_setattr; */
 | 
						|
	( cmpfunc ) Metaelem_compare,   /* cmpfunc tp_compare; */
 | 
						|
	( reprfunc ) Metaelem_repr,     /* reprfunc tp_repr; */
 | 
						|
 | 
						|
	/* Method suites for standard classes */
 | 
						|
 | 
						|
	NULL,                       /* PyNumberMethods *tp_as_number; */
 | 
						|
	NULL,                       /* 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 */
 | 
						|
	NULL,                       /* getiterfunc tp_iter; */
 | 
						|
	NULL,                       /* iternextfunc tp_iternext; */
 | 
						|
 | 
						|
  /*** Attribute descriptor and subclassing stuff ***/
 | 
						|
	BPy_Metaelem_methods,           /* struct PyMethodDef *tp_methods; */
 | 
						|
	NULL,                       /* struct PyMemberDef *tp_members; */
 | 
						|
	BPy_Metaelem_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:              M_Metaball_New                                     */
 | 
						|
/* Python equivalent:     Blender.Metaball.New                               */
 | 
						|
/*****************************************************************************/
 | 
						|
static PyObject *M_Metaball_New( PyObject * self, PyObject * args )
 | 
						|
{
 | 
						|
	char *name = 0;
 | 
						|
	BPy_Metaball *pymball;	/* for Data object wrapper in Python */
 | 
						|
	MetaBall *blmball;	/* for actual Data we create in Blender */
 | 
						|
	char buf[21];
 | 
						|
	if( !PyArg_ParseTuple( args, "|s", &name ) )
 | 
						|
		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
 | 
						|
						"expected string argument (or nothing)" ) );
 | 
						|
 | 
						|
	blmball = add_mball(  );	/* first create the MetaBall Data in Blender */
 | 
						|
 | 
						|
	if( blmball ) {
 | 
						|
		/* return user count to zero since add_mball() incref'ed it */
 | 
						|
		blmball->id.us = 0;
 | 
						|
		/* now create the wrapper obj in Python */
 | 
						|
		pymball =
 | 
						|
			( BPy_Metaball * ) PyObject_NEW( BPy_Metaball,
 | 
						|
							 &Metaball_Type );
 | 
						|
	} else
 | 
						|
		return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
 | 
						|
						"couldn't create MetaBall Data in Blender" ) );
 | 
						|
 | 
						|
	if( pymball == NULL )
 | 
						|
		return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
 | 
						|
						"couldn't create MetaBall Data object" ) );
 | 
						|
 | 
						|
	pymball->metaball = blmball;
 | 
						|
	/*link Python mballer wrapper to Blender MetaBall */
 | 
						|
	if( name ) {		/* user gave us a name for the metaball, use it */
 | 
						|
		PyOS_snprintf( buf, sizeof( buf ), "%s", name );
 | 
						|
		rename_id( &blmball->id, buf );
 | 
						|
	}
 | 
						|
	return ( PyObject * ) pymball;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Function:             M_Metaball_Get                                     */
 | 
						|
/* Python equivalent:    Blender.Metaball.Get                               */
 | 
						|
/* Description:          Receives a string and returns the metaball data obj */
 | 
						|
/*                       whose name matches the string.  If no argument is  */
 | 
						|
/*                       passed in, a list of all metaball data names in the */
 | 
						|
/*                       current scene is returned.                         */
 | 
						|
/*****************************************************************************/
 | 
						|
static PyObject *M_Metaball_Get( PyObject * self, PyObject * args )
 | 
						|
{
 | 
						|
	char error_msg[64];
 | 
						|
	char *name = NULL;
 | 
						|
	MetaBall *mball_iter;
 | 
						|
 | 
						|
	if( !PyArg_ParseTuple( args, "|s", &name ) )
 | 
						|
		return ( EXPP_ReturnPyObjError( PyExc_TypeError,
 | 
						|
						"expected string argument (or nothing)" ) );
 | 
						|
 | 
						|
	mball_iter = G.main->mball.first;
 | 
						|
 | 
						|
	if( name ) {		/* (name) - Search mball by name */
 | 
						|
 | 
						|
		BPy_Metaball *wanted_mball = NULL;
 | 
						|
 | 
						|
		while( ( mball_iter ) && ( wanted_mball == NULL ) ) {
 | 
						|
			if( strcmp( name, mball_iter->id.name + 2 ) == 0 ) {
 | 
						|
				wanted_mball =
 | 
						|
					( BPy_Metaball * )
 | 
						|
					PyObject_NEW( BPy_Metaball,
 | 
						|
						      &Metaball_Type );
 | 
						|
				if( wanted_mball )
 | 
						|
					wanted_mball->metaball = mball_iter;
 | 
						|
			}
 | 
						|
			mball_iter = mball_iter->id.next;
 | 
						|
		}
 | 
						|
 | 
						|
		if( wanted_mball == NULL ) {	/* Requested mball doesn't exist */
 | 
						|
			PyOS_snprintf( error_msg, sizeof( error_msg ),
 | 
						|
				       "MetaBall \"%s\" not found", name );
 | 
						|
			return ( EXPP_ReturnPyObjError
 | 
						|
				 ( PyExc_NameError, error_msg ) );
 | 
						|
		}
 | 
						|
 | 
						|
		return ( PyObject * ) wanted_mball;
 | 
						|
	}
 | 
						|
 | 
						|
	else {			/* () - return a list of all mballs in the scene */
 | 
						|
		PyObject *mballlist;
 | 
						|
 | 
						|
		mballlist = PyList_New( 0 );
 | 
						|
 | 
						|
		if( mballlist == NULL )
 | 
						|
			return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
 | 
						|
							"couldn't create PyList" ) );
 | 
						|
 | 
						|
		while( mball_iter ) {
 | 
						|
			BPy_Metaball *found_mball =
 | 
						|
				( BPy_Metaball * ) PyObject_NEW( BPy_Metaball,
 | 
						|
								 &Metaball_Type );
 | 
						|
			found_mball->metaball = mball_iter;
 | 
						|
			PyList_Append( mballlist, ( PyObject * ) found_mball );
 | 
						|
			mball_iter = mball_iter->id.next;
 | 
						|
		}
 | 
						|
 | 
						|
		return ( mballlist );
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Function:	 initObject						*/
 | 
						|
/*****************************************************************************/
 | 
						|
PyObject *Metaball_Init( void )
 | 
						|
{
 | 
						|
	PyObject *submodule;
 | 
						|
	PyObject *Types= M_MetaElem_TypesDict( );
 | 
						|
	
 | 
						|
	if( PyType_Ready( &Metaball_Type ) < 0 )
 | 
						|
		return NULL;
 | 
						|
	if( PyType_Ready( &Metaelem_Type ) < 0 )
 | 
						|
		return NULL;
 | 
						|
	if( PyType_Ready( &MetaElemSeq_Type ) < 0 )
 | 
						|
		return NULL;
 | 
						|
	
 | 
						|
	submodule = Py_InitModule3( "Blender.Metaball", M_Metaball_methods, M_Metaball_doc);
 | 
						|
 | 
						|
	if( Types )
 | 
						|
		PyModule_AddObject( submodule, "Types", Types );
 | 
						|
	
 | 
						|
	/*Add SUBMODULES to the module*/
 | 
						|
	/*PyDict_SetItemString(dict, "Constraint", Constraint_Init()); */ /*creates a *new* module*/
 | 
						|
	return submodule;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
int Metaball_CheckPyObject( PyObject * pyobj )
 | 
						|
{
 | 
						|
	return ( pyobj->ob_type == &Metaball_Type );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
MetaBall *Metaball_FromPyObject( PyObject * pyobj )
 | 
						|
{
 | 
						|
	return ( ( BPy_Metaball * ) pyobj )->metaball;
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *Metaball_getName( BPy_Metaball * self )
 | 
						|
{
 | 
						|
 | 
						|
	PyObject *attr = PyString_FromString( self->metaball->id.name + 2 );
 | 
						|
 | 
						|
	if( attr )
 | 
						|
		return attr;
 | 
						|
 | 
						|
	return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
 | 
						|
					"couldn't get Metaball.name attribute" ) );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
static int Metaball_setName( BPy_Metaball * self, PyObject * value )
 | 
						|
{
 | 
						|
	char *name = NULL;
 | 
						|
	char buf[21];
 | 
						|
	
 | 
						|
	name = PyString_AsString ( value );
 | 
						|
	if( !name )
 | 
						|
		return ( EXPP_ReturnIntError( PyExc_TypeError,
 | 
						|
						"expected string argument" ) );
 | 
						|
	PyOS_snprintf( buf, sizeof( buf ), "%s", name );
 | 
						|
	rename_id( &self->metaball->id, buf );
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *Metaball_getMaterials( BPy_Metaball *self )
 | 
						|
{
 | 
						|
	return EXPP_PyList_fromMaterialList( self->metaball->mat,
 | 
						|
			self->metaball->totcol, 1 );
 | 
						|
}
 | 
						|
static int Metaball_setMaterials( BPy_Metaball *self, PyObject * value )
 | 
						|
{
 | 
						|
    Material **matlist;
 | 
						|
	int len;
 | 
						|
 | 
						|
    if( !PySequence_Check( value ) ||
 | 
						|
			!EXPP_check_sequence_consistency( value, &Material_Type ) )
 | 
						|
        return EXPP_ReturnIntError( PyExc_TypeError,
 | 
						|
                  "list should only contain materials or None)" );
 | 
						|
 | 
						|
    len = PyList_Size( value );
 | 
						|
    if( len > 16 )
 | 
						|
        return EXPP_ReturnIntError( PyExc_TypeError,
 | 
						|
                          "list can't have more than 16 materials" );
 | 
						|
 | 
						|
	/* free old material list (if it exists) and adjust user counts */
 | 
						|
	if( self->metaball->mat ) {
 | 
						|
		MetaBall *mb = self->metaball;
 | 
						|
		int i;
 | 
						|
		for( i = mb->totcol; i-- > 0; )
 | 
						|
			if( mb->mat[i] )
 | 
						|
           		mb->mat[i]->id.us--;
 | 
						|
		MEM_freeN( mb->mat );
 | 
						|
	}
 | 
						|
 | 
						|
	/* build the new material list, increment user count, store it */
 | 
						|
 | 
						|
	matlist = EXPP_newMaterialList_fromPyList( value );
 | 
						|
	EXPP_incr_mats_us( matlist, len );
 | 
						|
	self->metaball->mat = matlist;
 | 
						|
    	self->metaball->totcol = (short)len;
 | 
						|
 | 
						|
/**@ This is another ugly fix due to the weird material handling of blender.
 | 
						|
    * it makes sure that object material lists get updated (by their length)
 | 
						|
    * according to their data material lists, otherwise blender crashes.
 | 
						|
    * It just stupidly runs through all objects...BAD BAD BAD.
 | 
						|
    */
 | 
						|
 | 
						|
    	test_object_materials( ( ID * ) self->metaball );
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *Metaball_getWiresize( BPy_Metaball * self )
 | 
						|
{
 | 
						|
	return PyFloat_FromDouble( self->metaball->wiresize );
 | 
						|
}
 | 
						|
 | 
						|
static int Metaball_setWiresize( BPy_Metaball * self, PyObject * value )
 | 
						|
{
 | 
						|
	float param;
 | 
						|
	if( !PyNumber_Check( value ) )
 | 
						|
		return EXPP_ReturnIntError( PyExc_TypeError,
 | 
						|
					"expected float argument" );
 | 
						|
 | 
						|
	param = PyFloat_AsDouble( value );
 | 
						|
 | 
						|
	self->metaball->wiresize = EXPP_ClampFloat(param, 0.05, 1.0);
 | 
						|
	return 0;
 | 
						|
 | 
						|
}
 | 
						|
static PyObject *Metaball_getRendersize( BPy_Metaball * self )
 | 
						|
{
 | 
						|
	return PyFloat_FromDouble( self->metaball->rendersize );
 | 
						|
}
 | 
						|
 | 
						|
static int Metaball_setRendersize( BPy_Metaball * self, PyObject * value )
 | 
						|
{
 | 
						|
 | 
						|
	float param;
 | 
						|
	if( !PyNumber_Check( value ) )
 | 
						|
		return EXPP_ReturnIntError( PyExc_TypeError,
 | 
						|
					"expected float argument" );
 | 
						|
 | 
						|
	param = PyFloat_AsDouble( value );
 | 
						|
 | 
						|
	self->metaball->rendersize = EXPP_ClampFloat(param, 0.05, 1.0);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *Metaball_getThresh( BPy_Metaball * self )
 | 
						|
{
 | 
						|
	return PyFloat_FromDouble( self->metaball->thresh );
 | 
						|
}
 | 
						|
 | 
						|
static int Metaball_setThresh( BPy_Metaball * self, PyObject * value )
 | 
						|
{
 | 
						|
 | 
						|
	float param;
 | 
						|
	if( !PyNumber_Check( value ) )
 | 
						|
		return EXPP_ReturnIntError( PyExc_TypeError,
 | 
						|
					"expected float argument" );
 | 
						|
 | 
						|
	param = PyFloat_AsDouble( value );
 | 
						|
 | 
						|
	self->metaball->thresh = EXPP_ClampFloat(param, 0.0, 5.0);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static PyObject *Metaball_getUsers( BPy_Metaball * self )
 | 
						|
{
 | 
						|
	return PyInt_FromLong( self->metaball->id.us );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
static PyObject *Metaball_copy( BPy_Metaball * self )
 | 
						|
{
 | 
						|
	BPy_Metaball *pymball;	/* for Data object wrapper in Python */
 | 
						|
	MetaBall *blmball;	/* for actual Data we create in Blender */
 | 
						|
	
 | 
						|
	blmball = copy_mball( self->metaball );	/* first create the MetaBall Data in Blender */
 | 
						|
 | 
						|
	if( blmball ) {
 | 
						|
		/* return user count to zero since add_mball() incref'ed it */
 | 
						|
		blmball->id.us = 0;
 | 
						|
		/* now create the wrapper obj in Python */
 | 
						|
		pymball =
 | 
						|
			( BPy_Metaball * ) PyObject_NEW( BPy_Metaball,
 | 
						|
							 &Metaball_Type );
 | 
						|
	} else
 | 
						|
		return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
 | 
						|
						"couldn't create MetaBall Data in Blender" ) );
 | 
						|
 | 
						|
	if( pymball == NULL )
 | 
						|
		return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
 | 
						|
						"couldn't create MetaBall Data object" ) );
 | 
						|
 | 
						|
	pymball->metaball = blmball;
 | 
						|
	
 | 
						|
	return ( PyObject * ) pymball;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* These are needed by Object.c */
 | 
						|
PyObject *Metaball_CreatePyObject( MetaBall * mball)
 | 
						|
{
 | 
						|
	BPy_Metaball *py_mball= PyObject_NEW( BPy_Metaball, &Metaball_Type );
 | 
						|
 | 
						|
	if( !py_mball )
 | 
						|
		return EXPP_ReturnPyObjError( PyExc_MemoryError,
 | 
						|
				"couldn't create BPy_Metaball object" );
 | 
						|
 | 
						|
	py_mball->metaball= mball;
 | 
						|
 | 
						|
	return ( PyObject * ) py_mball;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static PyObject *MetaElemSeq_CreatePyObject(BPy_Metaball *self, MetaElem *iter)
 | 
						|
{
 | 
						|
	BPy_MetaElemSeq *seq = PyObject_NEW( BPy_MetaElemSeq, &MetaElemSeq_Type);
 | 
						|
	seq->bpymetaball = self; Py_INCREF(self);
 | 
						|
	seq->iter= iter;
 | 
						|
	return (PyObject *)seq;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Element, get an instance of the iterator.
 | 
						|
 */
 | 
						|
static PyObject *Metaball_getElements( BPy_Metaball * self )
 | 
						|
{
 | 
						|
	return MetaElemSeq_CreatePyObject(self, NULL);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Metaball dealloc - free from memory
 | 
						|
 */
 | 
						|
static void Metaball_dealloc( BPy_Metaball * self )
 | 
						|
{
 | 
						|
	PyObject_DEL( self );
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Metaelem dealloc - free from memory
 | 
						|
 */
 | 
						|
/* This is a callback function for the BPy_Metaelem type. It is */
 | 
						|
static void Metaelem_dealloc( BPy_Metaelem * self )
 | 
						|
{
 | 
						|
	self->metaelem= NULL; /* so any references to the same bpyobject will raise an error */
 | 
						|
	PyObject_DEL( self );
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * elem.type - int to set the shape of the element
 | 
						|
 */
 | 
						|
static PyObject *Metaelem_getType( BPy_Metaelem *self )
 | 
						|
{
 | 
						|
	PyObject *attr = NULL;
 | 
						|
	
 | 
						|
	METAELEM_DEL_CHECK_PY(self);
 | 
						|
	
 | 
						|
	attr = PyInt_FromLong( self->metaelem->type );
 | 
						|
	
 | 
						|
	if( attr )
 | 
						|
		return attr;
 | 
						|
 | 
						|
	return EXPP_ReturnPyObjError( PyExc_MemoryError,
 | 
						|
				"PyInt_FromLong() failed!" );
 | 
						|
}
 | 
						|
static int Metaelem_setType( BPy_Metaelem * self,  PyObject * value )
 | 
						|
{
 | 
						|
 | 
						|
	int type;
 | 
						|
	if( !PyInt_CheckExact( value ) )
 | 
						|
		return EXPP_ReturnIntError( PyExc_TypeError,
 | 
						|
			"expected an integer (bitmask) as argument" );
 | 
						|
	
 | 
						|
	METAELEM_DEL_CHECK_INT(self);
 | 
						|
	
 | 
						|
	type = PyInt_AS_LONG( value );
 | 
						|
	
 | 
						|
	if( (type < 0) || ( type > ( MB_BALL | MB_TUBEX | MB_TUBEY | MB_TUBEZ | MB_TUBE | MB_PLANE | MB_ELIPSOID | MB_CUBE ) ))
 | 
						|
		return EXPP_ReturnIntError( PyExc_ValueError,
 | 
						|
					      "value out of range" );
 | 
						|
	
 | 
						|
	self->metaelem->type= type;
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * elem.co - non wrapped vector representing location
 | 
						|
 */
 | 
						|
static PyObject *Metaelem_getCoord( BPy_Metaelem * self )
 | 
						|
{
 | 
						|
	float co[3];
 | 
						|
	
 | 
						|
	METAELEM_DEL_CHECK_PY(self);
 | 
						|
	
 | 
						|
	co[0]= self->metaelem->x;
 | 
						|
	co[1]= self->metaelem->y;
 | 
						|
	co[2]= self->metaelem->z;
 | 
						|
	
 | 
						|
	return newVectorObject( co, 3, Py_NEW );
 | 
						|
}
 | 
						|
static int Metaelem_setCoord( BPy_Metaelem * self,  VectorObject * value )
 | 
						|
{
 | 
						|
 | 
						|
	if( !VectorObject_Check( value ) || value->size != 3 )
 | 
						|
		return EXPP_ReturnIntError( PyExc_TypeError,
 | 
						|
				"expected vector argument of size 3" );
 | 
						|
	
 | 
						|
	METAELEM_DEL_CHECK_INT(self);
 | 
						|
	
 | 
						|
	self->metaelem->x= value->vec[0];
 | 
						|
	self->metaelem->y= value->vec[1];
 | 
						|
	self->metaelem->z= value->vec[2];
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * elem.dims - non wrapped vector representing the xyz dimensions
 | 
						|
 * only effects some element types
 | 
						|
 */
 | 
						|
static PyObject *Metaelem_getDims( BPy_Metaelem * self )
 | 
						|
{
 | 
						|
	float co[3];
 | 
						|
	METAELEM_DEL_CHECK_PY(self);
 | 
						|
	
 | 
						|
	co[0]= self->metaelem->expx;
 | 
						|
	co[1]= self->metaelem->expy;
 | 
						|
	co[2]= self->metaelem->expz;
 | 
						|
	return newVectorObject( co, 3, Py_NEW );
 | 
						|
}
 | 
						|
static int Metaelem_setDims( BPy_Metaelem * self,  VectorObject * value )
 | 
						|
{
 | 
						|
	if( !VectorObject_Check( value ) || value->size != 3 )
 | 
						|
		return EXPP_ReturnIntError( PyExc_TypeError,
 | 
						|
				"expected vector argument of size 3" );
 | 
						|
 | 
						|
	METAELEM_DEL_CHECK_INT(self);
 | 
						|
	
 | 
						|
	self->metaelem->expx= EXPP_ClampFloat(value->vec[0], 0.0, 20.0);
 | 
						|
	self->metaelem->expy= EXPP_ClampFloat(value->vec[1], 0.0, 20.0);
 | 
						|
	self->metaelem->expz= EXPP_ClampFloat(value->vec[2], 0.0, 20.0);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * elem.quat - non wrapped quat representing the rotation
 | 
						|
 * only effects some element types - a rotated ball has no effect for eg.
 | 
						|
 */
 | 
						|
static PyObject *Metaelem_getQuat( BPy_Metaelem * self )
 | 
						|
{
 | 
						|
	METAELEM_DEL_CHECK_PY(self);
 | 
						|
	return newQuaternionObject(self->metaelem->quat, Py_NEW); 
 | 
						|
}
 | 
						|
static int Metaelem_setQuat( BPy_Metaelem * self,  QuaternionObject * value )
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	if( !QuaternionObject_Check( value ) )
 | 
						|
		return EXPP_ReturnIntError( PyExc_TypeError,
 | 
						|
				"expected quat argument" );
 | 
						|
	
 | 
						|
	METAELEM_DEL_CHECK_INT(self);
 | 
						|
	
 | 
						|
	for (i = 0; i < 4; i++)
 | 
						|
		self->metaelem->quat[i]= value->quat[i];
 | 
						|
	
 | 
						|
	/* need to normalize or metaball drawing can go into an infinate loop */
 | 
						|
	NormalQuat(self->metaelem->quat);
 | 
						|
	
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * elem.hide and elem.sel - get/set true false
 | 
						|
 */
 | 
						|
static PyObject *Metaelem_getMFlagBits( BPy_Metaelem * self, void * type )
 | 
						|
{
 | 
						|
	METAELEM_DEL_CHECK_PY(self);
 | 
						|
	return EXPP_getBitfield( &(self->metaelem->flag), (int)((long)type ), 'h' );
 | 
						|
}
 | 
						|
static int Metaelem_setMFlagBits( BPy_Metaelem * self, PyObject * value,
 | 
						|
		void * type )
 | 
						|
{
 | 
						|
	METAELEM_DEL_CHECK_INT(self);
 | 
						|
	return EXPP_setBitfield( value, &(self->metaelem->flag), 
 | 
						|
			(int)((long)type), 'h' );
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * elem.stiffness - floating point, the volume of this element.
 | 
						|
 */
 | 
						|
static PyObject *Metaelem_getStiffness( BPy_Metaelem *self )
 | 
						|
{
 | 
						|
	METAELEM_DEL_CHECK_PY(self);
 | 
						|
	return PyFloat_FromDouble( self->metaelem->s );
 | 
						|
}
 | 
						|
static int Metaelem_setStiffness( BPy_Metaelem *self, PyObject *value)
 | 
						|
{
 | 
						|
	if( !PyNumber_Check( value ) )
 | 
						|
		return EXPP_ReturnIntError( PyExc_TypeError,
 | 
						|
					"expected float argument" );
 | 
						|
 | 
						|
	self->metaelem->s = EXPP_ClampFloat(PyFloat_AsDouble( value ), 0.0, 10.0);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * elem.radius- floating point, the size if the element
 | 
						|
 */
 | 
						|
static PyObject *Metaelem_getRadius( BPy_Metaelem *self )
 | 
						|
{
 | 
						|
	METAELEM_DEL_CHECK_PY(self);
 | 
						|
	return PyFloat_FromDouble( self->metaelem->rad );
 | 
						|
}
 | 
						|
static int Metaelem_setRadius( BPy_Metaelem *self, PyObject *value)
 | 
						|
{
 | 
						|
	if( !PyNumber_Check( value ) )
 | 
						|
		return EXPP_ReturnIntError( PyExc_TypeError,
 | 
						|
					"expected float argument" );
 | 
						|
 | 
						|
	self->metaelem->rad = /* is 5000 too small? */
 | 
						|
			EXPP_ClampFloat(PyFloat_AsDouble( value ), 0.0, 5000.0);
 | 
						|
	
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * callback functions for comparison.
 | 
						|
 * It compares two Metaball_Type objects. Only the "==" and "!="
 | 
						|
 * comparisons are meaninful. Returns 0 for equality and -1 if
 | 
						|
 * they don't point to the same Blender struct.
 | 
						|
 * In Python it becomes 1 if they are equal, 0 otherwise.	
 | 
						|
 */
 | 
						|
static int Metaball_compare( BPy_Metaball * a, BPy_Metaball * b )
 | 
						|
{
 | 
						|
	MetaBall *pa = a->metaball, *pb = b->metaball;
 | 
						|
	return ( pa == pb ) ? 0 : -1;
 | 
						|
}
 | 
						|
 | 
						|
static int MetaElemSeq_compare( BPy_MetaElemSeq * a, BPy_MetaElemSeq * b )
 | 
						|
{
 | 
						|
	MetaBall *pa = a->bpymetaball->metaball, *pb = b->bpymetaball->metaball;
 | 
						|
	return ( pa == pb ) ? 0 : -1;
 | 
						|
}
 | 
						|
 | 
						|
static int Metaelem_compare( BPy_Metaelem * a, BPy_Metaelem * b )
 | 
						|
{
 | 
						|
	MetaElem *pa = a->metaelem, *pb = b->metaelem;
 | 
						|
	return ( pa == pb ) ? 0 : -1;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * repr function
 | 
						|
 * callback functions building meaninful string to representations
 | 
						|
 */
 | 
						|
static PyObject *Metaball_repr( BPy_Metaball * self )
 | 
						|
{
 | 
						|
	return PyString_FromFormat( "[Metaball \"%s\"]",
 | 
						|
				    self->metaball->id.name + 2 );
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *Metaelem_repr( BPy_Metaelem * self )
 | 
						|
{
 | 
						|
	return PyString_FromString( "Metaelem" );
 | 
						|
}
 | 
						|
 | 
						|
static PyObject *MetaElemSeq_repr( BPy_MetaElemSeq * self )
 | 
						|
{
 | 
						|
	return PyString_FromFormat( "[Metaball Iterator \"%s\"]",
 | 
						|
				    self->bpymetaball->metaball->id.name + 2 );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * MeteElem Seq sequence 
 | 
						|
 */
 | 
						|
 | 
						|
static PyObject *MetaElem_CreatePyObject( MetaElem *metaelem )
 | 
						|
{
 | 
						|
	BPy_Metaelem *elem= PyObject_NEW( BPy_Metaelem, &Metaelem_Type);
 | 
						|
	elem->metaelem = metaelem; Py_INCREF(elem);
 | 
						|
	return (PyObject *)elem;
 | 
						|
}
 | 
						|
 | 
						|
static int MetaElemSeq_len( BPy_MetaElemSeq * self )
 | 
						|
{
 | 
						|
	return BLI_countlist( &( self->bpymetaball->metaball->elems ) );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static PySequenceMethods MetaElemSeq_as_sequence = {
 | 
						|
	( inquiry ) MetaElemSeq_len,	/* sq_length */
 | 
						|
	( binaryfunc ) 0,	/* sq_concat */
 | 
						|
	( intargfunc ) 0,	/* sq_repeat */
 | 
						|
	( intargfunc ) 0,	/* sq_item */
 | 
						|
	( intintargfunc ) 0,	/* sq_slice */
 | 
						|
	( intobjargproc ) 0,	/* sq_ass_item */
 | 
						|
	( intintobjargproc ) 0,	/* sq_ass_slice */
 | 
						|
	0,0,0,
 | 
						|
};
 | 
						|
 | 
						|
/************************************************************************
 | 
						|
 *
 | 
						|
 * Python MetaElemSeq_Type iterator (iterates over Metaballs)
 | 
						|
 *
 | 
						|
 ************************************************************************/
 | 
						|
 | 
						|
/*
 | 
						|
 * Initialize the interator
 | 
						|
 */
 | 
						|
 | 
						|
static PyObject *MetaElemSeq_getIter( BPy_MetaElemSeq * self )
 | 
						|
{
 | 
						|
	if (!self->iter) { /* not alredy looping on this data, */
 | 
						|
		self->iter = self->bpymetaball->metaball->elems.first;
 | 
						|
		return EXPP_incr_ret ( (PyObject *) self );
 | 
						|
	} else
 | 
						|
		return MetaElemSeq_CreatePyObject(self->bpymetaball, self->bpymetaball->metaball->elems.first);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Return next MetaElem.
 | 
						|
 */
 | 
						|
 | 
						|
static PyObject *MetaElemSeq_nextIter( BPy_MetaElemSeq * self )
 | 
						|
{
 | 
						|
	PyObject *object;
 | 
						|
	if( !(self->iter) ||  !(self->bpymetaball->metaball) ) {
 | 
						|
		self->iter= NULL;
 | 
						|
		return EXPP_ReturnPyObjError( PyExc_StopIteration,
 | 
						|
				"iterator at end" );
 | 
						|
	}
 | 
						|
	
 | 
						|
	object= MetaElem_CreatePyObject( self->iter ); 
 | 
						|
	self->iter= self->iter->next;
 | 
						|
	return object;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Adds and returns a new metaelement, 
 | 
						|
 * no args are taken so the returned metaball must be modified after adding.
 | 
						|
 * Accessed as mball.elements.add() where mball is a python metaball data type.
 | 
						|
 */
 | 
						|
static PyObject *MetaElemSeq_add( BPy_MetaElemSeq * self )
 | 
						|
{
 | 
						|
	MetaElem *ml;
 | 
						|
 | 
						|
	ml = MEM_callocN( sizeof( MetaElem ), "metaelem" );
 | 
						|
	BLI_addhead( &( self->bpymetaball->metaball->elems ), ml );
 | 
						|
	ml->x = 0;
 | 
						|
	ml->y = 0;
 | 
						|
	ml->z = 0;
 | 
						|
	ml->quat[0]= 1.0;
 | 
						|
	ml->quat[1]= 0.0;
 | 
						|
	ml->quat[2]= 0.0;
 | 
						|
	ml->quat[3]= 0.0;
 | 
						|
	ml->rad = 2;
 | 
						|
	ml->s = 2.0;
 | 
						|
	ml->flag = SELECT;
 | 
						|
	ml->type = 0;
 | 
						|
	ml->expx = 1;
 | 
						|
	ml->expy = 1;
 | 
						|
	ml->expz = 1;
 | 
						|
	ml->type = MB_BALL;
 | 
						|
 | 
						|
	return MetaElem_CreatePyObject(ml);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * removes a metaelement if it is a part of the metaball, 
 | 
						|
 * no args are taken so the returned metaball must be modified after adding.
 | 
						|
 * Accessed as mball.elements.add() where mball is a python metaball data type.
 | 
						|
 */
 | 
						|
static PyObject *MetaElemSeq_remove( BPy_MetaElemSeq * self, PyObject *args )
 | 
						|
{
 | 
						|
	BPy_Metaelem *elem;
 | 
						|
	MetaElem *ml_iter, *ml_py;
 | 
						|
	
 | 
						|
	if( !PyArg_ParseTuple( args, "O!", &Metaelem_Type, &elem) )
 | 
						|
		return EXPP_ReturnPyObjError( PyExc_TypeError,
 | 
						|
			"expected a Metaball element" );
 | 
						|
	
 | 
						|
	METAELEM_DEL_CHECK_PY(elem);
 | 
						|
	
 | 
						|
	ml_py= elem->metaelem;
 | 
						|
	
 | 
						|
	for (ml_iter= self->bpymetaball->metaball->elems.first; ml_iter; ml_iter= ml_iter->next) {
 | 
						|
		if (ml_py == ml_iter) {
 | 
						|
			elem->metaelem= NULL;
 | 
						|
			BLI_freelinkN( &(self->bpymetaball->metaball->elems), ml_py);
 | 
						|
			Py_RETURN_NONE;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	
 | 
						|
	return EXPP_ReturnPyObjError( PyExc_ValueError,
 | 
						|
		"elements.remove(elem): elem not in meta elements" );	
 | 
						|
	
 | 
						|
}
 | 
						|
 | 
						|
static struct PyMethodDef BPy_MetaElemSeq_methods[] = {
 | 
						|
	{"add", (PyCFunction)MetaElemSeq_add, METH_NOARGS,
 | 
						|
		"add metaelem to metaball data"},
 | 
						|
	{"remove", (PyCFunction)MetaElemSeq_remove, METH_VARARGS,
 | 
						|
		"remove element from metaball data"},
 | 
						|
	{NULL, NULL, 0, NULL}
 | 
						|
};
 | 
						|
 | 
						|
/************************************************************************
 | 
						|
 *
 | 
						|
 * Python MetaElemSeq_Type standard operations
 | 
						|
 *
 | 
						|
 ************************************************************************/
 | 
						|
 | 
						|
static void MetaElemSeq_dealloc( BPy_MetaElemSeq * self )
 | 
						|
{
 | 
						|
	Py_DECREF(self->bpymetaball);
 | 
						|
	PyObject_DEL( self );
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Python MetaElemSeq_Type structure definition:                               */
 | 
						|
/*****************************************************************************/
 | 
						|
PyTypeObject MetaElemSeq_Type = {
 | 
						|
	PyObject_HEAD_INIT( NULL )  /* required py macro */
 | 
						|
	0,                          /* ob_size */
 | 
						|
	/*  For printing, in format "<module>.<name>" */
 | 
						|
	"Blender MetaElemSeq",           /* char *tp_name; */
 | 
						|
	sizeof( BPy_MetaElemSeq ),       /* int tp_basicsize; */
 | 
						|
	0,                          /* tp_itemsize;  For allocation */
 | 
						|
 | 
						|
	/* Methods to implement standard operations */
 | 
						|
 | 
						|
	( destructor ) MetaElemSeq_dealloc,/* destructor tp_dealloc; */
 | 
						|
	NULL,                       /* printfunc tp_print; */
 | 
						|
	NULL,                       /* getattrfunc tp_getattr; */
 | 
						|
	NULL,                       /* setattrfunc tp_setattr; */
 | 
						|
	( cmpfunc ) MetaElemSeq_compare,   /* cmpfunc tp_compare; */
 | 
						|
	( reprfunc ) MetaElemSeq_repr,     /* reprfunc tp_repr; */
 | 
						|
 | 
						|
	/* Method suites for standard classes */
 | 
						|
 | 
						|
	NULL,                       /* PyNumberMethods *tp_as_number; */
 | 
						|
	&MetaElemSeq_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) MetaElemSeq_getIter, /* getiterfunc tp_iter; */
 | 
						|
	( iternextfunc ) MetaElemSeq_nextIter, /* iternextfunc tp_iternext; */
 | 
						|
 | 
						|
  /*** Attribute descriptor and subclassing stuff ***/
 | 
						|
	BPy_MetaElemSeq_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
 | 
						|
};
 | 
						|
 |