Index: /home/jmonteath/workspace/blender-trunk/blender/source/blender/python/api2_2x/Blender.c =================================================================== --- /home/jmonteath/workspace/blender-trunk/blender/source/blender/python/api2_2x/Blender.c (revision 12026) +++ /home/jmonteath/workspace/blender-trunk/blender/source/blender/python/api2_2x/Blender.c (working copy) @@ -69,6 +69,7 @@ #include "CurNurb.h" #include "Draw.h" #include "Effect.h" +#include "Fluid.h" #include "Ipo.h" #include "Ipocurve.h" #include "IDProp.h" @@ -950,6 +951,7 @@ PyDict_SetItemString(dict, "Camera", Camera_Init()); PyDict_SetItemString(dict, "Draw", Draw_Init()); PyDict_SetItemString(dict, "Effect", Effect_Init()); + PyDict_SetItemString(dict, "Fluid", Fluid_Init()); PyDict_SetItemString(dict, "Ipo", Ipo_Init()); PyDict_SetItemString(dict, "IpoCurve", IpoCurve_Init()); PyDict_SetItemString(dict, "Image", Image_Init()); Index: /home/jmonteath/workspace/blender-trunk/blender/source/blender/python/api2_2x/Fluid.c =================================================================== --- /home/jmonteath/workspace/blender-trunk/blender/source/blender/python/api2_2x/Fluid.c (revision 0) +++ /home/jmonteath/workspace/blender-trunk/blender/source/blender/python/api2_2x/Fluid.c (revision 0) @@ -0,0 +1,746 @@ +/* + * $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): James Monteath - ponderz + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ + +#include "Fluid.h" /* This must come first */ +#include + +#include "Mesh.h" + +#include "BKE_main.h" +#include "BKE_global.h" +#include "BKE_object.h" +#include "BKE_library.h" +#include "BLI_blenlib.h" +#include "BLI_arithb.h" /* for M_PI */ +#include "BIF_space.h" +#include "mydevice.h" +#include "gen_utils.h" +#include "gen_library.h" + + +/**************************************************************************** +* Constants +*****************************************************************************/ + +enum Fluid_consts { + PY_FLUID_TYPE_ALL = -1, + PY_FLUID_TYPE_NONE = 0, + PY_FLUID_TYPE_DOMAIN, + PY_FLUID_TYPE_FLUID, + PY_FLUID_TYPE_OBSTACLE, + PY_FLUID_TYPE_INFLOW, + PY_FLUID_TYPE_OUTFLOW, + PY_FLUID_TYPE_PARTICLE, +}; + + +/**************************************************************************** +* +* Python Module declaration section +* +*****************************************************************************/ + +/**************************************************************************** +* Python API function prototypes for the Fluid Module. +*****************************************************************************/ +static PyObject *M_Fluid_findAll( PyObject * self ); +static PyObject *M_Fluid_findDomain( PyObject * self ); +static PyObject *M_Fluid_find( PyObject * self, PyObject * args, PyObject * kwords ); +static PyObject *M_Fluid_startBake( PyObject * self ); + +/***************************************************************************** +* The following string definitions are used for documentation strings. +* In Python these will be written to the console when doing a +* Blender.Fluid.__doc__ +*****************************************************************************/ +static char M_Fluid_doc[] = "The Blender Fluid module\n\ +This module provides access to **Fluid Data** objects in Blender\n\n\ +Example::\n\ +\n\ +from Blender import Fluid, Object, Scene\n\ +fluid = Fluid.findAll() # find all fluid objects\n"; + +static char M_Fluid_findAll_doc[] = + "Fluid.findAll():\n\ + Return a list with all Fluid Data objects in the current scene,\n\ + if no argument was given."; + +static char M_Fluid_findDomain_doc[] = "Fluid.findDomain():\n\ + Return the fluid domain object, None if not found"; + +static char M_Fluid_find_doc[] = "Fluid.find( name=\"Cube\", type=Fluid.Types.DOMAIN ):\n\ + Return the fluid data with the given 'name' and type, None if not found"; + +static char M_Fluid_startBake_doc[] = "Fluid.startBake():\n\ + Kick off the bake process, this will find the domain object and start the bake"; + +/*****************************************************************************/ +/* Python method structure definition for Blender.Fluid module: */ +/*****************************************************************************/ +struct PyMethodDef M_Fluid_methods[] = +{ + {"findAll", M_Fluid_findAll, METH_NOARGS, M_Fluid_findAll_doc}, + {"findDomain", M_Fluid_findDomain, METH_NOARGS, M_Fluid_findDomain_doc}, + {"find", M_Fluid_find, METH_VARARGS | METH_KEYWORDS, M_Fluid_find_doc}, + {"startBake", M_Fluid_startBake, METH_NOARGS, M_Fluid_startBake_doc}, + {NULL, NULL, 0, NULL} +}; + + +/**************************************************************************** +* +* Python Module implementation section +* +*****************************************************************************/ + +/* + * Find all fluid objects in the scene. + * + * This code uses 100% of the Blender Python C API. This is so that we don't duplictae + * the logic/code required which is already present. + * + * TODO: This should return an iterator not a list + * + * @return list type, never NULL + */ +static PyObject *M_Fluid_findAll( PyObject * self ) +{ + //int index = 0; + PyObject *module = NULL; + PyObject *objectList = NULL; + PyObject *fluidlist = NULL; + PyObject *object = NULL; + PyObject *getFunction = NULL; + + fluidlist = PyList_New( 0 ); + //printf( "findAll: Begin\n" ); +// // Get the function by name + //function = PyObject_GetAttrString( ((PyObject *)&Object_Type), "Get"); + + // Get the Object module + module = PyImport_ImportModule( "Blender.Object" ); + if ( module == NULL ) + return EXPP_ReturnPyObjError( PyExc_ImportError, "Fluid.findAll: module Blender.Object not loaded" ); + + // Get the function Get + getFunction = PyObject_GetAttrString( module, "Get" ); + if ( getFunction == NULL ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, "Fluid.findAll: function Get not found" ); + + //printf( "findAll: call get\n" ); + objectList = PyObject_CallObject( getFunction, Py_BuildValue( "()" ) ); // need an empty tupple + //printf( "findAll: use iter\n" ); + // Allows use to iterate through the obejct without having to create duplicate + // objects. + objectList = PyObject_GetIter( objectList ); // use the iterator protocol + + //printf( "findAll: now check all the object for fluid objects\n" ); + if ( ! objectList ) + return fluidlist; + + while( ( object = PyIter_Next( objectList ) ) ) { + int result; + // get the Fluid object from the Object using the callable + // this is the fun part of properties, since it is an attribute + // we will receive the object returned buy the getIsFluidEnabled method + PyObject *isFluidEnabled = PyObject_GetAttrString( object, "isFluidEnabled" ); + if ( isFluidEnabled == NULL ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, "Fluid.findAll: Object.isFluidEnabled function failed" ); + + result = PyObject_IsTrue( isFluidEnabled ); + + if ( result ) { + PyObject *fluid; + + fluid = PyObject_GetAttrString( object, "fluid" ); + + // Found a Object with Fluid enabled, add it to the list + //printf( "Fluid.findAll: found a fluid object\n" ); + PyList_Append( fluidlist, fluid ); + Py_DECREF( fluid ); // Done with this one + } + + Py_DECREF( object ); // Done with this one + + } + + Py_DECREF( objectList ); + + if ( fluidlist == NULL ) + return EXPP_ReturnPyObjError( PyExc_AssertionError, "Fluid.findAll: must not return NULL" ); + + //printf( "findAll: End\n" ); + return fluidlist; + +} + +/* + * Find Domain object in the scene and return it, return None if not found + * + */ +static PyObject *M_Fluid_findDomain( PyObject * self ) +{ + //int index = 0; + PyObject *fluid = NULL; + PyObject *domainFluid = NULL; + PyObject *fluidlist = NULL; + int domainCount = 0; + + printf( "Fluid.findDomain: find all first\n" ); + + fluidlist = M_Fluid_findAll( self ); + fluidlist = PyObject_GetIter( fluidlist ); // use the iterator protocol + + while( ( fluid = PyIter_Next( fluidlist ) ) ) { + int result; + // get the Fluid object from the Object using the callable + // this is the fun part of properties, since it is an attribute + // we will receive the object returned buy the getIsFluidEnabled method + PyObject *type = PyObject_GetAttrString( fluid, "type" ); + if ( type == NULL ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, "Fluid.findDomain: type function failed" ); + + result = (( int ) PyLong_AsLong( type )) == PY_FLUID_TYPE_DOMAIN; + + if ( result ) { + //printf( "Fluid.findDomain: found a domain\n" ); + domainCount++; + domainFluid = fluid; // might have to INCREF, or simply not DEC it here + } + + //Py_DECREF( fluid ); // Done with this one + + } + Py_DECREF( fluidlist ); + + if ( domainCount > 1 ) + { + return EXPP_ReturnPyObjError( PyExc_AssertionError, "Fluid.findDomain: found more than 1 domain" ); + } + + return domainFluid; + +} + +/* + * Find specific object by properties, None if not found. + */ +static PyObject *M_Fluid_find( PyObject * self, PyObject * args, PyObject * kwords ) +{ + static char *kwlist[] = { "name", "type", NULL }; + char *name = NULL; // by default all names + int type = PY_FLUID_TYPE_ALL; // by default all types + + PyObject *fluidlist = NULL; + + { + BPy_Fluid *foundFluid = NULL; + } + + /* Parse the arguments passed in by the Python interpreter */ + if( ! PyArg_ParseTupleAndKeywords( args, kwords, "|si", kwlist, &name, &type ) ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, "Fluid.find: expected [name=string|type=int]" ); + + fluidlist = PyList_New( 0 ); + + return ( PyObject * ) fluidlist; +} + +/* + * Start bake process, first find the domain and then kick of the bake process. + * Will throw and error if no Domain was found. + * + */ +static PyObject *M_Fluid_startBake( PyObject * self ) +{ + PyObject *domainFluid; + PyObject *result; + + domainFluid = M_Fluid_findDomain( self ); + if ( domainFluid == NULL ) + return EXPP_ReturnPyObjError( PyExc_TypeError, "Fluid.startBake: was not able to find a domain object" ); + + // Find the domain and call the bake method on it. + result = PyObject_CallMethod( domainFluid, "bake", NULL ); + + return result; + +} + +/* + * Python module init + * + */ +PyObject *Fluid_Init( void ) +{ + PyObject *submodule; + PyObject *types; + + if( PyType_Ready( &Fluid_Type ) < 0 ) + return NULL; // TODO: is this valid ? + + submodule = Py_InitModule3( "Blender.Fluid", M_Fluid_methods, M_Fluid_doc ); + + types = PyConstant_New( ); + + if( types ) { + BPy_constant *d = ( BPy_constant * ) types; + PyConstant_Insert( d, "NONE", PyInt_FromLong( PY_FLUID_TYPE_NONE ) ); + PyConstant_Insert( d, "DOMAIN", PyInt_FromLong( PY_FLUID_TYPE_DOMAIN ) ); + PyConstant_Insert( d, "FLUID", PyInt_FromLong( PY_FLUID_TYPE_FLUID ) ); + PyConstant_Insert( d, "OBSTACLE", PyInt_FromLong( PY_FLUID_TYPE_OBSTACLE ) ); + PyConstant_Insert( d, "INFLOW", PyInt_FromLong( PY_FLUID_TYPE_INFLOW ) ); + PyConstant_Insert( d, "OUTFLOW", PyInt_FromLong( PY_FLUID_TYPE_OUTFLOW ) ); + PyConstant_Insert( d, "PARTICLE", PyInt_FromLong( PY_FLUID_TYPE_PARTICLE ) ); + + PyModule_AddObject( submodule, "Types", types ); + + } + + return submodule; +} + +/* + * Python factory function + * + * For now, you have to enable the sim using the GUI, + * so that you may get the Fuild object instance. + * + * @pre bpyObject - must be a Mesh object and have vertices + * @pre bpyObject - fluid sim must be enabled + * + */ +PyObject *Fluid_CreatePyObject( BPy_Object * bpyObject ) +{ + BPy_Fluid *bpyFluid = NULL; + FluidsimSettings * fluidsimSettings = NULL; + + // TODO: Change the code to use a Python object instead and use the Parse +// if( ! PyArg_ParseTuple( args, "o", &name, &type ) +// return EXPP_ReturnPyObjError( PyExc_AttributeError, "expected BPy_Object" ); +// + if( ! BPy_Object_Check( bpyObject ) ) + { + return EXPP_ReturnPyObjError( PyExc_TypeError, "Fluid_CreatePyObject: expected BPy_Object type" ); + } + + if( bpyObject->object->type == OB_MESH ) { + if ( ( (Mesh *) bpyObject->object->data )->totvert == 0 ) { + return EXPP_ReturnPyObjError( PyExc_AssertionError, "Fluid_CreatePyObject: object must have vertices" ); + } + + // TODO: This code belongs in the Fluid object, but for now we will + // initialise the data anyway + if( bpyObject->object->fluidsimFlag & OB_FLUIDSIM_ENABLE ) { + // Since it was enabled, we will do that at this point + fluidsimSettings = bpyObject->object->fluidsimSettings; + + if( fluidsimSettings == NULL ) { + // Lets create the data since it is the first time, this should + // not happen unless the python code tried to enable it for the + // first time. + + // fluidsimSettingsNew does not keep a refrence to its related object + // so we will do it here. + fluidsimSettings = bpyObject->object->fluidsimSettings = fluidsimSettingsNew( bpyObject->object ); + + } + else { + printf( "DEBUG: Fluid_CreatePyObject: fluid sim was already setup\n" ); + } + + } else { + return EXPP_ReturnPyObjError( PyExc_AssertionError, + "Fluid_CreatePyObject: fluid simulation was not enabled for this object" ); + } + } else { + return EXPP_ReturnPyObjError( PyExc_AssertionError, + "Fluid_CreatePyObject: only Mesh Objects can participate" ); + } + + bpyFluid = ( BPy_Fluid * ) PyObject_NEW( BPy_Fluid, &Fluid_Type ); + + if( ! bpyFluid ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, + "Fluid_CreatePyObject: couldn't create BPy_Fluid PyObject" ); + + //bpyFluid->fluidsimSettings = fluidsimSettings; + bpyFluid->bpyObject = bpyObject; + + // TODO: Might have to incemrnet the ref count to the bpyObject, not sure how yet + return ( PyObject * ) bpyFluid; +} + + + +/***************************************************************************** +* Python BPy_fluid properties (getter/setter) implementation: +******************************************************************************/ + +static PyObject *Fluid_getName( BPy_Fluid * self ); +static PyObject *Fluid_getType( BPy_Fluid * self ); +static int Fluid_setType( BPy_Fluid * self, PyObject * value ); +static PyObject *Fluid_getBakePath( BPy_Fluid * self ); +static int Fluid_setBakePath( BPy_Fluid * self, PyObject * value ); + +static PyObject *Fluid_getType( BPy_Fluid * self ) +{ + // TODO: need to implement this + // get the type from the C API and return the Python type + //char *type; + char *message; + + PyObject * value = NULL; + FluidsimSettings * fluidsimSettings = self->bpyObject->object->fluidsimSettings; + + switch ( fluidsimSettings->type ) { + case PY_FLUID_TYPE_NONE: // TODO: need a OB type NONE + { + value = Py_BuildValue( "i", PY_FLUID_TYPE_NONE ); + } + break; + case OB_FLUIDSIM_DOMAIN: + { + value = Py_BuildValue( "i", PY_FLUID_TYPE_DOMAIN ); + } + break; + case OB_FLUIDSIM_FLUID: + { + value = Py_BuildValue( "i", PY_FLUID_TYPE_FLUID ); + } + break; + case OB_FLUIDSIM_OBSTACLE: + { + value = Py_BuildValue( "i", PY_FLUID_TYPE_OBSTACLE ); + } + break; + case OB_FLUIDSIM_INFLOW: + { + value = Py_BuildValue( "i", PY_FLUID_TYPE_INFLOW ); + } + break; + case OB_FLUIDSIM_OUTFLOW: + { + value = Py_BuildValue( "i", PY_FLUID_TYPE_OUTFLOW ); + } + break; + case OB_FLUIDSIM_PARTICLE: + { + value = Py_BuildValue( "i", PY_FLUID_TYPE_PARTICLE ); + } + break; + default: + value = Py_BuildValue( "" ); + break; + } + + return value; +} + + +static int Fluid_setType( BPy_Fluid * self, PyObject * value ) +{ + char message[2048]; + int type = 0; + FluidsimSettings * fluidsimSettings = NULL; + + if( ! PyInt_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, "Fluid.setType: expected an integer (short) as argument" ); + + type = ( int ) PyInt_AS_LONG( value ); // no error checking, already done, by check + //printf( "DEBUG: passed value=[%d]\n", type ); + + //#define OB_FLUIDSIM_ENABLE 1 + //#define OB_FLUIDSIM_DOMAIN 2 + //#define OB_FLUIDSIM_FLUID 4 + //#define OB_FLUIDSIM_OBSTACLE 8 + //#define OB_FLUIDSIM_INFLOW 16 + //#define OB_FLUIDSIM_OUTFLOW 32 + //#define OB_FLUIDSIM_PARTICLE 64 + fluidsimSettings = self->bpyObject->object->fluidsimSettings; + + switch ( type ) { + case PY_FLUID_TYPE_NONE: + fluidsimSettings->type = 0; + break; + case PY_FLUID_TYPE_DOMAIN: + fluidsimSettings->type = OB_FLUIDSIM_DOMAIN; + break; + case PY_FLUID_TYPE_FLUID: + fluidsimSettings->type = OB_FLUIDSIM_FLUID; + break; + case PY_FLUID_TYPE_OBSTACLE: + fluidsimSettings->type = OB_FLUIDSIM_OBSTACLE; + break; + case PY_FLUID_TYPE_INFLOW: + fluidsimSettings->type = OB_FLUIDSIM_INFLOW; + break; + case PY_FLUID_TYPE_OUTFLOW: + fluidsimSettings->type = OB_FLUIDSIM_OUTFLOW; + break; + case PY_FLUID_TYPE_PARTICLE: + fluidsimSettings->type = OB_FLUIDSIM_PARTICLE; + break; + default: + EXPP_ReturnIntError(PyExc_ValueError, "Fluid.setType: not valid value, check Fluid module constants" ); + break; + } + //printf( "DEBUG: set value=[%d]\n", fluidsimSettings->type ); + return 0; +} + +/* + * Get the object name + */ +static PyObject *Fluid_getName( BPy_Fluid * self ) +{ + // TODO: need to convert the aray to string + //printf( "DEBUG: Fluid::getName\n" ); + return PyString_FromString( self->bpyObject->object->id.name ); + +} + + +/* + * Get the bake path value + */ +static PyObject *Fluid_getBakePath( BPy_Fluid * self ) +{ + FluidsimSettings * fluidsimSettings = self->bpyObject->object->fluidsimSettings; + + // TODO: need to convert the aray to string + //printf( "DEBUG: Fluid::getBakePath\n" ); + //printf( "DEBUG: surf data path [%s]\n", fluidsimSettings->surfdataPath ); + + return PyString_FromString( fluidsimSettings->surfdataPath ); +} + +/* + * Set the bake path value + */ +static int Fluid_setBakePath( BPy_Fluid * self, PyObject * value ) +{ + char *path; + char message[512]; + FluidsimSettings * fluidsimSettings = self->bpyObject->object->fluidsimSettings; + + //printf( "DEBUG: Fluid::setBakePath\n" ); + path = PyString_AsString(value); + + if (!path) { + sprintf( message, "expected a string, got [%s]", path ); + return EXPP_ReturnIntError( PyExc_TypeError, "expected a string" ); + } + + // TODO: Check for the lenght < 240 see DNA_object_fluidsim.h + // TODO: need to convert the string to const + strcpy( fluidsimSettings->surfdataPath, path ); + + return 0; +} + +/**************************************************************************** +* Python BPy_Fluid methods: +*****************************************************************************/ + +/* + * Declarations + */ +static PyObject *Fluid_bake( BPy_Fluid * self ); + +/* + * Start the bake + */ +static PyObject *Fluid_bake( BPy_Fluid * self ) +{ + //int key = 0; + // Start baking + //printf("Fluid::bake() called\n" ); + fluidsimBake( self->bpyObject->object ); + + Py_RETURN_NONE; +} + + +/***************************************************************************** +* Python BPy_fluid standard python methods: +*****************************************************************************/ + +static int Fluid_compare( BPy_Fluid * a, BPy_Fluid * b ); +static PyObject *Fluid_repr( BPy_Fluid * self ); + +/* + * Compare Fluid objects + */ +static int Fluid_compare( BPy_Fluid * a, BPy_Fluid * b ) +{ + FluidsimSettings *pa = a->bpyObject->object->fluidsimSettings; + FluidsimSettings *pb = b->bpyObject->object->fluidsimSettings; + return ( pa == pb ) ? 0 : -1; +} + +/* + * String representation of object + */ +static PyObject *Fluid_repr( BPy_Fluid * self ) +{ + // TODO: access all the properties and print the string out + // This is a good way to excesie all the properties in a test also + PyObject *name = Fluid_getName( self ); + PyObject *type = Fluid_getType( self ); + PyObject *bakePath = Fluid_getBakePath( self ); + + PyObject *string = PyString_FromFormat( "[Fluid: object.name=%s, type=%ld, bakePath=%s]", + PyString_AsString( name ), + PyInt_AsLong( type ), + PyString_AsString( bakePath ) ); + + return string; +} + +/***************************************************************************** +* Python method structure: +*****************************************************************************/ +static PyMethodDef BPy_Fluid_methods[] = { + /* name, method, flags, doc */ + {"bake", ( PyCFunction ) Fluid_bake, METH_NOARGS, + "() - Start the bake process."}, + {NULL, NULL, 0, NULL} +}; + +/***************************************************************************** +* Python attributes get/set structure: +*****************************************************************************/ +static PyGetSetDef BPy_Fluid_getseters[] = { + GENERIC_LIB_GETSETATTR, + { "name", (getter)Fluid_getName, NULL, // Cant change the name + "object name", + NULL + }, + { "type", (getter)Fluid_getType, (setter)Fluid_setType, + "fluid type \"domain\" or \"fluid\"", + NULL + }, + { "bakePath", (getter)Fluid_getBakePath, (setter)Fluid_setBakePath, + "path where to save bake files", + NULL + }, + {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ +}; + + + +/**************************************************************************** +* Python Fluid_Type structure: +*****************************************************************************/ +PyTypeObject Fluid_Type = { + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ + /* For printing, in format "." */ + "Fluid", /* char *tp_name; */ + sizeof( BPy_Fluid ), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ + + /* Methods to implement standard operations */ + NULL, /* destructor tp_dealloc; */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + ( cmpfunc ) Fluid_compare, /* cmpfunc tp_compare; */ + ( reprfunc ) Fluid_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; */ + ( reprfunc ) Fluid_repr, /* 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_Fluid_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + BPy_Fluid_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 +}; + + + + Index: /home/jmonteath/workspace/blender-trunk/blender/source/blender/python/api2_2x/Fluid.h =================================================================== --- /home/jmonteath/workspace/blender-trunk/blender/source/blender/python/api2_2x/Fluid.h (revision 0) +++ /home/jmonteath/workspace/blender-trunk/blender/source/blender/python/api2_2x/Fluid.h (revision 0) @@ -0,0 +1,64 @@ +/* + * $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): James Monteath - ponderz + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ + +#ifndef EXPP_FLUID_H +#define EXPP_FLUID_H + +#include "Object.h" +#include "DNA_object_fluidsim.h" + +#include "LBM_fluidsim.h" +//#include "elbeem.h" + +extern PyTypeObject Fluid_Type; + +#define BPy_Fluid_Check(v) \ + ((v)->ob_type == &Fluid_Type) // for type checking + +/* Python BPy_Camera structure definition */ +typedef struct { + PyObject_HEAD // required py macro + BPy_Object * bpyObject; ///back refrence to blender python Object +} BPy_Fluid; + +/**************************************************************************** +* Python BPy_Fluid defaults: +*****************************************************************************/ + +/* Fluid types */ + +PyObject *Fluid_Init( void ); +PyObject *Fluid_CreatePyObject( BPy_Object * bpyObject ); + +#endif /* EXPP_FLUID_H */ + + Index: /home/jmonteath/workspace/blender-trunk/blender/source/blender/python/api2_2x/Object.c =================================================================== --- /home/jmonteath/workspace/blender-trunk/blender/source/blender/python/api2_2x/Object.c (revision 12026) +++ /home/jmonteath/workspace/blender-trunk/blender/source/blender/python/api2_2x/Object.c (working copy) @@ -43,6 +43,7 @@ #include "DNA_object_types.h" #include "DNA_view3d_types.h" #include "DNA_object_force.h" +#include "DNA_object_fluidsim.h" #include "DNA_userdef_types.h" #include "DNA_key_types.h" /* for pinShape and activeShape */ @@ -112,6 +113,7 @@ #include "NLA.h" #include "logic.h" #include "Effect.h" +#include "Fluid.h" #include "Group.h" #include "Modifier.h" #include "Constraint.h" @@ -455,6 +457,9 @@ static PyObject *Object_copyNLA( BPy_Object * self, PyObject * args ); static PyObject *Object_convertActionToStrip( BPy_Object * self ); static PyObject *Object_copy(BPy_Object * self); /* __copy__ */ +static PyObject *Object_getIsFluidEnabled(BPy_Object * self); +static int Object_setIsFluidEnabled(BPy_Object * self, PyObject * value ); +static PyObject *Object_getFluid(BPy_Object * self); /*****************************************************************************/ /* Python BPy_Object methods table: */ @@ -763,6 +768,8 @@ "() - Return a copy of this object."}, {"copy", ( PyCFunction ) Object_copy, METH_NOARGS, "() - Return a copy of this object."}, + {"getFluid", ( PyCFunction ) Object_getFluid, METH_NOARGS, + "Returns the fluid object"}, {NULL, NULL, 0, NULL} }; @@ -5076,7 +5083,14 @@ (getter)getIntAttr, (setter)setIntAttrClamp, "set the index for the active shape key", (void *)EXPP_OBJ_ATTR_ACT_SHAPE}, - + {"isFluidEnabled", + (getter)Object_getIsFluidEnabled, (setter)Object_setIsFluidEnabled, + "State of the fluid simulation for the object", + NULL}, + {"fluid", + (getter)Object_getFluid, (setter)NULL, + "Get the fluid object", + NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; @@ -5940,3 +5954,56 @@ return EXPP_setterWrapper( (void *)self, args, (setter)Object_setSBStiffQuads ); } + +static PyObject *Object_getIsFluidEnabled( BPy_Object * self ) +{ +// printf ( "DEBUG: get fluidsimFlag value is [%d]\n", self->object->fluidsimFlag ); +// printf ( "DEBUG: get fluidsimFlag & value is [%d]\n", self->object->fluidsimFlag & OB_FLUIDSIM_ENABLE ); +// printf ( "DEBUG: get fluidsimFlag | value is [%d]\n", self->object->fluidsimFlag | OB_FLUIDSIM_ENABLE ); + + // What if object was not setup yet ? + if ( self->object->fluidsimFlag & OB_FLUIDSIM_ENABLE ) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +/* + * Enable the fluid sim for this object. + */ +static int Object_setIsFluidEnabled( BPy_Object * self, PyObject * value ) +{ + int param = PyObject_IsTrue( value ); + if( param == -1 ) + return EXPP_ReturnIntError( PyExc_TypeError, "Object.setIsFluidEnabled: expected True/False or 0/1" ); + +// printf ( "DEBUG: set param value is [%d]\n", param ); +// printf ( "DEBUG: set fluidsimFlag value is [%d]\n", self->object->fluidsimFlag ); +// printf ( "DEBUG: set fluidsimFlag & value is [%d]\n", self->object->fluidsimFlag & OB_FLUIDSIM_ENABLE ); +// printf ( "DEBUG: set fluidsimFlag | value is [%d]\n", self->object->fluidsimFlag | OB_FLUIDSIM_ENABLE ); + + // This value is proper to set the flag directly + self->object->fluidsimFlag = param; + + return 0; +} + +/* + * Get the python Fluid object. + * + */ +static PyObject *Object_getFluid( BPy_Object * self ) +{ + // We need the blender object to build the Fluid object properly, + // since the fluidsim code needs a refrence to an object and not the just + // the FluidsimSettings. + + // TODO: we might be able to keep a refrence to the object so we don't have + // to recrete the instance again. + return Fluid_CreatePyObject( self ); + +} + + + + Index: /home/jmonteath/workspace/blender-trunk/blender/source/blender/python/SConscript =================================================================== --- /home/jmonteath/workspace/blender-trunk/blender/source/blender/python/SConscript (revision 12026) +++ /home/jmonteath/workspace/blender-trunk/blender/source/blender/python/SConscript (working copy) @@ -5,7 +5,9 @@ incs = 'api2_2x ../blenkernel ../blenlib ../blenloader' incs += ' ../render/extern/include ../radiosity/extern/include' -incs += ' ../makesdna #intern/guardedalloc #intern/bmfont ../imbuf ../include' +incs += ' ../makesdna #intern/guardedalloc #intern/bmfont ../imbuf' +incs += ' #intern/elbeem/extern' +incs += ' ../include' incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_OPENGL_INC']