===Python API===

Three more changes for the Mesh module:
(1) Bug fix for UV vertices ("sticky").  me->msticky was not being updated
   when vertices were added or deleted from the mesh.
(2) Vertex, edge and face .extend() methods accept zero-length sequences
   instead of throwing an exception.  (Note that not giving any argument
   is still an error).
(3) Edge and face .extend() methods ignore "invalid" edges or faces which
   have the same vertex twice instead of throwing an exception.  Cam and I
   argued about this for a while... :-)

Ken
This commit is contained in:
Ken Hughes
2006-02-10 00:08:06 +00:00
parent 5418969adf
commit 83ea72de1a
2 changed files with 90 additions and 33 deletions

View File

@@ -350,7 +350,7 @@ static void delete_verts( Mesh *mesh, unsigned int *vert_table, int to_delete )
char state; char state;
MVert *newvert, *srcvert, *dstvert; MVert *newvert, *srcvert, *dstvert;
int count; int count;
MSticky *newsticky = NULL, *srcsticky, *dststicky;
/* is there are deformed verts also, delete them first */ /* is there are deformed verts also, delete them first */
if( mesh->dvert ) if( mesh->dvert )
@@ -359,6 +359,11 @@ static void delete_verts( Mesh *mesh, unsigned int *vert_table, int to_delete )
newvert = (MVert *)MEM_mallocN( newvert = (MVert *)MEM_mallocN(
sizeof( MVert )*( mesh->totvert-to_delete ), "MVerts" ); sizeof( MVert )*( mesh->totvert-to_delete ), "MVerts" );
/* is there are UV verts, track them too */
if( mesh->msticky )
newsticky = (MSticky *)MEM_mallocN(
sizeof( MSticky )*( mesh->totvert-to_delete ), "MStickies" );
/* /*
* do "smart compaction" of the table; find and copy groups of vertices * do "smart compaction" of the table; find and copy groups of vertices
* which are not being deleted * which are not being deleted
@@ -367,6 +372,8 @@ static void delete_verts( Mesh *mesh, unsigned int *vert_table, int to_delete )
dstvert = newvert; dstvert = newvert;
srcvert = mesh->mvert; srcvert = mesh->mvert;
tmpvert = vert_table; tmpvert = vert_table;
dststicky = newsticky;
srcsticky = mesh->msticky;
count = 0; count = 0;
state = 1; state = 1;
for( i = 0; i < mesh->totvert; ++i, ++tmpvert ) { for( i = 0; i < mesh->totvert; ++i, ++tmpvert ) {
@@ -376,6 +383,7 @@ static void delete_verts( Mesh *mesh, unsigned int *vert_table, int to_delete )
++count; ++count;
} else { } else {
srcvert = mesh->mvert + i; srcvert = mesh->mvert + i;
srcsticky = mesh->msticky + i;
count = 1; count = 1;
state = 1; state = 1;
} }
@@ -387,6 +395,11 @@ static void delete_verts( Mesh *mesh, unsigned int *vert_table, int to_delete )
if( count ) { if( count ) {
memcpy( dstvert, srcvert, sizeof( MVert ) * count ); memcpy( dstvert, srcvert, sizeof( MVert ) * count );
dstvert += count; dstvert += count;
if( newsticky ) {
memcpy( dststicky, srcsticky, sizeof( MSticky )
* count );
dststicky += count;
}
} }
count = 1; count = 1;
state = 0; state = 0;
@@ -395,13 +408,20 @@ static void delete_verts( Mesh *mesh, unsigned int *vert_table, int to_delete )
} }
/* if we were gathering verts at the end of the loop, copy those */ /* if we were gathering verts at the end of the loop, copy those */
if( state && count ) if( state && count ) {
memcpy( dstvert, srcvert, sizeof( MVert ) * count ); memcpy( dstvert, srcvert, sizeof( MVert ) * count );
if( newsticky )
memcpy( dststicky, srcsticky, sizeof( MSticky ) * count );
}
/* delete old vertex list, install the new one, update vertex count */ /* delete old vertex list, install the new one, update vertex count */
MEM_freeN( mesh->mvert ); MEM_freeN( mesh->mvert );
mesh->mvert = newvert; mesh->mvert = newvert;
if( newsticky ) {
MEM_freeN( mesh->msticky );
mesh->msticky = newsticky;
}
mesh->totvert -= to_delete; mesh->totvert -= to_delete;
} }
@@ -1605,6 +1625,9 @@ static PyObject *MVertSeq_extend( BPy_MVertSeq * self, PyObject *args )
if( !PySequence_Check ( tmp ) ) if( !PySequence_Check ( tmp ) )
return EXPP_ReturnPyObjError( PyExc_TypeError, return EXPP_ReturnPyObjError( PyExc_TypeError,
"expected a sequence of sequence triplets" ); "expected a sequence of sequence triplets" );
else if( !PySequence_Size ( tmp ) ) {
Py_RETURN_NONE;
}
args = tmp; args = tmp;
} }
Py_INCREF( args ); /* so we can safely DECREF later */ Py_INCREF( args ); /* so we can safely DECREF later */
@@ -1707,7 +1730,22 @@ static PyObject *MVertSeq_extend( BPy_MVertSeq * self, PyObject *args )
mesh->mvert = newvert; mesh->mvert = newvert;
/* /*
* maybe not quite done; if there are keys, have to fix those lists up * if there are UV vertives, have to fix those
*/
if( mesh->msticky ) {
MSticky *tmpsticky;
tmpsticky = MEM_mallocN( newlen*sizeof( MSticky ), "sticky" );
memset( tmpsticky +mesh->totvert, 255,
(newlen-mesh->totvert)*sizeof( MSticky ) );
memcpy( tmpsticky, mesh->msticky, mesh->totvert*sizeof( MSticky ) );
MEM_freeN( mesh->msticky );
mesh->msticky = tmpsticky;
}
/*
* if there are keys, have to fix those lists up
*/ */
if( mesh->key ) { if( mesh->key ) {
@@ -2461,7 +2499,13 @@ static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
case 1: case 1:
/* if a sequence... */ /* if a sequence... */
tmp = PyTuple_GET_ITEM( args, 0 ); tmp = PyTuple_GET_ITEM( args, 0 );
if( PySequence_Check( tmp ) && PySequence_Size( tmp ) > 0 ) { if( PySequence_Check( tmp ) ) {
/* ignore empty sequences */
if( !PySequence_Size( tmp ) ) {
Py_RETURN_NONE;
}
/* if another sequence, use it */ /* if another sequence, use it */
PyObject *tmp2 = PySequence_ITEM( tmp, 0 ); PyObject *tmp2 = PySequence_ITEM( tmp, 0 );
if( PySequence_Check( tmp2 ) ) if( PySequence_Check( tmp2 ) )
@@ -2526,8 +2570,8 @@ static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
return EXPP_ReturnPyObjError( PyExc_ValueError, return EXPP_ReturnPyObjError( PyExc_ValueError,
"expected 2 to 4 MVerts per sequence" ); "expected 2 to 4 MVerts per sequence" );
} }
Py_DECREF( tmp );
Py_DECREF( tmp );
if( nverts == 2 ) if( nverts == 2 )
++new_edge_count; /* if only two vert, then add only edge */ ++new_edge_count; /* if only two vert, then add only edge */
else else
@@ -2563,26 +2607,21 @@ static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
if( k == nverts ) /* final edge */ if( k == nverts ) /* final edge */
k = 0; k = 0;
/* sort verts into search list, abort if two are the same */ /* sort verts into search list, skip if two are the same */
if( e[j]->index < e[k]->index ) { if( e[j]->index != e[k]->index ) {
tmppair->v[0] = e[j]->index; if( e[j]->index < e[k]->index ) {
tmppair->v[1] = e[k]->index; tmppair->v[0] = e[j]->index;
tmppair->swap = 0; tmppair->v[1] = e[k]->index;
} else if( e[j]->index > e[k]->index ) { tmppair->swap = 0;
tmppair->v[0] = e[k]->index; } else {
tmppair->v[1] = e[j]->index; tmppair->v[0] = e[k]->index;
tmppair->swap = 1; tmppair->v[1] = e[j]->index;
} else { tmppair->swap = 1;
MEM_freeN( newpair ); }
for(j = 0; j < nverts; ++j ) tmppair->index = new_edge_count;
Py_DECREF( e[j] ); ++new_edge_count;
Py_DECREF( args ); tmppair++;
return EXPP_ReturnPyObjError( PyExc_ValueError,
"tuple contains duplicate vertices" );
} }
tmppair->index = new_edge_count;
++new_edge_count;
tmppair++;
} }
/* free the new references */ /* free the new references */
@@ -4028,7 +4067,13 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
case 1: /* better be a sequence or a tuple */ case 1: /* better be a sequence or a tuple */
/* if a sequence... */ /* if a sequence... */
tmp = PyTuple_GET_ITEM( args, 0 ); tmp = PyTuple_GET_ITEM( args, 0 );
if( PySequence_Check( tmp ) && PySequence_Size( tmp ) > 0 ) { if( PySequence_Check( tmp ) ) {
/* ignore empty sequences */
if( !PySequence_Size( tmp ) ) {
Py_RETURN_NONE;
}
/* if another sequence, use it */ /* if another sequence, use it */
PyObject *tmp2 = PySequence_ITEM( tmp, 0 ); PyObject *tmp2 = PySequence_ITEM( tmp, 0 );
if( PySequence_Check( tmp2 ) ) if( PySequence_Check( tmp2 ) )
@@ -4103,6 +4148,7 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
/* scan the input list and build the new face pair list */ /* scan the input list and build the new face pair list */
len = PySequence_Size( args ); len = PySequence_Size( args );
tmppair = newpair; tmppair = newpair;
for( i = 0; i < len; ++i ) { for( i = 0; i < len; ++i ) {
BPy_MVert *e; BPy_MVert *e;
MFace tmpface; MFace tmpface;
@@ -4158,14 +4204,24 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
SWAP( int, vert[k], vert[k+1] ); SWAP( int, vert[k], vert[k+1] );
SWAP( char, order[k], order[k+1] ); SWAP( char, order[k], order[k+1] );
} else if( vert[k] == vert[k+1] ) { } else if( vert[k] == vert[k+1] ) {
#if 0
MEM_freeN( newpair ); MEM_freeN( newpair );
Py_DECREF( args ); Py_DECREF( args );
return EXPP_ReturnPyObjError( PyExc_ValueError, return EXPP_ReturnPyObjError( PyExc_ValueError,
"tuple contains duplicate vertices" ); "tuple contains duplicate vertices" );
#else
break;
#endif
} }
} }
if( k < j )
break;
tmppair->v[j] = vert[j]; tmppair->v[j] = vert[j];
} }
if( j >= 0 ) {
--new_face_count;
continue;
}
tmppair->index = i; tmppair->index = i;
/* pack order into a byte */ /* pack order into a byte */

