===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:
@@ -350,7 +350,7 @@ static void delete_verts( Mesh *mesh, unsigned int *vert_table, int to_delete )
|
||||
char state;
|
||||
MVert *newvert, *srcvert, *dstvert;
|
||||
int count;
|
||||
|
||||
MSticky *newsticky = NULL, *srcsticky, *dststicky;
|
||||
|
||||
/* is there are deformed verts also, delete them first */
|
||||
if( mesh->dvert )
|
||||
@@ -359,6 +359,11 @@ static void delete_verts( Mesh *mesh, unsigned int *vert_table, int to_delete )
|
||||
newvert = (MVert *)MEM_mallocN(
|
||||
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
|
||||
* which are not being deleted
|
||||
@@ -367,6 +372,8 @@ static void delete_verts( Mesh *mesh, unsigned int *vert_table, int to_delete )
|
||||
dstvert = newvert;
|
||||
srcvert = mesh->mvert;
|
||||
tmpvert = vert_table;
|
||||
dststicky = newsticky;
|
||||
srcsticky = mesh->msticky;
|
||||
count = 0;
|
||||
state = 1;
|
||||
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;
|
||||
} else {
|
||||
srcvert = mesh->mvert + i;
|
||||
srcsticky = mesh->msticky + i;
|
||||
count = 1;
|
||||
state = 1;
|
||||
}
|
||||
@@ -387,6 +395,11 @@ static void delete_verts( Mesh *mesh, unsigned int *vert_table, int to_delete )
|
||||
if( count ) {
|
||||
memcpy( dstvert, srcvert, sizeof( MVert ) * count );
|
||||
dstvert += count;
|
||||
if( newsticky ) {
|
||||
memcpy( dststicky, srcsticky, sizeof( MSticky )
|
||||
* count );
|
||||
dststicky += count;
|
||||
}
|
||||
}
|
||||
count = 1;
|
||||
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( state && count )
|
||||
if( state && 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 */
|
||||
|
||||
MEM_freeN( mesh->mvert );
|
||||
mesh->mvert = newvert;
|
||||
if( newsticky ) {
|
||||
MEM_freeN( mesh->msticky );
|
||||
mesh->msticky = newsticky;
|
||||
}
|
||||
mesh->totvert -= to_delete;
|
||||
}
|
||||
|
||||
@@ -1605,6 +1625,9 @@ static PyObject *MVertSeq_extend( BPy_MVertSeq * self, PyObject *args )
|
||||
if( !PySequence_Check ( tmp ) )
|
||||
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
||||
"expected a sequence of sequence triplets" );
|
||||
else if( !PySequence_Size ( tmp ) ) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
args = tmp;
|
||||
}
|
||||
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;
|
||||
|
||||
/*
|
||||
* 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 ) {
|
||||
@@ -2461,7 +2499,13 @@ static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
|
||||
case 1:
|
||||
/* if a sequence... */
|
||||
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 */
|
||||
PyObject *tmp2 = PySequence_ITEM( tmp, 0 );
|
||||
if( PySequence_Check( tmp2 ) )
|
||||
@@ -2526,8 +2570,8 @@ static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
|
||||
return EXPP_ReturnPyObjError( PyExc_ValueError,
|
||||
"expected 2 to 4 MVerts per sequence" );
|
||||
}
|
||||
Py_DECREF( tmp );
|
||||
|
||||
Py_DECREF( tmp );
|
||||
if( nverts == 2 )
|
||||
++new_edge_count; /* if only two vert, then add only edge */
|
||||
else
|
||||
@@ -2563,26 +2607,21 @@ static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
|
||||
if( k == nverts ) /* final edge */
|
||||
k = 0;
|
||||
|
||||
/* sort verts into search list, abort if two are the same */
|
||||
if( e[j]->index < e[k]->index ) {
|
||||
tmppair->v[0] = e[j]->index;
|
||||
tmppair->v[1] = e[k]->index;
|
||||
tmppair->swap = 0;
|
||||
} else if( e[j]->index > e[k]->index ) {
|
||||
tmppair->v[0] = e[k]->index;
|
||||
tmppair->v[1] = e[j]->index;
|
||||
tmppair->swap = 1;
|
||||
} else {
|
||||
MEM_freeN( newpair );
|
||||
for(j = 0; j < nverts; ++j )
|
||||
Py_DECREF( e[j] );
|
||||
Py_DECREF( args );
|
||||
return EXPP_ReturnPyObjError( PyExc_ValueError,
|
||||
"tuple contains duplicate vertices" );
|
||||
/* 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;
|
||||
tmppair->v[1] = e[k]->index;
|
||||
tmppair->swap = 0;
|
||||
} else {
|
||||
tmppair->v[0] = e[k]->index;
|
||||
tmppair->v[1] = e[j]->index;
|
||||
tmppair->swap = 1;
|
||||
}
|
||||
tmppair->index = new_edge_count;
|
||||
++new_edge_count;
|
||||
tmppair++;
|
||||
}
|
||||
tmppair->index = new_edge_count;
|
||||
++new_edge_count;
|
||||
tmppair++;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
/* if a sequence... */
|
||||
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 */
|
||||
PyObject *tmp2 = PySequence_ITEM( tmp, 0 );
|
||||
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 */
|
||||
len = PySequence_Size( args );
|
||||
tmppair = newpair;
|
||||
|
||||
for( i = 0; i < len; ++i ) {
|
||||
BPy_MVert *e;
|
||||
MFace tmpface;
|
||||
@@ -4158,14 +4204,24 @@ static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
|
||||
SWAP( int, vert[k], vert[k+1] );
|
||||
SWAP( char, order[k], order[k+1] );
|
||||
} else if( vert[k] == vert[k+1] ) {
|
||||
#if 0
|
||||
MEM_freeN( newpair );
|
||||
Py_DECREF( args );
|
||||
return EXPP_ReturnPyObjError( PyExc_ValueError,
|
||||
"tuple contains duplicate vertices" );
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if( k < j )
|
||||
break;
|
||||
tmppair->v[j] = vert[j];
|
||||
}
|
||||
if( j >= 0 ) {
|
||||
--new_face_count;
|
||||
continue;
|
||||
}
|
||||
tmppair->index = i;
|
||||
|
||||
/* pack order into a byte */
|
||||
|
||||
@@ -258,7 +258,7 @@ class MVertSeq:
|
||||
|
||||
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
|
||||
the parameter list, or for vertices already in the mesh.
|
||||
|
||||
@@ -334,10 +334,10 @@ class MEdgeSeq:
|
||||
|
||||
def extend(vertseq):
|
||||
"""
|
||||
Add one 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,
|
||||
an edge is also created between the first and last vertices (this is
|
||||
useful when adding faces).
|
||||
Add zero or more edges to the mesh. Edges which already exist in the
|
||||
mesh or with both vertices the same are ignored. If three or four verts
|
||||
are specified in any sequence, an edge is also created between the first
|
||||
and last vertices (this is useful when adding faces).
|
||||
|
||||
Example::
|
||||
import Blender
|
||||
@@ -523,9 +523,10 @@ class MFaceSeq:
|
||||
|
||||
def extend(vertseq):
|
||||
"""
|
||||
Add one or more faces to the mesh. Faces which already exist in the
|
||||
mesh are ignored. Sequences of two vertices are accepted, but no face
|
||||
will be created.
|
||||
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
|
||||
ignored. Sequences of two vertices are accepted, but no face will be
|
||||
created.
|
||||
|
||||
Example::
|
||||
import Blender
|
||||
|
||||
Reference in New Issue
Block a user