diff options
62 files changed, 1092 insertions, 362 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index aed1b3eeea9..13fd55d244f 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -43,7 +43,7 @@ extern "C" { struct ListBase; struct MemFile; -#define BLENDER_VERSION 239 +#define BLENDER_VERSION 240 int BKE_read_file(char *dir, void *type_r); int BKE_read_file_from_memory(char* filebuf, int filelength, void *type_r); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 090c1c71884..ae187c0e0f7 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -1550,7 +1550,15 @@ static void dag_object_time_update_flags(Object *ob) { if(ob->ipo) ob->recalc |= OB_RECALC_OB; - else if(ob->constraints.first) ob->recalc |= OB_RECALC_OB; + else if(ob->constraints.first) { + bConstraint *con; + for (con = ob->constraints.first; con; con=con->next){ + if (constraint_has_target(con)) { + ob->recalc |= OB_RECALC_OB; + break; + } + } + } else if(ob->scriptlink.totscript) ob->recalc |= OB_RECALC_OB; else if(ob->parent) { /* motion path or bone child */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 3b37c2aba6c..34777930b4b 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -1210,9 +1210,15 @@ static void *booleanModifier_applyModifier(ModifierData *md, Object *ob, void *d if( ((Mesh *)ob->data)->totface>3 && bmd->object && ((Mesh *)bmd->object->data)->totface>3) { DispListMesh *dlm= NewBooleanMeshDLM(bmd->object, ob, 1+bmd->operation); - return derivedmesh_from_displistmesh(dlm, NULL); + /* if new mesh returned, get derived mesh; otherwise there was + * an error, so delete the modifier object */ + + if( dlm ) + return derivedmesh_from_displistmesh(dlm, NULL); + else + bmd->object = NULL; } - else return derivedData; + return derivedData; } /***/ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 970d0306fd6..5095cc42836 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -625,6 +625,9 @@ static BHeadN *get_bhead(FileData *fd) } } + /* make sure people are not trying to pass bad blend files */ + if (bhead.len < 0) fd->eof = 1; + // bhead now contains the (converted) bhead structure. Now read // the associated data and put everything in a BHeadN (creative naming !) @@ -639,6 +642,7 @@ static BHeadN *get_bhead(FileData *fd) if (readsize != bhead.len) { fd->eof = 1; MEM_freeN(new_bhead); + new_bhead = 0; } } else { fd->eof = 1; @@ -5205,12 +5209,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main) cam->flag |= CAM_SHOWPASSEPARTOUT; /* make sure old cameras have title safe on */ - - /* *** to be uncommented before 2.40 release! *** */ - /* if (!(cam->flag & CAM_SHOWTITLESAFE)) cam->flag |= CAM_SHOWTITLESAFE; - */ /* set an appropriate camera passepartout alpha */ if (!(cam->passepartalpha)) cam->passepartalpha = 0.2f; @@ -5222,11 +5222,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) ma->mode |= MA_TANGENT_STR; } if(ma->mode & MA_TRACEBLE) ma->mode |= MA_SHADBUF; - - /* orange stuff, so should be done for 2.40 too */ - if(ma->layers.first==NULL) { - ma->ml_flag= ML_RENDER; - } } } diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c index 5b86a2c2dfa..616531b3a77 100644 --- a/source/blender/imbuf/intern/tiff.c +++ b/source/blender/imbuf/intern/tiff.c @@ -303,7 +303,7 @@ struct ImBuf *imb_loadtiff(unsigned char *mem, int size, int flags) { TIFF *image = NULL; struct ImBuf *ibuf = NULL; - struct ImbTIFFMemFile memFile = { mem, 0, size }; + struct ImbTIFFMemFile memFile; uint32 width, height; int bytesperpixel; int success; @@ -312,6 +312,10 @@ struct ImBuf *imb_loadtiff(unsigned char *mem, int size, int flags) uint32 pixel; unsigned char *to = NULL; + memFile.mem = mem; + memFile.offset = 0; + memFile.size = size; + /* check whether or not we have a TIFF file */ assert(size >= IMB_TIFF_NCB); if (imb_is_a_tiff(mem) == 0) diff --git a/source/blender/include/BDR_editcurve.h b/source/blender/include/BDR_editcurve.h index 9355eebb85d..9cddad4bf67 100644 --- a/source/blender/include/BDR_editcurve.h +++ b/source/blender/include/BDR_editcurve.h @@ -81,7 +81,7 @@ void selectrow_nurb(void); void adduplicate_nurb(void); void delNurb(void); void nurb_set_smooth(short event); -void join_curve(int type); +int join_curve(int type); struct Nurb *addNurbprim(int type, int stype, int newname); void default_curve_ipo(struct Curve *cu); void add_primitiveCurve(int stype); diff --git a/source/blender/include/BDR_editobject.h b/source/blender/include/BDR_editobject.h index 99c9655a763..a3f2a1061f1 100644 --- a/source/blender/include/BDR_editobject.h +++ b/source/blender/include/BDR_editobject.h @@ -92,7 +92,7 @@ void single_tex_users_expand(void); void single_mat_users_expand(void); void single_user(void); void make_local(void); -void adduplicate(int noTrans); +void adduplicate(int mode, int dupflag); /* when the dupflag is 0 no data is duplicated */ void selectlinks_menu(void); void selectlinks(int nr); void image_aspect(void); diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index 75aa02bfa57..7766accdab6 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -87,7 +87,7 @@ void subdivide_armature(void); void free_editArmature(void); -void join_armature(void); +int join_armature(void); void load_editArmature(void); void make_bone_parent(void); diff --git a/source/blender/include/BIF_meshtools.h b/source/blender/include/BIF_meshtools.h index 8df5e7255a5..e926d41faf1 100644 --- a/source/blender/include/BIF_meshtools.h +++ b/source/blender/include/BIF_meshtools.h @@ -36,7 +36,7 @@ struct Object; struct EditVert; -extern void join_mesh(void); +extern int join_mesh(void); extern void fasterdraw(void); extern void slowerdraw(void); diff --git a/source/blender/include/BIF_space.h b/source/blender/include/BIF_space.h index 7970ed5e41d..8213192a2ae 100644 --- a/source/blender/include/BIF_space.h +++ b/source/blender/include/BIF_space.h @@ -115,6 +115,7 @@ extern void set_rects_butspace(struct SpaceButs *buts); extern void test_butspace(void); extern void start_game(void); extern void select_grouped(short nr); +extern void join_menu(void); extern void BIF_undo_push(char *str); extern void BIF_undo(void); diff --git a/source/blender/python/api2_2x/Armature.c b/source/blender/python/api2_2x/Armature.c index 05a89dbda21..a2a3db05bc8 100644 --- a/source/blender/python/api2_2x/Armature.c +++ b/source/blender/python/api2_2x/Armature.c @@ -172,28 +172,25 @@ static int BonesDict_InitEditBones(BPy_BonesDict *self) //This is the string representation of the object static PyObject *BonesDict_repr(BPy_BonesDict *self) { - char buffer[128], str[4096]; + char str[4096]; PyObject *key, *value; int pos = 0; + char *p = str; + + p += sprintf(str, "[Bone Dict: {"); - BLI_strncpy(str,"",4096); - sprintf(buffer, "[Bone Dict: {"); - strcat(str,buffer); if (self->editmode_flag){ while (PyDict_Next(self->editbonesMap, &pos, &key, &value)) { - sprintf(buffer, "%s : %s, ", PyString_AsString(key), + p += sprintf(p, "%s : %s, ", PyString_AsString(key), PyString_AsString(value->ob_type->tp_repr(value))); - strcat(str,buffer); } }else{ while (PyDict_Next(self->bonesMap, &pos, &key, &value)) { - sprintf(buffer, "%s : %s, ", PyString_AsString(key), + p += sprintf(p, "%s : %s, ", PyString_AsString(key), PyString_AsString(value->ob_type->tp_repr(value))); - strcat(str,buffer); } } - sprintf(buffer, "}]\n"); - strcat(str,buffer); + p += sprintf(p, "}]\n"); return PyString_FromString(str); } diff --git a/source/blender/python/api2_2x/BezTriple.c b/source/blender/python/api2_2x/BezTriple.c index 98e53d2fef8..3d610e38fd6 100644 --- a/source/blender/python/api2_2x/BezTriple.c +++ b/source/blender/python/api2_2x/BezTriple.c @@ -136,43 +136,55 @@ PyTypeObject BezTriple_Type = { static PyObject *M_BezTriple_New( PyObject* self, PyObject * args ) { float numbuf[9]; - int status, length; PyObject* in_args = NULL; + int length; - if( !PyArg_ParseTuple( args, "|O", &in_args) ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected sequence of 3 or 9 floats or nothing" ); + /* accept list, tuple, or 3 or 9 args (which better be floats) */ + + length = PyTuple_Size( args ); + if( length == 3 || length == 9 ) + in_args = args; + else if( !PyArg_ParseTuple( args, "|O", &in_args) ) + goto TypeError; if( !in_args ) { numbuf[0] = 0.0f; numbuf[1] = 0.0f; numbuf[2] = 0.0f; numbuf[3] = 0.0f; numbuf[4] = 0.0f; numbuf[5] = 0.0f; numbuf[6] = 0.0f; numbuf[7] = 0.0f; numbuf[8] = 0.0f; } else { + int i, length; if( !PySequence_Check( in_args ) ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected sequence of 3 or 9 floats or nothing" ); - + goto TypeError; + length = PySequence_Length( in_args ); - if( length == 9 ) - status = PyArg_ParseTuple( in_args, "fffffffff", - &numbuf[0], &numbuf[1], &numbuf[2], - &numbuf[3], &numbuf[4], &numbuf[5], - &numbuf[6], &numbuf[7], &numbuf[8]); - else if( length == 3 ) { - status = PyArg_ParseTuple( in_args, "fff", - &numbuf[0], &numbuf[1], &numbuf[2]); + if( length != 9 && length != 3 ) + goto TypeError; + + for(i=0; i<length; i++) { + PyObject *item, *pyfloat; + item=PySequence_ITEM(in_args, i); + if( !item ) + goto TypeError; + pyfloat=PyNumber_Float(item); + Py_DECREF(item); + if( !pyfloat ) + goto TypeError; + numbuf[i]=(float)PyFloat_AS_DOUBLE(pyfloat); + Py_DECREF(pyfloat); + } + + if( length == 3 ) { numbuf[3] = numbuf[0]; numbuf[6] = numbuf[0]; numbuf[4] = numbuf[1]; numbuf[7] = numbuf[1]; numbuf[5] = numbuf[2]; numbuf[8] = numbuf[2]; - } else - return EXPP_ReturnPyObjError( PyExc_TypeError, - "wrong number of points" ); - if( !status ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "sequence item not number"); + } } return newBezTriple( numbuf ); + +TypeError: + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected sequence of 3 or 9 floats or nothing" ); } /**************************************************************************** diff --git a/source/blender/python/api2_2x/Lamp.c b/source/blender/python/api2_2x/Lamp.c index a54e2988763..f60e68697ee 100644 --- a/source/blender/python/api2_2x/Lamp.c +++ b/source/blender/python/api2_2x/Lamp.c @@ -84,6 +84,7 @@ #define EXPP_LAMP_MODE_DEEPSHADOW 1024 #define EXPP_LAMP_MODE_NODIFFUSE 2048 #define EXPP_LAMP_MODE_NOSPECULAR 4096 +#define EXPP_LAMP_MODE_SHAD_RAY 8192 /* Lamp MIN, MAX values */ #define EXPP_LAMP_SAMPLES_MIN 1 @@ -120,8 +121,8 @@ /* Raytracing settings */ #define EXPP_LAMP_RAYSAMPLES_MIN 1 #define EXPP_LAMP_RAYSAMPLES_MAX 16 -#define EXPP_LAMP_AREASIZE_MIN 0.01 -#define EXPP_LAMP_AREASIZE_MAX 100.0 +#define EXPP_LAMP_AREASIZE_MIN 0.01f +#define EXPP_LAMP_AREASIZE_MAX 100.0f /* Lamp_setComponent() keys for which color to get/set */ #define EXPP_LAMP_COMP_R 0x00 @@ -781,8 +782,8 @@ static PyObject *Lamp_ModesDict( void ) PyInt_FromLong( EXPP_LAMP_MODE_ONLYSHADOW ) ); PyConstant_Insert( c, "NoDiffuse", PyInt_FromLong( EXPP_LAMP_MODE_NODIFFUSE ) ); - PyConstant_Insert( c, "NoSpecular", - PyInt_FromLong( EXPP_LAMP_MODE_NOSPECULAR ) ); + PyConstant_Insert( c, "RayShadow", + PyInt_FromLong( EXPP_LAMP_MODE_SHAD_RAY ) ); } return Modes; @@ -1165,7 +1166,8 @@ static int Lamp_setMode( BPy_Lamp * self, PyObject * value ) | EXPP_LAMP_MODE_SPHERE | EXPP_LAMP_MODE_SQUARE | EXPP_LAMP_MODE_NODIFFUSE - | EXPP_LAMP_MODE_NOSPECULAR; + | EXPP_LAMP_MODE_NOSPECULAR + | EXPP_LAMP_MODE_SHAD_RAY; if( !PyInt_CheckExact ( value ) ) { char errstr[128]; @@ -1550,7 +1552,7 @@ static PyObject *Lamp_insertIpoKey( BPy_Lamp * self, PyObject * args ) static PyObject *Lamp_getModesConst( void ) { PyObject * attr = Py_BuildValue - ( "{s:h,s:h,s:h,s:h,s:h,s:h,s:h,s:h,s:h,s:h}", + ( "{s:h,s:h,s:h,s:h,s:h,s:h,s:h,s:h,s:h,s:h,s:h}", "Shadows", EXPP_LAMP_MODE_SHADOWS, "Halo", EXPP_LAMP_MODE_HALO, "Layer", EXPP_LAMP_MODE_LAYER, "Quad", EXPP_LAMP_MODE_QUAD, "Negative", @@ -1559,7 +1561,8 @@ static PyObject *Lamp_getModesConst( void ) EXPP_LAMP_MODE_SPHERE, "Square", EXPP_LAMP_MODE_SQUARE, "NoDiffuse", EXPP_LAMP_MODE_NODIFFUSE, "NoSpecular", - EXPP_LAMP_MODE_NOSPECULAR ); + EXPP_LAMP_MODE_NOSPECULAR, "RayShadow", + EXPP_LAMP_MODE_SHAD_RAY); if( !attr ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, @@ -1804,6 +1807,8 @@ static PyObject *Lamp_oldsetMode( BPy_Lamp * self, PyObject * args ) flag |= ( short ) EXPP_LAMP_MODE_NODIFFUSE; else if( !strcmp( name, "NoSpecular" ) ) flag |= ( short ) EXPP_LAMP_MODE_NOSPECULAR; + else if( !strcmp( name, "RayShadow" ) ) + flag |= ( short ) EXPP_LAMP_MODE_SHAD_RAY; else return EXPP_ReturnPyObjError( PyExc_AttributeError, "unknown lamp flag argument" ); diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c index b9f9937d1fd..aa3c86e30fd 100644 --- a/source/blender/python/api2_2x/Material.c +++ b/source/blender/python/api2_2x/Material.c @@ -522,6 +522,8 @@ static PyObject *Material_getColorComponent( BPy_Material * self, static PyObject *Material_getOopsLoc( BPy_Material * self ); static PyObject *Material_getOopsSel( BPy_Material * self ); static PyObject *Material_getUsers( BPy_Material * self ); +static int Material_setSeptex( BPy_Material * self, PyObject * value ); +static PyObject *Material_getSeptex( BPy_Material * self ); /*****************************************************************************/ /* Python BPy_Material methods declarations: */ @@ -2891,17 +2893,20 @@ static PyObject *Matr_oldsetZOffset( BPy_Material * self, PyObject * args ) static PyObject *Matr_oldsetRGBCol( BPy_Material * self, PyObject * args ) { - return EXPP_setterWrapper( (void *)self, args, (setter)Material_setRGBCol ); + return EXPP_setterWrapperTuple( (void *)self, args, + (setter)Material_setRGBCol ); } static PyObject *Matr_oldsetSpecCol( BPy_Material * self, PyObject * args ) { - return EXPP_setterWrapper( (void *)self, args, (setter)Material_setSpecCol ); + return EXPP_setterWrapperTuple( (void *)self, args, + (setter)Material_setSpecCol ); } static PyObject *Matr_oldsetMirCol( BPy_Material * self, PyObject * args ) { - return EXPP_setterWrapper( (void *)self, args, (setter)Material_setMirCol ); + return EXPP_setterWrapperTuple( (void *)self, args, + (setter)Material_setMirCol ); } diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c index ec5d75f16df..0bb882a046c 100644 --- a/source/blender/python/api2_2x/Mesh.c +++ b/source/blender/python/api2_2x/Mesh.c @@ -4084,7 +4084,7 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args ) /* eliminate new faces already in the mesh */ tmppair = newpair; - for( i = len; i-- ; ) { + for( i = good_faces; i-- ; ) { if( tmppair->v[1] ) { if( bsearch( tmppair, oldpair, mesh->totface, sizeof(SrchFaces), mface_comp ) ) { @@ -4101,6 +4101,16 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args ) if( good_faces ) { int totface = mesh->totface+good_faces; /* new face count */ + /* if mesh has tfaces, reallocate them first */ + if( mesh->tface ) { + TFace *tmptface; + + tmptface = MEM_callocN(totface*sizeof(TFace), "Mesh_addFaces"); + memcpy( tmptface, mesh->tface, mesh->totface*sizeof(TFace)); + MEM_freeN( mesh->tface ); + mesh->tface = tmptface; + } + /* allocate new face list */ tmpface = MEM_callocN(totface*sizeof(MFace), "Mesh_addFaces"); @@ -4761,11 +4771,11 @@ static PyObject *Mesh_getFromObject( BPy_Mesh * self, PyObject * args ) char *name; ID tmpid; Mesh *tmpmesh; - Curve *tmpcu; + Curve *tmpcu = NULL; DispListMesh *dlm; DerivedMesh *dm; Object *tmpobj = NULL; - int cage = 0; + int cage = 0, i; if( !PyArg_ParseTuple( args, "s|i", &name, &cage ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -4839,7 +4849,8 @@ static PyObject *Mesh_getFromObject( BPy_Mesh * self, PyObject * args ) displistmesh_to_mesh( dlm, tmpmesh ); dm->release( dm ); } - + + /* take control of mesh before object is freed */ tmpobj->data = NULL; free_libblock_us( &G.main->object, tmpobj ); @@ -4855,11 +4866,60 @@ static PyObject *Mesh_getFromObject( BPy_Mesh * self, PyObject * args ) tmpid = self->mesh->id; memcpy( self->mesh, tmpmesh, sizeof( Mesh ) ); self->mesh->id = tmpid; - + /* if mesh has keys, make sure they point back to this mesh */ if( self->mesh->key ) self->mesh->key->from = (ID *)self->mesh; + + + + /* Copy materials to new object */ + switch (ob->type) { + case OB_SURF: + self->mesh->totcol = tmpcu->totcol; + + /* free old material list (if it exists) and adjust user counts */ + if( tmpcu->mat ) { + for( i = tmpcu->totcol; i-- > 0; ) { + self->mesh->mat[i] = tmpcu->mat[i]; + if (self->mesh->mat[i]) { + tmpmesh->mat[i]->id.us++; + } + } + } + break; +#if 0 + /* Crashes when assigning the new material, not sure why */ + case OB_MBALL: + tmpmb = (MetaBall *)ob->data; + self->mesh->totcol = tmpmb->totcol; + + /* free old material list (if it exists) and adjust user counts */ + if( tmpmb->mat ) { + for( i = tmpmb->totcol; i-- > 0; ) { + self->mesh->mat[i] = tmpmb->mat[i]; /* CRASH HERE ??? */ + if (self->mesh->mat[i]) { + tmpmb->mat[i]->id.us++; + } + } + } + break; +#endif + + case OB_MESH: + self->mesh->totcol = tmpmesh->totcol; + if( tmpmesh->mat ) { + for( i = tmpmesh->totcol; i-- > 0; ) { + self->mesh->mat[i] = tmpmesh->mat[i]; + /* user count dosent need to change */ + } + } + break; + } /* end copy materials */ + + + /* remove the temporary mesh */ BLI_remlink( &G.main->mesh, tmpmesh ); MEM_freeN( tmpmesh ); diff --git a/source/blender/python/api2_2x/NMesh.c b/source/blender/python/api2_2x/NMesh.c index a22307c7574..f285557d5ee 100644 --- a/source/blender/python/api2_2x/NMesh.c +++ b/source/blender/python/api2_2x/NMesh.c @@ -317,6 +317,77 @@ void mesh_update( Mesh * mesh, Object * ob ) } } +/* + * before trying to convert NMesh data back to mesh, verify that the + * lists contain the right type of data + */ + +static int check_NMeshLists( BPy_NMesh *nmesh ) +{ + int i; + + if( !PySequence_Check( nmesh->verts ) ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "nmesh verts are not a sequence" ); + if( !PySequence_Check( nmesh->edges ) ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "nmesh edges are not a sequence" ); + if( !PySequence_Check( nmesh->faces ) ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "nmesh faces are not a sequence" ); + if( !PySequence_Check( nmesh->materials ) ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "nmesh materials are not a sequence" ); + + if( EXPP_check_sequence_consistency( nmesh->verts, &NMVert_Type ) != 1 ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "nmesh vertices must be NMVerts" ); + if( EXPP_check_sequence_consistency( nmesh->edges, &NMEdge_Type ) != 1 ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "nmesh edges must be NMEdges" ); + if( EXPP_check_sequence_consistency( nmesh->faces, &NMFace_Type ) != 1 ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "nmesh faces must be NMFaces" ); + for( i = 0 ; i < PySequence_Length(nmesh->faces); ++i ) { + int j, err=0; + PyObject *col, *v, *uv; + BPy_NMFace *face=(BPy_NMFace *)PySequence_GetItem(nmesh->faces, i); + + col = face->col; + uv = face->uv; + v = face->v; + Py_DECREF( face ); + if( EXPP_check_sequence_consistency( face->col, &NMCol_Type ) != 1 ) { + return EXPP_ReturnIntError( PyExc_AttributeError, + "nmesh face col must be NMCols" ); + } + if( EXPP_check_sequence_consistency( face->v, &NMVert_Type ) != 1 ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "nmesh face v must be NMVerts" ); + + for( j = 0 ; !err && j < PySequence_Length( face->uv ); ++j ) { + PyObject *uv = PySequence_GetItem( face->uv, j); + if( PySequence_Check(uv) && PySequence_Length(uv) == 2 ) { + PyObject *p1 = PySequence_GetItem(uv, 0); + PyObject *p2 = PySequence_GetItem(uv, 1); + if( !PyNumber_Check(p1) || !PyNumber_Check(p2) ) + err = 1; + Py_DECREF( p1 ); + Py_DECREF( p2 ); + } + else { + err = 1; + } + + Py_DECREF( uv ); + } + if( err ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "nmesh face uv must contain sequence of 2 floats" ); + } + return 0; +} + /*****************************/ /* Mesh Color Object */ @@ -602,7 +673,7 @@ static int NMFace_setattr( PyObject * self, char *name, PyObject * v ) if( strcmp( name, "v" ) == 0 ) { - if( PyList_Check( v ) ) { + if( PySequence_Check( v ) ) { Py_DECREF( mf->v ); mf->v = EXPP_incr_ret( v ); @@ -610,7 +681,7 @@ static int NMFace_setattr( PyObject * self, char *name, PyObject * v ) } } else if( strcmp( name, "col" ) == 0 ) { - if( PyList_Check( v ) ) { + if( PySequence_Check( v ) ) { Py_DECREF( mf->col ); mf->col = EXPP_incr_ret( v ); @@ -642,7 +713,7 @@ static int NMFace_setattr( PyObject * self, char *name, PyObject * v ) } else if( strcmp( name, "uv" ) == 0 ) { - if( PyList_Check( v ) ) { + if( PySequence_Check( v ) ) { Py_DECREF( mf->uv ); mf->uv = EXPP_incr_ret( v ); @@ -1327,6 +1398,9 @@ static PyObject *NMesh_update( PyObject *self, PyObject *a, PyObject *kwd ) return EXPP_ReturnPyObjError( PyExc_AttributeError, "expected nothing or one to three bool(s) (0 or 1) as argument" ); + if( check_NMeshLists( nmesh ) ) + return NULL; + if( mesh ) { old_totvert = mesh->totvert; unlink_existingMeshData( mesh ); @@ -1767,7 +1841,7 @@ static int NMesh_setattr( PyObject * self, char *name, PyObject * v ) else if( !strcmp( name, "verts" ) || !strcmp( name, "faces" ) || !strcmp( name, "materials" ) ) { - if( PyList_Check( v ) ) { + if( PySequence_Check( v ) ) { if( strcmp( name, "materials" ) == 0 ) { Py_DECREF( me->materials ); @@ -2988,6 +3062,10 @@ static int convert_NMeshToMesh( Mesh * mesh, BPy_NMesh * nmesh) mesh->subdiv = nmesh->subdiv[0]; mesh->subdivr = nmesh->subdiv[1]; + + + + /*@ material assignment moved to PutRaw */ mesh->totvert = PySequence_Length( nmesh->verts ); if( mesh->totvert ) { @@ -3144,24 +3222,8 @@ static PyObject *M_NMesh_PutRaw( PyObject * self, PyObject * args ) return EXPP_ReturnPyObjError( PyExc_AttributeError, "expected an NMesh object and optionally also a string and two ints" ); - if( !PySequence_Check( nmesh->verts ) ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "nmesh vertices are not a sequence" ); - if( !PySequence_Check( nmesh->faces ) ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "nmesh faces are not a sequence" ); - if( !PySequence_Check( nmesh->materials ) ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "nmesh materials are not a sequence" ); - - if( EXPP_check_sequence_consistency( nmesh->verts, &NMVert_Type ) != - 1 ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "nmesh vertices must be NMVerts" ); - if( EXPP_check_sequence_consistency( nmesh->faces, &NMFace_Type ) != - 1 ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "nmesh faces must be NMFaces" ); + if( check_NMeshLists( nmesh ) ) + return NULL; if( name ) mesh = ( Mesh * ) GetIdFromList( &( G.main->mesh ), name ); diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index f74a0a176e4..af945ea09c0 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -62,12 +62,16 @@ struct rctf; #include "BKE_curve.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_scene.h" #include "BSE_editipo.h" #include "BSE_edit.h" #include "BIF_space.h" #include "BIF_editview.h" +#include "BIF_drawscene.h" +#include "BIF_meshtools.h" +#include "BIF_editarmature.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -123,6 +127,7 @@ struct rctf; static PyObject *M_Object_New( PyObject * self, PyObject * args ); PyObject *M_Object_Get( PyObject * self, PyObject * args ); static PyObject *M_Object_GetSelected( PyObject * self ); +static PyObject *M_Object_Duplicate( PyObject * self, PyObject * args, PyObject *kwd); /* HELPER FUNCTION FOR PARENTING */ static PyObject *internal_makeParent(Object *parent, PyObject *py_child, int partype, int noninverse, int fast, int v1, int v2, int v3); @@ -148,6 +153,10 @@ char M_Object_GetSelected_doc[] = "() - Returns a list of selected Objects in the active layer(s)\n\ The active object is the first in the list, if visible"; +char M_Object_Duplicate_doc[] = + "(linked) - Duplicate all selected, visible objects in the current scene"; + + /*****************************************************************************/ /* Python method structure definition for Blender.Object module: */ /*****************************************************************************/ @@ -158,9 +167,12 @@ struct PyMethodDef M_Object_methods[] = { M_Object_Get_doc}, {"GetSelected", ( PyCFunction ) M_Object_GetSelected, METH_NOARGS, M_Object_GetSelected_doc}, + {"Duplicate", ( PyCFunction ) M_Object_Duplicate, METH_VARARGS | METH_KEYWORDS, + M_Object_Duplicate_doc}, {NULL, NULL, 0, NULL} }; + /*****************************************************************************/ /* Python BPy_Object methods declarations: */ /*****************************************************************************/ @@ -195,6 +207,7 @@ static PyObject *Object_isSelected( BPy_Object * self ); static PyObject *Object_makeDisplayList( BPy_Object * self ); static PyObject *Object_link( BPy_Object * self, PyObject * args ); static PyObject *Object_makeParent( BPy_Object * self, PyObject * args ); +static PyObject *Object_join( BPy_Object * self, PyObject * args ); static PyObject *Object_makeParentDeform( BPy_Object * self, PyObject * args ); static PyObject *Object_makeParentVertex( BPy_Object * self, PyObject * args ); static PyObject *Object_materialUsage( void ); @@ -466,6 +479,8 @@ mode:\n\t0: make parent with inverse\n\t1: without inverse\n\ fast:\n\t0: update scene hierarchy automatically\n\t\ don't update scene hierarchy (faster). In this case, you must\n\t\ explicitely update the Scene hierarchy."}, + {"join", ( PyCFunction ) Object_join, METH_VARARGS, + "(object_list) - Joins the objects in object list of the same type, into this object."}, {"makeParentDeform", ( PyCFunction ) Object_makeParentDeform, METH_VARARGS, "Makes the object the deformation parent of the objects provided in the \n\ argument which must be a list of valid Objects. Optional extra arguments:\n\ @@ -779,12 +794,13 @@ static PyObject *M_Object_GetSelected( PyObject * self ) PyObject *list; Base *base_iter; + list = PyList_New( 0 ); + if( G.vd == NULL ) { - // No 3d view has been initialized yet, simply return None - Py_INCREF( Py_None ); - return Py_None; + /* No 3d view has been initialized yet, simply return an empty list */ + return list; } - list = PyList_New( 0 ); + if( ( G.scene->basact ) && ( ( G.scene->basact->flag & SELECT ) && ( G.scene->basact->lay & G.vd->lay ) ) ) { @@ -802,22 +818,66 @@ static PyObject *M_Object_GetSelected( PyObject * self ) base_iter = G.scene->base.first; while( base_iter ) { if( ( ( base_iter->flag & SELECT ) && - ( base_iter->lay & G.vd->lay ) ) && + ( base_iter->lay & G.vd->lay ) ) && ( base_iter != G.scene->basact ) ) { blen_object = Object_CreatePyObject( base_iter->object ); - if( !blen_object ) { - Py_DECREF( list ); - Py_RETURN_NONE; + if( blen_object ) { + PyList_Append( list, blen_object ); + Py_DECREF( blen_object ); } - PyList_Append( list, blen_object ); - Py_DECREF( blen_object ); } base_iter = base_iter->next; } return list; } + +/*****************************************************************************/ +/* Function: M_Object_Duplicate */ +/* Python equivalent: Blender.Object.Duplicate */ +/*****************************************************************************/ +static PyObject *M_Object_Duplicate( PyObject * self, PyObject * args, PyObject *kwd ) +{ + int dupflag= 0; /* this a flag, passed to adduplicate() and used instead of U.dupflag sp python can set what is duplicated */ + + /* the following variables are bools, if set true they will modify the dupflag to pass to adduplicate() */ + int mesh_dupe = 0; + int surface_dupe = 0; + int curve_dupe = 0; + int text_dupe = 0; + int metaball_dupe = 0; + int armature_dupe = 0; + int lamp_dupe = 0; + int material_dupe = 0; + int texture_dupe = 0; + int ipo_dupe = 0; + + static char *kwlist[] = {"mesh", "surface", "curve", + "text", "metaball", "armature", "lamp", "material", "texture", "ipo", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwd, "|iiiiiiiiii", kwlist, + &mesh_dupe, &surface_dupe, &curve_dupe, &text_dupe, &metaball_dupe, + &armature_dupe, &lamp_dupe, &material_dupe, &texture_dupe, &ipo_dupe)) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "expected nothing or bool keywords 'mesh', 'surface', 'curve', 'text', 'metaball', 'armature', 'lamp' 'material', 'texture' and 'ipo' 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; + if (surface_dupe) dupflag |= USER_DUP_SURF; + if (curve_dupe) dupflag |= USER_DUP_CURVE; + if (text_dupe) dupflag |= USER_DUP_FONT; + if (metaball_dupe) dupflag |= USER_DUP_MBALL; + if (armature_dupe) dupflag |= USER_DUP_ARM; + if (lamp_dupe) dupflag |= USER_DUP_LAMP; + if (material_dupe) dupflag |= USER_DUP_MAT; + if (texture_dupe) dupflag |= USER_DUP_TEX; + if (ipo_dupe) dupflag |= USER_DUP_IPO; + adduplicate(2, dupflag); /* 2 is a mode with no transform and no redraw, Duplicate the current selection, context sensitive */ + Py_RETURN_NONE; +} + + /*****************************************************************************/ /* Function: initObject */ /*****************************************************************************/ @@ -970,7 +1030,8 @@ int EXPP_add_obdata( struct Object *object ) object->data = add_mball( ); break; - /* TODO the following types will be supported later + /* TODO the following types will be supported later, + be sure to update Scene_link when new types are supported case OB_SURF: object->data = add_curve(OB_SURF); G.totcurve++; @@ -1783,6 +1844,125 @@ static PyObject *Object_makeParent( BPy_Object * self, PyObject * args ) return EXPP_incr_ret( Py_None ); } + +static PyObject *Object_join( BPy_Object * self, PyObject * args ) +{ + PyObject *list; + PyObject *py_child; + Object *parent; + Object *child; + Scene *temp_scene; + Scene *orig_scene; + Base *temp_base; + short type; + int i, ok=0, ret_value=0, list_length=0; + + /* cant join in editmode */ + if( G.obedit ) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "can't join objects while in edit mode" ); + + /* Check if the arguments passed to makeParent are valid. */ + if( !PyArg_ParseTuple( args, "O", &list ) ) + return ( EXPP_ReturnPyObjError( PyExc_AttributeError, + "expected a list of objects and one or two integers as arguments" ) ); + + if( !PySequence_Check( list ) ) + return ( EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a list of objects" ) ); + + list_length = PySequence_Length( list ); /* if there are no objects to join then exit silently */ + + if( !list_length ) + return EXPP_incr_ret( Py_None ); + + + parent = ( Object * ) self->object; + type = parent->type; + + if (type==OB_MESH || type==OB_MESH || type==OB_CURVE || type==OB_SURF || type==OB_ARMATURE); + else + return ( EXPP_ReturnPyObjError( PyExc_TypeError, + "Base object is not a type blender can join" ) ); + + temp_scene = add_scene( "Scene" ); /* make the new scene */ + temp_scene->lay= 2097151; /* all layers on */ + + /* Check if the PyObject passed in list is a Blender object. */ + for( i = 0; i < list_length; i++ ) { + child = NULL; + py_child = PySequence_GetItem( list, i ); + if( !Object_CheckPyObject( py_child ) ) { + /* Cleanup */ + free_libblock( &G.main->scene, temp_scene ); + return ( EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a list of objects, one or more of the list items is not a Blender Object." ) ); + } else { + /* List item is an object, is it the same type? */ + child = ( Object * ) Object_FromPyObject( py_child ); + if (parent->type == child->type) { + ok =1; + /* Add a new base, then link the base to the temp_scene */ + temp_base = MEM_callocN( sizeof( Base ), "pynewbase" ); + /*we know these types are the same, link to the temp scene for joining*/ + temp_base->object = child; /* link object to the new base */ + temp_base->flag |= SELECT; + temp_base->lay = 1; /*1 layer on */ + + BLI_addhead( &temp_scene->base, temp_base ); /* finally, link new base to scene */ + /*child->id.us += 1;*/ /*Would useually increase user count but in this case its ok not to */ + } else { + child->id.us -= 1; /* python object user oddness */ + } + + } + } + + orig_scene = G.scene; /* backup our scene */ + + /* Add the main object into the temp_scene */ + temp_base = MEM_callocN( sizeof( Base ), "pynewbase" ); + temp_base->object = parent; /* link object to the new base */ + temp_base->flag |= SELECT; + temp_base->lay = 1; /*1 layer on */ + BLI_addhead( &temp_scene->base, temp_base ); /* finally, link new base to scene */ + parent->id.us += 1; + + /* all objects in the scene, set it active and the active object */ + set_scene( temp_scene ); + set_active_base( temp_base ); + + /* Do the joining now we know everythings OK. */ + if(type == OB_MESH) + ret_value = join_mesh(); + else if(type == OB_CURVE) + ret_value = join_curve(OB_CURVE); + else if(type == OB_SURF) + ret_value = join_curve(OB_SURF); + else if(type == OB_ARMATURE) + ret_value = join_armature (); + /* May use for correcting object user counts */ + /* + if (!ret_value) { + temp_base = temp_scene->base.first; + while( base ) { + object = base->object; + object->id.us +=1 + base = base->next; + } + }*/ + + + /* remove old scene */ + set_scene( orig_scene ); + free_libblock( &G.main->scene, temp_scene ); + + if (!ok) /* no objects were of the correct type, return 0 */ + return ( PyInt_FromLong(0) ); + + return ( PyInt_FromLong(ret_value) ); +} + static PyObject *internal_makeParent(Object *parent, PyObject *py_child, int partype, /* parenting type */ int noninverse, int fast, /* parenting arguments */ diff --git a/source/blender/python/api2_2x/Scene.c b/source/blender/python/api2_2x/Scene.c index d90b5843540..90aa548d7ce 100644 --- a/source/blender/python/api2_2x/Scene.c +++ b/source/blender/python/api2_2x/Scene.c @@ -734,6 +734,7 @@ static PyObject *Scene_link( BPy_Scene * self, PyObject * args ) { Scene *scene = self->scene; BPy_Object *bpy_obj; + Object *object = NULL; if( !scene ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, @@ -742,9 +743,19 @@ static PyObject *Scene_link( BPy_Scene * self, PyObject * args ) if( !PyArg_ParseTuple( args, "O!", &Object_Type, &bpy_obj ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected Object argument" ); - - else { /* Ok, all is fine, let's try to link it */ - Object *object = bpy_obj->object; + + + //return EXPP_ReturnPyObjError( PyExc_RuntimeError, + // "Could not create data on demand for this object type!" ); + + object = bpy_obj->object; + + /* Object.c's EXPP_add_obdata does not support these objects */ + if (!object->data && (object->type == OB_SURF || object->type == OB_FONT || object->type == OB_WAVE )) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Object has no data and new data cant be automaticaly created for Surf, Text or Wave type objects!" ); + } else { + /* Ok, all is fine, let's try to link it */ Base *base; /* We need to link the object to a 'Base', then link this base @@ -766,8 +777,9 @@ static PyObject *Scene_link( BPy_Scene * self, PyObject * args ) "couldn't allocate new Base for object" ); /* check if this object has obdata, case not, try to create it */ + if( !object->data && ( object->type != OB_EMPTY ) ) - EXPP_add_obdata( object ); /* returns -1 on error, defined in Object.c */ + EXPP_add_obdata( object ); /* returns -1 on error, defined in Object.c */ base->object = object; /* link object to the new base */ base->lay = object->lay; @@ -823,7 +835,6 @@ static PyObject *Scene_getChildren( BPy_Scene * self ) PyObject *bpy_obj; Object *object; Base *base; - PyObject *name; if( !scene ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, @@ -833,22 +844,16 @@ static PyObject *Scene_getChildren( BPy_Scene * self ) while( base ) { object = base->object; - - name = Py_BuildValue( "(s)", object->id.name + 2 ); - if( !name ) - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Py_BuildValue() failed" ); - - bpy_obj = M_Object_Get( Py_None, name ); - Py_DECREF ( name ); - + + bpy_obj = Object_CreatePyObject( object ); + if( !bpy_obj ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't create new object wrapper" ); PyList_Append( pylist, bpy_obj ); Py_XDECREF( bpy_obj ); /* PyList_Append incref'ed it */ - + base = base->next; } @@ -869,11 +874,7 @@ static PyObject *Scene_getActiveObject(BPy_Scene *self) ob = ((scene->basact) ? (scene->basact->object) : 0); if (ob) { - PyObject *arg = Py_BuildValue("(s)", ob->id.name+2); - - pyob = M_Object_Get(Py_None, arg); - - Py_DECREF(arg); + pyob = Object_CreatePyObject( ob ); if (!pyob) return EXPP_ReturnPyObjError(PyExc_MemoryError, @@ -889,8 +890,9 @@ static PyObject *Scene_getActiveObject(BPy_Scene *self) static PyObject *Scene_getCurrentCamera( BPy_Scene * self ) { Object *cam_obj; + PyObject *pyob; Scene *scene = self->scene; - + if( !scene ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "Blender Scene was deleted!" ); @@ -898,16 +900,11 @@ static PyObject *Scene_getCurrentCamera( BPy_Scene * self ) cam_obj = scene->camera; if( cam_obj ) { /* if found, return a wrapper for it */ - PyObject *camera = NULL; - PyObject *name = Py_BuildValue( "(s)", cam_obj->id.name + 2 ); - - if( !name ) - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Py_BuildValue() failed" ); - - camera = M_Object_Get( Py_None, name ); - Py_DECREF ( name ); - return camera; + pyob = Object_CreatePyObject( cam_obj ); + if (!pyob) + return EXPP_ReturnPyObjError(PyExc_MemoryError, + "couldn't create new object wrapper!"); + return pyob; } Py_INCREF( Py_None ); /* none found */ diff --git a/source/blender/python/api2_2x/doc/Ipo.py b/source/blender/python/api2_2x/doc/Ipo.py index b4a99c0216b..8621bd18ca0 100644 --- a/source/blender/python/api2_2x/doc/Ipo.py +++ b/source/blender/python/api2_2x/doc/Ipo.py @@ -410,6 +410,17 @@ class BezTriple: @type hide: int """ + def __init__(coords): + """ + Create a new BezTriple object. + + @type coords: sequence of three or nine floats + @param coords: the coordinate values for the new control point. If three + floats are given, then the handle values are automatically generated. + @rtype: BezTriple + @return: a new BezTriple object + """ + def getPoints(): """ Returns the xy coordinates of the Bezier knot point. diff --git a/source/blender/python/api2_2x/doc/Lamp.py b/source/blender/python/api2_2x/doc/Lamp.py index e6ac1c05f4a..52ec301f994 100644 --- a/source/blender/python/api2_2x/doc/Lamp.py +++ b/source/blender/python/api2_2x/doc/Lamp.py @@ -14,7 +14,7 @@ Example:: from Blender import Lamp l = Lamp.New('Spot') # create new 'Spot' lamp data - l.setMode('square', 'shadow') # set these two lamp mode flags + l.setMode('Square', 'Shadow') # set these two lamp mode flags ob = Object.New('Lamp') # create new lamp object ob.link(l) # link lamp obj with lamp data @@ -36,6 +36,8 @@ Example:: - 'OnlyShadow' - 'Sphere' - 'Square' + - 'NoDiffuse' + - 'RayShadow' """ def New (type = 'Lamp', name = 'LampData'): diff --git a/source/blender/python/api2_2x/doc/Mesh.py b/source/blender/python/api2_2x/doc/Mesh.py index 9e1b3e6610f..f60d84ff02a 100644 --- a/source/blender/python/api2_2x/doc/Mesh.py +++ b/source/blender/python/api2_2x/doc/Mesh.py @@ -530,9 +530,9 @@ class MFaceSeq: me = Mesh.Get("Plane") # get the mesh data called "Plane" v = me.verts # get vertices if len(v) >= 6: # if there are enough vertices... - me.face.extend(v[1],v[2],v[3]) # add a single edge + me.faces.extend(v[1],v[2],v[3]) # add a single edge l=[(v[0],v[1]),(v[0],v[2],v[4],v[5])] - me.face.extend(l) # add another face + me.faces.extend(l) # add another face @type vertseq: tuple(s) of MVerts @param vertseq: either two to four MVerts, or sequence (list or tuple) @@ -583,6 +583,8 @@ class Mesh: B{Note}: L{Object.colbits<Object.Object.colbits>} needs to be set correctly for each object in order for these materials to be used instead of the object's materials. + B{Note}: Making the material list shorter does not change the faces material indicies, + take care when using the faces material indices to reference a material in the materials list. @type materials: list of Materials @ivar degr: The max angle for auto smoothing in [1,80]. @type degr: int @@ -630,6 +632,8 @@ class Mesh: @note: The mesh coordinates are in I{local space}, not the world space of its object. For world space vertex coordinates, each vertex location must be multiplied by the object's 4x4 transform matrix (see L{transform}). + @note: The objects materials will not be copied into the existing mesh, + however the face material indices will match the material list of the original data. @type name: string @param name: name of the Blender object which contains the geometry data. @type cage: int diff --git a/source/blender/python/api2_2x/doc/Object.py b/source/blender/python/api2_2x/doc/Object.py index 4fd3edc42cd..dac594d9259 100644 --- a/source/blender/python/api2_2x/doc/Object.py +++ b/source/blender/python/api2_2x/doc/Object.py @@ -37,11 +37,12 @@ def New (type, name='type'): """ Creates a new Object. @type type: string - @param type: The Object type: 'Armature', 'Camera', 'Curve', 'Lamp', 'Mesh' - or 'Empty'. + @param type: The Object type: 'Armature', 'Camera', 'Curve', 'Lamp', 'Lattice', + 'Mball', 'Mesh', 'Surf' or 'Empty'. @type name: string @param name: The name of the object. By default, the name will be the same as the object type. + If the name is alredy in use, this new object will have a number at the end of the name. @return: The created Object. I{B{Example:}} @@ -50,11 +51,11 @@ def New (type, name='type'): location (0, 0, 0) in the current scene:: import Blender - object = Blender.Object.New ('Lamp') - lamp = Blender.Lamp.New ('Spot') - object.link (lamp) - scene = Blender.Scene.getCurrent () - scene.link (object) + object = Blender.Object.New('Lamp') + lamp = Blender.Lamp.New('Spot') + object.link(lamp) + scene = Blender.Scene.GetCurrent() + scene.link(object) Blender.Redraw() """ @@ -70,8 +71,7 @@ def Get (name = None): I{B{Example 1:}} - The example below works on the default scene. The script returns the plane - object and prints the location of the plane:: + The example below works on the default scene. The script returns the plane object and prints the location of the plane:: import Blender object = Blender.Object.Get ('plane') @@ -85,12 +85,15 @@ def Get (name = None): objects = Blender.Object.Get () print objects + @note: Get will return objects from all scenes. + Most user tools should only operate on objects from the current scene - Blender.Scene.GetCurrent().getChildren() """ def GetSelected (): """ - Get the selected objects from Blender. If no objects are selected, an empty + Get the selected objects on visible layers from Blenders current scene. If no objects are selected, an empty list will be returned. + The active object of the current scene will always be the first object in the list (if selected). @return: A list of all selected Objects in the current scene. I{B{Example:}} @@ -99,10 +102,74 @@ def GetSelected (): the script will print the selected objects:: import Blender - objects = Blender.Object.GetSelected () + objects = Blender.Object.GetSelected() print objects """ + +def Duplicate (mesh=0, surface=0, curve=0, text=0, metaball=0, armature=0, lamp=0, material=0, texture=0, ipo=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. + By default no data linked to the object is duplicated, use the kayword arguments to change this. + Object.GetSelected() will return the list of objects resulting from duplication. + + @type mesh: bool + @param mesh: When non zero, mesh object data will be duplicated with the objects. + @type surface: bool + @param surface: When non zero, surface object data will be duplicated with the objects. + @type curve: bool + @param curve: When non zero, curve object data will be duplicated with the objects. + @type text: bool + @param text: When non zero, text object data will be duplicated with the objects. + @type metaball: bool + @param metaball: When non zero, metaball object data will be duplicated with the objects. + @type armature: bool + @param armature: When non zero, armature object data will be duplicated with the objects. + @type lamp: bool + @param lamp: When non zero, lamp object data will be duplicated with the objects. + @type material: bool + @param material: When non zero, materials used my the object or its object data will be duplicated with the objects. + @type texture: bool + @param texture: When non zero, texture data used by the objects 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. + @return: None + + I{B{Example:}} + + The example below creates duplicates the active object 10 times + and moves each object 1.0 on the X axis:: + import Blender + + scn = Scene.GetCurrent() + activeObject = scn.getActiveObject() + + # Unselect all + for ob in Blender.Object.GetSelected(): + ob.sel = 0 + activeObject.sel = 1 + + for x in xrange(10): + Blender.Object.Duplicate() # Duplicate linked + activeObject = scn.getActiveObject() + activeObject.LocX += 1 + Blender.Redraw() + """ +''' +def Join (): + """ + Joins selected objects on visible layers from Blenders current scene. + The active object is used as a base for all other objects of the same type to join into - just like pressing Ctrl+J + + @return: None + @note: Being in edit mode, mesh objects with keys and a large number of verts in the + resulting mesh will all raise a RuntimeError. + @note: The join may be unsucsessfull because of the selection or object types and no error raised. + Checking if the number of selected objects has changed is a way to know the join worked. + """ +''' + class Object: """ The Object object @@ -187,22 +254,22 @@ class Object: of: 2 - axis, 4 - texspace, 8 - drawname, 16 - drawimage, 32 - drawwire. @ivar name: The name of the object. - @ivar sel: The selection state of the object in the current scene, 1 is selected, 0 is unselected. + @ivar sel: The selection state of the object in the current scene, 1 is selected, 0 is unselected. (Selecting makes the object active) @ivar effects: The list of particle effects associated with the object. (Read-only) @ivar parentbonename: The string name of the parent bone. @ivar users: The number of users of the object. Read-only. @type users: int @ivar protectFlags: The "transform locking" bitfield flags for the object. Setting bits lock the following attributes: - - bit 0: X location - - bit 1: Y location - - bit 2: Z location - - bit 3: X rotation - - bit 4: Y rotation - - bit 5: Z rotation - - bit 6: X size - - bit 7: Y size - - bit 8: Z size + - bit 0: X location + - bit 1: Y location + - bit 2: Z location + - bit 3: X rotation + - bit 4: Y rotation + - bit 5: Z rotation + - bit 6: X size + - bit 7: Y size + - bit 8: Z size @type protectFlags: int """ @@ -399,7 +466,7 @@ class Object: For objects parented to bones, this is the name of the bone. @rtype: String @return: The parent object sub-name of the object. - If not available, None will be returned. + If not available, None will be returned. """ def getTimeOffset(): @@ -418,7 +485,8 @@ class Object: def getType(): """ - Returns the type of the object. + Returns the type of the object in 'Armature', 'Camera', 'Curve', 'Lamp', 'Lattice', + 'Mball', 'Mesh', 'Surf', 'Empty', 'Wave' (deprecated) or 'unknown' in exceptional cases. @return: The type of object. I{B{Example:}} @@ -491,7 +559,21 @@ class Object: parents of other objects. Calling this makeParent method for an unlinked object will result in an error. """ - + + def join(objects): + """ + Uses the object as a base for all of the objects in the provided list to join into. + + @type objects: Sequence of Blender Object + @param objects: A list of objects matching the objects type. + @note: Objects in the list will not be removed, to avoid duplicate data you may want to remove them manualy after joining. + @note: Join modifies the object in place so that other objects are joined into it. no new object or data is created. + @note: Join will only work for object types Mesh, Armature, Curve and Surface, an error will be raised if the object is not of this type. + @note: objects in the list will be ignored if they to not match the base object. + @rtype: int + @return: 0 is returned if the join is not successfull, otherwise 1 will be returned. + """ + def makeParentDeform(objects, noninverse = 0, fast = 0): """ Makes the object the deformation parent of the objects provided in the argument @@ -514,7 +596,7 @@ class Object: @warn: child objects must be of mesh type to deform correctly. Other object types will fall back to normal parenting silently. """ - + def makeParentVertex(objects, indices, noninverse = 0, fast = 0): """ Makes the object the vertex parent of the objects provided in the argument @@ -620,7 +702,7 @@ class Object: def setSize(x, y, z): """ - Sets the object's size, relative to the parent object (if any) + Sets the object's size, relative to the parent object (if any), clamped @type x: float @param x: The X size multiplier. @type y: float @@ -647,6 +729,7 @@ class Object: def select(boolean): """ Sets the object's selection state in the current scene. + setting the selection will make this object the active object of this scene. @type boolean: Integer @param boolean: - 0 - unselected diff --git a/source/blender/python/api2_2x/gen_utils.c b/source/blender/python/api2_2x/gen_utils.c index 4e42c06d2a8..4460a93d38f 100644 --- a/source/blender/python/api2_2x/gen_utils.c +++ b/source/blender/python/api2_2x/gen_utils.c @@ -176,27 +176,29 @@ int EXPP_ReturnIntError( PyObject * type, char *error_msg ) int EXPP_intError(PyObject *type, const char *format, ...) { - char *error = ""; + PyObject *error; va_list vlist; va_start(vlist, format); - vsprintf(error, format, vlist); + error = PyString_FromFormatV(format, vlist); va_end(vlist); - PyErr_SetString(type, error); + PyErr_SetObject(type, error); + Py_DECREF(error); return -1; } //Like EXPP_ReturnPyObjError but takes a printf format string and multiple arguments PyObject *EXPP_objError(PyObject *type, const char *format, ...) { - char *error = ""; + PyObject *error; va_list vlist; va_start(vlist, format); - vsprintf(error, format, vlist); + error = PyString_FromFormatV(format, vlist); va_end(vlist); - PyErr_SetString(type, error); + PyErr_SetObject(type, error); + Py_DECREF(error); return NULL; } diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index aba3a34929c..c728c51038d 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -658,8 +658,8 @@ int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexRe // Now thread safe if(load_ibuf_lock) SDL_mutexP(load_ibuf_lock); if(env->ima->ibuf==NULL) ima_ibuf_is_nul(tex, tex->ima); - if(load_ibuf_lock) SDL_mutexV(load_ibuf_lock); if(env->ima->ok && env->ok==0) envmap_split_ima(env); + if(load_ibuf_lock) SDL_mutexV(load_ibuf_lock); } } diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index f412df84bca..7e0a26e2116 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -838,19 +838,15 @@ int imagewraposa(Tex *tex, Image *ima, float *texvec, float *dxt, float *dyt, Te boxsample(previbuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr); val3= dy*val3+ dx*(texr.tr + texr.tg + texr.tb); - if(dx>=1.0f) { - texres->nor[0]= (val1-val2); - texres->nor[1]= (val1-val3); - } - else { + texres->nor[0]= (val1-val2); /* vals have been interpolated above! */ + texres->nor[1]= (val1-val3); + + if(dx<1.0f) { dy= 1.0f-dx; texres->tb= dy*texres->tb+ dx*texr.tb; texres->tg= dy*texres->tg+ dx*texr.tg; texres->tr= dy*texres->tr+ dx*texr.tr; texres->ta= dy*texres->ta+ dx*texr.ta; - - texres->nor[0]= dy*texres->nor[0] + dx*(val1-val2); - texres->nor[1]= dy*texres->nor[1] + dx*(val1-val3); } } } diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index 518ab581efc..b3d053b3f34 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -1014,8 +1014,10 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, float *dxt, float fy= (t[1] + 1.0) / 2.0; dxt[0]/= 2.0; dxt[1]/= 2.0; + dxt[2]/= 2.0; dyt[0]/= 2.0; dyt[1]/= 2.0; + dyt[2]/= 2.0; } else if ELEM(wrap, MTEX_TUBE, MTEX_SPHERE) { /* exception: the seam behind (y<0.0) */ @@ -1056,19 +1058,25 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, float *dxt, float else proj = cubemap(mtex, vlr, t[0], t[1], t[2], &fx, &fy); if(proj==1) { - dxt[1]= dxt[2]; - dyt[1]= dyt[2]; + SWAP(float, dxt[1], dxt[2]); + SWAP(float, dyt[1], dyt[2]); } else if(proj==2) { + float f1= dxt[0], f2= dyt[0]; dxt[0]= dxt[1]; dyt[0]= dyt[1]; dxt[1]= dxt[2]; dyt[1]= dyt[2]; + dxt[2]= f1; + dyt[2]= f2; } dxt[0]/= 2.0; dxt[1]/= 2.0; + dxt[2]/= 2.0; + dyt[0]/= 2.0; dyt[1]/= 2.0; + dyt[2]/= 2.0; } /* if area, then reacalculate dxt[] and dyt[] */ @@ -1083,7 +1091,9 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, float *dxt, float /* repeat */ if(tex->extend==TEX_REPEAT) { + float max= 1.0f; if(tex->xrepeat>1) { + max= tex->xrepeat; fx *= tex->xrepeat; dxt[0]*= tex->xrepeat; dyt[0]*= tex->xrepeat; @@ -1091,12 +1101,19 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, float *dxt, float else if(fx<0.0) fx+= 1-(int)(fx); } if(tex->yrepeat>1) { + if(max<tex->yrepeat) + max= tex->yrepeat; fy *= tex->yrepeat; dxt[1]*= tex->yrepeat; dyt[1]*= tex->yrepeat; if(fy>1.0) fy -= (int)(fy); else if(fy<0.0) fy+= 1-(int)(fy); } + if(max!=1.0f) { + dxt[1]*= max; + dyt[2]*= max; + } + } /* crop */ if(tex->cropxmin!=0.0 || tex->cropxmax!=1.0) { @@ -1502,10 +1519,25 @@ void do_material_tex(ShadeInput *shi) else texvec[2]= 0.0; if(shi->osatex) { - VECCOPY(dxt, dx); - VECCOPY(dyt, dy); + + if(mtex->projx) { + dxt[0]= dx[mtex->projx-1]; + dyt[0]= dy[mtex->projx-1]; + } + else dxt[0]= dyt[0]= 0.0f; + + if(mtex->projy) { + dxt[1]= dx[mtex->projy-1]; + dyt[1]= dy[mtex->projy-1]; + } + else dxt[1]= dyt[1]= 0.0f; + if(mtex->projz) { + dxt[2]= dx[mtex->projz-1]; + dyt[2]= dy[mtex->projz-1]; + } + else dxt[2]= dyt[2]= 0.0; } - + do_2d_mapping(mtex, texvec, shi->vlr, dxt, dyt); /* translate and scale */ @@ -1531,8 +1563,21 @@ void do_material_tex(ShadeInput *shi) else texvec[2]= mtex->size[2]*(mtex->ofs[2]); if(shi->osatex) { - VECCOPY(dxt, dx); - VECCOPY(dyt, dy); + if(mtex->projx) { + dxt[0]= mtex->size[0]*dx[mtex->projx-1]; + dyt[0]= mtex->size[0]*dy[mtex->projx-1]; + } + else dxt[0]= 0.0; + if(mtex->projy) { + dxt[1]= mtex->size[1]*dx[mtex->projy-1]; + dyt[1]= mtex->size[1]*dy[mtex->projy-1]; + } + else dxt[1]= 0.0; + if(mtex->projz) { + dxt[2]= mtex->size[2]*dx[mtex->projz-1]; + dyt[2]= mtex->size[2]*dy[mtex->projz-1]; + } + else dxt[2]= 0.0; } } @@ -1685,9 +1730,18 @@ void do_material_tex(ShadeInput *shi) shi->tang[2]+= Tnor*tex->norfac*texres.nor[2]; } else { - shi->vn[0]+= Tnor*tex->norfac*texres.nor[0]; - shi->vn[1]+= Tnor*tex->norfac*texres.nor[1]; - shi->vn[2]+= Tnor*tex->norfac*texres.nor[2]; + float nor[3], dot; + + /* prevent bump to become negative normal */ + nor[0]= Tnor*tex->norfac*texres.nor[0]; + nor[1]= Tnor*tex->norfac*texres.nor[1]; + nor[2]= Tnor*tex->norfac*texres.nor[2]; + + dot= 0.5f + 0.5f*INPR(nor, shi->vn); + + shi->vn[0]+= dot*nor[0]; + shi->vn[1]+= dot*nor[1]; + shi->vn[2]+= dot*nor[2]; } } Normalise(shi->vn); diff --git a/source/blender/src/booleanops.c b/source/blender/src/booleanops.c index 1b1d5705ab9..17850d08aaa 100644 --- a/source/blender/src/booleanops.c +++ b/source/blender/src/booleanops.c @@ -498,37 +498,48 @@ DispListMesh *NewBooleanMeshDLM(Object *ob, Object *ob_select, int int_op_type) InterpFaceVertexData ); } - - if (success) { - // descriptions of the output; - CSG_VertexIteratorDescriptor vd_o; - CSG_FaceIteratorDescriptor fd_o; - - dlm = MEM_callocN(sizeof(*dlm),"dlm"); - CSG_OutputFaceDescriptor(bool_op,&fd_o); - CSG_OutputVertexDescriptor(bool_op,&vd_o); + switch( success ) { + case 1: + { + // descriptions of the output; + CSG_VertexIteratorDescriptor vd_o; + CSG_FaceIteratorDescriptor fd_o; + + dlm = MEM_callocN(sizeof(*dlm),"dlm"); - // iterate through results of operation and insert into new object + CSG_OutputFaceDescriptor(bool_op,&fd_o); + CSG_OutputVertexDescriptor(bool_op,&vd_o); - ConvertCSGDescriptorsToDLM( - dlm, - NULL, - &output_mpd, - &fd_o, - &vd_o, - inv_mat - ); + // iterate through results of operation and insert into new object - // free up the memory + ConvertCSGDescriptorsToDLM( + dlm, + NULL, + &output_mpd, + &fd_o, + &vd_o, + inv_mat + ); - CSG_FreeVertexDescriptor(&vd_o); - CSG_FreeFaceDescriptor(&fd_o); + // free up the memory + + CSG_FreeVertexDescriptor(&vd_o); + CSG_FreeFaceDescriptor(&fd_o); + } + break; + case -1: + error("Selected meshes must have faces to perform boolean operations"); + break; + case -2: + error("Both meshes must be closed"); + break; + default: + error("unknown internal error"); + break; } CSG_FreeBooleanOperation(bool_op); - bool_op = NULL; - } // We may need to map back the tfaces to mcols here. diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 77a9b8580ed..5137af7a12b 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -3243,8 +3243,8 @@ static void editing_panel_mesh_tools(Object *ob, Mesh *me) uiBlockBeginAlign(block); //uiDefButBitS(block, TOG, B_AUTOFGON, 0, "FGon", 10,195,30,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "Causes 'Subdivide' To create FGon on inner edges where possible"); - uiDefButBitS(block, TOG, B_BEAUTY, 0, "Beauty", 10,195,40,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "Causes 'Subdivide' to split faces in halves instead of quarters using Long Edges Unless short is selected"); - uiDefButBitS(block, TOG, B_BEAUTY_SHORT, 0, "Short", 50,195,40,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "Causes 'Subdivide' to split faces in halves instead of quarters using Short Edges"); + uiDefButBitS(block, TOG, B_BEAUTY, 0, "Beauty", 10,195,40,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "Causes 'Subdivide' to split faces in halves instead of quarters using long edges unless 'Short' is selected"); + uiDefButBitS(block, TOG, B_BEAUTY_SHORT, 0, "Short", 50,195,40,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "If Beauty is set, 'Subdivide' splits faces in halves using short edges"); uiDefBut(block, BUT,B_SUBDIV,"Subdivide", 90,195,80,19, 0, 0, 0, 0, 0, "Splits selected faces into halves or quarters"); diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index f76b5021922..cc247cae715 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -2795,8 +2795,6 @@ static void material_panel_texture(Material *ma) uiBlockSetCol(block, TH_AUTO); uiDefBut(block, BUT, B_TEXCLEAR, "Clear", 122, 130, 72, 20, 0, 0, 0, 0, 0, "Erases link to texture"); - uiDefButBitS(block, TOG, MTEX_VIEWSPACE, B_DIFF, "Correct Nor Map", 100,18,163,19, &(mtex->texflag), 0, 0, 0, 0, "This channel will correct normal mapping for View space and Object space"); - } else uiDefButS(block, TOG, B_EXTEXBROWSE, "Add New" ,100, 150, 163, 20, &(G.buts->texnr), -1.0, 32767.0, 0, 0, "Adds a new texture datablock"); diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c index f2f8fa6f062..407d5779354 100644 --- a/source/blender/src/drawipo.c +++ b/source/blender/src/drawipo.c @@ -2292,6 +2292,8 @@ int view2dmove(unsigned short event) else left= 0.0; leftret= 0; } + if((event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE)) + facy= -facy; } else if(IN_2D_HORIZ_SCROLL((int)mvalo)) { facx= -(G.v2d->tot.xmax-G.v2d->tot.xmin)/(float)(G.v2d->mask.xmax-G.v2d->mask.xmin); diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 5b3b27b2c3e..26c8c30d611 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -553,9 +553,9 @@ static void drawlamp(Object *ob) /* Inner Circle */ VECCOPY(vec, ob->obmat[3]); glEnable(GL_BLEND); - drawcircball(GL_LINE_LOOP, vec, lampsize/2, imat); + drawcircball(GL_LINE_LOOP, vec, lampsize, imat); glDisable(GL_BLEND); - drawcircball(GL_POLYGON, vec, lampsize/2, imat); + drawcircball(GL_POLYGON, vec, lampsize, imat); /* restore */ if(ob->id.us>1) diff --git a/source/blender/src/drawoops.c b/source/blender/src/drawoops.c index 0fc22ceea91..dbf245179df 100644 --- a/source/blender/src/drawoops.c +++ b/source/blender/src/drawoops.c @@ -87,7 +87,7 @@ void boundbox_oops(short sel) oops= G.soops->oops.first; while(oops) { - if (oops->hide==0 && !sel || (sel && oops->flag & SELECT )) { + if ((oops->hide==0 && !sel) || (sel && oops->flag & SELECT )) { ok= 1; min[0]= MIN2(min[0], oops->x); @@ -132,7 +132,9 @@ void draw_oopslink(Oops *oops) if(oops->type==ID_SCE) { if(oops->flag & SELECT) { - if(oops->id->lib) cpack(0x4080A0); + /* when using python Mesh to make meshes a file was saved + that had an oops with no ID, stops a segfault when looking for lib */ + if(oops->id && oops->id->lib) cpack(0x4080A0); else cpack(0x808080); } else cpack(0x606060); @@ -346,7 +348,10 @@ void draw_oops(Oops *oops) glRectf(x1, y1, x2, y2); } - if(oops->id->lib) { + + /* it has never happened that an oops was missing an ID at + this point but has occured elseware so lets be safe */ + if(oops->id && oops->id->lib) { if(oops->id->flag & LIB_INDIRECT) cpack(0x1144FF); else cpack(0x11AAFF); @@ -369,8 +374,8 @@ void draw_oops(Oops *oops) } else { /* NO ICON, UNINDENT*/ v1[0] -= 1.3 / oopscalex; } - if(oops->flag & SELECT) cpack(0xFFFFFF); - else cpack(0x0); + if(oops->flag & SELECT) BIF_ThemeColor(TH_TEXT_HI); + else BIF_ThemeColor(TH_TEXT); glRasterPos3f(v1[0], v1[1], 0.0); BMF_DrawString(font, str); @@ -423,6 +428,12 @@ void drawoopsspace(ScrArea *sa, void *spacedata) float col[3]; BIF_GetThemeColor3fv(TH_BACK, col); + + /* darker background for oops */ + if(soops->type!=SO_OUTLINER) { + col[0] = col[0] * 0.75; col[1] = col[1] * 0.75; col[2] = col[2] * 0.75; + } + glClearColor(col[0], col[1], col[2], 0.0); glClear(GL_COLOR_BUFFER_BIT); if(soops==0) return; @@ -438,7 +449,20 @@ void drawoopsspace(ScrArea *sa, void *spacedata) oopscalex= .14*((float)curarea->winx)/(G.v2d->cur.xmax-G.v2d->cur.xmin); calc_ipogrid(); /* for scrollvariables */ - + + + /* Draw a page about the oops */ + BIF_GetThemeColor3fv(TH_BACK, col); + glColor3fv(col); + glRectf(G.v2d->tot.xmin-2, G.v2d->tot.ymin-2, G.v2d->tot.xmax+2, G.v2d->tot.ymax+2); /* light square in the centre */ + BIF_ThemeColorShade(TH_BACK, -96); /* drop shadow color */ + glRectf(G.v2d->tot.xmin-1, G.v2d->tot.ymin-2, G.v2d->tot.xmax+3, G.v2d->tot.ymin-3); /* bottom dropshadow */ + glRectf(G.v2d->tot.xmax+2, G.v2d->tot.ymin-2, G.v2d->tot.xmax+3, G.v2d->tot.ymax+1); /* right hand dropshadow */ + /* box around the oops. */ + cpack(0x0); + mysbox(G.v2d->tot.xmin-2, G.v2d->tot.ymin-2, G.v2d->tot.xmax+2, G.v2d->tot.ymax+2); + + /* Set the font size for the oops based on the zoom level */ if (oopscalex > 6.0) font = BMF_GetFont(BMF_kScreen15); else if (oopscalex > 3.5) font = G.font; diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c index 3d0bee6f080..355aee6e6c9 100644 --- a/source/blender/src/edit.c +++ b/source/blender/src/edit.c @@ -62,7 +62,7 @@ #include "DNA_scene_types.h" #include "DNA_space_types.h" #include "DNA_view3d_types.h" - +#include "DNA_userdef_types.h" /* for U.dupflag */ #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BLI_editVert.h" @@ -1592,7 +1592,7 @@ void duplicate_context_selected(void) else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) adduplicate_nurb(); } else { - adduplicate(0); + adduplicate(0, U.dupflag); } } diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index fc54e50a251..0c315e65005 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -351,7 +351,7 @@ void apply_rot_armature (Object *ob, float mat[3][3]) } } -void join_armature(void) +int join_armature(void) { Object *ob; Base *base, *nextbase; @@ -360,13 +360,10 @@ void join_armature(void) float mat[4][4], imat[4][4]; /* Ensure we're not in editmode and that the active object is an armature*/ - if(G.obedit) return; + /* if(G.obedit) return; */ /* Alredy checked in join_menu() */ ob= OBACT; - if(ob->type!=OB_ARMATURE) return; - - /* Make sure the user wants to continue*/ - if(okee("Join selected armatures")==0) return; + if(ob->type!=OB_ARMATURE) return 0; /* Put the active armature into editmode and join the bones from the other one*/ @@ -436,7 +433,7 @@ void join_armature(void) exit_editmode(1); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWOOPS, 0); - + return 1; } /* **************** END tools on Editmode Armature **************** */ diff --git a/source/blender/src/editcurve.c b/source/blender/src/editcurve.c index d87450e7a72..b660836f9d2 100644 --- a/source/blender/src/editcurve.c +++ b/source/blender/src/editcurve.c @@ -375,9 +375,7 @@ void separate_nurb() oldob= G.obedit; oldbase= BASACT; - G.qual |= LR_ALTKEY; /* patch to make sure we get a linked dupli */ - adduplicate(1); - G.qual &= ~LR_ALTKEY; + adduplicate(1, 0); /* no transform and zero so do get a linked dupli */ G.obedit= BASACT->object; /* basact is set in adduplicate() */ @@ -3277,7 +3275,7 @@ void nurb_set_smooth(short event) else if(event==0) BIF_undo_push("Set Solid"); } -void join_curve(int type) +int join_curve(int type) { Base *base, *nextb; Object *ob; @@ -3289,18 +3287,11 @@ void join_curve(int type) float imat[4][4], cmat[4][4]; int a; - if(G.obedit) return; - ob= OBACT; - if(ob->type!=type) return; - if(ob->lay & G.vd->lay); else return; + if(ob->type!=type) return 0; + if(ob->lay & G.vd->lay); else return 0; tempbase.first= tempbase.last= 0; - if(type==OB_SURF) { - if(okee("Join selected NURBS")==0) return; - } - else if(okee("Join selected curves")==0) return; - /* trasnform all selected curves inverse in obact */ Mat4Invert(imat, ob->obmat); @@ -3360,7 +3351,7 @@ void join_curve(int type) allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); BIF_undo_push("Join"); - + return 1; } diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index 79faf918c52..e54bb0c156d 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -1327,9 +1327,7 @@ void separate_mesh(void) oldob= G.obedit; oldbase= BASACT; - G.qual |= LR_ALTKEY; /* patch to make sure we get a linked duplicate */ - adduplicate(1); - G.qual &= ~LR_ALTKEY; + adduplicate(1, 0); /* notrans and a linked duplicate*/ G.obedit= BASACT->object; /* basact was set in adduplicate() */ @@ -1494,9 +1492,7 @@ void separate_mesh_loose(void) oldob= G.obedit; oldbase= BASACT; - G.qual |= LR_ALTKEY; /* patch to make sure we get a linked duplicate */ - adduplicate(1); - G.qual &= ~LR_ALTKEY; + adduplicate(1, 0); /* notrans and 0 for linked duplicate */ G.obedit= BASACT->object; /* basact was set in adduplicate() */ diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index 44b1f8be055..8cefaf4221b 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -1462,7 +1462,8 @@ void reveal_mesh(void) EM_fgon_flags(); // redo flags and indices for fgons EM_selectmode_flush(); - + countall(); + allqueue(REDRAWVIEW3D, 0); DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); BIF_undo_push("Reveal"); diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c index ffb10a215ab..c244f1d249c 100644 --- a/source/blender/src/editmesh_tools.c +++ b/source/blender/src/editmesh_tools.c @@ -377,7 +377,7 @@ int removedoublesflag(short flag, float limit) /* return amount */ efa= em->faces.first; while(efa) { efa->f1= 0; - if(faceselectedAND(efa, 1)) { + if(faceselectedOR(efa, 1)) { efa->f1= 1; amount++; } diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 00855a5fef6..5c3655094cc 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -1892,7 +1892,7 @@ void split_font() int i; for (i = 0; i<=slen; p++, i++) { - adduplicate(1); + adduplicate(1, U.dupflag); cu= OBACT->data; cu->sepchar = i+1; text_to_curve(OBACT, 0); // pass 1: only one letter, adapt position @@ -4197,7 +4197,19 @@ static void adduplicate__forwardModifierLinks(void *userData, Object *ob, Object ID_NEW(*obpoin); } -void adduplicate(int noTrans) +/* This function duplicated the current visible selection, its used by Duplicate and Linked Duplicate +Alt+D/Shift+D as well as Pythons Object.Duplicate(), it takes +mode: + 0: Duplicate with transform, Redraw. + 1: Duplicate, no transform, Redraw + 2: Duplicate, no transform, no redraw (Only used by python) +if true the user will not be dropped into grab mode directly after and.. +dupflag: a flag made from constants declared in DNA_userdef_types.h + The flag tells adduplicate() weather to copy data linked to the object, or to reference the existing data. + U.dupflag for default operations or you can construct a flag as python does + if the dupflag is 0 then no data will be copied (linked duplicate) */ + +void adduplicate(int mode, int dupflag) { Base *base, *basen; Object *ob, *obn; @@ -4205,15 +4217,12 @@ void adduplicate(int noTrans) ID *id; Ipo *ipo; bConstraintChannel *chan; - int a, didit, dupflag; + int a, didit; if(G.scene->id.lib) return; clear_id_newpoins(); clear_sca_new_poins(); /* sensor/contr/act */ - if( G.qual & LR_ALTKEY ) dupflag= 0; - else dupflag= U.dupflag; - base= FIRSTBASE; while(base) { if TESTBASELIB(base) { @@ -4261,7 +4270,7 @@ void adduplicate(int noTrans) } } } - if(dupflag & USER_DUP_ACT){ + if(dupflag & USER_DUP_ACT){ /* Not buttons in the UI to modify this, add later? */ id= (ID *)obn->action; if (id){ ID_NEW_US(obn->action) @@ -4467,16 +4476,17 @@ void adduplicate(int noTrans) clear_id_newpoins(); countall(); - if(!noTrans) { + if(mode==0) { BIF_TransformSetUndo("Add Duplicate"); initTransform(TFM_TRANSLATION, CTX_NONE); Transform(); } set_active_base(BASACT); - - allqueue(REDRAWNLA, 0); - allqueue(REDRAWACTION, 0); /* also oops */ - allqueue(REDRAWIPO, 0); /* also oops */ + if(mode!=2) { /* mode of 2 is used by python to avoid unrequested redraws */ + allqueue(REDRAWNLA, 0); + allqueue(REDRAWACTION, 0); /* also oops */ + allqueue(REDRAWIPO, 0); /* also oops */ + } } void selectlinks_menu(void) diff --git a/source/blender/src/editoops.c b/source/blender/src/editoops.c index 6c8fa7d5f9d..2b4a3e869f8 100644 --- a/source/blender/src/editoops.c +++ b/source/blender/src/editoops.c @@ -56,6 +56,7 @@ #include "DNA_space_types.h" #include "DNA_scene_types.h" #include "DNA_image_types.h" +#include "DNA_ipo_types.h" #include "BKE_global.h" #include "BKE_scene.h" @@ -428,13 +429,25 @@ static void do_activate_oops(Oops *oops) case ID_IM: if(oops->id && G.sima) { /* only set if the new image isnt alredy active */ - if (G.sima->image != (Image *)oops->id) { + if ((ID *)G.sima->image != oops->id) { G.sima->image = (Image *)oops->id; allqueue(REDRAWIMAGE, 0); scrarea_queue_winredraw(curarea); } } break; + /* + case ID_IP: + if(oops->id && G.sipo) { + *//* only set if the new ipo isnt alredy active *//* + if ((ID *)G.sipo->ipo != oops->id) { + G.sipo->ipo = (Ipo *)oops->id; + allqueue(REDRAWIPO, 0); + scrarea_queue_winredraw(curarea); + } + } + break; + */ } } diff --git a/source/blender/src/header_ipo.c b/source/blender/src/header_ipo.c index c61c726c868..36334a7d295 100644 --- a/source/blender/src/header_ipo.c +++ b/source/blender/src/header_ipo.c @@ -597,7 +597,7 @@ static uiBlock *ipo_editmenu(void *arg_unused) uiDefIconTextBlockBut(block, ipo_editmenu_joinmenu, NULL, ICON_RIGHTARROW_THIN, "Join", 0, yco-=20, 120, 19, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Clamped Handles|ALT H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Clamped Handles|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); if (!G.sipo->showkey){ uiDefIconTextBlockBut(block, ipo_editmenu_extendmenu, NULL, ICON_RIGHTARROW_THIN, "Extend Mode", 0, yco-=20, 120, 19, ""); diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index c52704e4020..a95ee43a311 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -1992,9 +1992,7 @@ static void do_view3d_edit_objectmenu(void *arg, int event) duplicate_context_selected(); break; case 3: /* duplicate linked */ - G.qual |= LR_ALTKEY; - adduplicate(0); - G.qual &= ~LR_ALTKEY; + adduplicate(0, 0); break; case 5: /* make single user */ single_user(); @@ -2003,12 +2001,7 @@ static void do_view3d_edit_objectmenu(void *arg, int event) special_editmenu(); break; case 8: /* join objects */ - if( (ob= OBACT) ) { - if(ob->type == OB_MESH) join_mesh(); - else if(ob->type == OB_CURVE) join_curve(OB_CURVE); - else if(ob->type == OB_SURF) join_curve(OB_SURF); - else if(ob->type == OB_ARMATURE) join_armature(); - } + join_menu(); break; case 9: /* convert object type */ convertmenu(); @@ -2176,7 +2169,7 @@ static uiBlock *view3d_edit_mesh_verticesmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Smooth|W, 0", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Remove Doubles|W, 5", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Remove Doubles|W, 6", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -2260,15 +2253,15 @@ static uiBlock *view3d_edit_mesh_edgesmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Bevel|W, Alt 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Bevel|W, Alt 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Loop Subdivide...|Ctrl R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Knife Subdivide...|Shift K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide|W, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide Fractal|W, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide Smooth|W, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide Fractal|W, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide Smooth|W, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -2347,8 +2340,8 @@ static uiBlock *view3d_edit_mesh_facesmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Smooth|W, Alt 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Solid|W, Alt 5", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Smooth|W, Alt 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Set Solid|W, Alt 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, ""); uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 60); @@ -2384,7 +2377,7 @@ static uiBlock *view3d_edit_mesh_normalsmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Flip|W, 9", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Flip|W, 0", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 60); diff --git a/source/blender/src/meshtools.c b/source/blender/src/meshtools.c index 2b96bbc20b6..3a7df18c584 100644 --- a/source/blender/src/meshtools.c +++ b/source/blender/src/meshtools.c @@ -34,7 +34,7 @@ meshtools.c: no editmode, tools operating on meshes -void join_mesh(void); +int join_mesh(void); void fasterdraw(void); void slowerdraw(void); @@ -115,7 +115,9 @@ static int testSelected_TfaceMesh(void) return 0; } -void join_mesh(void) +/* join selected meshes into the active mesh, context sensitive +return 0 if no join is made (error) and 1 of the join is done */ +int join_mesh(void) { Base *base, *nextb; Object *ob; @@ -132,10 +134,10 @@ void join_mesh(void) bDeformGroup *dg, *odg; MDeformVert *dvert, *dvertmain; - if(G.obedit) return; + if(G.obedit) return 0; ob= OBACT; - if(!ob || ob->type!=OB_MESH) return; + if(!ob || ob->type!=OB_MESH) return 0; /* count */ base= FIRSTBASE; @@ -159,14 +161,13 @@ void join_mesh(void) if(haskey) { error("Can't join meshes with vertex keys"); - return; + return 0; } /* that way the active object is always selected */ - if(ok==0) return; + if(ok==0) return 0; - if(totvert==0 || totvert>MESH_MAX_VERTS) return; + if(totvert==0 || totvert>MESH_MAX_VERTS) return 0; - if(okee("Join selected meshes")==0) return; /* if needed add edges to other meshes */ @@ -439,6 +440,7 @@ void join_mesh(void) allqueue(REDRAWBUTSSHADING, 0); BIF_undo_push("Join Mesh"); + return 1; } diff --git a/source/blender/src/renderwin.c b/source/blender/src/renderwin.c index ae6ffee5df5..c629beee9c3 100644 --- a/source/blender/src/renderwin.c +++ b/source/blender/src/renderwin.c @@ -644,7 +644,7 @@ void calc_renderwin_rectangle(int posmask, int renderpos_r[2], int rendersize_r[ rendersize_r[1]= CLAMPIS(rendersize_r[1], 0, scr_h-44-RW_HEADERY); renderpos_r[1]= -44-RW_HEADERY+(scr_h-rendersize_r[1])*(ndc_y*0.5 + 0.5); #else - renderpos_r[1]= (scr_h-rendersize_r[1])*(ndc_y*0.5 + 0.5); + renderpos_r[1]= -RW_HEADERY+(scr_h-rendersize_r[1])*(ndc_y*0.5 + 0.5); #endif } diff --git a/source/blender/src/space.c b/source/blender/src/space.c index b2b091f572b..4fdc764bc76 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -624,6 +624,26 @@ static void select_grouped_menu(void) select_grouped(nr); } +void join_menu(void) +{ + Object *ob= OBACT; + if (ob && !G.obedit) { + if(ob->type == OB_MESH) { + if(okee("Join selected meshes")==0) return; + join_mesh(); + } else if(ob->type == OB_CURVE) { + if(okee("Join selected curves")==0) return; + join_curve(OB_CURVE); + } else if(ob->type == OB_SURF) { + if(okee("Join selected NURBS")==0) return; + join_curve(OB_SURF); + } else if(ob->type == OB_ARMATURE) { + /* Make sure the user wants to continue*/ + if(okee("Join selected armatures")==0) return; + join_armature (); + } + } +} static unsigned short convert_for_nonumpad(unsigned short event) { @@ -1198,7 +1218,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(ob && (ob->flag & OB_POSEMODE)) error ("Duplicate not possible in posemode."); else if((G.obedit==NULL)) - adduplicate(0); + adduplicate(0, 0); } else if(G.qual==LR_CTRLKEY) { imagestodisplist(); @@ -1378,14 +1398,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case JKEY: if(G.qual==LR_CTRLKEY) { if( ob ) { - if(ob->type == OB_MESH) - join_mesh(); - else if(ob->type == OB_CURVE) - join_curve(OB_CURVE); - else if(ob->type == OB_SURF) - join_curve(OB_SURF); - else if(ob->type == OB_ARMATURE) - join_armature (); + join_menu(); } else if ((G.obedit) && ELEM(G.obedit->type, OB_CURVE, OB_SURF)) addsegment_nurb(); diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index f6136d52684..fe0cf281a1a 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -961,11 +961,11 @@ static KX_GameObject *gameobject_from_blenderobject( // If this is a skin object, make Skin Controller if (ob->parent && ob->parent->type == OB_ARMATURE && ob->partype==PARSKEL && ((Mesh*)ob->data)->dvert){ - BL_SkinDeformer *dcont = new BL_SkinDeformer(ob, (BL_SkinMeshObject*)meshobj); + BL_SkinDeformer *dcont = new BL_SkinDeformer(ob, (BL_SkinMeshObject*)meshobj,ob->parent); ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; } else if (((Mesh*)ob->data)->dvert){ - BL_MeshDeformer *dcont = new BL_MeshDeformer(ob, (BL_SkinMeshObject*)meshobj); + BL_MeshDeformer *dcont = new BL_MeshDeformer(ob, (BL_SkinMeshObject*)meshobj,ob->parent); ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; } diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h index 04e0f3b0628..c9030ceca36 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.h +++ b/source/gameengine/Converter/BL_MeshDeformer.h @@ -48,12 +48,14 @@ public: void VerifyStorage(); void RecalcNormals(); virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map){}; - BL_MeshDeformer(struct Object* obj, class BL_SkinMeshObject *meshobj): + BL_MeshDeformer(struct Object* obj, class BL_SkinMeshObject *meshobj,struct Object* armatureObj): m_pMeshObject(meshobj), m_bmesh((struct Mesh*)(obj->data)), m_transnors(NULL), m_transverts(NULL), - m_tvtot(0) + m_tvtot(0), + m_blenderMeshObject(obj), + m_blenderArmatureObj(armatureObj) {}; virtual ~BL_MeshDeformer(); virtual void SetSimulatedTime(double time){}; @@ -67,6 +69,8 @@ protected: MT_Point3 *m_transnors; MT_Point3 *m_transverts; int m_tvtot; + Object* m_blenderMeshObject; + Object* m_blenderArmatureObj; }; diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index ee298d70baf..84a3b8dcc5c 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -145,6 +145,10 @@ void BL_SkinDeformer::ProcessReplica() { } +//void where_is_pose (Object *ob); +//void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts, int deformflag); +extern "C" void armature_deform_verts(struct Object *armOb, struct Object *target, float (*vertexCos)[3], int numVerts, int deformflag); + void BL_SkinDeformer::Update(void) { @@ -156,7 +160,8 @@ void BL_SkinDeformer::Update(void) /* XXX note: where_is_pose() (from BKE_armature.h) calculates all matrices needed to start deforming */ /* but it requires the blender object pointer... */ -// void where_is_pose (Object *ob); + //void where_is_pose (Object *ob); + where_is_pose (m_blenderArmatureObj); /* store verts locally */ for (int v =0; v<m_bmesh->totvert; v++){ @@ -165,6 +170,11 @@ void BL_SkinDeformer::Update(void) m_transverts[v]=MT_Point3(m_bmesh->mvert[v].co); } + float test[1000][3]; + + armature_deform_verts(m_blenderArmatureObj,m_blenderMeshObject,test,m_bmesh->totvert,ARM_DEF_VGROUP); + + /* XXX note: now use this call instead */ // void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts, int deformflag) // - armOb = armature object diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h index a61ebf59b22..49c69298336 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.h +++ b/source/gameengine/Converter/BL_SkinDeformer.h @@ -63,9 +63,10 @@ public: m_armobj=NULL; } void SetArmature (class BL_ArmatureObject *armobj); - BL_SkinDeformer( struct Object *bmeshobj, - class BL_SkinMeshObject *mesh) - :BL_MeshDeformer(bmeshobj, mesh), + + BL_SkinDeformer( struct Object *bmeshobj, + class BL_SkinMeshObject *mesh,struct Object* blenderArmatureObj) + :BL_MeshDeformer(bmeshobj, mesh,blenderArmatureObj), m_armobj(NULL), m_lastUpdate(-1), m_defbase(&bmeshobj->defbase) @@ -85,8 +86,8 @@ public: BL_SkinDeformer( struct Object *bmeshobj_old, struct Object *bmeshobj_new, - class BL_SkinMeshObject *mesh) - :BL_MeshDeformer(bmeshobj_old, mesh), + class BL_SkinMeshObject *mesh,struct Object *bArmatureObj) + :BL_MeshDeformer(bmeshobj_old, mesh,bArmatureObj), m_armobj(NULL), m_lastUpdate(-1), m_defbase(&bmeshobj_old->defbase) diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index b75da2c12a2..55cd76824c9 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -77,6 +77,12 @@ PyTypeObject PyObjectPlus::Type = { 0, /*tp_call */ }; +PyObjectPlus::~PyObjectPlus() +{ + _Py_ForgetReference(this); +// assert(ob_refcnt==0); +} + PyObjectPlus::PyObjectPlus(PyTypeObject *T) // constructor { MT_assert(T != NULL); diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index c261012a3bc..026a58cdbca 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -136,18 +136,18 @@ class PyObjectPlus : public PyObject public: PyObjectPlus(PyTypeObject *T); - virtual ~PyObjectPlus() {}; // destructor + virtual ~PyObjectPlus(); // destructor static void PyDestructor(PyObject *P) // python wrapper { delete ((PyObjectPlus *) P); }; - //void INCREF(void) { - // Py_INCREF(this); - // }; // incref method - //void DECREF(void) { - // Py_DECREF(this); - // }; // decref method +// void INCREF(void) { +// Py_INCREF(this); +// }; // incref method +// void DECREF(void) { +// Py_DECREF(this); +// }; // decref method virtual PyObject *_getattr(const STR_String& attr); // _getattr method static PyObject *__getattr(PyObject * PyObj, char *attr) // This should be the entry in Type. diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 1a09123c107..bb9ad81f245 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -558,6 +558,10 @@ void CValue::DisableRefCount() void CValue::AddDataToReplica(CValue *replica) { replica->m_refcount = 1; + + //register with Python + _Py_NewReference(replica); + #ifdef _DEBUG //gRefCountValue++; #endif diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index 5857c614e2d..7806b77257a 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -7,6 +7,14 @@ #include "Dynamics/RigidBody.h" +#include "SG_Spatial.h" + +#include "KX_GameObject.h" +#include "KX_MotionState.h" +#include "KX_ClientObjectInfo.h" + +#include "PHY_IPhysicsEnvironment.h" + KX_BulletPhysicsController::KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna) : KX_IPhysicsController(dyna,(PHY_IPhysicsController*)this), CcdPhysicsController(ci) @@ -38,6 +46,16 @@ void KX_BulletPhysicsController::applyImpulse(const MT_Point3& attach, const MT_ void KX_BulletPhysicsController::SetObject (SG_IObject* object) { + SG_Controller::SetObject(object); + + // cheating here... + //should not be necessary, is it for duplicates ? + + KX_GameObject* gameobj = (KX_GameObject*) object->GetSGClientObject(); + gameobj->SetPhysicsController(this,gameobj->IsDynamic()); + //GetSumoObject()->setClientObject(gameobj->getClientInfo()); + + } void KX_BulletPhysicsController::RelativeTranslate(const MT_Vector3& dloc,bool local) @@ -55,22 +73,25 @@ void KX_BulletPhysicsController::RelativeRotate(const MT_Matrix3x3& drot,bool lo void KX_BulletPhysicsController::ApplyTorque(const MT_Vector3& torque,bool local) { + CcdPhysicsController::ApplyTorque(torque.x(),torque.y(),torque.z(),local); } void KX_BulletPhysicsController::ApplyForce(const MT_Vector3& force,bool local) { + CcdPhysicsController::ApplyForce(force.x(),force.y(),force.z(),local); } MT_Vector3 KX_BulletPhysicsController::GetLinearVelocity() { - assert(0); - return MT_Vector3(0.f,0.f,0.f); - + float angVel[3]; + CcdPhysicsController::GetAngularVelocity(angVel[0],angVel[1],angVel[2]); + return MT_Vector3(angVel[0],angVel[1],angVel[2]); } MT_Vector3 KX_BulletPhysicsController::GetVelocity(const MT_Point3& pos) { - assert(0); - return MT_Vector3(0.f,0.f,0.f); - + float linVel[3]; + CcdPhysicsController::GetLinearVelocity(linVel[0],linVel[1],linVel[2]); + return MT_Vector3(linVel[0],linVel[1],linVel[2]); } + void KX_BulletPhysicsController::SetAngularVelocity(const MT_Vector3& ang_vel,bool local) { CcdPhysicsController::SetAngularVelocity(ang_vel.x(),ang_vel.y(),ang_vel.z(),local); @@ -82,16 +103,21 @@ void KX_BulletPhysicsController::SetLinearVelocity(const MT_Vector3& lin_vel,boo } void KX_BulletPhysicsController::getOrientation(MT_Quaternion& orn) { + float myorn[4]; + CcdPhysicsController::getOrientation(myorn[0],myorn[1],myorn[2],myorn[3]); + orn = MT_Quaternion(myorn[0],myorn[1],myorn[2],myorn[3]); } void KX_BulletPhysicsController::setOrientation(const MT_Quaternion& orn) { + CcdPhysicsController::setOrientation(orn.x(),orn.y(),orn.z(),orn.w()); } void KX_BulletPhysicsController::setPosition(const MT_Point3& pos) { - + CcdPhysicsController::setPosition(pos.x(),pos.y(),pos.z()); } void KX_BulletPhysicsController::setScaling(const MT_Vector3& scaling) { + CcdPhysicsController::setScaling(scaling.x(),scaling.y(),scaling.z()); } MT_Scalar KX_BulletPhysicsController::GetMass() { @@ -113,6 +139,7 @@ void KX_BulletPhysicsController::setRigidBody(bool rigid) void KX_BulletPhysicsController::SuspendDynamics() { + } void KX_BulletPhysicsController::RestoreDynamics() { @@ -120,8 +147,42 @@ void KX_BulletPhysicsController::RestoreDynamics() SG_Controller* KX_BulletPhysicsController::GetReplica(class SG_Node* destnode) { - assert(0); - return 0; + PHY_IMotionState* motionstate = new KX_MotionState(destnode); + + KX_BulletPhysicsController* physicsreplica = new KX_BulletPhysicsController(*this); + + //parentcontroller is here be able to avoid collisions between parent/child + + PHY_IPhysicsController* parentctrl = NULL; + + if (destnode != destnode->GetRootSGParent()) + { + KX_GameObject* clientgameobj = (KX_GameObject*) destnode->GetRootSGParent()->GetSGClientObject(); + if (clientgameobj) + { + parentctrl = (KX_BulletPhysicsController*)clientgameobj->GetPhysicsController(); + } else + { + // it could be a false node, try the children + NodeList::const_iterator childit; + for ( + childit = destnode->GetSGChildren().begin(); + childit!= destnode->GetSGChildren().end(); + ++childit + ) { + KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject()); + if (clientgameobj) + { + parentctrl = (KX_BulletPhysicsController*)clientgameobj->GetPhysicsController(); + } + } + } + } + + physicsreplica->PostProcessReplica(motionstate,parentctrl); + + return physicsreplica; + } diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index e9a6c2442b0..fb5037345a8 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -673,6 +673,7 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, #include "CollisionShapes/ConvexHullShape.h" #include "CollisionShapes/TriangleMesh.h" #include "CollisionShapes/TriangleMeshShape.h" +#include "CollisionShapes/BvhTriangleMeshShape.h" static GEN_Map<GEN_HashedPtr,CollisionShape*> map_gamemesh_to_bulletshape; @@ -770,8 +771,8 @@ static CollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool p } else { collisionMeshData = new TriangleMesh(); - concaveShape = new TriangleMeshShape(collisionMeshData); - collisionMeshShape = concaveShape; +// concaveShape = new TriangleMeshShape(collisionMeshData); + //collisionMeshShape = concaveShape; } @@ -843,7 +844,20 @@ static CollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool p if (numvalidpolys > 0) { + //map_gamemesh_to_bulletshape.insert(GEN_HashedPtr(meshobj),collisionMeshShape); + if (!polytope) + { + concaveShape = new BvhTriangleMeshShape( collisionMeshData ); + //concaveShape = new TriangleMeshShape( collisionMeshData ); + + concaveShape->RecalcLocalAabb(); + collisionMeshShape = concaveShape; + + } + + + return collisionMeshShape; } @@ -1000,17 +1014,21 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, ci.m_collisionShape = bm; ci.m_broadphaseHandle = 0; - ci.m_friction = smmaterial->m_friction; + ci.m_friction = 5.f* smmaterial->m_friction;//tweak the friction a bit, so the default 0.5 works nice ci.m_restitution = smmaterial->m_restitution; - + ci.m_physicsEnv = env; // drag / damping is inverted ci.m_linearDamping = 1.f - shapeprops->m_lin_drag; ci.m_angularDamping = 1.f - shapeprops->m_ang_drag; //need a bit of damping, else system doesn't behave well + ci.m_inertiaFactor = shapeprops->m_inertia/0.4f;//defaults to 0.4, don't want to change behaviour - KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna); - env->addCcdPhysicsController( physicscontroller); + + if (objprop->m_in_active_layer) + { + env->addCcdPhysicsController( physicscontroller); + } gameobj->SetPhysicsController(physicscontroller,isbulletdyna); diff --git a/source/gameengine/Ketsji/KX_EmptyObject.cpp b/source/gameengine/Ketsji/KX_EmptyObject.cpp index 8a72ba62f51..4636f2f0a3e 100644 --- a/source/gameengine/Ketsji/KX_EmptyObject.cpp +++ b/source/gameengine/Ketsji/KX_EmptyObject.cpp @@ -35,3 +35,7 @@ #include <config.h> #endif +KX_EmptyObject::~KX_EmptyObject() +{ + +} diff --git a/source/gameengine/Ketsji/KX_EmptyObject.h b/source/gameengine/Ketsji/KX_EmptyObject.h index b2038eb4816..46858b5c46d 100644 --- a/source/gameengine/Ketsji/KX_EmptyObject.h +++ b/source/gameengine/Ketsji/KX_EmptyObject.h @@ -39,7 +39,7 @@ public: KX_EmptyObject(void* sgReplicationInfo,SG_Callbacks callbacks) : KX_GameObject(sgReplicationInfo,callbacks) {}; - virtual ~KX_EmptyObject() {}; + virtual ~KX_EmptyObject(); }; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index e82ecd83fee..bd7ce6cc36d 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -364,10 +364,14 @@ void KX_KetsjiEngine::NextFrame() scene->setSuspendedDelta(scene->getSuspendedDelta()+curtime-scene->getSuspendedTime()); m_suspendeddelta = scene->getSuspendedDelta(); - m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); + m_logger->StartLog(tc_network, m_kxsystem->GetTimeInSeconds(), true); scene->GetNetworkScene()->proceed(localtime); + m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); + scene->UpdateParents(localtime); + + m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); // set Python hooks for each scene PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); PHY_SetActiveScene(scene); @@ -399,11 +403,11 @@ void KX_KetsjiEngine::NextFrame() m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); scene->UpdateParents(localtime); + m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); scene->GetPhysicsEnvironment()->beginFrame(); // Perform physics calculations on the scene. This can involve // many iterations of the physics solver. - m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); scene->GetPhysicsEnvironment()->proceedDeltaTime(localtime,realDeltaTime); m_previoustime = curtime; @@ -462,6 +466,9 @@ void KX_KetsjiEngine::NextFrame() PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); PHY_SetActiveScene(scene); + m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); + scene->UpdateParents(curtime); + // Perform physics calculations on the scene. This can involve // many iterations of the physics solver. m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 6ad420375e6..f13df6bfa44 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -732,7 +732,7 @@ void KX_Scene::ReplaceMesh(class CValue* gameobj,void* meshobj) Object* blendobj = (struct Object*)m_logicmgr->FindBlendObjByGameObj(newobj); Object* oldblendobj = (struct Object*)m_logicmgr->FindBlendObjByGameMeshName(mesh->GetName()); if (blendobj->parent && blendobj->parent->type == OB_ARMATURE && blendobj->partype==PARSKEL && ((Mesh*)blendobj->data)->dvert) { - BL_SkinDeformer* skindeformer = new BL_SkinDeformer(oldblendobj, blendobj, (BL_SkinMeshObject*)mesh); + BL_SkinDeformer* skindeformer = new BL_SkinDeformer(oldblendobj, blendobj, (BL_SkinMeshObject*)mesh,blendobj->parent); skindeformer->SetArmature((BL_ArmatureObject*) newobj->GetParent()); // FIXME: should the old m_pDeformer be deleted? @@ -741,7 +741,7 @@ void KX_Scene::ReplaceMesh(class CValue* gameobj,void* meshobj) ((BL_DeformableGameObject*)newobj)->m_pDeformer = skindeformer; } else if (((Mesh*)blendobj->data)->dvert) { - BL_MeshDeformer* meshdeformer = new BL_MeshDeformer(oldblendobj, (BL_SkinMeshObject*)mesh); + BL_MeshDeformer* meshdeformer = new BL_MeshDeformer(oldblendobj, (BL_SkinMeshObject*)mesh,oldblendobj->parent); // FIXME: should the old m_pDeformer be deleted? // delete ((BL_DeformableGameObject*)newobj)->m_pDeformer diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index d9c5575f657..7051b8f7e13 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -4,6 +4,8 @@ #include "PHY_IMotionState.h" #include "BroadphaseCollision/BroadphaseProxy.h" #include "CollisionShapes/ConvexShape.h" +#include "CcdPhysicsEnvironment.h" + class BP_Proxy; @@ -20,6 +22,7 @@ float gAngularSleepingTreshold = 1.0f; SimdVector3 startVel(0,0,0);//-10000); CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci) +:m_cci(ci) { m_collisionDelay = 0; m_newClientInfo = 0; @@ -27,6 +30,22 @@ CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci) m_MotionState = ci.m_MotionState; + m_broadphaseHandle = ci.m_broadphaseHandle; + + m_collisionShape = ci.m_collisionShape; + + CreateRigidbody(); + + + #ifdef WIN32 + if (m_body->getInvMass()) + m_body->setLinearVelocity(startVel); + #endif + +} + +void CcdPhysicsController::CreateRigidbody() +{ SimdTransform trans; float tmp[3]; m_MotionState->getWorldPosition(tmp[0],tmp[1],tmp[2]); @@ -36,31 +55,19 @@ CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci) m_MotionState->getWorldOrientation(orn[0],orn[1],orn[2],orn[3]); trans.setRotation(orn); - MassProps mp(ci.m_mass, ci.m_localInertiaTensor); + MassProps mp(m_cci.m_mass, m_cci.m_localInertiaTensor); - m_body = new RigidBody(mp,0,0,ci.m_friction,ci.m_restitution); + m_body = new RigidBody(mp,0,0,m_cci.m_friction,m_cci.m_restitution); - m_broadphaseHandle = ci.m_broadphaseHandle; - - m_collisionShape = ci.m_collisionShape; - // // init the rigidbody properly // - m_body->setMassProps(ci.m_mass, ci.m_localInertiaTensor); - m_body->setGravity( ci.m_gravity); - - - m_body->setDamping(ci.m_linearDamping, ci.m_angularDamping); - - + m_body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); + m_body->setGravity( m_cci.m_gravity); + m_body->setDamping(m_cci.m_linearDamping, m_cci.m_angularDamping); m_body->setCenterOfMassTransform( trans ); - #ifdef WIN32 - if (m_body->getInvMass()) - m_body->setLinearVelocity(startVel); - #endif } @@ -68,6 +75,7 @@ CcdPhysicsController::~CcdPhysicsController() { //will be reference counted, due to sharing //delete m_collisionShape; + m_cci.m_physicsEnv->removeCcdPhysicsController(this); delete m_MotionState; delete m_body; } @@ -87,11 +95,9 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time) float scale[3]; m_MotionState->getWorldScaling(scale[0],scale[1],scale[2]); - SimdVector3 scaling(scale[0],scale[1],scale[2]); m_collisionShape->setLocalScaling(scaling); - return true; } @@ -109,6 +115,45 @@ void CcdPhysicsController::WriteDynamicsToMotionState() // controller replication void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl) { + + m_MotionState = motionstate; + m_broadphaseHandle = 0; + m_body = 0; + CreateRigidbody(); + + m_cci.m_physicsEnv->addCcdPhysicsController(this); + + +/* SM_Object* dynaparent=0; + SumoPhysicsController* sumoparentctrl = (SumoPhysicsController* )parentctrl; + + if (sumoparentctrl) + { + dynaparent = sumoparentctrl->GetSumoObject(); + } + + SM_Object* orgsumoobject = m_sumoObj; + + + m_sumoObj = new SM_Object( + orgsumoobject->getShapeHandle(), + orgsumoobject->getMaterialProps(), + orgsumoobject->getShapeProps(), + dynaparent); + + m_sumoObj->setRigidBody(orgsumoobject->isRigidBody()); + + m_sumoObj->setMargin(orgsumoobject->getMargin()); + m_sumoObj->setPosition(orgsumoobject->getPosition()); + m_sumoObj->setOrientation(orgsumoobject->getOrientation()); + //if it is a dyna, register for a callback + m_sumoObj->registerCallback(*this); + + m_sumoScene->add(* (m_sumoObj)); + */ + + + } // kinematic methods @@ -190,15 +235,26 @@ void CcdPhysicsController::resolveCombinedVelocities(float linvelX,float linvel void CcdPhysicsController::getPosition(PHY__Vector3& pos) const { - assert(0); + const SimdTransform& xform = m_body->getCenterOfMassTransform(); + pos[0] = xform.getOrigin().x(); + pos[1] = xform.getOrigin().y(); + pos[2] = xform.getOrigin().z(); } void CcdPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ) { - if (m_body && m_body->GetCollisionShape()) + if (!SimdFuzzyZero(m_cci.m_scaling.x()-scaleX) || + !SimdFuzzyZero(m_cci.m_scaling.y()-scaleY) || + !SimdFuzzyZero(m_cci.m_scaling.z()-scaleZ)) { - SimdVector3 scaling(scaleX,scaleY,scaleZ); - m_body->GetCollisionShape()->setLocalScaling(scaling); + m_cci.m_scaling = SimdVector3(scaleX,scaleY,scaleZ); + + if (m_body && m_body->GetCollisionShape()) + { + m_body->GetCollisionShape()->setLocalScaling(m_cci.m_scaling); + m_body->GetCollisionShape()->CalculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor); + m_body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); + } } } @@ -269,6 +325,15 @@ void CcdPhysicsController::GetLinearVelocity(float& linvX,float& linvY,float& l linvZ = linvel.z(); } + +void CcdPhysicsController::GetAngularVelocity(float& angVelX,float& angVelY,float& angVelZ) +{ + const SimdVector3& angvel= m_body->getAngularVelocity(); + angVelX = angvel.x(); + angVelY = angvel.y(); + angVelZ = angvel.z(); +} + void CcdPhysicsController::GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ) { SimdVector3 pos(posX,posY,posZ); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 4f189b7f324..3becd14028a 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -16,6 +16,7 @@ extern float gDeactivationTime; extern float gLinearSleepingTreshold; extern float gAngularSleepingTreshold; extern bool gDisableDeactivation; +class CcdPhysicsEnvironment; struct CcdConstructionInfo @@ -27,12 +28,16 @@ struct CcdConstructionInfo m_linearDamping(0.1f), m_angularDamping(0.1f), m_MotionState(0), - m_collisionShape(0) - + m_collisionShape(0), + m_physicsEnv(0), + m_inertiaFactor(1.f), + m_scaling(1.f,1.f,1.f) { } + SimdVector3 m_localInertiaTensor; SimdVector3 m_gravity; + SimdVector3 m_scaling; SimdScalar m_mass; SimdScalar m_restitution; SimdScalar m_friction; @@ -42,7 +47,8 @@ struct CcdConstructionInfo class PHY_IMotionState* m_MotionState; CollisionShape* m_collisionShape; - + CcdPhysicsEnvironment* m_physicsEnv; //needed for self-replication + float m_inertiaFactor;//tweak the inertia (hooked up to Blender 'formfactor' }; @@ -56,8 +62,11 @@ class CcdPhysicsController : public PHY_IPhysicsController CollisionShape* m_collisionShape; void* m_newClientInfo; + CcdConstructionInfo m_cci;//needed for replication void GetWorldOrientation(SimdMatrix3x3& mat); + void CreateRigidbody(); + public: int m_collisionDelay; @@ -110,6 +119,7 @@ class CcdPhysicsController : public PHY_IPhysicsController // reading out information from physics virtual void GetLinearVelocity(float& linvX,float& linvY,float& linvZ); + virtual void GetAngularVelocity(float& angVelX,float& angVelY,float& angVelZ); virtual void GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ); virtual void getReactionForce(float& forceX,float& forceY,float& forceZ); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index c1bfa43d788..75a67e3cb37 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -226,11 +226,13 @@ void CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctr if (removeFromBroadphase) { + } // // only clear the cached algorithms // scene->CleanProxyFromPairs(bp); + scene->DestroyProxy(bp);//?? } { std::vector<CcdPhysicsController*>::iterator i = @@ -294,7 +296,10 @@ void CcdPhysicsEnvironment::UpdateActivationState() } +void CcdPhysicsEnvironment::beginFrame() +{ +} /// Perform an integration step of duration 'timeStep'. bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) @@ -320,8 +325,8 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) //this is needed because scaling is not known in advance, and scaling has to propagate to the shape if (!m_scalingPropagated) { - //SyncMotionStates(timeStep); - //m_scalingPropagated = true; + SyncMotionStates(timeStep); + m_scalingPropagated = true; } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 8bacbad8914..329239db667 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -59,7 +59,7 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment virtual void setLinearAirDamping(float damping); virtual void setUseEpa(bool epa) ; - virtual void beginFrame() {}; + virtual void beginFrame(); virtual void endFrame() {}; /// Perform an integration step of duration 'timeStep'. virtual bool proceedDeltaTime(double curTime,float timeStep); |