View File

@@ -258,7 +258,7 @@ class MVertSeq:
def extend(coords): def extend(coords):
""" """
Append one or more vertices to the mesh. Unlike L{MEdgeSeq.extend()} and Append zero or more vertices to the mesh. Unlike L{MEdgeSeq.extend()} and
L{MFaceSeq.extend()} no attempt is made to check for duplicate vertices in L{MFaceSeq.extend()} no attempt is made to check for duplicate vertices in
the parameter list, or for vertices already in the mesh. the parameter list, or for vertices already in the mesh.
@@ -334,10 +334,10 @@ class MEdgeSeq:
def extend(vertseq): def extend(vertseq):
""" """
Add one or more edges to the mesh. Edges which already exist in the Add zero or more edges to the mesh. Edges which already exist in the
mesh are ignored. If three or four verts are specified in any tuple, mesh or with both vertices the same are ignored. If three or four verts
an edge is also created between the first and last vertices (this is are specified in any sequence, an edge is also created between the first
useful when adding faces). and last vertices (this is useful when adding faces).
Example:: Example::
import Blender import Blender
@@ -523,9 +523,10 @@ class MFaceSeq:
def extend(vertseq): def extend(vertseq):
""" """
Add one or more faces to the mesh. Faces which already exist in the Add zero or more faces and edges to the mesh. Faces which already exist
mesh are ignored. Sequences of two vertices are accepted, but no face in the mesh, or faces which contain the same vertex multiple times are
will be created. ignored. Sequences of two vertices are accepted, but no face will be
created.
Example:: Example::
import Blender import Blender