---------- Add optional string argument to Object.newParticleSystem() method, so that objects can link to existing particle systems (if the name of the particle system is known). Also cleans up some code in Object.c which accesses the particle sys listbase.
2013 lines
52 KiB
C
2013 lines
52 KiB
C
/*
|
|
* $Id$
|
|
*
|
|
* ***** BEGIN GPL 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.
|
|
*
|
|
* 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):
|
|
* Original version: Jacques Guignot, Jean-Michel Soler
|
|
* Rewrite : Cedric Paille, Stephen Swaney, Joilnen Leite
|
|
*
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
*/
|
|
|
|
#include "Particle.h"
|
|
#include "gen_utils.h"
|
|
#include "BKE_object.h"
|
|
#include "BKE_main.h"
|
|
#include "BKE_particle.h"
|
|
#include "BKE_global.h"
|
|
#include "BKE_depsgraph.h"
|
|
#include "BKE_modifier.h"
|
|
#include "BKE_material.h"
|
|
#include "BKE_utildefines.h"
|
|
#include "BKE_pointcache.h"
|
|
#include "BKE_DerivedMesh.h"
|
|
#include "BIF_editparticle.h"
|
|
#include "BIF_space.h"
|
|
#include "blendef.h"
|
|
#include "DNA_modifier_types.h"
|
|
#include "DNA_scene_types.h"
|
|
#include "DNA_material_types.h"
|
|
#include "BLI_blenlib.h"
|
|
#include "mydevice.h"
|
|
#include "Object.h"
|
|
#include "Material.h"
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
/* Type Methods */
|
|
static PyObject *M_ParticleSys_New( PyObject * self, PyObject * args );
|
|
static PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args );
|
|
|
|
/* Particle Methods */
|
|
static PyObject *Part_freeEdit( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_GetLoc( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_GetRot( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_GetMat( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args );
|
|
static int Part_setSeed( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getSeed( BPy_PartSys * self );
|
|
static int Part_setType( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getType( BPy_PartSys * self );
|
|
static int Part_setResol( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getResol( BPy_PartSys * self );
|
|
static int Part_setStart( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getStart( BPy_PartSys * self );
|
|
static int Part_setEnd( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getEnd( BPy_PartSys * self );
|
|
static int Part_setEditable( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getEditable( BPy_PartSys * self );
|
|
static int Part_setAmount( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getAmount( BPy_PartSys * self );
|
|
static int Part_setMultiReact( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getMultiReact( BPy_PartSys * self );
|
|
static int Part_setReactShape( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getReactShape( BPy_PartSys * self );
|
|
static int Part_setSegments( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getSegments( BPy_PartSys * self );
|
|
static int Part_setLife( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getLife( BPy_PartSys * self );
|
|
static int Part_setRandLife( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getRandLife( BPy_PartSys * self );
|
|
static int Part_set2d( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_get2d( BPy_PartSys * self );
|
|
static int Part_setMaxVel( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getMaxVel( BPy_PartSys * self );
|
|
static int Part_setAvVel( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getAvVel( BPy_PartSys * self );
|
|
static int Part_setLatAcc( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getLatAcc( BPy_PartSys * self );
|
|
static int Part_setMaxTan( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getMaxTan( BPy_PartSys * self );
|
|
static int Part_setGroundZ( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getGroundZ( BPy_PartSys * self );
|
|
static int Part_setOb( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getOb( BPy_PartSys * self );
|
|
static PyObject *Part_getRandEmission( BPy_PartSys * self );
|
|
static int Part_setRandEmission( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getRandEmission( BPy_PartSys * self );
|
|
static int Part_setParticleDist( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getParticleDist( BPy_PartSys * self );
|
|
static int Part_setEvenDist( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getEvenDist( BPy_PartSys * self );
|
|
static int Part_setDist( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getDist( BPy_PartSys * self );
|
|
static int Part_setParticleDisp( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getParticleDisp( BPy_PartSys * self );
|
|
static int Part_setJitterAmount( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getJitterAmount( BPy_PartSys * self );
|
|
static int Part_setPF( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getPF( BPy_PartSys * self );
|
|
static int Part_setInvert( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getInvert( BPy_PartSys * self );
|
|
static int Part_setTargetOb( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getTargetOb( BPy_PartSys * self );
|
|
static int Part_setTargetPsys( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getTargetPsys( BPy_PartSys * self );
|
|
static int Part_setRenderObject( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getRenderObject( BPy_PartSys * self );
|
|
static int Part_setStep( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getStep( BPy_PartSys * self );
|
|
static int Part_setRenderStep( BPy_PartSys * self, PyObject * args );
|
|
static PyObject *Part_getRenderStep( BPy_PartSys * self );
|
|
static PyObject *Part_getDupOb( BPy_PartSys * self );
|
|
static PyObject *Part_getDrawAs( BPy_PartSys * self );
|
|
static PyObject *Part_GetAge( BPy_PartSys * self, PyObject * args );
|
|
|
|
/*****************************************************************************/
|
|
/* Python Effect_Type callback function prototypes: */
|
|
/*****************************************************************************/
|
|
static PyObject *ParticleSys_repr( BPy_PartSys * self );
|
|
|
|
/*****************************************************************************/
|
|
/* The following string definitions are used for documentation strings. */
|
|
/* In Python these will be written to the console when doing a */
|
|
/* Blender.Particle.__doc__ */
|
|
/*****************************************************************************/
|
|
static char M_ParticleSys_doc[] = "The Blender Effect module\n\n\
|
|
This module provides access to **Object Data** in Blender.\n\
|
|
Functions :\n\
|
|
Get(name) : retreives particle system (as list) with the given name\n";
|
|
static char M_ParticleSys_Get_doc[] = "xxx";
|
|
static char M_ParticleSys_New_doc[] = "xxx";
|
|
|
|
/*****************************************************************************/
|
|
/* Python BPy_ParticleSys methods table: */
|
|
/*****************************************************************************/
|
|
|
|
static PyMethodDef BPy_ParticleSys_methods[] = {
|
|
{"freeEdit", ( PyCFunction ) Part_freeEdit,
|
|
METH_NOARGS, "() - Free from edit mode"},
|
|
{"getLoc", ( PyCFunction ) Part_GetLoc,
|
|
METH_VARARGS, "() - Get particles location"},
|
|
{"getRot", ( PyCFunction ) Part_GetRot,
|
|
METH_VARARGS, "() - Get particles rotations (list of 4 floats quaternion)"},
|
|
{"getMat", ( PyCFunction ) Part_GetMat,
|
|
METH_NOARGS, "() - Get particles material"},
|
|
{"getSize", ( PyCFunction ) Part_GetSize,
|
|
METH_VARARGS, "() - Get particles size in a list"},
|
|
{"getAge", ( PyCFunction ) Part_GetAge,
|
|
METH_VARARGS, "() - Get particles life in a list"},
|
|
{NULL, NULL, 0, NULL}
|
|
};
|
|
|
|
/*****************************************************************************/
|
|
/* Python BPy_ParticleSys attributes get/set structure: */
|
|
/*****************************************************************************/
|
|
static PyGetSetDef BPy_ParticleSys_getseters[] = {
|
|
/* Extras */
|
|
{"seed",
|
|
(getter)Part_getSeed, (setter)Part_setSeed,
|
|
"Set an offset in the random table",
|
|
NULL},
|
|
/* basics */
|
|
{"type",
|
|
(getter)Part_getType, (setter)Part_setType,
|
|
"Type of particle system ( Particle.TYPE[ 'HAIR' | 'REACTOR' | 'EMITTER' ] )",
|
|
NULL},
|
|
{"resolutionGrid",
|
|
(getter)Part_getResol, (setter)Part_setResol,
|
|
"The resolution of the particle grid",
|
|
NULL},
|
|
{"startFrame",
|
|
(getter)Part_getStart, (setter)Part_setStart,
|
|
"Frame # to start emitting particles",
|
|
NULL},
|
|
{"endFrame",
|
|
(getter)Part_getEnd, (setter)Part_setEnd,
|
|
"Frame # to stop emitting particles",
|
|
NULL},
|
|
{"editable",
|
|
(getter)Part_getEditable, (setter)Part_setEditable,
|
|
"Finalize hair to enable editing in particle mode",
|
|
NULL},
|
|
{"amount",
|
|
(getter)Part_getAmount, (setter)Part_setAmount,
|
|
"The total number of particles",
|
|
NULL},
|
|
{"multireact",
|
|
(getter)Part_getMultiReact, (setter)Part_setMultiReact,
|
|
"React multiple times ( Paricle.REACTON[ 'NEAR' | 'COLLISION' | 'DEATH' ] )",
|
|
NULL},
|
|
{"reactshape",
|
|
(getter)Part_getReactShape, (setter)Part_setReactShape,
|
|
"Power of reaction strength dependence on distance to target",
|
|
NULL},
|
|
{"hairSegments",
|
|
(getter)Part_getSegments, (setter)Part_setSegments,
|
|
"Amount of hair segments",
|
|
NULL},
|
|
{"lifetime",
|
|
(getter)Part_getLife, (setter)Part_setLife,
|
|
"Specify the life span of the particles",
|
|
NULL},
|
|
{"randlife",
|
|
(getter)Part_getRandLife, (setter)Part_setRandLife,
|
|
"Give the particle life a random variation",
|
|
NULL},
|
|
{"randemission",
|
|
(getter)Part_getRandEmission, (setter)Part_setRandEmission,
|
|
"Give the particle life a random variation",
|
|
NULL},
|
|
{"particleDistribution",
|
|
(getter)Part_getParticleDist, (setter)Part_setParticleDist,
|
|
"Where to emit particles from Paricle.EMITFROM[ 'PARTICLE' | 'VOLUME' | 'FACES' | 'VERTS' ] )",
|
|
NULL},
|
|
{"evenDistribution",
|
|
(getter)Part_getEvenDist, (setter)Part_setEvenDist,
|
|
"Use even distribution from faces based on face areas or edge lengths",
|
|
NULL},
|
|
{"distribution",
|
|
(getter)Part_getDist, (setter)Part_setDist,
|
|
"How to distribute particles on selected element Paricle.DISTRIBUTION[ 'GRID' | 'RANDOM' | 'JITTERED' ] )",
|
|
NULL},
|
|
{"jitterAmount",
|
|
(getter)Part_getJitterAmount, (setter)Part_setJitterAmount,
|
|
"Amount of jitter applied to the sampling",
|
|
NULL},
|
|
{"pf",
|
|
(getter)Part_getPF, (setter)Part_setPF,
|
|
"Emission locations / face (0 = automatic)",
|
|
NULL},
|
|
{"invert",
|
|
(getter)Part_getInvert, (setter)Part_setInvert,
|
|
"Invert what is considered object and what is not.",
|
|
NULL},
|
|
{"targetObject",
|
|
(getter)Part_getTargetOb, (setter)Part_setTargetOb,
|
|
"The object that has the target particle system (empty if same object)",
|
|
NULL},
|
|
{"targetpsys",
|
|
(getter)Part_getTargetPsys, (setter)Part_setTargetPsys,
|
|
"The target particle system number in the object",
|
|
NULL},
|
|
/* Physics */
|
|
{"2d",
|
|
(getter)Part_get2d, (setter)Part_set2d,
|
|
"Constrain boids to a surface",
|
|
NULL},
|
|
{"maxvel",
|
|
(getter)Part_getMaxVel, (setter)Part_setMaxVel,
|
|
"Maximum velocity",
|
|
NULL},
|
|
{"avvel",
|
|
(getter)Part_getAvVel, (setter)Part_setAvVel,
|
|
"The usual speed % of max velocity",
|
|
NULL},
|
|
{"latacc",
|
|
(getter)Part_getLatAcc, (setter)Part_setLatAcc,
|
|
"Lateral acceleration % of max velocity",
|
|
NULL},
|
|
{"tanacc",
|
|
(getter)Part_getMaxTan, (setter)Part_setMaxTan,
|
|
"Tangential acceleration % of max velocity",
|
|
NULL},
|
|
{"groundz",
|
|
(getter)Part_getGroundZ, (setter)Part_setGroundZ,
|
|
"Default Z value",
|
|
NULL},
|
|
{"object",
|
|
(getter)Part_getOb, (setter)Part_setOb,
|
|
"Constrain boids to object's surface",
|
|
NULL},
|
|
/* Visualisation */
|
|
{"renderEmitter",
|
|
(getter)Part_getRenderObject, (setter)Part_setRenderObject,
|
|
"Render emitter object",
|
|
NULL},
|
|
{"displayPercentage",
|
|
(getter)Part_getParticleDisp, (setter)Part_setParticleDisp,
|
|
"Particle display percentage",
|
|
NULL},
|
|
{"hairDisplayStep",
|
|
(getter)Part_getStep, (setter)Part_setStep,
|
|
"How many steps paths are drawn with (power of 2)",
|
|
NULL},
|
|
{"hairRenderStep",
|
|
(getter)Part_getRenderStep, (setter)Part_setRenderStep,
|
|
"How many steps paths are rendered with (power of 2)",
|
|
NULL},
|
|
{"duplicateObject",
|
|
(getter)Part_getDupOb, NULL,
|
|
"Get the duplicate ob",
|
|
NULL},
|
|
{"drawAs",
|
|
(getter)Part_getDrawAs, NULL,
|
|
"Get draw type Particle.DRAWAS([ 'NONE' | 'OBJECT' | 'POINT' | ... ] )",
|
|
NULL},
|
|
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
|
|
};
|
|
|
|
/*****************************************************************************/
|
|
/* Python method structure definition for Blender.Particle module: */
|
|
/*****************************************************************************/
|
|
static struct PyMethodDef M_ParticleSys_methods[] = {
|
|
{"New", ( PyCFunction ) M_ParticleSys_New, METH_VARARGS, M_ParticleSys_New_doc},
|
|
{"Get", M_ParticleSys_Get, METH_VARARGS, M_ParticleSys_Get_doc},
|
|
{NULL, NULL, 0, NULL}
|
|
};
|
|
|
|
/*****************************************************************************/
|
|
/* Python ParticleSys_Type structure definition: */
|
|
/*****************************************************************************/
|
|
PyTypeObject ParticleSys_Type = {
|
|
PyObject_HEAD_INIT( NULL ) /* required py macro */
|
|
0, /* ob_size */
|
|
/* For printing, in format "<module>.<name>" */
|
|
"Blender ParticleSys", /* char *tp_name; */
|
|
sizeof( BPy_PartSys ), /* int tp_basicsize; */
|
|
0, /* tp_itemsize; For allocation */
|
|
|
|
/* Methods to implement standard operations */
|
|
|
|
NULL, /* destructor tp_dealloc; */
|
|
NULL, /* printfunc tp_print; */
|
|
NULL, /* getattrfunc tp_getattr; */
|
|
NULL, /* setattrfunc tp_setattr; */
|
|
NULL, /* cmpfunc tp_compare; */
|
|
( reprfunc ) ParticleSys_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_ParticleSys_methods, /* struct PyMethodDef *tp_methods; */
|
|
NULL, /* struct PyMemberDef *tp_members; */
|
|
BPy_ParticleSys_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: PARTICLESYS_repr */
|
|
/* Description: This is a callback function for the BPy_PartSys type. It */
|
|
/* builds a meaningful string to represent effect objects. */
|
|
/*****************************************************************************/
|
|
|
|
static PyObject *ParticleSys_repr( BPy_PartSys * self )
|
|
{
|
|
return PyString_FromFormat( "ParticleSys \"%s\"",
|
|
self->psys->part->id.name+2 );
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* Function : P_sys_FromPyObject */
|
|
/*****************************************************************************/
|
|
|
|
struct ParticleSystem *P_sys_FromPyObject( BPy_PartSys * py_obj )
|
|
{
|
|
BPy_PartSys *blen_obj;
|
|
|
|
blen_obj = ( BPy_PartSys * ) py_obj;
|
|
return ( blen_obj->psys );
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* Function : ParticleSysCreatePyObject */
|
|
/*****************************************************************************/
|
|
PyObject *ParticleSys_CreatePyObject( ParticleSystem * psystem, Object *ob )
|
|
{
|
|
BPy_PartSys *blen_object;
|
|
|
|
blen_object =
|
|
( BPy_PartSys * ) PyObject_NEW( BPy_PartSys, &ParticleSys_Type );
|
|
|
|
if( blen_object )
|
|
blen_object->psys = (ParticleSystem *)psystem;
|
|
|
|
blen_object->object = ob;
|
|
|
|
return ( PyObject * ) blen_object;
|
|
}
|
|
|
|
|
|
PyObject *M_ParticleSys_New( PyObject * self, PyObject * args ){
|
|
ParticleSystem *psys = 0;
|
|
ParticleSystem *rpsys = 0;
|
|
ModifierData *md;
|
|
ParticleSystemModifierData *psmd;
|
|
Object *ob = NULL;
|
|
char *name = NULL;
|
|
ID *id;
|
|
int nr;
|
|
|
|
if( !PyArg_ParseTuple( args, "s", &name ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected string argument" );
|
|
|
|
for( ob = G.main->object.first; ob; ob = ob->id.next )
|
|
if( !strcmp( name, ob->id.name + 2 ) )
|
|
break;
|
|
|
|
if( !ob )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"object does not exist" );
|
|
|
|
id = (ID *)psys_new_settings("PSys", G.main);
|
|
|
|
psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
|
|
psys->pointcache = BKE_ptcache_add();
|
|
psys->flag |= PSYS_ENABLED;
|
|
BLI_addtail(&ob->particlesystem,psys);
|
|
|
|
md = modifier_new(eModifierType_ParticleSystem);
|
|
sprintf(md->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
|
|
psmd = (ParticleSystemModifierData*) md;
|
|
psmd->psys=psys;
|
|
BLI_addtail(&ob->modifiers, md);
|
|
|
|
psys->part=(ParticleSettings*)id;
|
|
psys->totpart=0;
|
|
psys->flag=PSYS_ENABLED|PSYS_CURRENT;
|
|
psys->cfra=bsystem_time(ob,(float)G.scene->r.cfra+1,0.0);
|
|
rpsys = psys;
|
|
|
|
/* check need for dupliobjects */
|
|
|
|
nr=0;
|
|
for(psys=ob->particlesystem.first; psys; psys=psys->next){
|
|
if(ELEM(psys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR))
|
|
nr++;
|
|
}
|
|
if(nr)
|
|
ob->transflag |= OB_DUPLIPARTS;
|
|
else
|
|
ob->transflag &= ~OB_DUPLIPARTS;
|
|
|
|
BIF_undo_push("Browse Particle System");
|
|
|
|
DAG_scene_sort(G.scene);
|
|
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
|
|
|
return ParticleSys_CreatePyObject(rpsys,ob);
|
|
}
|
|
|
|
|
|
/*
|
|
|
|
Get( name ) returns named particle sys or list of all
|
|
throws NameError if name not found
|
|
|
|
*/
|
|
|
|
PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args )
|
|
{
|
|
#if 1
|
|
return EXPP_ReturnPyObjError( PyExc_NotImplementedError,
|
|
"Particle.Get() not implemented" );
|
|
#else
|
|
ParticleSettings *psys_iter;
|
|
char *name = NULL;
|
|
|
|
ParticleSystem *blparticlesys = 0;
|
|
Object *ob;
|
|
|
|
PyObject *partsyslist,*current;
|
|
|
|
if( !PyArg_ParseTuple( args, "|s", &name ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected string argument" );
|
|
|
|
psys_iter = G.main->particle.first; /* initialize our iterator */
|
|
|
|
if( name ) { /* find psys by name */
|
|
|
|
PyObject *wanted_obj = NULL;
|
|
|
|
while( psys_iter && ! wanted_obj ){
|
|
if( !strcmp( name, psys_iter->id.name + 2)){
|
|
printf("** found %s\n", psys_iter->id.name+2);
|
|
//wanted_obj = ParticleSys_CreatePyObject( psys_iter );
|
|
break;
|
|
}
|
|
psys_iter = psys_iter->id.next;
|
|
}
|
|
|
|
if( !wanted_obj){ /* requested object not found */
|
|
char error_msg[64];
|
|
PyOS_snprintf( error_msg, sizeof( error_msg ),
|
|
"Particle System '%s' not found", name);
|
|
return EXPP_ReturnPyObjError( PyExc_NameError, error_msg );
|
|
}
|
|
|
|
return wanted_obj;
|
|
|
|
}else { /* no arg - return a list of bpy objs all P. systems */
|
|
|
|
PyObject *pylist;
|
|
int index = 0;
|
|
|
|
pylist = PyList_New( BLI_countlist( &G.main->particle ));
|
|
printf("** list is %d long\n", PyList_Size( pylist));
|
|
if( ! pylist ){
|
|
return EXPP_ReturnPyObjError(
|
|
PyExc_MemoryError,
|
|
"could not create ParticleSystem list");
|
|
}
|
|
|
|
while( psys_iter ){
|
|
pyobj = ParticleSystem_CreatePyObject( psys_iter);
|
|
if( !pyobj){
|
|
Py_DECREF( pylist );
|
|
return EXPP_ReturnPyObjError(
|
|
PyExc_MemoryError,
|
|
"could not create ParticleSystem PyObject");
|
|
}
|
|
PyList_SET_ITEM( pylist, index, pyobj);
|
|
printf("name is %s\n", psys_iter->id.name+2);
|
|
psys_iter = psys_iter->id.next;
|
|
index++;
|
|
}
|
|
|
|
return pylist;
|
|
|
|
}
|
|
|
|
for( ob = G.main->particlesystem.first; ob; ob = ob->id.next )
|
|
if( !strcmp( name, ob->id.name + 2 ) )
|
|
break;
|
|
|
|
if( !ob )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"object does not exist" );
|
|
|
|
blparticlesys = ob->particlesystem.first;
|
|
|
|
|
|
partsyslist = PyList_New( 0 );
|
|
|
|
if (!blparticlesys)
|
|
return partsyslist;
|
|
|
|
current = ParticleSys_CreatePyObject( blparticlesys, ob );
|
|
PyList_Append(partsyslist,current);
|
|
|
|
|
|
while((blparticlesys = blparticlesys->next)){
|
|
current = ParticleSys_CreatePyObject( blparticlesys, ob );
|
|
PyList_Append(partsyslist,current);
|
|
}
|
|
|
|
return partsyslist;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Function: ParticleSys_Init */
|
|
/*****************************************************************************/
|
|
|
|
/* create the Blender.Particle.Type constant dict */
|
|
|
|
static PyObject *Particle_TypeDict( void )
|
|
{
|
|
PyObject *Types = PyConstant_New( );
|
|
|
|
if( Types ) {
|
|
BPy_constant *c = ( BPy_constant * ) Types;
|
|
|
|
PyConstant_Insert( c, "HAIR",
|
|
PyInt_FromLong( 2 ) );
|
|
PyConstant_Insert( c, "REACTOR",
|
|
PyInt_FromLong( 1 ) );
|
|
PyConstant_Insert( c, "EMITTER",
|
|
PyInt_FromLong( 0 ) );
|
|
}
|
|
return Types;
|
|
}
|
|
|
|
/* create the Blender.Particle.Distribution constant dict */
|
|
|
|
static PyObject *Particle_DistrDict( void )
|
|
{
|
|
PyObject *Distr = PyConstant_New( );
|
|
|
|
if( Distr ) {
|
|
BPy_constant *c = ( BPy_constant * ) Distr;
|
|
|
|
PyConstant_Insert( c, "GRID",
|
|
PyInt_FromLong( 2 ) );
|
|
PyConstant_Insert( c, "RANDOM",
|
|
PyInt_FromLong( 1 ) );
|
|
PyConstant_Insert( c, "JITTERED",
|
|
PyInt_FromLong( 0 ) );
|
|
}
|
|
return Distr;
|
|
}
|
|
|
|
/* create the Blender.Particle.EmitFrom constant dict */
|
|
|
|
static PyObject *Particle_EmitFrom( void )
|
|
{
|
|
PyObject *EmitFrom = PyConstant_New( );
|
|
|
|
if( EmitFrom ) {
|
|
BPy_constant *c = ( BPy_constant * ) EmitFrom;
|
|
|
|
PyConstant_Insert( c, "VERTS",
|
|
PyInt_FromLong( 0 ) );
|
|
PyConstant_Insert( c, "FACES",
|
|
PyInt_FromLong( 1 ) );
|
|
PyConstant_Insert( c, "VOLUME",
|
|
PyInt_FromLong( 2 ) );
|
|
PyConstant_Insert( c, "PARTICLE",
|
|
PyInt_FromLong( 3 ) );
|
|
}
|
|
return EmitFrom;
|
|
}
|
|
|
|
/* create the Blender.Particle.Collision constant dict */
|
|
|
|
static PyObject *Particle_ReactOnDict( void )
|
|
{
|
|
PyObject *ReactOn = PyConstant_New( );
|
|
|
|
if( ReactOn ) {
|
|
BPy_constant *c = ( BPy_constant * ) ReactOn;
|
|
|
|
PyConstant_Insert( c, "NEAR",
|
|
PyInt_FromLong( 2 ) );
|
|
PyConstant_Insert( c, "COLLISION",
|
|
PyInt_FromLong( 1 ) );
|
|
PyConstant_Insert( c, "DEATH",
|
|
PyInt_FromLong( 0 ) );
|
|
}
|
|
return ReactOn;
|
|
}
|
|
|
|
static PyObject *Particle_DrawAs( void )
|
|
{
|
|
PyObject *DrawAs = PyConstant_New( );
|
|
|
|
if( DrawAs ) {
|
|
BPy_constant *c = ( BPy_constant * ) DrawAs;
|
|
|
|
PyConstant_Insert( c, "NONE",
|
|
PyInt_FromLong( 0 ) );
|
|
PyConstant_Insert( c, "POINT",
|
|
PyInt_FromLong( 1 ) );
|
|
PyConstant_Insert( c, "CIRCLE",
|
|
PyInt_FromLong( 2 ) );
|
|
PyConstant_Insert( c, "CROSS",
|
|
PyInt_FromLong( 3 ) );
|
|
PyConstant_Insert( c, "AXIS",
|
|
PyInt_FromLong( 4 ) );
|
|
PyConstant_Insert( c, "LINE",
|
|
PyInt_FromLong( 5 ) );
|
|
PyConstant_Insert( c, "PATH",
|
|
PyInt_FromLong( 6 ) );
|
|
PyConstant_Insert( c, "OBJECT",
|
|
PyInt_FromLong( 7 ) );
|
|
PyConstant_Insert( c, "GROUP",
|
|
PyInt_FromLong( 8 ) );
|
|
PyConstant_Insert( c, "BILLBOARD",
|
|
PyInt_FromLong( 9 ) );
|
|
}
|
|
return DrawAs;
|
|
}
|
|
|
|
void Particle_Recalc(BPy_PartSys* self,int child){
|
|
psys_flush_settings(self->psys->part,0,child );
|
|
}
|
|
|
|
void Particle_RecalcPsys_distr(BPy_PartSys* self,int child){
|
|
psys_flush_settings(self->psys->part,PSYS_DISTR,child);
|
|
}
|
|
|
|
PyObject *ParticleSys_Init( void ){
|
|
PyObject *submodule;
|
|
PyObject *Types;
|
|
PyObject *React;
|
|
PyObject *EmitFrom;
|
|
PyObject *Dist;
|
|
PyObject *DrawAs;
|
|
|
|
if( PyType_Ready( &ParticleSys_Type ) < 0)
|
|
return NULL;
|
|
|
|
Types = Particle_TypeDict ();
|
|
React = Particle_ReactOnDict();
|
|
EmitFrom = Particle_EmitFrom();
|
|
DrawAs = Particle_DrawAs();
|
|
Dist = Particle_DistrDict();
|
|
|
|
submodule = Py_InitModule3( "Blender.Particle",
|
|
M_ParticleSys_methods, M_ParticleSys_doc );
|
|
|
|
if( Types )
|
|
PyModule_AddObject( submodule, "TYPE", Types );
|
|
if( React )
|
|
PyModule_AddObject( submodule, "REACTON", React );
|
|
if( EmitFrom )
|
|
PyModule_AddObject( submodule, "EMITFROM", EmitFrom );
|
|
if( Dist )
|
|
PyModule_AddObject( submodule, "DISTRIBUTION", Dist );
|
|
if( DrawAs )
|
|
PyModule_AddObject( submodule, "DRAWAS", DrawAs );
|
|
|
|
return ( submodule );
|
|
}
|
|
|
|
static PyObject *Part_freeEdit( BPy_PartSys * self, PyObject * args ){
|
|
|
|
if(self->psys->flag & PSYS_EDITED){
|
|
if(self->psys->edit)
|
|
PE_free_particle_edit(self->psys);
|
|
|
|
self->psys->flag &= ~PSYS_EDITED;
|
|
self->psys->recalc |= PSYS_RECALC_HAIR;
|
|
|
|
DAG_object_flush_update(G.scene, self->object, OB_RECALC_DATA);
|
|
}
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
static PyObject *Part_GetLoc( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
ParticleSystem *psys = 0L;
|
|
Object *ob = 0L;
|
|
PyObject *partlist,*seglist=0L;
|
|
ParticleCacheKey **cache,*path;
|
|
PyObject* loc = 0L;
|
|
ParticleKey state;
|
|
DerivedMesh* dm;
|
|
float cfra;
|
|
int i,j,k;
|
|
float vm[4][4],wm[4][4];
|
|
int childexists = 0;
|
|
int all = 0;
|
|
int id = 0;
|
|
|
|
cfra = bsystem_time(ob,(float)CFRA,0.0);
|
|
|
|
if( !PyArg_ParseTuple( args, "|ii", &all,&id ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected two optional integers as arguments" );
|
|
|
|
psys = self->psys;
|
|
ob = self->object;
|
|
|
|
if (!ob || !psys)
|
|
Py_RETURN_NONE;
|
|
|
|
G.rendering = 1;
|
|
|
|
/* Just to create a valid rendering context */
|
|
psys_render_set(ob,psys,vm,wm,0,0,0);
|
|
|
|
dm = mesh_create_derived_render(ob,CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
|
|
dm->release(dm);
|
|
|
|
if ( !psys_check_enabled(ob,psys) ){
|
|
G.rendering = 0;
|
|
psys_render_restore(ob,psys);
|
|
Particle_Recalc(self,1);
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
partlist = PyList_New( 0 );
|
|
if( !partlist ){
|
|
PyErr_SetString( PyExc_MemoryError, "PyList_New() failed" );
|
|
goto error;
|
|
}
|
|
|
|
if (psys->part->type == PART_HAIR){
|
|
cache = psys->pathcache;
|
|
|
|
if ( ((self->psys->part->draw & PART_DRAW_PARENT) && (self->psys->part->childtype != 0)) || (self->psys->part->childtype == 0) ){
|
|
|
|
for(i = 0; i < psys->totpart; i++){
|
|
seglist = PyList_New( 0 );
|
|
if (!seglist){
|
|
PyErr_SetString( PyExc_MemoryError,
|
|
"PyList_New() failed" );
|
|
goto error;
|
|
}
|
|
|
|
path=cache[i];
|
|
k = path->steps+1;
|
|
for( j = 0; j < k ; j++, path++){
|
|
loc = Py_BuildValue("(fff)",(double)path->co[0],
|
|
(double)path->co[1], (double)path->co[2]);
|
|
|
|
if (!loc){
|
|
PyErr_SetString( PyExc_RuntimeError,
|
|
"Couldn't build tuple" );
|
|
goto error;
|
|
}
|
|
|
|
if ( (PyList_Append(seglist,loc) < 0) ){
|
|
PyErr_SetString( PyExc_RuntimeError,
|
|
"Couldn't append item to PyList" );
|
|
goto error;
|
|
}
|
|
Py_DECREF(loc); /* PyList_Append increfs */
|
|
loc = NULL;
|
|
}
|
|
|
|
if ( PyList_Append(partlist,seglist) < 0 ){
|
|
PyErr_SetString( PyExc_RuntimeError,
|
|
"Couldn't append item to PyList" );
|
|
goto error;
|
|
}
|
|
Py_DECREF(seglist); /* PyList_Append increfs */
|
|
seglist = NULL;
|
|
}
|
|
}
|
|
|
|
cache=psys->childcache;
|
|
|
|
for(i = 0; i < psys->totchild; i++){
|
|
seglist = PyList_New( 0 );
|
|
if (!seglist){
|
|
PyErr_SetString( PyExc_MemoryError,
|
|
"PyList_New() failed" );
|
|
goto error;
|
|
}
|
|
|
|
path=cache[i];
|
|
k = path->steps+1;
|
|
for( j = 0; j < k ; j++, path++ ){
|
|
loc = Py_BuildValue("(fff)",(double)path->co[0],
|
|
(double)path->co[1], (double)path->co[2]);
|
|
|
|
if (!loc){
|
|
PyErr_SetString( PyExc_RuntimeError,
|
|
"Couldn't build tuple" );
|
|
goto error;
|
|
}
|
|
|
|
if ( PyList_Append(seglist,loc) < 0){
|
|
PyErr_SetString( PyExc_RuntimeError,
|
|
"Couldn't append item to PyList" );
|
|
goto error;
|
|
}
|
|
Py_DECREF(loc);/* PyList_Append increfs */
|
|
loc = NULL;
|
|
}
|
|
|
|
if ( PyList_Append(partlist,seglist) < 0){
|
|
PyErr_SetString( PyExc_RuntimeError,
|
|
"Couldn't append item to PyList" );
|
|
goto error;
|
|
}
|
|
Py_DECREF(seglist); /* PyList_Append increfs */
|
|
seglist = NULL;
|
|
}
|
|
} else {
|
|
int init;
|
|
char *fmt = NULL;
|
|
|
|
if(id)
|
|
fmt = "(fffi)";
|
|
else
|
|
fmt = "(fff)";
|
|
|
|
if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
|
|
childexists = 1;
|
|
|
|
for (i = 0; i < psys->totpart + psys->totchild; i++){
|
|
if (childexists && (i < psys->totpart))
|
|
continue;
|
|
|
|
state.time = cfra;
|
|
if(psys_get_particle_state(ob,psys,i,&state,0)==0)
|
|
init = 0;
|
|
else
|
|
init = 1;
|
|
|
|
if (init){
|
|
loc = Py_BuildValue(fmt,(double)state.co[0],
|
|
(double)state.co[1], (double)state.co[2],i);
|
|
|
|
if (!loc){
|
|
PyErr_SetString( PyExc_RuntimeError,
|
|
"Couldn't build tuple" );
|
|
goto error;
|
|
}
|
|
|
|
if ( PyList_Append(partlist,loc) < 0 ){
|
|
PyErr_SetString( PyExc_RuntimeError,
|
|
"Couldn't append item to PyList" );
|
|
goto error;
|
|
}
|
|
Py_DECREF(loc);
|
|
loc = NULL;
|
|
} else {
|
|
if ( all && PyList_Append(partlist,Py_None) < 0 ){
|
|
PyErr_SetString( PyExc_RuntimeError,
|
|
"Couldn't append item to PyList" );
|
|
goto error;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
psys_render_restore(ob,psys);
|
|
G.rendering = 0;
|
|
Particle_Recalc(self,1);
|
|
return partlist;
|
|
|
|
error:
|
|
Py_XDECREF(partlist);
|
|
Py_XDECREF(seglist);
|
|
Py_XDECREF(loc);
|
|
psys_render_restore(ob,psys);
|
|
G.rendering = 0;
|
|
Particle_Recalc(self,1);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *Part_GetRot( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
ParticleSystem *psys = 0L;
|
|
Object *ob = 0L;
|
|
PyObject *partlist = 0L;
|
|
PyObject* loc = 0L;
|
|
ParticleKey state;
|
|
DerivedMesh* dm;
|
|
float vm[4][4],wm[4][4];
|
|
int i;
|
|
int childexists = 0;
|
|
int all = 0;
|
|
int id = 0;
|
|
char *fmt = NULL;
|
|
|
|
float cfra=bsystem_time(ob,(float)CFRA,0.0);
|
|
|
|
if( !PyArg_ParseTuple( args, "|ii", &all, &id ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected two optional integers as arguments" );
|
|
|
|
psys = self->psys;
|
|
ob = self->object;
|
|
|
|
if (!ob || !psys)
|
|
Py_RETURN_NONE;
|
|
|
|
G.rendering = 1;
|
|
|
|
/* Just to create a valid rendering context */
|
|
psys_render_set(ob,psys,vm,wm,0,0,0);
|
|
|
|
dm = mesh_create_derived_render(ob,CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
|
|
dm->release(dm);
|
|
|
|
if ( !psys_check_enabled(ob,psys) ){
|
|
G.rendering = 0;
|
|
psys_render_restore(ob,psys);
|
|
Particle_Recalc(self,1);
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
if (psys->part->type != PART_HAIR){
|
|
partlist = PyList_New( 0 );
|
|
|
|
if( !partlist ){
|
|
PyErr_SetString( PyExc_MemoryError, "PyList_New() failed" );
|
|
goto error;
|
|
}
|
|
|
|
if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
|
|
childexists = 1;
|
|
|
|
if(id)
|
|
fmt = "(ffffi)";
|
|
else
|
|
fmt = "(ffff)";
|
|
|
|
for (i = 0; i < psys->totpart + psys->totchild; i++){
|
|
if (childexists && (i < psys->totpart))
|
|
continue;
|
|
|
|
state.time = cfra;
|
|
if(psys_get_particle_state(ob,psys,i,&state,0)==0){
|
|
if ( all && PyList_Append(partlist,Py_None) < 0){
|
|
PyErr_SetString( PyExc_RuntimeError,
|
|
"Couldn't append item to PyList" );
|
|
goto error;
|
|
}
|
|
} else {
|
|
loc = Py_BuildValue(fmt,(double)state.rot[0], (double)state.rot[1],
|
|
(double)state.rot[2], (double)state.rot[3], i);
|
|
|
|
if (!loc){
|
|
PyErr_SetString( PyExc_RuntimeError,
|
|
"Couldn't build tuple" );
|
|
goto error;
|
|
}
|
|
if (PyList_Append(partlist,loc) < 0){
|
|
PyErr_SetString ( PyExc_RuntimeError,
|
|
"Couldn't append item to PyList" );
|
|
goto error;
|
|
}
|
|
Py_DECREF(loc); /* PyList_Append increfs */
|
|
loc = NULL;
|
|
}
|
|
}
|
|
} else {
|
|
partlist = EXPP_incr_ret( Py_None );
|
|
}
|
|
|
|
psys_render_restore(ob,psys);
|
|
G.rendering = 0;
|
|
Particle_Recalc(self,1);
|
|
return partlist;
|
|
|
|
error:
|
|
Py_XDECREF(partlist);
|
|
Py_XDECREF(loc);
|
|
psys_render_restore(ob,psys);
|
|
G.rendering = 0;
|
|
Particle_Recalc(self,1);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
ParticleKey state;
|
|
ParticleSystem *psys = 0L;
|
|
ParticleData *data;
|
|
Object *ob = 0L;
|
|
PyObject *partlist,*tuple=0L;
|
|
DerivedMesh* dm;
|
|
float vm[4][4],wm[4][4];
|
|
float size;
|
|
int i;
|
|
int childexists = 0;
|
|
int all = 0;
|
|
int id = 0;
|
|
char *fmt = NULL;
|
|
|
|
float cfra=bsystem_time(ob,(float)CFRA,0.0);
|
|
|
|
if( !PyArg_ParseTuple( args, "|ii", &all, &id ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected two optional integers as arguments" );
|
|
|
|
psys = self->psys;
|
|
ob = self->object;
|
|
|
|
if (!ob || !psys)
|
|
Py_RETURN_NONE;
|
|
|
|
G.rendering = 1;
|
|
|
|
/* Just to create a valid rendering context */
|
|
psys_render_set(ob,psys,vm,wm,0,0,0);
|
|
|
|
dm = mesh_create_derived_render(ob,CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
|
|
dm->release(dm);
|
|
data = self->psys->particles;
|
|
|
|
if ( !psys_check_enabled(ob,psys) ){
|
|
psys_render_restore(ob,psys);
|
|
G.rendering = 0;
|
|
Particle_Recalc(self,1);
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
partlist = PyList_New( 0 );
|
|
|
|
if( !partlist ){
|
|
PyErr_SetString( PyExc_MemoryError, "PyList_New() failed" );
|
|
goto error;
|
|
}
|
|
|
|
if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
|
|
childexists = 1;
|
|
|
|
if(id)
|
|
fmt = "(fi)";
|
|
else
|
|
fmt = "f";
|
|
|
|
for (i = 0; i < psys->totpart + psys->totchild; i++, data++){
|
|
if (psys->part->type != PART_HAIR){
|
|
if (childexists && (i < psys->totpart))
|
|
continue;
|
|
|
|
if ( !all ){
|
|
state.time = cfra;
|
|
if(psys_get_particle_state(ob,psys,i,&state,0)==0)
|
|
continue;
|
|
}
|
|
|
|
if (i < psys->totpart){
|
|
size = data->size;
|
|
} else {
|
|
ChildParticle *cpa= &psys->child[i-psys->totpart];
|
|
size = psys_get_child_size(psys,cpa,cfra,0);
|
|
}
|
|
|
|
tuple = Py_BuildValue(fmt,(double)size,i);
|
|
|
|
if (!tuple){
|
|
PyErr_SetString( PyExc_RuntimeError,
|
|
"Couldn't build tuple" );
|
|
goto error;
|
|
}
|
|
|
|
if (PyList_Append(partlist,tuple) < 0){
|
|
PyErr_SetString( PyExc_RuntimeError,
|
|
"Couldn't append item to PyList" );
|
|
goto error;
|
|
}
|
|
Py_DECREF(tuple);
|
|
tuple = NULL;
|
|
}
|
|
}
|
|
|
|
psys_render_restore(ob,psys);
|
|
G.rendering = 0;
|
|
Particle_Recalc(self,1);
|
|
return partlist;
|
|
|
|
error:
|
|
Py_XDECREF(partlist);
|
|
Py_XDECREF(tuple);
|
|
psys_render_restore(ob,psys);
|
|
G.rendering = 0;
|
|
Particle_Recalc(self,1);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
static PyObject *Part_GetAge( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
ParticleKey state;
|
|
ParticleSystem *psys = 0L;
|
|
ParticleData *data;
|
|
Object *ob = 0L;
|
|
PyObject *partlist,*tuple=0L;
|
|
DerivedMesh* dm;
|
|
float vm[4][4],wm[4][4];
|
|
float life;
|
|
int i;
|
|
int childexists = 0;
|
|
int all = 0;
|
|
int id = 0;
|
|
char *fmt = NULL;
|
|
|
|
float cfra=bsystem_time(ob,(float)CFRA,0.0);
|
|
|
|
if( !PyArg_ParseTuple( args, "|ii", &all, &id ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"expected two optional integers as arguments" );
|
|
|
|
psys = self->psys;
|
|
ob = self->object;
|
|
|
|
if (!ob || !psys)
|
|
Py_RETURN_NONE;
|
|
|
|
G.rendering = 1;
|
|
|
|
/* Just to create a valid rendering context */
|
|
psys_render_set(ob,psys,vm,wm,0,0,0);
|
|
|
|
dm = mesh_create_derived_render(ob,CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
|
|
dm->release(dm);
|
|
data = self->psys->particles;
|
|
|
|
if ( !psys_check_enabled(ob,psys) ){
|
|
psys_render_restore(ob,psys);
|
|
G.rendering = 0;
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
partlist = PyList_New( 0 );
|
|
if( !partlist ){
|
|
PyErr_SetString( PyExc_MemoryError, "PyList_New() failed" );
|
|
goto error;
|
|
}
|
|
|
|
if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
|
|
childexists = 1;
|
|
|
|
if(id)
|
|
fmt = "(fi)";
|
|
else
|
|
fmt = "f";
|
|
|
|
for (i = 0; i < psys->totpart + psys->totchild; i++, data++){
|
|
if (psys->part->type != PART_HAIR){
|
|
|
|
if (childexists && (i < psys->totpart))
|
|
continue;
|
|
|
|
if ( !all ){
|
|
state.time = cfra;
|
|
if(psys_get_particle_state(ob,psys,i,&state,0)==0)
|
|
continue;
|
|
}
|
|
|
|
if (i < psys->totpart){
|
|
life = (cfra-data->time)/data->lifetime;
|
|
} else {
|
|
ChildParticle *cpa= &psys->child[i-psys->totpart];
|
|
life = psys_get_child_time(psys,cpa,cfra);
|
|
}
|
|
|
|
tuple = Py_BuildValue(fmt,(double)life,i);
|
|
|
|
if (!tuple){
|
|
PyErr_SetString( PyExc_RuntimeError,
|
|
"Couldn't build tuple" );
|
|
goto error;
|
|
}
|
|
|
|
if (PyList_Append(partlist,tuple) < 0){
|
|
PyErr_SetString( PyExc_RuntimeError,
|
|
"Couldn't append item to PyList" );
|
|
goto error;
|
|
}
|
|
Py_DECREF(tuple);
|
|
tuple = NULL;
|
|
}
|
|
}
|
|
|
|
psys_render_restore(ob,psys);
|
|
G.rendering = 0;
|
|
Particle_Recalc(self,1);
|
|
return partlist;
|
|
|
|
error:
|
|
Py_XDECREF(partlist);
|
|
Py_XDECREF(tuple);
|
|
psys_render_restore(ob,psys);
|
|
G.rendering = 0;
|
|
Particle_Recalc(self,1);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
static PyObject *Part_GetMat( BPy_PartSys * self, PyObject * args ){
|
|
Material *ma;
|
|
PyObject* mat = 0L;
|
|
ma = give_current_material(self->object,self->psys->part->omat);
|
|
if(!ma)
|
|
Py_RETURN_NONE;
|
|
|
|
mat = Material_CreatePyObject(ma);
|
|
return mat;
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Function: Set/Get Seed */
|
|
/*****************************************************************************/
|
|
|
|
static int Part_setSeed( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
return EXPP_setIValueRange( args, &self->psys->seed,
|
|
0, 255, 'i' );
|
|
}
|
|
|
|
static PyObject *Part_getSeed( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( (long)( self->psys->seed ) );
|
|
}
|
|
|
|
static int Part_setType( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setIValueRange( args, &self->psys->part->type,
|
|
0, 2, 'h' );
|
|
|
|
psys_flush_settings( self->psys->part, PSYS_TYPE, 1 );
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getType( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( (short)( self->psys->part->type ) );
|
|
}
|
|
|
|
static int Part_setResol( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setIValueRange( args, &self->psys->part->grid_res,
|
|
0, 100, 'i' );
|
|
|
|
psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getResol( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( ((int)( self->psys->part->grid_res )) );
|
|
}
|
|
|
|
static int Part_setStart( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setFloatRange( args, &self->psys->part->sta,
|
|
0.0f, 100000.0f );
|
|
|
|
psys_flush_settings(self->psys->part,PSYS_INIT,1);
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getStart( BPy_PartSys * self )
|
|
{
|
|
return PyFloat_FromDouble( (float)( self->psys->part->sta ) );
|
|
}
|
|
|
|
static int Part_setEnd( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setFloatRange( args, &self->psys->part->end,
|
|
0.0f, 100000.0f );
|
|
|
|
psys_flush_settings(self->psys->part,PSYS_INIT,1);
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getEnd( BPy_PartSys * self )
|
|
{
|
|
return PyFloat_FromDouble( (long)( self->psys->part->end ) );
|
|
}
|
|
|
|
static int Part_setEditable( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int number;
|
|
|
|
if( !PyInt_Check( args ) ) {
|
|
char errstr[128];
|
|
sprintf ( errstr, "expected int argument" );
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
}
|
|
|
|
number = PyInt_AS_LONG( args );
|
|
|
|
if(!number){
|
|
if(self->psys->edit)
|
|
PE_free_particle_edit(self->psys);
|
|
|
|
self->psys->flag &= ~PSYS_EDITED;
|
|
self->psys->recalc |= PSYS_RECALC_HAIR;
|
|
|
|
DAG_object_flush_update(G.scene, self->object, OB_RECALC_DATA);
|
|
}
|
|
else
|
|
{
|
|
self->psys->flag |= PSYS_EDITED;
|
|
if(G.f & G_PARTICLEEDIT)
|
|
PE_create_particle_edit(self->object, self->psys);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *Part_getEditable( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( ((long)( self->psys->flag & PSYS_EDITED )) > 0 );
|
|
}
|
|
|
|
static int Part_setAmount( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setIValueRange( args, &self->psys->part->totpart,
|
|
0, 100000, 'i' );
|
|
|
|
psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getAmount( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( ((int)( self->psys->part->totpart )) );
|
|
}
|
|
|
|
static int Part_setMultiReact( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int number;
|
|
|
|
if( !PyInt_Check( args ) ) {
|
|
char errstr[128];
|
|
sprintf ( errstr, "expected int argument" );
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
}
|
|
|
|
number = PyInt_AS_LONG( args );
|
|
|
|
|
|
if (number){
|
|
self->psys->part->flag |= PART_REACT_MULTIPLE;
|
|
}else{
|
|
self->psys->part->flag &= ~PART_REACT_MULTIPLE;
|
|
}
|
|
|
|
Particle_Recalc(self,1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *Part_getMultiReact( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( ((long)( self->psys->part->flag & PART_REACT_MULTIPLE )) > 0 );
|
|
}
|
|
|
|
static int Part_setReactShape( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setFloatRange( args, &self->psys->part->reactshape,
|
|
0.0f, 10.0f );
|
|
|
|
Particle_Recalc(self,1);
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getReactShape( BPy_PartSys * self )
|
|
{
|
|
return PyFloat_FromDouble( ((double)( self->psys->part->reactshape )) );
|
|
}
|
|
|
|
static int Part_setSegments( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setIValueRange( args, &self->psys->part->hair_step,
|
|
2, 50, 'h' );
|
|
|
|
Particle_Recalc(self,1);
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getSegments( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( ((long)( self->psys->part->hair_step )) );
|
|
}
|
|
|
|
static int Part_setLife( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setFloatRange( args, &self->psys->part->lifetime,
|
|
1.0f, MAXFRAMEF );
|
|
|
|
Particle_Recalc(self,1);
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getLife( BPy_PartSys * self )
|
|
{
|
|
return PyFloat_FromDouble( ((double)( self->psys->part->lifetime )) );
|
|
}
|
|
|
|
static int Part_setRandLife( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setFloatRange( args, &self->psys->part->randlife,
|
|
0.0f, 2.0f );
|
|
|
|
Particle_Recalc(self,1);
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getRandLife( BPy_PartSys * self )
|
|
{
|
|
return PyFloat_FromDouble( ((double)( self->psys->part->randlife )) );
|
|
}
|
|
|
|
static int Part_set2d( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int number;
|
|
|
|
if( !PyInt_Check( args ) )
|
|
return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" );
|
|
|
|
number = PyInt_AS_LONG( args );
|
|
|
|
if (number){
|
|
self->psys->part->flag |= PART_BOIDS_2D;
|
|
}else{
|
|
self->psys->part->flag &= ~PART_BOIDS_2D;
|
|
}
|
|
|
|
Particle_Recalc(self,1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *Part_get2d( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( ((long)( self->psys->part->flag & PART_BOIDS_2D )) > 0 );
|
|
}
|
|
|
|
static int Part_setMaxVel( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setFloatRange( args, &self->psys->part->max_vel,
|
|
0.0f, 200.0f );
|
|
|
|
Particle_Recalc(self,1);
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getMaxVel( BPy_PartSys * self )
|
|
{
|
|
return PyFloat_FromDouble( ((double)( self->psys->part->max_vel )) );
|
|
}
|
|
|
|
static int Part_setAvVel( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setFloatRange( args, &self->psys->part->average_vel,
|
|
0.0f, 1.0f );
|
|
|
|
Particle_Recalc(self,1);
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getAvVel( BPy_PartSys * self )
|
|
{
|
|
return PyFloat_FromDouble( ((double)( self->psys->part->average_vel )) );
|
|
}
|
|
|
|
static int Part_setLatAcc( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setFloatRange( args, &self->psys->part->max_lat_acc,
|
|
0.0f, 1.0f );
|
|
|
|
Particle_Recalc(self,1);
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getLatAcc( BPy_PartSys * self )
|
|
{
|
|
return PyFloat_FromDouble( ((double)( self->psys->part->max_lat_acc )) );
|
|
}
|
|
|
|
static int Part_setMaxTan( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setFloatRange( args, &self->psys->part->max_tan_acc,
|
|
0.0f, 1.0f );
|
|
|
|
Particle_Recalc(self,1);
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getMaxTan( BPy_PartSys * self )
|
|
{
|
|
return PyFloat_FromDouble( ((double)( self->psys->part->max_tan_acc )) );
|
|
}
|
|
|
|
static int Part_setGroundZ( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setFloatRange( args, &self->psys->part->groundz,
|
|
-100.0f, 100.0f );
|
|
|
|
Particle_Recalc(self,1);
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getGroundZ( BPy_PartSys * self )
|
|
{
|
|
return PyFloat_FromDouble( ((double)( self->psys->part->groundz )) );
|
|
}
|
|
|
|
static int Part_setOb( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
Object *obj;
|
|
if( !BPy_Object_Check( args ) ) {
|
|
char errstr[128];
|
|
sprintf ( errstr, "expected object argument" );
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
}
|
|
|
|
obj = Object_FromPyObject(args);
|
|
|
|
self->psys->keyed_ob = obj;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *Part_getOb( BPy_PartSys * self )
|
|
{
|
|
Object * obj;
|
|
obj = self->psys->keyed_ob;
|
|
if (!obj)
|
|
Py_RETURN_NONE;
|
|
|
|
return Object_CreatePyObject( obj );
|
|
}
|
|
|
|
static int Part_setRandEmission( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int number;
|
|
|
|
if( !PyInt_Check( args ) ) {
|
|
char errstr[128];
|
|
sprintf ( errstr, "expected int argument" );
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
}
|
|
|
|
number = PyInt_AS_LONG( args );
|
|
|
|
if (number){
|
|
self->psys->part->flag |= PART_TRAND;
|
|
}else{
|
|
self->psys->part->flag &= ~PART_TRAND;
|
|
}
|
|
|
|
Particle_RecalcPsys_distr(self,1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *Part_getRandEmission( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( ((long)( self->psys->part->flag & PART_TRAND )) > 0 );
|
|
}
|
|
|
|
static int Part_setParticleDist( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int number;
|
|
char errstr[128];
|
|
|
|
if( !PyInt_Check( args ) ) {
|
|
sprintf ( errstr, "expected int argument" );
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
}
|
|
|
|
number = PyInt_AS_LONG( args );
|
|
|
|
if (number < 0 || number > 3){
|
|
sprintf ( errstr, "expected int argument between 0 - 3" );
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
}
|
|
|
|
self->psys->part->from = (short)number;
|
|
|
|
Particle_RecalcPsys_distr(self,1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *Part_getParticleDist( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( (long)( self->psys->part->from ) );
|
|
}
|
|
|
|
static int Part_setEvenDist( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int number;
|
|
|
|
if( !PyInt_Check( args ) ) {
|
|
char errstr[128];
|
|
sprintf ( errstr, "expected int argument" );
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
}
|
|
|
|
number = PyInt_AS_LONG( args );
|
|
|
|
if (number){
|
|
self->psys->part->flag |= PART_EDISTR;
|
|
}else{
|
|
self->psys->part->flag &= ~PART_EDISTR;
|
|
}
|
|
|
|
Particle_RecalcPsys_distr(self,1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *Part_getEvenDist( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( ((long)( self->psys->part->flag & PART_EDISTR )) > 0 );
|
|
}
|
|
|
|
static int Part_setDist( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int number;
|
|
char errstr[128];
|
|
|
|
if( !PyInt_Check( args ) ) {
|
|
sprintf ( errstr, "expected int argument" );
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
}
|
|
|
|
number = PyInt_AS_LONG( args );
|
|
|
|
if (number < 0 || number > 2){
|
|
sprintf ( errstr, "expected int argument between 0 - 2" );
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
}
|
|
|
|
self->psys->part->distr = (short)number;
|
|
|
|
Particle_RecalcPsys_distr(self,1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *Part_getDist( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( (long)( self->psys->part->distr ) );
|
|
}
|
|
|
|
static int Part_setJitterAmount( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setFloatRange( args, &self->psys->part->jitfac,
|
|
0.0f, 2.0f );
|
|
|
|
Particle_RecalcPsys_distr(self,1);
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getJitterAmount( BPy_PartSys * self )
|
|
{
|
|
return PyFloat_FromDouble( ((double)( self->psys->part->jitfac )) );
|
|
}
|
|
|
|
|
|
|
|
static int Part_setPF( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setIValueRange( args, &self->psys->part->userjit,
|
|
0, 1000, 'i' );
|
|
|
|
Particle_RecalcPsys_distr(self,1);
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getPF( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( ((short)( self->psys->part->userjit )) );
|
|
}
|
|
|
|
static int Part_setInvert( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int number;
|
|
|
|
if( !PyInt_Check( args ) ) {
|
|
char errstr[128];
|
|
sprintf ( errstr, "expected int argument" );
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
}
|
|
|
|
number = PyInt_AS_LONG( args );
|
|
|
|
if (number){
|
|
self->psys->part->flag |= PART_GRID_INVERT;
|
|
}else{
|
|
self->psys->part->flag &= ~PART_GRID_INVERT;
|
|
}
|
|
|
|
Particle_RecalcPsys_distr(self,1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *Part_getInvert( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( ((long)( self->psys->part->flag & PART_GRID_INVERT )) > 0 );
|
|
}
|
|
|
|
static int Part_setTargetOb( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
Object *obj;
|
|
if( !BPy_Object_Check( args ) ) {
|
|
char errstr[128];
|
|
sprintf ( errstr, "expected object argument" );
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
}
|
|
|
|
obj = Object_FromPyObject(args);
|
|
|
|
self->psys->target_ob = obj;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *Part_getTargetOb( BPy_PartSys * self )
|
|
{
|
|
Object * obj;
|
|
obj = self->psys->target_ob;
|
|
if (!obj)
|
|
Py_RETURN_NONE;
|
|
|
|
return Object_CreatePyObject( obj );
|
|
}
|
|
|
|
|
|
|
|
PyObject *Part_getDupOb( BPy_PartSys * self )
|
|
{
|
|
Object * obj;
|
|
obj = self->psys->part->dup_ob;
|
|
if (!obj)
|
|
Py_RETURN_NONE;
|
|
|
|
return Object_CreatePyObject( obj );
|
|
}
|
|
|
|
static int Part_setTargetPsys( BPy_PartSys * self, PyObject * args ){
|
|
int tottpsys;
|
|
int res;
|
|
Object *tob=0;
|
|
ParticleSystem *psys = self->psys;
|
|
Object *ob;
|
|
|
|
ob = self->object;
|
|
|
|
if(psys->target_ob)
|
|
tob=psys->target_ob;
|
|
else
|
|
tob=ob;
|
|
|
|
tottpsys = BLI_countlist(&tob->particlesystem);
|
|
|
|
res = EXPP_setIValueRange( args, &self->psys->target_psys, 0, tottpsys, 'h' );
|
|
|
|
if( ( psys = psys_get_current(ob) ) ){
|
|
if(psys->keyed_ob==ob || psys->target_ob==ob){
|
|
if(psys->keyed_ob==ob)
|
|
psys->keyed_ob=NULL;
|
|
else
|
|
psys->target_ob=NULL;
|
|
}
|
|
else{
|
|
DAG_scene_sort(G.scene);
|
|
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getTargetPsys( BPy_PartSys * self ){
|
|
return PyInt_FromLong( (short)( self->psys->target_psys ) );
|
|
}
|
|
|
|
static int Part_setRenderObject( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int number,nr;
|
|
ParticleSystem *psys = 0L;
|
|
|
|
if( !PyInt_Check( args ) ) {
|
|
char errstr[128];
|
|
sprintf ( errstr, "expected int argument" );
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
}
|
|
|
|
number = PyInt_AS_LONG( args );
|
|
|
|
if (number){
|
|
self->psys->part->draw |= PART_DRAW_EMITTER;
|
|
}else{
|
|
self->psys->part->draw &= ~PART_DRAW_EMITTER;
|
|
}
|
|
|
|
/* check need for dupliobjects */
|
|
nr=0;
|
|
for(psys=self->object->particlesystem.first; psys; psys=psys->next){
|
|
if(ELEM(psys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR))
|
|
nr++;
|
|
}
|
|
if(nr)
|
|
self->object->transflag |= OB_DUPLIPARTS;
|
|
else
|
|
self->object->transflag &= ~OB_DUPLIPARTS;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *Part_getRenderObject( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( ((long)( self->psys->part->draw & PART_DRAW_EMITTER )) > 0 );
|
|
}
|
|
|
|
static int Part_setParticleDisp( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setIValueRange( args, &self->psys->part->disp,
|
|
0, 100, 'i' );
|
|
|
|
Particle_Recalc(self,0);
|
|
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getParticleDisp( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( ((short)( self->psys->part->disp )) );
|
|
}
|
|
|
|
static int Part_setStep( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setIValueRange( args, &self->psys->part->draw_step,
|
|
0, 7, 'i' );
|
|
|
|
Particle_Recalc(self,1);
|
|
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getStep( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( ((short)( self->psys->part->draw_step )) );
|
|
}
|
|
|
|
static int Part_setRenderStep( BPy_PartSys * self, PyObject * args )
|
|
{
|
|
int res = EXPP_setIValueRange( args, &self->psys->part->ren_step,
|
|
0, 7, 'i' );
|
|
|
|
/*Particle_Recalc(self,1);*/
|
|
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject *Part_getRenderStep( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( ((short)( self->psys->part->ren_step )) );
|
|
}
|
|
|
|
static PyObject *Part_getDrawAs( BPy_PartSys * self )
|
|
{
|
|
return PyInt_FromLong( (long)( self->psys->part->draw_as ) );
|
|
}
|