===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;
|
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 */
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user