diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c index 978e679e8af..19d9e41cdd5 100644 --- a/source/blender/python/api2_2x/Mesh.c +++ b/source/blender/python/api2_2x/Mesh.c @@ -4594,7 +4594,8 @@ static PyObject *MFaceSeq_nextIter( BPy_MFaceSeq * self ) * ************************************************************************/ -static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args ) +static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args, + PyObject *keywds ) { /* * (a) check input for valid edge objects, faces which consist of @@ -4615,15 +4616,27 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args ) PyObject *tmp; MFace *tmpface; Mesh *mesh = self->mesh; + int ignore_dups = 0; + PyObject *return_list = NULL; /* before we try to add faces, add edges; if it fails; exit */ tmp = MEdgeSeq_extend( self, args ); if( !tmp ) return NULL; - Py_DECREF( tmp ); + /* process any keyword arguments */ + if( keywds ) { + PyObject *res = PyDict_GetItemString( keywds, "ignoreDups" ); + if( res ) + ignore_dups = PyObject_IsTrue( res ); + + res = PyDict_GetItemString( keywds, "indexList" ); + if( res && PyObject_IsTrue( res ) ) + return_list = PyList_New( 0 ); + } + /* make sure we get a tuple of sequences of something */ switch( PySequence_Size( args ) ) { @@ -4775,9 +4788,6 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args ) ++tmppair; } - /* sort the new face pairs */ - qsort( newpair, new_face_count, sizeof(SrchFaces), mface_comp ); - /* * find duplicates in the new list and mark. if it's a duplicate, * then mark by setting second vert index to 0 (a real edge won't have @@ -4788,18 +4798,24 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args ) tmppair = newpair; /* "last good edge" */ tmppair2 = &tmppair[1]; /* "current candidate edge" */ - for( i = 0; i < new_face_count; ++i ) { - if( mface_comp( tmppair, tmppair2 ) ) - tmppair = tmppair2; /* last != current, so current == last */ - else { - tmppair2->v[1] = 0; /* last == current, so mark as duplicate */ - --good_faces; /* one less good face */ + if( !ignore_dups ) { + + /* sort the new face pairs */ + qsort( newpair, new_face_count, sizeof(SrchFaces), mface_comp ); + + for( i = 0; i < new_face_count; ++i ) { + if( mface_comp( tmppair, tmppair2 ) ) + tmppair = tmppair2; /* last != current, so current == last */ + else { + tmppair2->v[1] = 0; /* last == current, so mark as duplicate */ + --good_faces; /* one less good face */ + } + tmppair2++; } - tmppair2++; } /* if mesh has faces, see if any of the new faces are already in it */ - if( mesh->totface ) { + if( mesh->totface && !ignore_dups ) { oldpair = (SrchFaces *)MEM_callocN( sizeof(SrchFaces)*mesh->totface, "MFacePairs" ); @@ -4837,8 +4853,7 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args ) /* eliminate new faces already in the mesh */ tmppair = newpair; - i = good_faces; - while( i ) { + for( i = good_faces; i ; ) { if( tmppair->v[1] ) { if( bsearch( tmppair, oldpair, mesh->totface, sizeof(SrchFaces), mface_comp ) ) { @@ -4853,7 +4868,7 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args ) } /* if any new faces are left, add to list */ - if( good_faces ) { + if( good_faces || return_list ) { int totface = mesh->totface+good_faces; /* new face count */ /* if mesh has tfaces, reallocate them first */ @@ -4882,7 +4897,9 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args ) } /* sort the faces back into their original input list order */ - qsort( newpair, new_face_count, sizeof(SrchFaces), mface_index_comp ); + if( !ignore_dups ) + qsort( newpair, new_face_count, sizeof(SrchFaces), + mface_index_comp ); /* allocate new face list */ tmpface = MEM_callocN(totface*sizeof(MFace), "Mesh_addFaces"); @@ -4898,6 +4915,9 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args ) tmpface = &mesh->mface[mesh->totface]; tmppair = newpair; + if( return_list ) + good_faces = new_face_count; /* assume all faces good to start */ + /* as we find a good face, add it */ while ( good_faces ) { if( tmppair->v[1] ) { @@ -4918,9 +4938,18 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args ) tmpface->v4 = tmppair->v[index[3]]; tmpface->flag = 0; + + if( return_list ) + PyList_Append( return_list, + PyInt_FromLong( mesh->totface ) ); + mesh->totface++; ++tmpface; --good_faces; + } else if( return_list ) { + Py_INCREF( Py_None ); + PyList_Append( return_list, Py_None ); + --good_faces; } tmppair++; } @@ -4930,7 +4959,11 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args ) mesh_update( mesh ); Py_DECREF ( args ); MEM_freeN( newpair ); - Py_RETURN_NONE; + + if( return_list ) + return return_list; + else + Py_RETURN_NONE; } struct fourEdges @@ -5177,7 +5210,7 @@ static PyObject *MFaceSeq_selected( BPy_MFaceSeq * self ) } static struct PyMethodDef BPy_MFaceSeq_methods[] = { - {"extend", (PyCFunction)MFaceSeq_extend, METH_VARARGS, + {"extend", (PyCFunction)MFaceSeq_extend, METH_VARARGS|METH_KEYWORDS, "add faces to mesh"}, {"delete", (PyCFunction)MFaceSeq_delete, METH_VARARGS, "delete faces from mesh"}, diff --git a/source/blender/python/api2_2x/doc/Mesh.py b/source/blender/python/api2_2x/doc/Mesh.py index 4121a0ceb48..32e6667f867 100644 --- a/source/blender/python/api2_2x/doc/Mesh.py +++ b/source/blender/python/api2_2x/doc/Mesh.py @@ -17,32 +17,32 @@ face's attributes (the vertex color): Example:: - from Blender import * + from Blender import * - editmode = Window.EditMode() # are we in edit mode? If so ... - if editmode: Window.EditMode(0) # leave edit mode before getting the mesh + editmode = Window.EditMode() # are we in edit mode? If so ... + if editmode: Window.EditMode(0) # leave edit mode before getting the mesh - # define vertices and faces for a pyramid - coords=[ [-1,-1,-1], [1,-1,-1], [1,1,-1], [-1,1,-1], [0,0,1] ] - faces= [ [3,2,1,0], [0,1,4], [1,2,4], [2,3,4], [3,0,4] ] + # define vertices and faces for a pyramid + coords=[ [-1,-1,-1], [1,-1,-1], [1,1,-1], [-1,1,-1], [0,0,1] ] + faces= [ [3,2,1,0], [0,1,4], [1,2,4], [2,3,4], [3,0,4] ] - me = Mesh.New('myMesh') # create a new mesh + me = Mesh.New('myMesh') # create a new mesh - me.verts.extend(coords) # add vertices to mesh - me.faces.extend(faces) # add faces to the mesh (also adds edges) + me.verts.extend(coords) # add vertices to mesh + me.faces.extend(faces) # add faces to the mesh (also adds edges) - me.vertexColors = 1 # enable vertex colors - me.faces[1].col[0].r = 255 # make each vertex a different color - me.faces[1].col[1].g = 255 - me.faces[1].col[2].b = 255 + me.vertexColors = 1 # enable vertex colors + me.faces[1].col[0].r = 255 # make each vertex a different color + me.faces[1].col[1].g = 255 + me.faces[1].col[2].b = 255 - ob = Object.New('Mesh','myObj') # link mesh to an object - ob.link(me) + ob = Object.New('Mesh','myObj') # link mesh to an object + ob.link(me) - sc = Scene.GetCurrent() # link object to current scene - sc.link(ob) + sc = Scene.GetCurrent() # link object to current scene + sc.link(ob) - if editmode: Window.EditMode(1) # optional, just being nice + if editmode: Window.EditMode(1) # optional, just being nice Vertices, edges and faces are added to a mesh using the .extend() methods. For best speed and efficiency, gather all vertices, edges or faces into a @@ -613,7 +613,7 @@ class MFaceSeq: This object provides sequence and iterator access to the mesh's faces. """ - def extend(vertseq): + def extend(vertseq,ignoreDups=True,indexList=True): """ Add zero or more faces and edges to the mesh. Faces which already exist in the mesh, or faces which contain the same vertex multiple times are @@ -634,6 +634,16 @@ class MFaceSeq: @type vertseq: sequence(s) of MVerts @param vertseq: either two to four ints or MVerts, or sequence (list or tuple) of sequences each containing two to four ints or MVerts. + @type ignoreDups: boolean + @param ignoreDups: keyword parameter (default is False). If supplied and + True, do not check the input list or mesh for duplicate faces. This can + speed up scripts but can prossibly produce undesirable effects. Only + use if you know what you're doing. + @type indexList: boolean + @param indexList: keyword parameter (default is False). If supplied and + True, the method will return a list representing the new index for each + face in the input list. If faces are removed as duplicates, None is + inserted in place of the index. """ def delete(deledges, faces):