From 9967037e92ad75e76c3536a93a63a7100e4ccdc9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 24 Aug 2009 10:16:39 +0000 Subject: [PATCH 1/8] [#19029] Baking selected to active with nearby dupliframes objects crashes blender from Jorge Hodge (watcom) Confirmed the crash. baking didn't account for RE_RAY_TRANSFORM_OFFS in R.objectinstance. --- source/blender/render/intern/source/rendercore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 2793e238dc7..6b6a736a420 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -2241,7 +2241,7 @@ static int bake_check_intersect(Isect *is, int ob, RayFace *face) /* no direction checking for now, doesn't always improve the result * (INPR(shi->facenor, bs->dir) > 0.0f); */ - return (R.objectinstance[ob].obr->ob != bs->actob); + return (R.objectinstance[ob & ~RE_RAY_TRANSFORM_OFFS].obr->ob != bs->actob); } static int bake_intersect_tree(RayTree* raytree, Isect* isect, float *start, float *dir, float sign, float *hitco, float *dist) From 9261efa4d6dd59f9284443fea85a24282eb72d27 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 24 Aug 2009 10:37:39 +0000 Subject: [PATCH 2/8] [#18936] Particle Related Patch from Alberto Santos (dnakhain) This also adds the option to duplicate a particle system with an object. --- description from the patch submission. This patch includes my latest additions to the Python API developed for my Degree's Project. It includes: - Particle - Vertex group dictionary in doc (to use with setvertexgroup/getvertexgroup) - Particle.New return psys (not specified in doc) - Draw As variable and dict - Strand render toggle - Object - psys variable in duplicate - Material - Strand render variables - Texture - Use colorbands - Lamp - Spot buffer type selection --- source/blender/makesdna/DNA_userdef_types.h | 1 + source/blender/python/api2_2x/Lamp.c | 41 +++- source/blender/python/api2_2x/Material.c | 203 ++++++++++++++++++ source/blender/python/api2_2x/Object.c | 10 +- source/blender/python/api2_2x/Particle.c | 100 ++++++++- source/blender/python/api2_2x/Texture.c | 29 +++ source/blender/python/api2_2x/doc/Lamp.py | 7 + source/blender/python/api2_2x/doc/Material.py | 18 ++ source/blender/python/api2_2x/doc/Object.py | 5 +- source/blender/python/api2_2x/doc/Particle.py | 32 ++- source/blender/python/api2_2x/doc/Texture.py | 2 + source/blender/src/editobject.c | 11 + 12 files changed, 450 insertions(+), 9 deletions(-) diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index fbd962f9372..a986f993722 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -313,6 +313,7 @@ extern UserDef U; /* from usiblender.c !!!! */ #define USER_DUP_TEX (1 << 8) #define USER_DUP_ARM (1 << 9) #define USER_DUP_ACT (1 << 10) +#define USER_DUP_PSYS (1 << 11) /* gameflags */ #define USER_DEPRECATED_FLAG 1 diff --git a/source/blender/python/api2_2x/Lamp.c b/source/blender/python/api2_2x/Lamp.c index 3b7a785f32e..d3acc089944 100644 --- a/source/blender/python/api2_2x/Lamp.c +++ b/source/blender/python/api2_2x/Lamp.c @@ -125,6 +125,8 @@ #define EXPP_LAMP_COL_MAX 1.0 #define EXPP_LAMP_FALLOFF_MIN LA_FALLOFF_CONSTANT #define EXPP_LAMP_FALLOFF_MAX LA_FALLOFF_SLIDERS +#define EXPP_LAMP_BUFFERTYPE_MIN LA_SHADBUF_REGULAR +#define EXPP_LAMP_BUFFERTYPE_MAX LA_SHADBUF_HALFWAY /* Raytracing settings */ #define EXPP_LAMP_RAYSAMPLES_MIN 1 @@ -268,6 +270,8 @@ static PyObject *Lamp_clearScriptLinks( BPy_Lamp * self, PyObject * args ); static int Lamp_setComponent( BPy_Lamp * self, PyObject * value, void * closure ); static PyObject *Lamp_getFalloffType( BPy_Lamp * self ); static int Lamp_setFalloffType( BPy_Lamp * self, PyObject * value ); +static PyObject *Lamp_getBufferType( BPy_Lamp * self ); +static int Lamp_setBufferType( BPy_Lamp * self, PyObject * value ); /*****************************************************************************/ /* Python BPy_Lamp methods table: */ @@ -489,6 +493,10 @@ static PyGetSetDef BPy_Lamp_getseters[] = { (getter)Lamp_getFalloffType, (setter)Lamp_setFalloffType, "Lamp falloff type", NULL}, + {"bufferType", + (getter)Lamp_getBufferType, (setter)Lamp_setBufferType, + "Lamp buffer type", + NULL}, {"R", (getter)Lamp_getComponent, (setter)Lamp_setComponent, "Lamp color red component", @@ -828,13 +836,31 @@ static PyObject *Lamp_FalloffsDict( void ) return Falloffs; } +static PyObject *Lamp_BufferTypesDict( void ) +{ /* create the Blender.Lamp.BufferTypes constant dict */ + PyObject *Types = PyConstant_New( ); + + if( Types ) { + BPy_constant *c = ( BPy_constant * ) Types; + + PyConstant_Insert( c, "REGULAR", + PyInt_FromLong( LA_SHADBUF_REGULAR ) ); + PyConstant_Insert( c, "IRREGULAR", + PyInt_FromLong( LA_SHADBUF_IRREGULAR ) ); + PyConstant_Insert( c, "HALFWAY", + PyInt_FromLong( LA_SHADBUF_HALFWAY ) ); + } + + return Types; +} + /*****************************************************************************/ /* Function: Lamp_Init */ /*****************************************************************************/ /* Needed by the Blender module, to register the Blender.Lamp submodule */ PyObject *Lamp_Init( void ) { - PyObject *submodule, *Types, *Modes, *Falloffs; + PyObject *submodule, *Types, *Modes, *Falloffs, *BufferTypes; if( PyType_Ready( &Lamp_Type ) < 0) return NULL; @@ -842,6 +868,7 @@ PyObject *Lamp_Init( void ) Types = Lamp_TypesDict( ); Modes = Lamp_ModesDict( ); Falloffs = Lamp_FalloffsDict( ); + BufferTypes = Lamp_BufferTypesDict( ); submodule = Py_InitModule3( "Blender.Lamp", M_Lamp_methods, M_Lamp_doc ); @@ -852,6 +879,8 @@ PyObject *Lamp_Init( void ) PyModule_AddObject( submodule, "Modes", Modes ); if( Falloffs ) PyModule_AddObject( submodule, "Falloffs", Falloffs ); + if( BufferTypes ) + PyModule_AddObject( submodule, "BufferTypes", BufferTypes ); PyModule_AddIntConstant( submodule, "RGB", IPOKEY_RGB ); PyModule_AddIntConstant( submodule, "ENERGY", IPOKEY_ENERGY ); @@ -1029,6 +1058,11 @@ static PyObject *Lamp_getFalloffType( BPy_Lamp * self ) return PyInt_FromLong( (int)self->lamp->falloff_type ); } +static PyObject *Lamp_getBufferType( BPy_Lamp * self ) +{ + return PyInt_FromLong( (int)self->lamp->buftype ); +} + static int Lamp_setType( BPy_Lamp * self, PyObject * value ) { return EXPP_setIValueRange ( value, &self->lamp->type, @@ -1217,6 +1251,11 @@ static int Lamp_setFalloffType( BPy_Lamp * self, PyObject * value ) EXPP_LAMP_FALLOFF_MIN, EXPP_LAMP_FALLOFF_MAX, 'h' ); } +static int Lamp_setBufferType( BPy_Lamp * self, PyObject * value ) +{ + return EXPP_setIValueRange ( value, &self->lamp->buftype, + EXPP_LAMP_BUFFERTYPE_MIN, EXPP_LAMP_BUFFERTYPE_MAX, 'h' ); +} static PyObject *Lamp_getComponent( BPy_Lamp * self, void * closure ) { diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c index 50a1be3fa97..cc0dd9ff6a5 100644 --- a/source/blender/python/api2_2x/Material.c +++ b/source/blender/python/api2_2x/Material.c @@ -747,6 +747,26 @@ static PyObject *Material_getColorbandSpecularInput( BPy_Material * self ); static int Material_setColorbandDiffuseInput ( BPy_Material * self, PyObject * value); static int Material_setColorbandSpecularInput ( BPy_Material * self, PyObject * value); +static PyObject *Material_getStrandTangentShad( BPy_Material * self ); +static int Material_setStrandTangentShad( BPy_Material * self, PyObject * value); +static PyObject *Material_getStrandSurfDiff( BPy_Material * self ); +static int Material_setStrandSurfDiff( BPy_Material * self, PyObject * value); +static PyObject *Material_getStrandDist( BPy_Material * self ); +static int Material_setStrandDist( BPy_Material * self, PyObject * value); +static PyObject *Material_getStrandBlendUnit( BPy_Material * self ); +static int Material_setStrandBlendUnit( BPy_Material * self, PyObject * value); +static PyObject *Material_getStrandStart( BPy_Material * self ); +static int Material_setStrandStart( BPy_Material * self, PyObject * value); +static PyObject *Material_getStrandEnd( BPy_Material * self ); +static int Material_setStrandEnd( BPy_Material * self, PyObject * value); +static PyObject *Material_getStrandMin( BPy_Material * self ); +static int Material_setStrandMin( BPy_Material * self, PyObject * value); +static PyObject *Material_getStrandShape( BPy_Material * self ); +static int Material_setStrandShape( BPy_Material * self, PyObject * value); +static PyObject *Material_getStrandWidthFad( BPy_Material * self ); +static int Material_setStrandWidthFad( BPy_Material * self, PyObject * value); +static PyObject *Material_getStrandUV( BPy_Material * self ); +static int Material_setStrandUV( BPy_Material * self, PyObject * value); /*****************************************************************************/ @@ -1313,6 +1333,46 @@ static PyGetSetDef BPy_Material_getseters[] = { (getter)Material_getColorbandDiffuseInput, (setter)Material_setColorbandDiffuseInput, "The diffuse colorband input for this material", NULL}, + {"strandTanShad", + (getter)Material_getStrandTangentShad, (setter)Material_setStrandTangentShad, + "Uses direction of strands as normal for tangent-shading", + NULL}, + {"strandSurfDiff", + (getter)Material_getStrandSurfDiff, (setter)Material_setStrandSurfDiff, + "Make diffuse shading more similar to shading the surface", + NULL}, + {"strandDist", + (getter)Material_getStrandDist, (setter)Material_setStrandDist, + "Distance in Blender units over which to blend in the surface normal", + NULL}, + {"strandBlendUnit", + (getter)Material_getStrandBlendUnit, (setter)Material_setStrandBlendUnit, + "Use actual Blender units for widths instead of pixels", + NULL}, + {"strandStart", + (getter)Material_getStrandStart, (setter)Material_setStrandStart, + "Start size of strands", + NULL}, + {"strandEnd", + (getter)Material_getStrandEnd, (setter)Material_setStrandEnd, + "End size of strands", + NULL}, + {"strandMin", + (getter)Material_getStrandMin, (setter)Material_setStrandMin, + "Minimum size of strands in pixels", + NULL}, + {"strandShape", + (getter)Material_getStrandShape, (setter)Material_setStrandShape, + "Shape of strands, positive value makes it rounder, negative makes it spiky", + NULL}, + {"strandFade", + (getter)Material_getStrandWidthFad, (setter)Material_setStrandWidthFad, + "Transparency along the width of the strand", + NULL}, + {"strandUV", + (getter)Material_getStrandUV, (setter)Material_setStrandUV, + "Set name of UV layer to override", + NULL}, /* SSS settings */ {"enableSSS", @@ -3582,3 +3642,146 @@ static int Material_setColorbandSpecularInput ( BPy_Material * self, PyObject * return EXPP_setIValueClamped(value, &self->material->rampin_spec, MA_RAMP_IN_SHADER, MA_RAMP_IN_RESULT, 'b'); } + +/* Strand */ + +static PyObject *Material_getStrandTangentShad( BPy_Material * self ) +{ + return PyInt_FromLong( ((long)( self->material->mode & MA_TANGENT_STR )) > 0 ); +} + +static int Material_setStrandTangentShad( BPy_Material * self, PyObject * value) +{ + int number; + + if( !PyInt_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" ); + + number = PyInt_AS_LONG( value ); + + if (number){ + self->material->mode |= MA_TANGENT_STR; + }else{ + self->material->mode &= ~MA_TANGENT_STR; + } + + return 0; +} + +static PyObject *Material_getStrandSurfDiff( BPy_Material * self ) +{ + return PyInt_FromLong( ((long)( self->material->mode & MA_STR_SURFDIFF )) > 0 ); +} + +static int Material_setStrandSurfDiff( BPy_Material * self, PyObject * value) +{ + int number; + + if( !PyInt_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" ); + + number = PyInt_AS_LONG( value ); + + if (number){ + self->material->mode |= MA_STR_SURFDIFF; + }else{ + self->material->mode &= ~MA_STR_SURFDIFF; + } + + return 0; +} + +static PyObject *Material_getStrandDist( BPy_Material * self ) +{ + return PyFloat_FromDouble( ((float)( self->material->strand_surfnor )) ); +} + +static int Material_setStrandDist( BPy_Material * self, PyObject * value) +{ + return EXPP_setFloatRange( value, &self->material->strand_surfnor, 0.0, 10.0 ); +} + +static PyObject *Material_getStrandBlendUnit( BPy_Material * self ) +{ + return PyInt_FromLong( ((long)( self->material->mode & MA_STR_B_UNITS )) > 0 ); +} + +static int Material_setStrandBlendUnit( BPy_Material * self, PyObject * value) +{ + int number; + + if( !PyInt_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" ); + + number = PyInt_AS_LONG( value ); + + if (number){ + self->material->mode |= MA_STR_B_UNITS; + }else{ + self->material->mode &= ~MA_STR_B_UNITS; + } + + return 0; +} + +static PyObject *Material_getStrandStart( BPy_Material * self ) +{ + return PyFloat_FromDouble( ((float)( self->material->strand_sta )) ); +} + +static int Material_setStrandStart( BPy_Material * self, PyObject * value) +{ + return EXPP_setFloatRange( value, &self->material->strand_sta, 0.0001, 2.0 ); +} + +static PyObject *Material_getStrandEnd( BPy_Material * self ) +{ + return PyFloat_FromDouble( ((float)( self->material->strand_end )) ); +} + +static int Material_setStrandEnd( BPy_Material * self, PyObject * value) +{ + return EXPP_setFloatRange( value, &self->material->strand_end, 0.0001, 1.0 ); +} + +static PyObject *Material_getStrandMin( BPy_Material * self ) +{ + return PyFloat_FromDouble( ((float)( self->material->strand_min )) ); +} + +static int Material_setStrandMin( BPy_Material * self, PyObject * value) +{ + return EXPP_setFloatRange( value, &self->material->strand_min, 0.0001, 10.0 ); +} + +static PyObject *Material_getStrandShape( BPy_Material * self ) +{ + return PyFloat_FromDouble( ((float)( self->material->strand_ease )) ); +} + +static int Material_setStrandShape( BPy_Material * self, PyObject * value) +{ + return EXPP_setFloatRange( value, &self->material->strand_ease, -0.9, 0.9 ); +} + +static PyObject *Material_getStrandWidthFad( BPy_Material * self ) +{ + return PyFloat_FromDouble( ((float)( self->material->strand_widthfade )) ); +} + +static int Material_setStrandWidthFad( BPy_Material * self, PyObject * value) +{ + return EXPP_setFloatRange( value, &self->material->strand_widthfade, 0.0, 2.0 ); +} + +static PyObject *Material_getStrandUV( BPy_Material * self ) +{ + return EXPP_ReturnPyObjError( PyExc_NotImplementedError, + "Material.strandUV not implemented" ); +} + +static int Material_setStrandUV( BPy_Material * self, PyObject * value) +{ + return EXPP_ReturnPyObjError( PyExc_NotImplementedError, + "Material.strandUV not implemented" ); +} diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index b50b0082bf4..8617491e950 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -1001,9 +1001,10 @@ static PyObject *M_Object_Duplicate( PyObject * self_unused, int material_dupe = 0; int texture_dupe = 0; int ipo_dupe = 0; + int psys_dupe = 0; static char *kwlist[] = {"mesh", "surface", "curve", - "text", "metaball", "armature", "lamp", "material", "texture", "ipo", NULL}; + "text", "metaball", "armature", "lamp", "material", "texture", "ipo", "psys", NULL}; /* duplicating in background causes segfaults */ if( G.background == 1 ) @@ -1011,11 +1012,11 @@ static PyObject *M_Object_Duplicate( PyObject * self_unused, "cannot duplicate objects in background mode" ); - if (!PyArg_ParseTupleAndKeywords(args, kwd, "|iiiiiiiiii", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwd, "|iiiiiiiiiii", kwlist, &mesh_dupe, &surface_dupe, &curve_dupe, &text_dupe, &metaball_dupe, - &armature_dupe, &lamp_dupe, &material_dupe, &texture_dupe, &ipo_dupe)) + &armature_dupe, &lamp_dupe, &material_dupe, &texture_dupe, &ipo_dupe, &psys_dupe)) return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected nothing or bool keywords 'mesh', 'surface', 'curve', 'text', 'metaball', 'armature', 'lamp' 'material', 'texture' and 'ipo' as arguments" ); + "expected nothing or bool keywords 'mesh', 'surface', 'curve', 'text', 'metaball', 'armature', 'lamp' 'material', 'texture', 'ipo' and 'psys' as arguments" ); /* USER_DUP_ACT for actions is not supported in the UI so dont support it here */ if (mesh_dupe) dupflag |= USER_DUP_MESH; @@ -1028,6 +1029,7 @@ static PyObject *M_Object_Duplicate( PyObject * self_unused, if (material_dupe) dupflag |= USER_DUP_MAT; if (texture_dupe) dupflag |= USER_DUP_TEX; if (ipo_dupe) dupflag |= USER_DUP_IPO; + if (psys_dupe) dupflag |= USER_DUP_PSYS; adduplicate(2, dupflag); /* 2 is a mode with no transform and no redraw, Duplicate the current selection, context sensitive */ Py_RETURN_NONE; } diff --git a/source/blender/python/api2_2x/Particle.c b/source/blender/python/api2_2x/Particle.c index f69cb6a01b9..850100d29a9 100644 --- a/source/blender/python/api2_2x/Particle.c +++ b/source/blender/python/api2_2x/Particle.c @@ -42,6 +42,7 @@ #include "BKE_utildefines.h" #include "BKE_pointcache.h" #include "BKE_DerivedMesh.h" +#include "BKE_library.h" #include "BIF_editparticle.h" #include "BIF_space.h" #include "blendef.h" @@ -70,6 +71,9 @@ static PyObject *Part_GetMat( BPy_PartSys * self, PyObject * args ); static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args ); static PyObject *Part_GetVertGroup( BPy_PartSys * self, PyObject * args ); static PyObject *Part_SetVertGroup( BPy_PartSys * self, PyObject * args ); +static int Part_SetName( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_SetNameWithMethod( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_GetName( 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 ); @@ -141,11 +145,16 @@ static int Part_setRenderDied( BPy_PartSys * self, PyObject * args ); static PyObject *Part_getRenderDied( BPy_PartSys * self ); static int Part_setRenderMaterialIndex( BPy_PartSys * self, PyObject * args ); static PyObject *Part_getRenderMaterialIndex( BPy_PartSys * self ); +static int Part_setStrandRender( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getStrandRender( BPy_PartSys * self ); +static int Part_setStrandRenderAn( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getStrandRenderAn( 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 int Part_setDrawAs( BPy_PartSys * self, PyObject * args ); static PyObject *Part_getDrawAs( BPy_PartSys * self ); static int Part_setPhysType( BPy_PartSys * self, PyObject * args ); static PyObject *Part_getPhysType( BPy_PartSys * self ); @@ -283,6 +292,10 @@ static PyMethodDef BPy_ParticleSys_methods[] = { METH_VARARGS, "() - Get the vertex group which affects a particles attribute"}, {"setVertGroup", ( PyCFunction ) Part_SetVertGroup, METH_VARARGS, "() - Set the vertex group to affect a particles attribute"}, + {"getName", ( PyCFunction ) Part_GetName, METH_NOARGS, + "() - Return particle system's name"}, + {"setName", ( PyCFunction ) Part_SetNameWithMethod, METH_VARARGS, + "(s) - Change particle system's name"}, {NULL, NULL, 0, NULL} }; @@ -430,6 +443,14 @@ static PyGetSetDef BPy_ParticleSys_getseters[] = { (getter)Part_getRenderMaterialIndex, (setter)Part_setRenderMaterialIndex, "Specify material index used for the particles", NULL}, + {"strandRender", + (getter)Part_getStrandRender, (setter)Part_setStrandRender, + "Use the strand primitive to render", + NULL}, + {"strandRenderAngle", + (getter)Part_getStrandRenderAn, (setter)Part_setStrandRenderAn, + "How many degrees path has to curve to make another render segment", + NULL}, {"displayPercentage", (getter)Part_getParticleDisp, (setter)Part_setParticleDisp, "Particle display percentage", @@ -447,8 +468,8 @@ static PyGetSetDef BPy_ParticleSys_getseters[] = { "Get the duplicate ob", NULL}, {"drawAs", - (getter)Part_getDrawAs, NULL, - "Get draw type Particle.DRAWAS([ 'NONE' | 'OBJECT' | 'POINT' | ... ] )", + (getter)Part_getDrawAs, (setter)Part_setDrawAs, + "Draw type Particle.DRAWAS([ 'NONE' | 'OBJECT' | 'POINT' | ... ] )", NULL}, /* Newtonian Physics */ {"physics", @@ -2008,6 +2029,33 @@ static PyObject *Part_SetVertGroup( BPy_PartSys * self, PyObject * args ){ Py_RETURN_NONE; } +PyObject *Part_GetName( BPy_PartSys * self, PyObject * args ) +{ + ID *id = (ID*) self->psys->part; + if (!id) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "data has been removed" ) ); + return PyString_FromString( id->name + 2 ); +} + +int Part_SetName( BPy_PartSys * self, PyObject * args ) +{ + ID *id = (ID*) self->psys->part; + char *name = NULL; + if (!id) return ( EXPP_ReturnIntError( PyExc_RuntimeError, "data has been removed" ) ); + + name = PyString_AsString ( args ); + if( !name ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected string argument" ); + + rename_id( id, name ); + + return 0; +} + +PyObject * Part_SetNameWithMethod( BPy_PartSys *self, PyObject *args ) +{ + return EXPP_setterWrapper( (void *)self, args, (setter)Part_SetName ); +} /*****************************************************************************/ /* Function: Set/Get Seed */ @@ -2714,6 +2762,44 @@ static PyObject *Part_getRenderDied( BPy_PartSys * self ) return PyInt_FromLong( ((long)( self->psys->part->flag & PART_DIED )) > 0 ); } +static int Part_setStrandRender( 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->draw |= PART_DRAW_REN_STRAND; + }else{ + self->psys->part->draw &= ~PART_DRAW_REN_STRAND; + } + + return 0; +} + +static PyObject *Part_getStrandRender( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((long)( self->psys->part->draw & PART_DRAW_REN_STRAND )) > 0 ); +} + +static int Part_setStrandRenderAn( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->adapt_angle, + 0, 45, 'i' ); + + psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 ); + + return res; +} + +static PyObject *Part_getStrandRenderAn( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((int)( self->psys->part->adapt_angle )) ); +} + static int Part_setParticleDisp( BPy_PartSys * self, PyObject * args ) { int res = EXPP_setIValueRange( args, &self->psys->part->disp, @@ -2762,6 +2848,16 @@ static PyObject *Part_getRenderStep( BPy_PartSys * self ) return PyInt_FromLong( ((short)( self->psys->part->ren_step )) ); } +static int Part_setDrawAs( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->draw_as, + 0, 9, 'h' ); + + psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 ); + + return res; +} + static PyObject *Part_getDrawAs( BPy_PartSys * self ) { return PyInt_FromLong( (long)( self->psys->part->draw_as ) ); diff --git a/source/blender/python/api2_2x/Texture.c b/source/blender/python/api2_2x/Texture.c index 455badef4ad..e9e1c898fca 100644 --- a/source/blender/python/api2_2x/Texture.c +++ b/source/blender/python/api2_2x/Texture.c @@ -511,6 +511,8 @@ static int Texture_setNoiseBasis2( BPy_Texture *self, PyObject *args, static PyObject *Texture_getColorband( BPy_Texture * self); int Texture_setColorband( BPy_Texture * self, PyObject * value); +static PyObject *Texture_getUseColorband( BPy_Texture * self); +int Texture_setUseColorband( BPy_Texture * self, PyObject * value); static PyObject *Texture_evaluate( BPy_Texture *self, PyObject *value ); static PyObject *Texture_copy( BPy_Texture *self ); @@ -791,6 +793,10 @@ static PyGetSetDef BPy_Texture_getseters[] = { (getter)Texture_getColorband, (setter)Texture_setColorband, "The colorband for this texture", NULL}, + {"useColorband", + (getter)Texture_getUseColorband, (setter)Texture_setUseColorband, + "Use colorband for this texture", + NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; @@ -2525,6 +2531,29 @@ int Texture_setColorband( BPy_Texture * self, PyObject * value) return EXPP_Colorband_fromPyList( &self->texture->coba, value ); } +static PyObject *Texture_getUseColorband( BPy_Texture * self) +{ + return PyInt_FromLong( ((long)( self->texture->flag & TEX_COLORBAND )) > 0 ); +} + +int Texture_setUseColorband( BPy_Texture * self, PyObject * value) +{ + int number; + + if( !PyInt_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" ); + + number = PyInt_AS_LONG( value ); + + if (number){ + self->texture->flag |= TEX_COLORBAND; + }else{ + self->texture->flag &= ~TEX_COLORBAND; + } + + return 0; +} + static PyObject *Texture_evaluate( BPy_Texture * self, PyObject * value ) { TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; diff --git a/source/blender/python/api2_2x/doc/Lamp.py b/source/blender/python/api2_2x/doc/Lamp.py index 878ca53bb15..88b1c2cf800 100644 --- a/source/blender/python/api2_2x/doc/Lamp.py +++ b/source/blender/python/api2_2x/doc/Lamp.py @@ -46,6 +46,11 @@ Example:: - 'NoDiffuse' - 'NoSpecular' - 'RayShadow' +@type BufferTypes: read-only dictionary +@var BufferTypes: The lamp shadowbuffer types. + - 'Regular' + - 'Irregular' + - 'Halfway' Example:: from Blender import Lamp, Object @@ -101,6 +106,8 @@ class Lamp: @ivar bufferSize: Lamp shadow buffer size. Value is clamped to the range [512,5120]. @type bufferSize: int + @ivar bufferType: Lamp shadowbuffer type. See L{BufferTypes} for values. + @type bufferType: int @ivar clipEnd: Lamp shadow map clip end. Value is clamped to the range [1.0,5000.0]. @type clipEnd: float diff --git a/source/blender/python/api2_2x/doc/Material.py b/source/blender/python/api2_2x/doc/Material.py index 59ff4bc8503..801bb4cb04d 100644 --- a/source/blender/python/api2_2x/doc/Material.py +++ b/source/blender/python/api2_2x/doc/Material.py @@ -408,6 +408,24 @@ class Material: @type textures: a tuple of Blender MTex objects. @ivar textures: the Material's Texture list. Empty texture channels contains None. + @ivar strandTanShad: Uses direction of strands as normal for tangent-shading + @type strandTanShad: int + @ivar strandSurfDiff: Make diffuse shading more similar to shading the surface + @type strandSurfDiff: int + @ivar strandDist: Distance in Blender units over which to blend in the surface normal + @type strandDist: float + @ivar strandBlendUnit: Use actual Blender units for widths instead of pixels + @type strandBlendUnit: int + @ivar strandStart: Start size of strands + @type strandStart: float + @ivar strandEnd: End size of strands + @type strandEnd: float + @ivar strandMin: Minimum size of strands in pixels + @type strandMin: float + @ivar strandShape: Shape of strands, positive value makes it rounder, negative makes it spiky + @type strandShape: float + @ivar strandFade: Transparency along the width of the strand + @type strandFade: float @ivar enableSSS: If True, subsurface scattering will be rendered on this material. @type enableSSS: bool @ivar sssScale: If True, subsurface scattering will be rendered on this material. diff --git a/source/blender/python/api2_2x/doc/Object.py b/source/blender/python/api2_2x/doc/Object.py index 212ff95ef74..bd1bd2eb0b3 100644 --- a/source/blender/python/api2_2x/doc/Object.py +++ b/source/blender/python/api2_2x/doc/Object.py @@ -205,7 +205,7 @@ def GetSelected (): """ -def Duplicate (mesh=0, surface=0, curve=0, text=0, metaball=0, armature=0, lamp=0, material=0, texture=0, ipo=0): +def Duplicate (mesh=0, surface=0, curve=0, text=0, metaball=0, armature=0, lamp=0, material=0, texture=0, ipo=0, psys=0): """ Duplicate selected objects on visible layers from Blenders current scene, de-selecting the currently visible, selected objects and making a copy where all new objects are selected. @@ -234,6 +234,8 @@ def Duplicate (mesh=0, surface=0, curve=0, text=0, metaball=0, armature=0, lamp= @param texture: When non-zero, texture data used by the object's materials will be duplicated with the objects. @type ipo: bool @param ipo: When non-zero, Ipo data linked to the object will be duplicated with the objects. + @type psys: bool + @param psys: When non-zero, particle systems used by the object or its object data will be duplicated with the objects. I{B{Example:}} @@ -663,6 +665,7 @@ class Object: particle system with that name exists, it is linked to the object. @type name: string @param name: The name of the requested Particle system (optional). + @return: The particle system linked. """ def addVertexGroupsFromArmature(object): diff --git a/source/blender/python/api2_2x/doc/Particle.py b/source/blender/python/api2_2x/doc/Particle.py index 7193e365536..15481c9dd63 100644 --- a/source/blender/python/api2_2x/doc/Particle.py +++ b/source/blender/python/api2_2x/doc/Particle.py @@ -69,6 +69,20 @@ This module provides access to the B{Particle} in Blender. - NONE: No particle angular velocity - SPIN: Spin particle angular velocity - RANDOM: Random particle angular velocity +@type VERTEXGROUPS: readonly dictionary +@var VERTEXGROUPS: Constant dict used for with L{Particle.VERTEXGROUP} + - DENSITY: VertexGroup affect to particles density + - VELOCITY: VertexGroup affect to particles velocity + - LENGHT: VertexGroup affect to particles lenght + - CLUMP: VertexGroup affect to particles clump + - KINK: VertexGroup affect to particles kink + - ROUGH1: VertexGroup affect to particles rough1 + - ROUGH2: VertexGroup affect to particles rough2 + - ROUGHE: VertexGroup affect to particles roughE + - SIZE: VertexGroup affect to particles size + - TANVEL: VertexGroup affect to particles tangent velocity + - TANROT: VertexGroup affect to particles tangent rotation + - EFFECTOR: VertexGroup affect to particles effector @type CHILDTYPE: readonly dictionary @var CHILDTYPE: Constant dict used for with L{Particle.CHILDTYPE} - NONE: set no children @@ -171,6 +185,10 @@ class Particle: @type renderDied: int @ivar renderMaterial: Specify material used for the particles. @type renderMaterial: int + @ivar strandRender: Use the strand primitive to render. + @type strandRender: int + @ivar strandRenderAngle: How many degrees path has to curve to make another render segment. + @type strandRenderAngle: int @ivar displayPercentage: Particle display percentage. @type displayPercentage: int @ivar hairDisplayStep: How many steps paths are drawn with (power of 2) in visu mode. @@ -179,7 +197,7 @@ class Particle: @type hairRenderStep: int @ivar duplicateObject: Get the duplicate object. @type duplicateObject: Blender Object - @ivar drawAs: Get draw type Particle.DRAWAS([ 'NONE' | 'OBJECT' | 'POINT' | ... ]). + @ivar drawAs: Draw type Particle.DRAWAS([ 'NONE' | 'OBJECT' | 'POINT' | ... ]). @type drawAs: int @ivar physics: Select particle physics type Particle.PHYSICS([ 'BOIDS' | 'KEYED' | 'NEWTONIAN' | 'NONE' ]) @type physics: int @@ -276,6 +294,18 @@ class Particle: @ivar childBranch: Threshold of branching @type childBranch: float """ + def getName(): + """ + Get the name of this Particle System object. + @rtype: string + """ + + def setName(name): + """ + Set the name of this Particle System object. + @type name: string + @param name: The new name. + """ def freeEdit(): """ diff --git a/source/blender/python/api2_2x/doc/Texture.py b/source/blender/python/api2_2x/doc/Texture.py index ad57c303ed2..3431dceb6cd 100644 --- a/source/blender/python/api2_2x/doc/Texture.py +++ b/source/blender/python/api2_2x/doc/Texture.py @@ -393,6 +393,8 @@ class Texture: each color a list of 5 floats [0 - 1], [r,g,b,a,pos]. The colorband can have between 1 and 31 colors. @type colorband: list + @ivar useColorband: Use colorband for this texture. + @type colorband: int @ivar autoRefresh: Refresh image on frame changes enabled. @type autoRefresh: boolean """ diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index b6b6c3c8df9..801b086f980 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -5185,6 +5185,7 @@ void adduplicate(int mode, int dupflag) Object *ob, *obn; ID *id; int a, didit; + ParticleSystem *psys; if(G.scene->id.lib) return; clear_id_newpoins(); @@ -5260,6 +5261,16 @@ void adduplicate(int mode, int dupflag) } } } + if(dupflag & USER_DUP_PSYS) { + for(psys=obn->particlesystem.first; psys; psys=psys->next) { + id= (ID*) psys->part; + if(id) { + ID_NEW_US(psys->part) + else psys->part= psys_copy_settings(psys->part); + id->us--; + } + } + } id= obn->data; didit= 0; From 819a0d2f773a6db9b4dc6b2490f11d087014b1f3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 24 Aug 2009 11:34:48 +0000 Subject: [PATCH 3/8] EDL importer for the sequencer. supports... - audio and video edits - fades, wipes, speed changes (video only) - importing from multiple reels example import from final cut pro. http://www.graphicall.org/ftp/ideasman42/edl_in_blender_px.png http://www.graphicall.org/ftp/ideasman42/edl_import_ui.png --- release/scripts/import_edl.py | 961 ++++++++++++++++++++++++++++++++++ 1 file changed, 961 insertions(+) create mode 100755 release/scripts/import_edl.py diff --git a/release/scripts/import_edl.py b/release/scripts/import_edl.py new file mode 100755 index 00000000000..8c5d041b34c --- /dev/null +++ b/release/scripts/import_edl.py @@ -0,0 +1,961 @@ +#!BPY + +""" +Name: 'Video Sequence (.edl)...' +Blender: 248 +Group: 'Import' +Tooltip: 'Load a CMX formatted EDL into the sequencer' +""" + +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# Copyright (C) 2009: Campbell Barton, ideasman42@gmail.com +# +# 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, +# -------------------------------------------------------------------------- + +class TimeCode(object): + ''' + Simple timecode class + also supports conversion from other time strings used by EDL + ''' + def __init__(self, data, fps): + self.fps= fps + if type(data)==str: + self.fromString(data) + frame = self.asFrame() + self.fromFrame(frame) + else: + self.fromFrame(data) + + def fromString(self, text): + # hh:mm:ss:ff + # No dropframe support yet + + if text.lower().endswith('mps'): # 5.2mps + return self.fromFrame( int( float(text[:-3]) * self.fps ) ) + elif text.lower().endswith('s'): # 5.2s + return self.fromFrame( int( float(text[:-1]) * self.fps ) ) + elif text.isdigit(): # 1234 + return self.fromFrame( int(text) ) + elif ':' in text: # hh:mm:ss:ff + text= text.replace(';', ':').replace(',', ':').replace('.', ':') + text= text.split(':') + + self.hours= int(text[0]) + self.minutes= int(text[1]) + self.seconds= int(text[2]) + self.frame= int(text[3]) + return self + else: + print 'ERROR: could not convert this into timecode "%s"' % test + return self + + + def fromFrame(self, frame): + + if frame < 0: + frame = -frame; + neg=True + else: + neg=False + + fpm = 60 * self.fps + fph = 60 * fpm + + if frame < fph: + self.hours= 0 + else: + self.hours= int(frame/fph) + frame = frame % fph + + if frame < fpm: + self.minutes= 0 + else: + self.minutes= int(frame/fpm) + frame = frame % fpm + + if frame < self.fps: + self.seconds= 0 + else: + self.seconds= int(frame/self.fps) + frame = frame % self.fps + + self.frame= frame + + if neg: + self.frame = -self.frame + self.seconds = -self.seconds + self.minutes = -self.minutes + self.hours = -self.hours + + return self + + def asFrame(self): + abs_frame= self.frame + abs_frame += self.seconds * self.fps + abs_frame += self.minutes * 60 * self.fps + abs_frame += self.hours * 60 * 60 * self.fps + + return abs_frame + + def asString(self): + self.fromFrame(int(self)) + return '%.2d:%.2d:%.2d:%.2d' % (self.hours, self.minutes, self.seconds, self.frame) + + def __repr__(self): + return self.asString() + + # Numeric stuff, may as well have this + def __neg__(self): return TimeCode(-int(self), self.fps) + def __int__(self): return self.asFrame() + def __sub__(self, other): return TimeCode(int(self)-int(other), self.fps) + def __add__(self, other): return TimeCode(int(self)+int(other), self.fps) + def __mul__(self, other): return TimeCode(int(self)*int(other), self.fps) + def __div__(self, other): return TimeCode(int(self)/int(other), self.fps) + def __abs__(self): return TimeCode(abs(int(self)), self.fps) + def __iadd__(self, other): return self.fromFrame(int(self)+int(other)) + def __imul__(self, other): return self.fromFrame(int(self)*int(other)) + def __idiv__(self, other): return self.fromFrame(int(self)/int(other)) +# end timecode + + +'''Comments +Comments can appear at the beginning of the EDL file (header) or between the edit lines in the EDL. The first block of comments in the file is defined to be the header comments and they are associated with the EDL as a whole. Subsequent comments in the EDL file are associated with the first edit line that appears after them. +Edit Entries + [num] [duration] [srcIn] [srcOut] [recIn] [recOut] + + * : Filename or tag value. Filename can be for an MPEG file, Image file, or Image file template. Image file templates use the same pattern matching as for command line glob, and can be used to specify images to encode into MPEG. i.e. /usr/data/images/image*.jpg + * : 'V' | 'A' | 'VA' | 'B' | 'v' | 'a' | 'va' | 'b' which equals Video, Audio, Video_Audio edits (note B or b can be used in place of VA or va). + * : 'C' | 'D' | 'E' | 'FI' | 'FO' | 'W' | 'c' | 'd' | 'e' | 'fi' | 'fo' | 'w'. which equals Cut, Dissolve, Effect, FadeIn, FadeOut, Wipe. + * [num]: if TransitionType = Wipe, then a wipe number must be given. At the moment only wipe 'W0' and 'W1' are supported. + * [duration]: if the TransitionType is not equal to Cut, then an effect duration must be given. Duration is in frames. + * [srcIn]: Src in. If no srcIn is given, then it defaults to the first frame of the video or the first frame in the image pattern. If srcIn isn't specified, then srcOut, recIn, recOut can't be specified. + * [srcOut]: Src out. If no srcOut is given, then it defaults to the last frame of the video - or last image in the image pattern. if srcOut isn't given, then recIn and recOut can't be specified. + * [recIn]: Rec in. If no recIn is given, then it is calculated based on its position in the EDL and the length of its input. + [recOut]: Rec out. If no recOut is given, then it is calculated based on its position in the EDL and the length of its input. first frame of the video. + +For srcIn, srcOut, recIn, recOut, the values can be specified as either timecode, frame number, seconds, or mps seconds. i.e. +[tcode | fnum | sec | mps], where: + + * tcode : SMPTE timecode in hh:mm:ss:ff + * fnum : frame number (the first decodable frame in the video is taken to be frame 0). + * sec : seconds with 's' suffix (e.g. 5.2s) + * mps : seconds with 'mps' suffix (e.g. 5.2mps). This corresponds to the 'seconds' value displayed by Windows MediaPlayer. + +More notes, +Key + +''' + +enum= 0 +TRANSITION_UNKNOWN= enum +TRANSITION_CUT= enum; enum+=1 +TRANSITION_DISSOLVE= enum; enum+=1 +TRANSITION_EFFECT= enum; enum+=1 +TRANSITION_FADEIN= enum; enum+=1 +TRANSITION_FADEOUT= enum; enum+=1 +TRANSITION_WIPE= enum; enum+=1 +TRANSITION_KEY= enum; enum+=1 + +TRANSITION_DICT={ \ + 'c':TRANSITION_CUT, + 'd':TRANSITION_DISSOLVE, + 'e':TRANSITION_EFFECT, + 'fi':TRANSITION_FADEIN, + 'fo':TRANSITION_FADEOUT, + 'w':TRANSITION_WIPE, + 'k':TRANSITION_KEY, + } + +enum= 0 +EDIT_UNKNOWN= 1<= 1.0: + mov.endStill = int(mov.length * (scale - 1.0)) + else: + speed.speedEffectGlobalSpeed = 1.0/scale + meta.endOffset = mov.length - int(mov.length*scale) + + speed.update() + meta.update() + return meta + +def apply_dissolve_ipo(mov, blendin): + len_disp = float(mov.endDisp - mov.startDisp) + + if len_disp <= 0.0: + print 'Error, strip is zero length' + return + + mov.ipo= ipo= bpy.data.ipos.new("fade", "Sequence") + icu= ipo.addCurve('Fac') + + icu.interpolation= Blender.IpoCurve.InterpTypes.LINEAR + icu.append((0, 0)) + icu.append(((int(blendin)/len_disp) * 100, 1)) + + if mov.type not in (SEQ_HD_SOUND, SEQ_RAM_SOUND): + mov.blendMode = Blender.Scene.Sequence.BlendModes.ALPHAOVER + + +def replace_ext(path, ext): + return path[:path.rfind('.')+1] + ext + +def load_edl(filename, reel_files, reel_offsets): + ''' + reel_files - key:reel <--> reel:filename + ''' + + # For test file + # frame_offset = -769 + + + sce= bpy.data.scenes.active + fps= sce.render.fps + + elist= EditList() + if not elist.parse(filename, fps): + return 'Unable to parse "%s"' % filename + # elist.clean() + + + seq= sce.sequence + + track= 0 + + edits = elist.edits[:] + # edits.sort(key = lambda edit: int(edit.recIn)) + + prev_edit = None + for edit in edits: + print edit + frame_offset = reel_offsets[edit.reel] + + + src_start= int(edit.srcIn) + frame_offset + src_end= int(edit.srcOut) + frame_offset + src_length= src_end-src_start + + rec_start= int(edit.recIn) + 1 + rec_end= int(edit.recOut) + 1 + rec_length= rec_end-rec_start + + # print src_length, rec_length, src_start + + if edit.m2 != None: scale = fps/float(edit.m2.fps) + else: scale = 1.0 + + unedited_start= rec_start - src_start + offset_start = src_start - int(src_start*scale) # works for scaling up AND down + + if edit.transition_type == TRANSITION_CUT and (not elist.testOverlap(edit)): + track = 1 + + strip= None + final_strips = [] + if edit.reel.lower()=='bw': + strip= seq.new((0,0,0), rec_start, track+1) + strip.length= rec_length # for color its simple + final_strips.append(strip) + else: + + path_full = reel_files[edit.reel] + path_fileonly= path_full.split('/')[-1].split('\\')[-1] # os.path.basename(full) + path_dironly= path_full[:-len(path_fileonly)] # os.path.dirname(full) + + if edit.edit_type & EDIT_VIDEO: #and edit.transition_type == TRANSITION_CUT: + + try: + strip= seq.new((path_fileonly, path_dironly, path_full, 'movie'), unedited_start + offset_start, track+1) + except: + return 'Invalid input for movie' + + # Apply scaled rec in bounds + if scale != 1.0: + meta = scale_meta_speed(seq, strip, scale) + final_strip = meta + else: + final_strip = strip + + + final_strip.update() + final_strip.startOffset= rec_start - final_strip.startDisp + final_strip.endOffset= rec_end- final_strip.endDisp + final_strip.update() + final_strip.endOffset += (final_strip.endDisp - rec_end) + final_strip.update() + + + if edit.transition_duration: + if not prev_edit: + print "Error no previous strip" + else: + new_end = rec_start + int(edit.transition_duration) + for other in prev_edit.custom_data: + if other.type != SEQ_HD_SOUND and other.type != SEQ_RAM_SOUND: + other.endOffset += (other.endDisp - new_end) + other.update() + + # Apply disolve + if edit.transition_type == TRANSITION_DISSOLVE: + apply_dissolve_ipo(final_strip, edit.transition_duration) + + if edit.transition_type == TRANSITION_WIPE: + other_track = track + 2 + for other in prev_edit.custom_data: + if other.type != SEQ_HD_SOUND and other.type != SEQ_RAM_SOUND: + + strip_wipe= seq.new((SEQ_WIPE, other, final_strip), 1, other_track) + + if edit.wipe_type == WIPE_0: + strip_wipe.wipeEffectAngle = 90 + else: + strip_wipe.wipeEffectAngle = -90 + + other_track += 1 + + + + # strip.endOffset= strip.length - int(edit.srcOut) + #end_offset= (unedited_start+strip.length) - end + # print start, end, end_offset + #strip.endOffset = end_offset + + # break + # print strip + + final_strips.append(final_strip) + + + if edit.edit_type & (EDIT_AUDIO | EDIT_AUDIO_STEREO | EDIT_VIDEO_AUDIO): + + if scale == 1.0: # TODO - scaled audio + + try: + strip= seq.new((path_fileonly, path_dironly, path_full, 'audio_hd'), unedited_start + offset_start, track+6) + except: + + # See if there is a wave file there + path_full_wav = replace_ext(path_full, 'wav') + path_fileonly_wav = replace_ext(path_fileonly, 'wav') + + #try: + strip= seq.new((path_fileonly_wav, path_dironly, path_full_wav, 'audio_hd'), unedited_start + offset_start, track+6) + #except: + # return 'Invalid input for audio' + + final_strip = strip + + # Copied from above + final_strip.update() + final_strip.startOffset= rec_start - final_strip.startDisp + final_strip.endOffset= rec_end- final_strip.endDisp + final_strip.update() + final_strip.endOffset += (final_strip.endDisp - rec_end) + final_strip.update() + + if edit.transition_type == TRANSITION_DISSOLVE: + apply_dissolve_ipo(final_strip, edit.transition_duration) + + final_strips.append(final_strip) + + # strip= seq.new((0.6, 0.6, 0.6), start, track+1) + + if final_strips: + for strip in final_strips: + # strip.length= length + final_strip.name = edit.asName() + edit.custom_data[:]= final_strips + # track = not track + prev_edit = edit + track += 1 + + #break + + + def recursive_update(s): + s.update(1) + for s_kid in s: + recursive_update(s_kid) + + + for s in seq: + recursive_update(s) + + return '' + + + +#load_edl('/fe/edl/EP30CMXtrk1.edl') # /tmp/test.edl +#load_edl('/fe/edl/EP30CMXtrk2.edl') # /tmp/test.edl +#load_edl('/fe/edl/EP30CMXtrk3.edl') # /tmp/test.edl +#load_edl('/root/vid/rush/blender_edl.edl', ['/root/vid/rush/rushes3.avi',]) # /tmp/test.edl + + + + +# ---------------------- Blender UI part +from Blender import Draw, Window +import BPyWindow + +if 0: + DEFAULT_FILE_EDL = '/root/vid/rush/blender_edl.edl' + DEFAULT_FILE_MEDIA = '/root/vid/rush/rushes3_wav.avi' + DEFAULT_FRAME_OFFSET = -769 +else: + DEFAULT_FILE_EDL = '' + DEFAULT_FILE_MEDIA = '' + DEFAULT_FRAME_OFFSET = 0 + +B_EVENT_IMPORT = 1 +B_EVENT_RELOAD = 2 +B_EVENT_FILESEL_EDL = 3 +B_EVENT_NOP = 4 + +B_EVENT_FILESEL = 100 # or greater + +class ReelItemUI(object): + __slots__ = 'filename_but', 'offset_but', 'ui_text' + def __init__(self): + self.filename_but = Draw.Create(DEFAULT_FILE_MEDIA) + self.offset_but = Draw.Create(DEFAULT_FRAME_OFFSET) + self.ui_text = '' + + + +REEL_UI = {} # reel:ui_string + + +#REEL_FILENAMES = {} # reel:filename +#REEL_OFFSETS = {} # reel:filename + +PREF = {} + +PREF['filename'] = Draw.Create(DEFAULT_FILE_EDL) +PREF['reel_act'] = '' + +def edl_reload(): + Window.WaitCursor(1) + filename = PREF['filename'].val + sce= bpy.data.scenes.active + fps= sce.render.fps + + elist= EditList() + + if filename: + if not elist.parse(filename, fps): + Draw.PupMenu('Error%t|Could not open the file "' + filename + '"') + reels = elist.getReels() + else: + reels = {} + + REEL_UI.clear() + for reel_key, edits in reels.iteritems(): + + if reel_key == 'bw': + continue + + flag = 0 + for edit in edits: + flag |= edit.edit_type + + reel_item = REEL_UI[reel_key] = ReelItemUI() + + reel_item.ui_text = '%s (%s): ' % (reel_key, editFlagsToText(flag)) + + Window.WaitCursor(0) + +def edl_set_path(filename): + PREF['filename'].val = filename + edl_reload() + Draw.Redraw() + +def edl_set_path_reel(filename): + REEL_UI[PREF['reel_act']].filename_but.val = filename + Draw.Redraw() + +def edl_reel_keys(): + reel_keys = REEL_UI.keys() + + if 'bw' in reel_keys: + reel_keys.remove('bw') + + reel_keys.sort() + return reel_keys + +def edl_draw(): + + MARGIN = 4 + rect = BPyWindow.spaceRect() + but_width = int((rect[2]-MARGIN*2)/4.0) # 72 + # Clamp + if but_width>100: but_width = 100 + but_height = 17 + + x=MARGIN + y=rect[3]-but_height-MARGIN + xtmp = x + + + + # ---------- ---------- ---------- ---------- + Blender.Draw.BeginAlign() + PREF['filename'] = Draw.String('edl path: ', B_EVENT_RELOAD, xtmp, y, (but_width*3)-20, but_height, PREF['filename'].val, 256, 'EDL Path'); xtmp += (but_width*3)-20; + Draw.PushButton('..', B_EVENT_FILESEL_EDL, xtmp, y, 20, but_height, 'Select an EDL file'); xtmp += 20; + Blender.Draw.EndAlign() + + Draw.PushButton('Reload', B_EVENT_RELOAD, xtmp + MARGIN, y, but_width - MARGIN, but_height, 'Read the ID Property settings from the active curve object'); xtmp += but_width; + y-=but_height + MARGIN + xtmp = x + # ---------- ---------- ---------- ---------- + + reel_keys = edl_reel_keys() + + + + if reel_keys: text = 'Reel file list...' + elif PREF['filename'].val == '': text = 'No EDL loaded.' + else: text = 'No reels found!' + + Draw.Label(text, xtmp + MARGIN, y, but_width*4, but_height); xtmp += but_width*4; + + y-=but_height + MARGIN + xtmp = x + + # ---------- ---------- ---------- ---------- + + + for i, reel_key in enumerate(reel_keys): + reel_item = REEL_UI[reel_key] + + Blender.Draw.BeginAlign() + REEL_UI[reel_key].filename_but = Draw.String(reel_item.ui_text, B_EVENT_NOP, xtmp, y, (but_width*3)-20, but_height, REEL_UI[reel_key].filename_but.val, 256, 'Select the reel path'); xtmp += (but_width*3)-20; + Draw.PushButton('..', B_EVENT_FILESEL + i, xtmp, y, 20, but_height, 'Media path to use for this reel'); xtmp += 20; + Blender.Draw.EndAlign() + + reel_item.offset_but= Draw.Number('ofs:', B_EVENT_NOP, xtmp + MARGIN, y, but_width - MARGIN, but_height, reel_item.offset_but.val, -100000, 100000, 'Start offset in frames when applying timecode'); xtmp += but_width - MARGIN; + + y-=but_height + MARGIN + xtmp = x + + # ---------- ---------- ---------- ---------- + + Draw.PushButton('Import CMX-EDL Sequencer Strips', B_EVENT_IMPORT, xtmp + MARGIN, MARGIN, but_width*4 - MARGIN, but_height, 'Load the EDL file into the sequencer'); xtmp += but_width*4; + y-=but_height + MARGIN + xtmp = x + + +def edl_event(evt, val): + pass + +def edl_bevent(evt): + + if evt == B_EVENT_NOP: + pass + elif evt == B_EVENT_IMPORT: + ''' + Load the file into blender with UI settings + ''' + filename = PREF['filename'].val + + reel_files = {} + reel_offsets = {} + + for reel_key, reel_item in REEL_UI.iteritems(): + reel_files[reel_key] = reel_item.filename_but.val + reel_offsets[reel_key] = reel_item.offset_but.val + + error = load_edl(filename, reel_files, reel_offsets) + if error != '': + Draw.PupMenu('Error%t|' + error) + else: + Window.RedrawAll() + + elif evt == B_EVENT_RELOAD: + edl_reload() + Draw.Redraw() + + elif evt == B_EVENT_FILESEL_EDL: + filename = PREF['filename'].val + if not filename: filename = Blender.sys.join(Blender.sys.expandpath('//'), '*.edl') + + Window.FileSelector(edl_set_path, 'Select EDL', filename) + + elif evt >= B_EVENT_FILESEL: + reel_keys = edl_reel_keys() + reel_key = reel_keys[evt - B_EVENT_FILESEL] + + filename = REEL_UI[reel_key].filename_but.val + if not filename: filename = Blender.sys.expandpath('//') + + PREF['reel_act'] = reel_key # so file set path knows which one to set + Window.FileSelector(edl_set_path_reel, 'Reel Media', filename) + + + +if __name__ == '__main__': + Draw.Register(edl_draw, edl_event, edl_bevent) + edl_reload() + From 9dff2ad3d043de606dbc744cd13c11e1ef76e00b Mon Sep 17 00:00:00 2001 From: "Guillermo S. Romero" Date: Mon, 24 Aug 2009 23:09:35 +0000 Subject: [PATCH 4/8] SVN maintenance. --- release/scripts/import_edl.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 release/scripts/import_edl.py diff --git a/release/scripts/import_edl.py b/release/scripts/import_edl.py old mode 100755 new mode 100644 From 33e2d118bcc8d8301144cd90e7896175ae14d141 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 25 Aug 2009 12:43:25 +0000 Subject: [PATCH 5/8] removing GameLogic.EvalExpression(), unlikely anyone will miss it, was only accessible in 2.49, invalid expressions would crash, valid ones leak memory. --- source/gameengine/Ketsji/KX_PythonInit.cpp | 28 ---------------------- source/gameengine/PyDoc/GameLogic.py | 8 ------- 2 files changed, 36 deletions(-) diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index fcada7bfce4..91515587e8d 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -498,33 +498,6 @@ static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *) Py_RETURN_NONE; } - -static PyObject *gEvalExpression(PyObject*, PyObject* value) -{ - char* txt= PyString_AsString(value); - - if (txt==NULL) { - PyErr_SetString(PyExc_TypeError, "Expression.calc(text): expects a single string argument"); - return NULL; - } - - CParser parser; - CExpression* expr = parser.ProcessText(txt); - CValue* val = expr->Calculate(); - expr->Release(); - - if (val) { - PyObject* pyobj = val->ConvertValueToPython(); - if (pyobj) - return pyobj; - else - return val->GetProxy(); - } - - Py_RETURN_NONE; -} - - static struct PyMethodDef game_methods[] = { {"expandPath", (PyCFunction)gPyExpandPath, METH_VARARGS, (PY_METHODCHAR)gPyExpandPath_doc}, {"sendMessage", (PyCFunction)gPySendMessage, METH_VARARGS, (PY_METHODCHAR)gPySendMessage_doc}, @@ -553,7 +526,6 @@ static struct PyMethodDef game_methods[] = { {"getAverageFrameRate", (PyCFunction) gPyGetAverageFrameRate, METH_NOARGS, (PY_METHODCHAR)"Gets the estimated average frame rate"}, {"getBlendFileList", (PyCFunction)gPyGetBlendFileList, METH_VARARGS, (PY_METHODCHAR)"Gets a list of blend files in the same directory as the current blend file"}, {"PrintGLInfo", (PyCFunction)pyPrintExt, METH_NOARGS, (PY_METHODCHAR)"Prints GL Extension Info"}, - {"EvalExpression", (PyCFunction)gEvalExpression, METH_O, (PY_METHODCHAR)"Evaluate a string as a game logic expression"}, {NULL, (PyCFunction) NULL, 0, NULL } }; diff --git a/source/gameengine/PyDoc/GameLogic.py b/source/gameengine/PyDoc/GameLogic.py index 46f00fa7ea6..5d9b17316be 100644 --- a/source/gameengine/PyDoc/GameLogic.py +++ b/source/gameengine/PyDoc/GameLogic.py @@ -448,14 +448,6 @@ def setPhysicsTicRate(ticrate): @type ticrate: float """ -def EvalExpression(text): - """ - Evaluate the string as an expression, similar to the expression controller logic brick. - @param text: The expression to evaluate. - @type text: string - @return: The result of the expression. The type depends on the expression. - """ - #{ Utility functions def getAverageFrameRate(): """ From 0db2975ff6cc2592b062f749059e640dc1e2b140 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 26 Aug 2009 16:05:01 +0000 Subject: [PATCH 6/8] [#18837] if a sunlamp is set to a too high energy, speculars turn black shr->spec values could be greater then 1.0, causing negative color when using (1.0-shr->spec[i]) as a blending factor. When shr->spec[i] is 1.0 the mircol is ignored, so only mix the mircol when needed (like clamping the spec). --- source/blender/render/intern/source/rayshade.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 75b9557f337..182e60365a6 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -1239,15 +1239,18 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr) } if(shi->combinedflag & SCE_PASS_REFLECT) { + /* values in shr->spec can be greater then 1.0. + * in the case when it is 1.0 diff */ - f= fr*(1.0f-shr->spec[0]); f1= 1.0f-i; - diff[0]= f*mircol[0] + f1*diff[0]; + f1= 1.0f-i; - f= fg*(1.0f-shr->spec[1]); f1= 1.0f-i; - diff[1]= f*mircol[1] + f1*diff[1]; + diff[0] *= f1; + diff[1] *= f1; + diff[2] *= f1; - f= fb*(1.0f-shr->spec[2]); f1= 1.0f-i; - diff[2]= f*mircol[2] + f1*diff[2]; + if(shr->spec[0]<1.0f) diff[0] += mircol[0] * (fr*(1.0f-shr->spec[0])); + if(shr->spec[1]<1.0f) diff[1] += mircol[1] * (fg*(1.0f-shr->spec[1])); + if(shr->spec[2]<1.0f) diff[2] += mircol[2] * (fb*(1.0f-shr->spec[2])); } } } From 324b3fbe747a6544b60be1eb8a0cb6b01db736de Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 27 Aug 2009 06:55:54 +0000 Subject: [PATCH 7/8] - BGE crash fix when casting a ray to the same location as the object from python. - Incorrect Mathutils vector docstrings. - last rayshade commit had an incomplete comment. --- source/blender/python/api2_2x/vector.c | 4 ++-- source/blender/render/intern/source/rayshade.c | 4 +++- source/gameengine/Ketsji/KX_GameObject.cpp | 8 +++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source/blender/python/api2_2x/vector.c b/source/blender/python/api2_2x/vector.c index cb206363dbf..a7e00e2878a 100644 --- a/source/blender/python/api2_2x/vector.c +++ b/source/blender/python/api2_2x/vector.c @@ -58,8 +58,8 @@ struct PyMethodDef Vector_methods[] = { {"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, Vector_Normalize_doc}, {"negate", (PyCFunction) Vector_Negate, METH_NOARGS, Vector_Negate_doc}, {"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, Vector_Resize2D_doc}, - {"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, Vector_Resize2D_doc}, - {"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, Vector_Resize2D_doc}, + {"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, Vector_Resize3D_doc}, + {"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, Vector_Resize4D_doc}, {"toTrackQuat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, Vector_ToTrackQuat_doc}, {"reflect", ( PyCFunction ) Vector_Reflect, METH_O, Vector_Reflect_doc}, {"cross", ( PyCFunction ) Vector_Cross, METH_O, Vector_Dot_doc}, diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 182e60365a6..e683a499e17 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -1240,7 +1240,9 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr) if(shi->combinedflag & SCE_PASS_REFLECT) { /* values in shr->spec can be greater then 1.0. - * in the case when it is 1.0 diff */ + * In this case the mircol uses a zero blending factor, so ignoring it is ok. + * Fixes bug #18837 - when the spec is higher then 1.0, + * diff can become a negative color - Campbell */ f1= 1.0f-i; diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index d04174a32aa..ba8905973d5 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -2597,12 +2597,10 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, } } MT_Point3 fromPoint = NodeGetWorldPosition(); + if (dist != 0.0f) - { - MT_Vector3 toDir = toPoint-fromPoint; - toDir.normalize(); - toPoint = fromPoint + (dist) * toDir; - } + toPoint = fromPoint + dist * (toPoint-fromPoint).safe_normalized(); + PHY_IPhysicsEnvironment* pe = KX_GetActiveScene()->GetPhysicsEnvironment(); KX_IPhysicsController *spc = GetPhysicsController(); KX_GameObject *parent = GetParent(); From d7bf9688ac78169a37fbfc0d3d5bcd5b5be19170 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 27 Aug 2009 23:29:07 +0000 Subject: [PATCH 8/8] fix for crash when a parent compound object didn't get a physics controller. also show this in the UI. --- source/blender/src/buttons_logic.c | 22 ++++++++++++------- .../Converter/BL_BlenderDataConversion.cpp | 4 +++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 0412aa72b37..6117c10c718 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -3513,14 +3513,20 @@ static void buttons_bullet(uiBlock *block, Object *ob) } if (ob->body_type!=OB_BODY_TYPE_SOFT) { - if (ob->parent) - uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Add to parent", 240,105,110,19, - &ob->gameflag, 0, 0, 0, 0, - "Add this shape to the parent compound shape"); - else - uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 240,105,110,19, - &ob->gameflag, 0, 0, 0, 0, - "Create a compound shape with the children's shape that are tagged for addition"); + if (ob->parent) { + if(ob->parent->gameflag & (OB_DYNAMIC|OB_COLLISION)) { + uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Add to parent", 240,105,110,19, + &ob->gameflag, 0, 0, 0, 0, + "Add this shape to the parent compound shape"); + } + } + else { + if(ob->gameflag & (OB_DYNAMIC|OB_COLLISION)) { + uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 240,105,110,19, + &ob->gameflag, 0, 0, 0, 0, + "Create a compound shape with the children's shape that are tagged for addition"); + } + } } } uiBlockEndAlign(block); diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index d2e6bbb43f7..c2566caba1e 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1381,7 +1381,9 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, bool isCompoundChild = false; bool hasCompoundChildren = !parent && (blenderobject->gameflag & OB_CHILD); - if (parent/* && (parent->gameflag & OB_DYNAMIC)*/) { + /* When the parent is not OB_DYNAMIC and has no OB_COLLISION then it gets no bullet controller + * and cant be apart of the parents compound shape */ + if (parent && (parent->gameflag & (OB_DYNAMIC | OB_COLLISION))) { if ((parent->gameflag & OB_CHILD) != 0 && (blenderobject->gameflag & OB_CHILD)) {