==Python API==
[blender-staging.git] / source / blender / python / api2_2x / Mesh.c
1 /* 
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * This is a new part of Blender, partially based on NMesh.c API.
27  *
28  * Contributor(s): Ken Hughes
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include "Mesh.h" /*This must come first*/
34
35 #include "MEM_guardedalloc.h"
36
37 #include "DNA_key_types.h"
38 #include "DNA_armature_types.h"
39 #include "DNA_scene_types.h"
40 #include "DNA_oops_types.h"
41 #include "DNA_space_types.h"
42 #include "DNA_curve_types.h"
43 #include "DNA_meta_types.h"
44 #include "DNA_modifier_types.h"
45
46 #include "BDR_editface.h"       /* make_tfaces */
47 #include "BDR_vpaint.h"
48 #include "BDR_editobject.h"
49
50 #include "BIF_editdeform.h"
51 #include "BIF_editkey.h"        /* insert_meshkey */
52 #include "BIF_editview.h"
53 #include "BIF_editmesh.h"
54
55 #include "BKE_deform.h"
56 #include "BKE_mesh.h"
57 #include "BKE_material.h"
58 #include "BKE_main.h"
59 #include "BKE_global.h"
60 #include "BKE_library.h"
61 #include "BKE_displist.h"
62 #include "BKE_DerivedMesh.h"
63 #include "BKE_object.h"
64 #include "BKE_mball.h"
65 #include "BKE_utildefines.h"
66 #include "BKE_depsgraph.h"
67 #include "BSE_edit.h"           /* for countall(); */
68 #include "BKE_curve.h"          /* for copy_curve(); */
69 #include "BKE_modifier.h"       /* for modifier_new(), modifier_copyData(); */
70
71 #include "BLI_arithb.h"
72 #include "BLI_blenlib.h"
73
74 #include "blendef.h"
75 #include "mydevice.h"
76 #include "butspace.h"           /* for mesh tools */
77 #include "Object.h"
78 #include "Key.h"
79 #include "Image.h"
80 #include "Material.h"
81 #include "Mathutils.h"
82 #include "constant.h"
83 #include "gen_utils.h"
84
85 /* EXPP Mesh defines */
86
87 #define MESH_SMOOTHRESH               30
88 #define MESH_SMOOTHRESH_MIN            1
89 #define MESH_SMOOTHRESH_MAX           80
90 #define MESH_SUBDIV                    1
91 #define MESH_SUBDIV_MIN                0
92 #define MESH_SUBDIV_MAX                6
93
94 #define MESH_HASFACEUV                 0
95 #define MESH_HASMCOL                   1
96 #define MESH_HASVERTUV                 2
97
98 #define MESH_TOOL_TOSPHERE             0
99 #define MESH_TOOL_VERTEXSMOOTH         1
100 #define MESH_TOOL_FLIPNORM             2
101 #define MESH_TOOL_SUBDIV               3
102 #define MESH_TOOL_REMDOUB              4
103 #define MESH_TOOL_FILL                 5
104 #define MESH_TOOL_RECALCNORM           6
105 #define MESH_TOOL_TRI2QUAD             7
106 #define MESH_TOOL_QUAD2TRI             8
107
108 /************************************************************************
109  *
110  * internal utilities
111  *
112  ************************************************************************/
113
114 /*
115  * internal structures used for sorting edges and faces
116  */
117
118 typedef struct SrchEdges {
119         unsigned int v[2];              /* indices for verts */
120         unsigned char swap;             /* non-zero if verts swapped */
121         unsigned int index;             /* index in original param list of this edge */
122                                                         /* (will be used by findEdges) */
123 } SrchEdges;
124
125 typedef struct SrchFaces {
126         unsigned int v[4];              /* indices for verts */
127         unsigned int index;             /* index in original param list of this edge */
128         unsigned char order;    /* order of original verts, bitpacked */
129 } SrchFaces;
130
131 typedef struct FaceEdges {
132         unsigned int v[2];              /* search key (vert indices) */
133         unsigned int index;             /* location in edge list */
134         unsigned char sel;              /* selection state */
135 } FaceEdges;
136
137 /*
138  * compare edges by vertex indices
139  */
140
141 int medge_comp( const void *va, const void *vb )
142 {
143         const unsigned int *a = ((SrchEdges *)va)->v;
144         const unsigned int *b = ((SrchEdges *)vb)->v;
145
146         /* compare first index for differences */
147
148         if (a[0] < b[0]) return -1;     
149         else if (a[0] > b[0]) return 1;
150
151         /* if first indices equal, compare second index for differences */
152
153         else if (a[1] < b[1]) return -1;
154         else return (a[1] > b[1]);
155 }
156
157 /*
158  * compare edges by insert list indices
159  */
160
161 int medge_index_comp( const void *va, const void *vb )
162 {
163         const SrchEdges *a = (SrchEdges *)va;
164         const SrchEdges *b = (SrchEdges *)vb;
165
166         /* compare list indices for differences */
167
168         if (a->index < b->index) return -1;
169         else return (a->index > b->index);
170 }
171
172
173 /*
174  * compare faces by vertex indices
175  */
176
177 int mface_comp( const void *va, const void *vb )
178 {
179         const SrchFaces *a = va;
180         const SrchFaces *b = vb;
181         int i;
182
183         /* compare indices, first to last, for differences */
184         for( i = 0; i < 4; ++i ) {
185                 if( a->v[i] < b->v[i] )
186                         return -1;      
187                 if( a->v[i] > b->v[i] )
188                         return 1;
189         }
190
191         /*
192          * don't think this needs be done; if order is different then either
193          * (a) the face is good, just reversed or has a different starting
194          * vertex, or (b) face is bad (for 4 verts) and there's a "twist"
195          */
196
197 #if 0
198         /* if all the same verts, compare their order */
199         if( a->order < b->order )
200                 return -1;      
201         if( a->order > b->order )
202                 return 1;       
203 #endif
204
205         return 0;
206 }
207
208 /*
209  * compare faces by insert list indices
210  */
211
212 int mface_index_comp( const void *va, const void *vb )
213 {
214         const SrchFaces *a = va;
215         const SrchFaces *b = vb;
216
217         /* compare indices, first to last, for differences */
218         if( a->index < b->index )
219                 return -1;      
220         if( a->index > b->index )
221                 return 1;
222         return 0;
223 }
224
225 /*
226  * compare edges by vertex indices
227  */
228
229 int faceedge_comp( const void *va, const void *vb )
230 {
231         const unsigned int *a = ((FaceEdges *)va)->v;
232         const unsigned int *b = ((FaceEdges *)vb)->v;
233
234         /* compare first index for differences */
235
236         if (a[0] < b[0]) return -1;     
237         else if (a[0] > b[0]) return 1;
238
239         /* if first indices equal, compare second index for differences */
240
241         else if (a[1] < b[1]) return -1;
242         else return (a[1] > b[1]);
243 }
244
245 /*
246  * update the DAG for all objects linked to this mesh
247  */
248
249 static void mesh_update( Mesh * mesh )
250 {
251         Object_updateDag( (void *) mesh );
252 }
253
254 static void delete_dverts( Mesh *mesh, unsigned int *vert_table, int to_delete )
255 {
256         unsigned int *tmpvert;
257         int i;
258         char state;
259         MDeformVert *newvert, *srcvert, *dstvert;
260         int count;
261
262         newvert = (MDeformVert *)MEM_mallocN(
263                         sizeof( MDeformVert )*( mesh->totvert-to_delete ), "MDeformVerts" );
264
265         /*
266          * do "smart compaction" of the table; find and copy groups of vertices
267          * which are not being deleted
268          */
269
270         dstvert = newvert;
271         srcvert = mesh->dvert;
272         tmpvert = vert_table;
273         count = 0;
274         state = 1;
275         for( i = 0; i < mesh->totvert; ++i, ++tmpvert ) {
276                 switch( state ) {
277                 case 0:         /* skipping verts */
278                         if( *tmpvert == UINT_MAX )
279                                 ++count;
280                         else {
281                                 srcvert = mesh->dvert + i;
282                                 count = 1;
283                                 state = 1;
284                         }
285                         break;
286                 case 1:         /* gathering verts */
287                         if( *tmpvert != UINT_MAX ) {
288                                 ++count;
289                         } else {
290                                 if( count ) {
291                                         memcpy( dstvert, srcvert, sizeof( MDeformVert ) * count );
292                                         dstvert += count;
293                                 }
294                                 count = 1;
295                                 state = 0;
296                         }
297                 }
298                 if( !state && mesh->dvert[i].dw )
299                         MEM_freeN( mesh->dvert[i].dw );
300         }
301
302         /* if we were gathering verts at the end of the loop, copy those */
303         if( state && count )
304                 memcpy( dstvert, srcvert, sizeof( MDeformVert ) * count );
305
306         /* delete old vertex list, install the new one */
307
308         MEM_freeN( mesh->dvert );
309         mesh->dvert = newvert;
310 }
311
312 /*
313  * delete vertices from mesh, then delete edges/keys/faces which used those
314  * vertices
315  *
316  * Deletion is done by "smart compaction"; groups of verts/edges/faces which
317  * remain in the list are copied to new list instead of one at a time.  Since
318  * Blender has no realloc we would have to copy things anyway, so there's no
319  * point trying to fill empty entries with data from the end of the lists.
320  *
321  * vert_table is a lookup table for mapping old verts to new verts (after the
322  * vextex list has deleted vertices removed).  Each entry contains the
323  * vertex's new index.
324  */
325
326 static void delete_verts( Mesh *mesh, unsigned int *vert_table, int to_delete )
327 {
328         /*
329          * (1) allocate vertex table (initialize contents to 0)
330          * (2) mark each vertex being deleted in vertex table (= UINT_MAX)
331          * (3) update remaining table entries with "new" vertex index (after
332          *     compaction)
333          * (4) allocate new vertex list
334          * (5) do "smart copy" of vertices from old to new
335          *     * each moved vertex is entered into vertex table: if vertex i is
336          *       moving to index j in new list
337          *       vert_table[i] = j;
338          * (6) if keys, do "smart copy" of keys
339          * (7) process edge list
340          *      update vert index
341          *      delete edges which delete verts
342          * (7) allocate new edge list
343          * (8) do "smart copy" of edges
344          * (9) allocate new face list
345          * (10) do "smart copy" of face
346          */
347
348         unsigned int *tmpvert;
349         int i;
350         char state;
351         MVert *newvert, *srcvert, *dstvert;
352         int count;
353
354
355         /* is there are deformed verts also, delete them first */
356         if( mesh->dvert )
357                 delete_dverts( mesh, vert_table, to_delete );
358
359         newvert = (MVert *)MEM_mallocN(
360                         sizeof( MVert )*( mesh->totvert-to_delete ), "MVerts" );
361
362         /*
363          * do "smart compaction" of the table; find and copy groups of vertices
364          * which are not being deleted
365          */
366
367         dstvert = newvert;
368         srcvert = mesh->mvert;
369         tmpvert = vert_table;
370         count = 0;
371         state = 1;
372         for( i = 0; i < mesh->totvert; ++i, ++tmpvert ) {
373                 switch( state ) {
374                 case 0:         /* skipping verts */
375                         if( *tmpvert == UINT_MAX ) {
376                                 ++count;
377                         } else {
378                                 srcvert = mesh->mvert + i;
379                                 count = 1;
380                                 state = 1;
381                         }
382                         break;
383                 case 1:         /* gathering verts */
384                         if( *tmpvert != UINT_MAX ) {
385                                 ++count;
386                         } else {
387                                 if( count ) {
388                                         memcpy( dstvert, srcvert, sizeof( MVert ) * count );
389                                         dstvert += count;
390                                 }
391                                 count = 1;
392                                 state = 0;
393                         }
394                 }
395         }
396
397         /* if we were gathering verts at the end of the loop, copy those */
398         if( state && count )
399                 memcpy( dstvert, srcvert, sizeof( MVert ) * count );
400
401         /* delete old vertex list, install the new one, update vertex count */
402
403         MEM_freeN( mesh->mvert );
404         mesh->mvert = newvert;
405         mesh->totvert -= to_delete;
406 }
407
408 static void delete_edges( Mesh *mesh, unsigned int *vert_table, int to_delete )
409 {
410         int i;
411         MEdge *tmpedge;
412
413         /* if not given, then mark and count edges to be deleted */
414         if( !to_delete ) {
415                 tmpedge = mesh->medge;
416                 for( i = mesh->totedge; i-- ; ++tmpedge )
417                         if( vert_table[tmpedge->v1] == UINT_MAX ||
418                                         vert_table[tmpedge->v2] == UINT_MAX ) {
419                                 tmpedge->v1 = UINT_MAX;
420                                 ++to_delete;
421                         }
422         }
423
424         /* if there are edges to delete, handle it */
425         if( to_delete ) {
426                 MEdge *newedge, *srcedge, *dstedge;
427                 int count, state;
428
429         /* allocate new edge list and populate */
430                 newedge = (MEdge *)MEM_mallocN(
431                                 sizeof( MEdge )*( mesh->totedge-to_delete ), "MEdges" );
432
433         /*
434          * do "smart compaction" of the edges; find and copy groups of edges
435          * which are not being deleted
436          */
437
438                 dstedge = newedge;
439                 srcedge = mesh->medge;
440                 tmpedge = srcedge;
441                 count = 0;
442                 state = 1;
443                 for( i = 0; i < mesh->totedge; ++i, ++tmpedge ) {
444                         switch( state ) {
445                         case 0:         /* skipping edges */
446                                 if( tmpedge->v1 == UINT_MAX ) {
447                                         ++count;
448                                 } else {
449                                         srcedge = tmpedge;
450                                         count = 1;
451                                         state = 1;
452                                 }
453                                 break;
454                         case 1:         /* gathering edges */
455                                 if( tmpedge->v1 != UINT_MAX ) {
456                                         ++count;
457                                 } else {
458                                         if( count ) {
459                                                 memcpy( dstedge, srcedge, sizeof( MEdge ) * count );
460                                                 dstedge += count;
461                                         }
462                                         count = 1;
463                                         state = 0;
464                                 }
465                         }
466                 /* if edge is good, update vertex indices */
467                 }
468
469         /* copy any pending good edges */
470                 if( state && count )
471                         memcpy( dstedge, srcedge, sizeof( MEdge ) * count );
472
473         /* delete old vertex list, install the new one, update vertex count */
474                 MEM_freeN( mesh->medge );
475                 mesh->medge = newedge;
476                 mesh->totedge -= to_delete;
477         }
478
479         /* if vertices were deleted, update edge's vertices */
480         if( vert_table ) {
481                 tmpedge = mesh->medge;
482                 for( i = mesh->totedge; i--; ++tmpedge ) {
483                         tmpedge->v1 = vert_table[tmpedge->v1];
484                         tmpedge->v2 = vert_table[tmpedge->v2];
485                 }
486         }
487 }
488
489 /*
490  * Since all faces must have 3 or 4 verts, we can't have v3 or v4 be zero.
491  * If that happens during the deletion, we have to shuffle the vertices
492  * around; otherwise it can cause an Eeekadoodle or worse.  If there are
493  * texture faces as well, they have to be shuffled as well.
494  *
495  * (code borrowed from test_index_face() in mesh.c, but since we know the
496  * faces already have correct number of vertices, this is a little faster)
497  */
498
499 static void eeek_fix( MFace *mface, TFace *tface, int len4 )
500 {
501         /* if 4 verts, then neither v3 nor v4 can be zero */
502         if( len4 ) {
503                 if( !mface->v3 || !mface->v4 ) {
504                         SWAP( int, mface->v1, mface->v3 );
505                         SWAP( int, mface->v2, mface->v4 );
506                         if( tface ) {
507                                 SWAP( float, tface->uv[0][0], tface->uv[2][0] );
508                                 SWAP( float, tface->uv[0][1], tface->uv[2][1] );
509                                 SWAP( float, tface->uv[1][0], tface->uv[3][0] );
510                                 SWAP( float, tface->uv[1][1], tface->uv[3][1] );
511                                 SWAP( unsigned int, tface->col[0], tface->col[2] );
512                                 SWAP( unsigned int, tface->col[1], tface->col[3] );
513                         }
514                 }
515         } else if( !mface->v3 ) {
516         /* if 2 verts, then just v3 cannot be zero (v4 MUST be zero) */
517                 SWAP( int, mface->v1, mface->v2 );
518                 SWAP( int, mface->v2, mface->v3 );
519                 if( tface ) {
520                         SWAP( float, tface->uv[0][0], tface->uv[1][0] );
521                         SWAP( float, tface->uv[0][1], tface->uv[1][1] );
522                         SWAP( float, tface->uv[2][0], tface->uv[1][0] );
523                         SWAP( float, tface->uv[2][1], tface->uv[1][1] );
524                         SWAP( unsigned int, tface->col[0], tface->col[1] );
525                         SWAP( unsigned int, tface->col[1], tface->col[2] );
526                 }
527         }
528 }
529
530 static void delete_faces( Mesh *mesh, unsigned int *vert_table, int to_delete )
531 {
532         int i;
533         MFace *tmpface;
534         TFace *tmptface;
535
536                 /* if there are faces to delete, handle it */
537         if( to_delete ) {
538                 MFace *newface, *srcface, *dstface;
539                 TFace *newtface = NULL, *srctface, *dsttface;
540                 char state;
541                 int count;
542
543                 newface = (MFace *)MEM_mallocN( ( mesh->totface-to_delete )
544                                 * sizeof( MFace ), "MFace" );
545                 if( mesh->tface )
546                         newtface = (TFace *)MEM_mallocN( ( mesh->totface-to_delete )
547                                         * sizeof( TFace ), "TFace" );
548
549                 /*
550                  * do "smart compaction" of the faces; find and copy groups of faces
551                  * which are not being deleted
552                  */
553
554                 dstface = newface;
555                 srcface = mesh->mface;
556                 tmpface = srcface;
557                 dsttface = newtface;
558                 srctface = mesh->tface;
559                 tmptface = srctface;
560
561                 count = 0;
562                 state = 1;
563                 for( i = 0; i < mesh->totface; ++i ) {
564                         switch( state ) {
565                         case 0:         /* skipping faces */
566                                 if( tmpface->v1 == UINT_MAX ) {
567                                         ++count;
568                                 } else {
569                                         srcface = tmpface;
570                                         srctface = tmptface;
571                                         count = 1;
572                                         state = 1;
573                                 }
574                                 break;
575                         case 1:         /* gathering faces */
576                                 if( tmpface->v1 != UINT_MAX ) {
577                                         ++count;
578                                 } else {
579                                         if( count ) {
580                                                 memcpy( dstface, srcface, sizeof( MFace ) * count );
581                                                 dstface += count;
582                                                 if( newtface ) {
583                                                         memcpy( dsttface, srctface, sizeof( TFace )
584                                                                         * count );
585                                                         dsttface += count;
586                                                 }
587                                         }
588                                         count = 1;
589                                         state = 0;
590                                 }
591                         }
592                         ++tmpface; 
593                         ++tmptface; 
594                 }
595
596         /* if we were gathering faces at the end of the loop, copy those */
597                 if ( state && count ) {
598                         memcpy( dstface, srcface, sizeof( MFace ) * count );
599                         if( newtface )
600                                 memcpy( dsttface, srctface, sizeof( TFace ) * count );
601                 }
602
603         /* delete old face list, install the new one, update face count */
604
605                 MEM_freeN( mesh->mface );
606                 mesh->mface = newface;
607                 mesh->totface -= to_delete;
608                 if( newtface ) {
609                         MEM_freeN( mesh->tface );
610                         mesh->tface = newtface;
611                 }
612         }
613
614         /* if vertices were deleted, update face's vertices */
615         if( vert_table ) {
616                 tmpface = mesh->mface;
617                 tmptface = mesh->tface;
618                 for( i = mesh->totface; i--; ) {
619                         int len4 = tmpface->v4;
620                         tmpface->v1 = vert_table[tmpface->v1];
621                         tmpface->v2 = vert_table[tmpface->v2];
622                         tmpface->v3 = vert_table[tmpface->v3];
623                         tmpface->v4 = vert_table[tmpface->v4];
624
625                         eeek_fix( tmpface, tmptface, len4 );
626
627                         ++tmpface;
628                         if( mesh->tface )
629                                 ++tmptface;
630                 }
631         }
632 }
633
634 /*
635  * fill up vertex lookup table with old-to-new mappings
636  *
637  * returns the number of vertices marked for deletion
638  */
639
640 static unsigned int make_vertex_table( unsigned int *vert_table, int count )
641 {
642         int i;
643         unsigned int *tmpvert = vert_table;
644         unsigned int to_delete = 0;
645         unsigned int new_index = 0;
646
647         /* fill the lookup table with old->new index mappings */
648         for( i = count; i; --i, ++tmpvert ) {
649                 if( *tmpvert == UINT_MAX ) {
650                         ++to_delete;
651                 } else {
652                         *tmpvert = new_index;
653                         ++new_index;
654                 }
655         }
656         return to_delete;
657 }
658
659 /************************************************************************
660  *
661  * Color attributes
662  *
663  ************************************************************************/
664
665 /*
666  * get a color attribute
667  */
668
669 static PyObject *MCol_getAttr( BPy_MCol * self, void *type )
670 {
671         unsigned char param;
672         PyObject *attr;
673
674         switch( (long)type ) {
675     case 'R':   /* these are backwards, but that how it works */
676                 param = self->color->b;
677                 break;
678     case 'G':
679                 param = self->color->g;
680                 break;
681     case 'B':   /* these are backwards, but that how it works */
682                 param = self->color->r;
683                 break;
684     case 'A':
685                 param = self->color->a;
686                 break;
687         default:
688                 {
689                         char errstr[1024];
690                         sprintf( errstr, "undefined type '%d' in MCol_getAttr",
691                                         (int)((long)type & 0xff));
692                         return EXPP_ReturnPyObjError( PyExc_RuntimeError, errstr );
693                 }
694         }
695
696         attr = PyInt_FromLong( param );
697         if( attr )
698                 return attr;
699
700         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
701                         "PyInt_FromLong() failed"); 
702 }
703
704 /*
705  * set a color attribute
706  */
707
708 static int MCol_setAttr( BPy_MCol * self, PyObject * value, void * type )
709 {
710         unsigned char *param;
711
712         switch( (long)type ) {
713     case 'R':   /* these are backwards, but that how it works */
714                 param = (unsigned char *)&self->color->b;
715                 break;
716     case 'G':
717                 param = (unsigned char *)&self->color->g;
718                 break;
719     case 'B':   /* these are backwards, but that how it works */
720                 param = (unsigned char *)&self->color->r;
721                 break;
722     case 'A':
723                 param = (unsigned char *)&self->color->a;
724                 break;
725         default:
726                 {
727                         char errstr[1024];
728                         sprintf( errstr, "undefined type '%d' in MCol_setAttr",
729                                         (int)((long)type & 0xff));
730                         return EXPP_ReturnIntError( PyExc_RuntimeError, errstr );
731                 }
732         }
733
734         return EXPP_setIValueClamped( value, param, 0, 255, 'b' );
735 }
736
737 /************************************************************************
738  *
739  * Python MCol_Type attributes get/set structure
740  *
741  ************************************************************************/
742
743 static PyGetSetDef BPy_MCol_getseters[] = {
744         {"r",
745          (getter)MCol_getAttr, (setter)MCol_setAttr,
746          "red component",
747          (void *)'R'},
748         {"g",
749          (getter)MCol_getAttr, (setter)MCol_setAttr,
750          "green component",
751          (void *)'G'},
752         {"b",
753          (getter)MCol_getAttr, (setter)MCol_setAttr,
754          "blue component",
755          (void *)'B'},
756         {"a",
757          (getter)MCol_getAttr, (setter)MCol_setAttr,
758          "alpha component",
759          (void *)'A'},
760         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
761 };
762
763 /************************************************************************
764  *
765  * Python MCol_Type methods
766  *
767  ************************************************************************/
768
769 static void MCol_dealloc( BPy_MCol * self )
770 {
771         PyObject_DEL( self );
772 }
773
774 static PyObject *MCol_repr( BPy_MCol * self )
775 {
776         return PyString_FromFormat( "[MCol %d %d %d %d]",
777                         (int)self->color->r, (int)self->color->g, 
778                         (int)self->color->b, (int)self->color->a ); 
779 }
780
781 /************************************************************************
782  *
783  * Python MCol_Type structure definition
784  *
785  ************************************************************************/
786
787 PyTypeObject MCol_Type = {
788         PyObject_HEAD_INIT( NULL )  /* required py macro */
789         0,                          /* ob_size */
790         /*  For printing, in format "<module>.<name>" */
791         "Blender MCol",           /* char *tp_name; */
792         sizeof( BPy_MCol ),       /* int tp_basicsize; */
793         0,                          /* tp_itemsize;  For allocation */
794
795         /* Methods to implement standard operations */
796
797         ( destructor ) MCol_dealloc,/* destructor tp_dealloc; */
798         NULL,                       /* printfunc tp_print; */
799         NULL,                       /* getattrfunc tp_getattr; */
800         NULL,                       /* setattrfunc tp_setattr; */
801         NULL,                       /* cmpfunc tp_compare; */
802         ( reprfunc ) MCol_repr,     /* reprfunc tp_repr; */
803
804         /* Method suites for standard classes */
805
806         NULL,                       /* PyNumberMethods *tp_as_number; */
807         NULL,                                   /* PySequenceMethods *tp_as_sequence; */
808         NULL,                       /* PyMappingMethods *tp_as_mapping; */
809
810         /* More standard operations (here for binary compatibility) */
811
812         NULL,                       /* hashfunc tp_hash; */
813         NULL,                       /* ternaryfunc tp_call; */
814         NULL,                       /* reprfunc tp_str; */
815         NULL,                       /* getattrofunc tp_getattro; */
816         NULL,                       /* setattrofunc tp_setattro; */
817
818         /* Functions to access object as input/output buffer */
819         NULL,                       /* PyBufferProcs *tp_as_buffer; */
820
821   /*** Flags to define presence of optional/expanded features ***/
822         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
823
824         NULL,                       /*  char *tp_doc;  Documentation string */
825   /*** Assigned meaning in release 2.0 ***/
826         /* call function for all accessible objects */
827         NULL,                       /* traverseproc tp_traverse; */
828
829         /* delete references to contained objects */
830         NULL,                       /* inquiry tp_clear; */
831
832   /***  Assigned meaning in release 2.1 ***/
833   /*** rich comparisons ***/
834         NULL,                       /* richcmpfunc tp_richcompare; */
835
836   /***  weak reference enabler ***/
837         0,                          /* long tp_weaklistoffset; */
838
839   /*** Added in release 2.2 ***/
840         /*   Iterators */
841         NULL,                       /* getiterfunc tp_iter; */
842         NULL,                       /* iternextfunc tp_iternext; */
843
844   /*** Attribute descriptor and subclassing stuff ***/
845         NULL,                       /* struct PyMethodDef *tp_methods; */
846         NULL,                       /* struct PyMemberDef *tp_members; */
847         BPy_MCol_getseters,       /* struct PyGetSetDef *tp_getset; */
848         NULL,                       /* struct _typeobject *tp_base; */
849         NULL,                       /* PyObject *tp_dict; */
850         NULL,                       /* descrgetfunc tp_descr_get; */
851         NULL,                       /* descrsetfunc tp_descr_set; */
852         0,                          /* long tp_dictoffset; */
853         NULL,                       /* initproc tp_init; */
854         NULL,                       /* allocfunc tp_alloc; */
855         NULL,                       /* newfunc tp_new; */
856         /*  Low-level free-memory routine */
857         NULL,                       /* freefunc tp_free;  */
858         /* For PyObject_IS_GC */
859         NULL,                       /* inquiry tp_is_gc;  */
860         NULL,                       /* PyObject *tp_bases; */
861         /* method resolution order */
862         NULL,                       /* PyObject *tp_mro;  */
863         NULL,                       /* PyObject *tp_cache; */
864         NULL,                       /* PyObject *tp_subclasses; */
865         NULL,                       /* PyObject *tp_weaklist; */
866         NULL
867 };
868
869 static PyObject *MCol_CreatePyObject( MCol * color )
870 {
871         BPy_MCol *obj = PyObject_NEW( BPy_MCol, &MCol_Type );
872
873         if( !obj )
874                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
875                                 "PyObject_New() failed" );
876
877         obj->color = color;
878         return (PyObject *)obj;
879 }
880
881 /************************************************************************
882  *
883  * BPy_MVert attributes
884  *
885  ************************************************************************/
886
887 static MVert * MVert_get_pointer( BPy_MVert * self )
888 {
889         if( BPy_MVert_Check( self ) ) {
890                 if( self->index >= ((Mesh *)self->data)->totvert )
891                         return (MVert *)EXPP_ReturnPyObjError( PyExc_RuntimeError,
892                                         "MVert is no longer valid" );
893                 return &((Mesh *)self->data)->mvert[self->index];
894         }
895         else
896                 return (MVert *)self->data;
897 }
898
899 /*
900  * get a vertex's coordinate
901  */
902
903 static PyObject *MVert_getCoord( BPy_MVert * self )
904 {
905         MVert *v;
906
907         v = MVert_get_pointer( self );
908         if( !v )
909                 return NULL;
910
911         return newVectorObject( v->co, 3, Py_WRAP );
912 }
913
914 /*
915  * set a vertex's coordinate
916  */
917
918 static int MVert_setCoord( BPy_MVert * self, VectorObject * value )
919 {
920         int i;
921         MVert *v;
922
923         v = MVert_get_pointer( self );
924         if( !v )
925                 return -1;
926
927         if( !VectorObject_Check( value ) || value->size != 3 )
928                 return EXPP_ReturnIntError( PyExc_TypeError,
929                                 "expected vector argument of size 3" );
930
931         for( i=0; i<3 ; ++i)
932                 v->co[i] = value->vec[i];
933
934         return 0;
935 }
936
937 /*
938  * get a vertex's index
939  */
940
941 static PyObject *MVert_getIndex( BPy_MVert * self )
942 {
943         PyObject *attr;
944
945         if( self->index >= ((Mesh *)self->data)->totvert )
946                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
947                                 "MVert is no longer valid" );
948
949         attr = PyInt_FromLong( self->index );
950         if( attr )
951                 return attr;
952
953         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
954                         "PyInt_FromLong() failed" );
955 }
956
957 /*
958  * get a vertex's normal
959  */
960
961 static PyObject *MVert_getNormal( BPy_MVert * self )
962 {
963         float no[3];
964         int i;
965         MVert *v;
966
967         v = MVert_get_pointer( self );
968         if( !v )
969                 return NULL;
970
971         for( i = 0; i < 3; ++i )
972                 no[i] = (float)(v->no[i] / 32767.0);
973         return newVectorObject( no, 3, Py_NEW );
974 }
975
976 /*
977  * get a vertex's select status
978  */
979
980 static PyObject *MVert_getSel( BPy_MVert *self )
981 {
982         MVert *v;
983
984         v = MVert_get_pointer( self );
985         if( !v )
986                 return NULL;
987
988         return EXPP_getBitfield( &v->flag, SELECT, 'b' );
989 }
990
991 /*
992  * set a vertex's select status
993  */
994
995 static int MVert_setSel( BPy_MVert *self, PyObject *value )
996 {
997         MVert *v;
998
999         v = MVert_get_pointer( self );
1000         if( !v )
1001                 return -1;
1002
1003         return EXPP_setBitfield( value, &v->flag, SELECT, 'b' );
1004 }
1005
1006 /*
1007  * get a vertex's UV coordinates
1008  */
1009
1010 static PyObject *MVert_getUVco( BPy_MVert *self )
1011 {
1012         Mesh *me = (Mesh *)self->data;
1013
1014         if( !me->msticky )
1015                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
1016                                 "mesh has no 'sticky' coordinates" );
1017
1018         if( self->index >= ((Mesh *)self->data)->totvert )
1019                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1020                                 "MVert is no longer valid" );
1021
1022         return newVectorObject( me->msticky[self->index].co, 2, Py_WRAP );
1023 }
1024
1025 /*
1026  * set a vertex's UV coordinates
1027  */
1028
1029 static int MVert_setUVco( BPy_MVert *self, PyObject *value )
1030 {
1031         float uvco[3] = {0.0, 0.0};
1032         Mesh *me = (Mesh *)self->data;
1033         struct MSticky *v;
1034         int i;
1035
1036         /* 
1037          * at least for now, don't allow creation of sticky coordinates if they
1038          * don't already exist
1039          */
1040
1041         if( !me->msticky )
1042                 return EXPP_ReturnIntError( PyExc_AttributeError,
1043                                 "mesh has no 'sticky' coordinates" );
1044
1045         if( self->index >= ((Mesh *)self->data)->totvert )
1046                 return EXPP_ReturnIntError( PyExc_RuntimeError,
1047                                 "MVert is no longer valid" );
1048
1049         if( VectorObject_Check( value ) ) {
1050                 VectorObject *vect = (VectorObject *)value;
1051                 if( vect->size != 2 )
1052                         return EXPP_ReturnIntError( PyExc_AttributeError,
1053                                         "expected 2D vector" );
1054                 for( i = 0; i < vect->size; ++i )
1055                         uvco[i] = vect->vec[i];
1056         } else if( !PyArg_ParseTuple( value, "ff",
1057                                 &uvco[0], &uvco[1] ) )
1058                 return EXPP_ReturnIntError( PyExc_TypeError,
1059                                 "expected 2D vector" );
1060
1061         v = &me->msticky[self->index];
1062
1063         for( i = 0; i < 2; ++i )
1064                 v->co[i] = uvco[i];
1065
1066         return 0;
1067 }
1068
1069 /************************************************************************
1070  *
1071  * Python MVert_Type attributes get/set structure
1072  *
1073  ************************************************************************/
1074
1075 static PyGetSetDef BPy_MVert_getseters[] = {
1076         {"co",
1077          (getter)MVert_getCoord, (setter)MVert_setCoord,
1078          "vertex's coordinate",
1079          NULL},
1080         {"index",
1081          (getter)MVert_getIndex, (setter)NULL,
1082          "vertex's index",
1083          NULL},
1084         {"no",
1085          (getter)MVert_getNormal, (setter)NULL,
1086          "vertex's normal",
1087          NULL},
1088         {"sel",
1089          (getter)MVert_getSel, (setter)MVert_setSel,
1090          "vertex's select status",
1091          NULL},
1092         {"uvco",
1093          (getter)MVert_getUVco, (setter)MVert_setUVco,
1094          "vertex's UV coordinates",
1095          NULL},
1096         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
1097 };
1098
1099 static PyGetSetDef BPy_PVert_getseters[] = {
1100         {"co",
1101          (getter)MVert_getCoord, (setter)MVert_setCoord,
1102          "vertex's coordinate",
1103          NULL},
1104         {"no",
1105          (getter)MVert_getNormal, (setter)NULL,
1106          "vertex's normal",
1107          NULL},
1108         {"sel",
1109          (getter)MVert_getSel, (setter)MVert_setSel,
1110          "vertex's select status",
1111          NULL},
1112         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
1113 };
1114
1115 /************************************************************************
1116  *
1117  * Python MVert_Type standard operations
1118  *
1119  ************************************************************************/
1120
1121 static void MVert_dealloc( BPy_MVert * self )
1122 {
1123         if( BPy_PVert_Check( self ) ) /* free memory of thick objects */
1124                 MEM_freeN ( self->data );
1125
1126         PyObject_DEL( self );
1127 }
1128
1129 static int MVert_compare( BPy_MVert * a, BPy_MVert * b )
1130 {
1131         return( a->data == b->data && a->index == b->index ) ? 0 : -1;
1132 }
1133
1134 static PyObject *MVert_repr( BPy_MVert * self )
1135 {
1136         char format[512];
1137         char index[24];
1138         MVert *v;
1139
1140         v = MVert_get_pointer( self );
1141         if( !v )
1142                 return NULL;
1143
1144         if( BPy_MVert_Check( self ) )
1145                 sprintf( index, "%d", self->index );
1146         else
1147                 BLI_strncpy( index, "(None)", 24 );
1148
1149         sprintf( format, "[MVert (%f %f %f) (%f %f %f) %s]",
1150                         v->co[0], v->co[1], v->co[2], (float)(v->no[0] / 32767.0),
1151                         (float)(v->no[1] / 32767.0), (float)(v->no[2] / 32767.0),
1152                         index );
1153
1154         return PyString_FromString( format );
1155 }
1156
1157 static long MVert_hash( BPy_MVert *self )
1158 {
1159         return (long)self->index;
1160 }
1161
1162 /************************************************************************
1163  *
1164  * Python MVert_Type structure definition
1165  *
1166  ************************************************************************/
1167
1168 PyTypeObject MVert_Type = {
1169         PyObject_HEAD_INIT( NULL )  /* required py macro */
1170         0,                          /* ob_size */
1171         /*  For printing, in format "<module>.<name>" */
1172         "Blender MVert",            /* char *tp_name; */
1173         sizeof( BPy_MVert ),        /* int tp_basicsize; */
1174         0,                          /* tp_itemsize;  For allocation */
1175
1176         /* Methods to implement standard operations */
1177
1178         ( destructor ) MVert_dealloc,/* destructor tp_dealloc; */
1179         NULL,                       /* printfunc tp_print; */
1180         NULL,                       /* getattrfunc tp_getattr; */
1181         NULL,                       /* setattrfunc tp_setattr; */
1182         ( cmpfunc ) MVert_compare,  /* cmpfunc tp_compare; */
1183         ( reprfunc ) MVert_repr,    /* reprfunc tp_repr; */
1184
1185         /* Method suites for standard classes */
1186
1187         NULL,                       /* PyNumberMethods *tp_as_number; */
1188         NULL,                                   /* PySequenceMethods *tp_as_sequence; */
1189         NULL,                       /* PyMappingMethods *tp_as_mapping; */
1190
1191         /* More standard operations (here for binary compatibility) */
1192
1193         ( hashfunc ) MVert_hash,    /* hashfunc tp_hash; */
1194         NULL,                       /* ternaryfunc tp_call; */
1195         NULL,                       /* reprfunc tp_str; */
1196         NULL,                       /* getattrofunc tp_getattro; */
1197         NULL,                       /* setattrofunc tp_setattro; */
1198
1199         /* Functions to access object as input/output buffer */
1200         NULL,                       /* PyBufferProcs *tp_as_buffer; */
1201
1202   /*** Flags to define presence of optional/expanded features ***/
1203         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
1204
1205         NULL,                       /*  char *tp_doc;  Documentation string */
1206   /*** Assigned meaning in release 2.0 ***/
1207         /* call function for all accessible objects */
1208         NULL,                       /* traverseproc tp_traverse; */
1209
1210         /* delete references to contained objects */
1211         NULL,                       /* inquiry tp_clear; */
1212
1213   /***  Assigned meaning in release 2.1 ***/
1214   /*** rich comparisons ***/
1215         NULL,                       /* richcmpfunc tp_richcompare; */
1216
1217   /***  weak reference enabler ***/
1218         0,                          /* long tp_weaklistoffset; */
1219
1220   /*** Added in release 2.2 ***/
1221         /*   Iterators */
1222         NULL,                       /* getiterfunc tp_iter; */
1223         NULL,                       /* iternextfunc tp_iternext; */
1224
1225   /*** Attribute descriptor and subclassing stuff ***/
1226         NULL,                       /* struct PyMethodDef *tp_methods; */
1227         NULL,                       /* struct PyMemberDef *tp_members; */
1228         BPy_MVert_getseters,        /* struct PyGetSetDef *tp_getset; */
1229         NULL,                       /* struct _typeobject *tp_base; */
1230         NULL,                       /* PyObject *tp_dict; */
1231         NULL,                       /* descrgetfunc tp_descr_get; */
1232         NULL,                       /* descrsetfunc tp_descr_set; */
1233         0,                          /* long tp_dictoffset; */
1234         NULL,                       /* initproc tp_init; */
1235         NULL,                       /* allocfunc tp_alloc; */
1236         NULL,                       /* newfunc tp_new; */
1237         /*  Low-level free-memory routine */
1238         NULL,                       /* freefunc tp_free;  */
1239         /* For PyObject_IS_GC */
1240         NULL,                       /* inquiry tp_is_gc;  */
1241         NULL,                       /* PyObject *tp_bases; */
1242         /* method resolution order */
1243         NULL,                       /* PyObject *tp_mro;  */
1244         NULL,                       /* PyObject *tp_cache; */
1245         NULL,                       /* PyObject *tp_subclasses; */
1246         NULL,                       /* PyObject *tp_weaklist; */
1247         NULL
1248 };
1249
1250 /************************************************************************
1251  *
1252  * Python PVert_Type standard operations
1253  *
1254  ************************************************************************/
1255
1256 static int PVert_compare( BPy_MVert * a, BPy_MVert * b )
1257 {
1258         return( a->data == b->data ) ? 0 : -1;
1259 }
1260
1261 /************************************************************************
1262  *
1263  * Python PVert_Type structure definition
1264  *
1265  ************************************************************************/
1266
1267 PyTypeObject PVert_Type = {
1268         PyObject_HEAD_INIT( NULL )  /* required py macro */
1269         0,                          /* ob_size */
1270         /*  For printing, in format "<module>.<name>" */
1271         "Blender PVert",            /* char *tp_name; */
1272         sizeof( BPy_MVert ),        /* int tp_basicsize; */
1273         0,                          /* tp_itemsize;  For allocation */
1274
1275         /* Methods to implement standard operations */
1276
1277         ( destructor ) MVert_dealloc,/* destructor tp_dealloc; */
1278         NULL,                       /* printfunc tp_print; */
1279         NULL,                       /* getattrfunc tp_getattr; */
1280         NULL,                       /* setattrfunc tp_setattr; */
1281         ( cmpfunc ) PVert_compare,  /* cmpfunc tp_compare; */
1282         ( reprfunc ) MVert_repr,    /* reprfunc tp_repr; */
1283
1284         /* Method suites for standard classes */
1285
1286         NULL,                       /* PyNumberMethods *tp_as_number; */
1287         NULL,                                   /* PySequenceMethods *tp_as_sequence; */
1288         NULL,                       /* PyMappingMethods *tp_as_mapping; */
1289
1290         /* More standard operations (here for binary compatibility) */
1291
1292         ( hashfunc ) MVert_hash,    /* hashfunc tp_hash; */
1293         NULL,                       /* ternaryfunc tp_call; */
1294         NULL,                       /* reprfunc tp_str; */
1295         NULL,                       /* getattrofunc tp_getattro; */
1296         NULL,                       /* setattrofunc tp_setattro; */
1297
1298         /* Functions to access object as input/output buffer */
1299         NULL,                       /* PyBufferProcs *tp_as_buffer; */
1300
1301   /*** Flags to define presence of optional/expanded features ***/
1302         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
1303
1304         NULL,                       /*  char *tp_doc;  Documentation string */
1305   /*** Assigned meaning in release 2.0 ***/
1306         /* call function for all accessible objects */
1307         NULL,                       /* traverseproc tp_traverse; */
1308
1309         /* delete references to contained objects */
1310         NULL,                       /* inquiry tp_clear; */
1311
1312   /***  Assigned meaning in release 2.1 ***/
1313   /*** rich comparisons ***/
1314         NULL,                       /* richcmpfunc tp_richcompare; */
1315
1316   /***  weak reference enabler ***/
1317         0,                          /* long tp_weaklistoffset; */
1318
1319   /*** Added in release 2.2 ***/
1320         /*   Iterators */
1321         NULL,                       /* getiterfunc tp_iter; */
1322         NULL,                       /* iternextfunc tp_iternext; */
1323
1324   /*** Attribute descriptor and subclassing stuff ***/
1325         NULL,                       /* struct PyMethodDef *tp_methods; */
1326         NULL,                       /* struct PyMemberDef *tp_members; */
1327         BPy_PVert_getseters,        /* struct PyGetSetDef *tp_getset; */
1328         NULL,                       /* struct _typeobject *tp_base; */
1329         NULL,                       /* PyObject *tp_dict; */
1330         NULL,                       /* descrgetfunc tp_descr_get; */
1331         NULL,                       /* descrsetfunc tp_descr_set; */
1332         0,                          /* long tp_dictoffset; */
1333         NULL,                       /* initproc tp_init; */
1334         NULL,                       /* allocfunc tp_alloc; */
1335         NULL,                       /* newfunc tp_new; */
1336         /*  Low-level free-memory routine */
1337         NULL,                       /* freefunc tp_free;  */
1338         /* For PyObject_IS_GC */
1339         NULL,                       /* inquiry tp_is_gc;  */
1340         NULL,                       /* PyObject *tp_bases; */
1341         /* method resolution order */
1342         NULL,                       /* PyObject *tp_mro;  */
1343         NULL,                       /* PyObject *tp_cache; */
1344         NULL,                       /* PyObject *tp_subclasses; */
1345         NULL,                       /* PyObject *tp_weaklist; */
1346         NULL
1347 };
1348
1349 /*
1350  * create 'thin' or 'thick' MVert objects
1351  *
1352  * there are two types of objects; thin (wrappers for mesh vertex) and thick
1353  * (not contains in mesh).  Thin objects are MVert_Type and thick are
1354  * PVert_Type.  For thin objects, data is a pointer to a Mesh and index
1355  * is the vertex's index in mesh->mvert.  For thick objects, data is a
1356  * pointer to an MVert; index is unused.
1357  */
1358
1359 /*
1360  * create a thin MVert object
1361  */
1362
1363 static PyObject *MVert_CreatePyObject( Mesh *mesh, int i )
1364 {
1365         BPy_MVert *obj = (BPy_MVert *)PyObject_NEW( BPy_MVert, &MVert_Type );
1366
1367         if( !obj )
1368                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1369                                 "PyObject_New() failed" );
1370
1371         obj->index = i;
1372         obj->data = mesh;
1373         return (PyObject *)obj;
1374 }
1375
1376 /*
1377  * create a thick MVert object
1378  */
1379
1380 static PyObject *PVert_CreatePyObject( MVert *vert )
1381 {
1382         MVert *newvert;
1383         BPy_MVert *obj = (BPy_MVert *)PyObject_NEW( BPy_MVert, &PVert_Type );
1384
1385         if( !obj )
1386                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1387                                 "PyObject_New() failed" );
1388
1389         newvert = (MVert *)MEM_callocN( sizeof( MVert ), "MVert" );
1390         if( !newvert )
1391                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1392                                 "MEM_callocN() failed" );
1393
1394         memcpy( newvert, vert, sizeof( MVert ) );
1395         obj->data = newvert;
1396         return (PyObject *)obj;
1397 }
1398
1399 /************************************************************************
1400  *
1401  * Vertex sequence 
1402  *
1403  ************************************************************************/
1404
1405 static int MVertSeq_len( BPy_MVertSeq * self )
1406 {
1407         return self->mesh->totvert;
1408 }
1409
1410 /*
1411  * retrive a single MVert from somewhere in the vertex list
1412  */
1413
1414 static PyObject *MVertSeq_item( BPy_MVertSeq * self, int i )
1415 {
1416         if( i < 0 || i >= self->mesh->totvert )
1417                 return EXPP_ReturnPyObjError( PyExc_IndexError,
1418                                               "array index out of range" );
1419
1420         return MVert_CreatePyObject( self->mesh, i );
1421 }
1422
1423 /*
1424  * retrieve a slice of the vertex list (as a Python list)
1425  *
1426  * Python is nice enough to handle negative indices for us: if the user
1427  * specifies -1, Python will pass us len()-1.  So we can just check for
1428  * indices in the range 0:len()-1.  Of course, we should never actually
1429  * return the high index, but up to one less.
1430  */
1431
1432 static PyObject *MVertSeq_slice( BPy_MVertSeq *self, int low, int high )
1433 {
1434         PyObject *list;
1435         int i;
1436
1437         /*
1438          * Python list slice operator returns empty list when asked for a slice
1439          * outside the list, or if indices are reversed (low > high).  Clamp
1440          * our input to do the same.
1441          */
1442
1443         if( low < 0 ) low = 0;
1444         if( high > self->mesh->totvert ) high = self->mesh->totvert;
1445         if( low > high ) low = high;
1446
1447         list = PyList_New( high-low );
1448         if( !list )
1449                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1450                                               "PyList_New() failed" );
1451
1452         /*
1453          * return Py_NEW copies of requested vertices
1454          */
1455
1456         for( i = low; i < high; ++i )
1457                 PyList_SET_ITEM( list, i-low,
1458                                 PVert_CreatePyObject( (void *)&self->mesh->mvert[i] ) );
1459         return list;
1460 }
1461
1462 /*
1463  * assign a single MVert to somewhere in the vertex list
1464  */
1465
1466 static int MVertSeq_assign_item( BPy_MVertSeq * self, int i,
1467                 BPy_MVert *v )
1468 {
1469         MVert *dst = &self->mesh->mvert[i];
1470         MVert *src;
1471
1472         if( !v )
1473                 return EXPP_ReturnIntError( PyExc_IndexError,
1474                                               "del() not supported" );
1475
1476         if( i < 0 || i >= self->mesh->totvert )
1477                 return EXPP_ReturnIntError( PyExc_IndexError,
1478                                               "array index out of range" );
1479
1480         if( BPy_MVert_Check( v ) )
1481                 src = &((Mesh *)v->data)->mvert[v->index];
1482         else
1483                 src = (MVert *)v->data;
1484
1485         memcpy( dst, src, sizeof(MVert) );
1486         // mesh_update( self->mesh );
1487         return 0;
1488 }
1489
1490 static int MVertSeq_assign_slice( BPy_MVertSeq *self, int low, int high,
1491                    PyObject *args )
1492 {
1493         int len, i;
1494
1495         if( !PyList_Check( args ) )
1496                 return EXPP_ReturnIntError( PyExc_IndexError,
1497                                               "can only assign lists of MVerts" );
1498
1499         len = PyList_Size( args );
1500
1501         /*
1502          * Python list slice assign operator allows for changing the size of the
1503          * destination list, by replacement and appending....
1504          *
1505          * >>> l=[1,2,3,4]
1506          * >>> m=[11,12,13,14]
1507          * >>> l[5:7]=m
1508          * >>> print l
1509          * [1, 2, 3, 4, 11, 12, 13, 14]
1510          * >>> l=[1,2,3,4]
1511          * >>> l[2:3]=m
1512          * >>> print l
1513          * [1, 2, 11, 12, 13, 14, 4]
1514          *
1515          * We don't want the size of the list to change (at least not at time
1516          * point in development) so we are a little more strict:
1517          * - low and high indices must be in range [0:len()]
1518          * - high-low == PyList_Size(v)
1519          */
1520
1521         if( low < 0 || high > self->mesh->totvert || low > high )
1522                 return EXPP_ReturnIntError( PyExc_IndexError,
1523                                               "invalid slice range" );
1524
1525         if( high-low != len )
1526                 return EXPP_ReturnIntError( PyExc_IndexError,
1527                                               "slice range and input list sizes must be equal" );
1528
1529         for( i = low; i < high; ++i )
1530         {
1531                 BPy_MVert *v = (BPy_MVert *)PyList_GET_ITEM( args, i-low );
1532                 MVert *dst = &self->mesh->mvert[i];
1533                 MVert *src;
1534
1535                 if( BPy_MVert_Check( v ) )
1536                         src = &((Mesh *)v->data)->mvert[v->index];
1537                 else
1538                         src = (MVert *)v->data;
1539
1540                 memcpy( dst, src, sizeof(MVert) );
1541         }
1542         // mesh_update( self->mesh );
1543         return 0;
1544 }
1545
1546 static PySequenceMethods MVertSeq_as_sequence = {
1547         ( inquiry ) MVertSeq_len,       /* sq_length */
1548         ( binaryfunc ) 0,       /* sq_concat */
1549         ( intargfunc ) 0,       /* sq_repeat */
1550         ( intargfunc ) MVertSeq_item,   /* sq_item */
1551         ( intintargfunc ) MVertSeq_slice,       /* sq_slice */
1552         ( intobjargproc ) MVertSeq_assign_item, /* sq_ass_item */
1553         ( intintobjargproc ) MVertSeq_assign_slice,     /* sq_ass_slice */
1554         0,0,0,
1555 };
1556
1557 /************************************************************************
1558  *
1559  * Python MVertSeq_Type iterator (iterates over vertices)
1560  *
1561  ************************************************************************/
1562
1563 /*
1564  * Initialize the interator index
1565  */
1566
1567 static PyObject *MVertSeq_getIter( BPy_MVertSeq * self )
1568 {
1569         self->iter = 0;
1570         return EXPP_incr_ret ( (PyObject *) self );
1571 }
1572
1573 /*
1574  * Return next MVert.
1575  */
1576
1577 static PyObject *MVertSeq_nextIter( BPy_MVertSeq * self )
1578 {
1579         if( self->iter == self->mesh->totvert )
1580                 return EXPP_ReturnPyObjError( PyExc_StopIteration,
1581                                 "iterator at end" );
1582
1583         return MVert_CreatePyObject( self->mesh, self->iter++ );
1584 }
1585
1586 /************************************************************************
1587  *
1588  * Python MVertSeq_Type methods
1589  *
1590  ************************************************************************/
1591
1592 static PyObject *MVertSeq_extend( BPy_MVertSeq * self, PyObject *args )
1593 {
1594         int len, newlen;
1595         int i,j;
1596         PyObject *tmp;
1597         MVert *newvert, *tmpvert;
1598         Mesh *mesh = self->mesh;
1599         /* make sure we get a sequence of tuples of something */
1600
1601         switch( PySequence_Size( args ) ) {
1602         case 1:         /* better be a list or a tuple */
1603                 tmp = PyTuple_GET_ITEM( args, 0 );
1604                 if( !VectorObject_Check ( tmp ) ) {
1605                         if( !PySequence_Check ( tmp ) )
1606                                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1607                                                 "expected a sequence of sequence triplets" );
1608                         args = tmp;
1609                 }
1610                 Py_INCREF( args );              /* so we can safely DECREF later */
1611                 break;
1612         case 3:
1613                 tmp = PyTuple_GET_ITEM( args, 0 );
1614                 /* if first item is not a number, it's wrong */
1615                 if( !PyNumber_Check( tmp ) )
1616                         return EXPP_ReturnPyObjError( PyExc_TypeError,
1617                                         "expected a sequence of sequence triplets" );
1618
1619                 /* otherwise, put into a new tuple */
1620                 args = Py_BuildValue( "((OOO))", tmp,
1621                                 PyTuple_GET_ITEM( args, 1 ), PyTuple_GET_ITEM( args, 2 ) );
1622                 if( !args )
1623                         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1624                                         "Py_BuildValue() failed" );
1625                 break;
1626
1627         default:        /* anything else is definitely wrong */
1628                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1629                                 "expected a sequence of sequence triplets" );
1630         }
1631
1632         /* if no verts given, return quietly */
1633         len = PySequence_Size( args );
1634         if( len == 0 ) {
1635                 Py_DECREF ( args );
1636                 Py_RETURN_NONE;
1637         }
1638
1639         newlen = mesh->totvert + len;
1640         newvert = MEM_callocN( sizeof( MVert )*newlen, "MVerts" );
1641
1642         /* scan the input list and insert the new vertices */
1643
1644         tmpvert = &newvert[mesh->totvert];
1645         for( i = 0; i < len; ++i ) {
1646                 float co[3];
1647                 tmp = PySequence_GetItem( args, i );
1648                 if( VectorObject_Check( tmp ) ) {
1649                         if( ((VectorObject *)tmp)->size != 3 ) {
1650                                 MEM_freeN( newvert );
1651                                 Py_DECREF ( tmp );
1652                                 Py_DECREF ( args );
1653                                 return EXPP_ReturnPyObjError( PyExc_ValueError,
1654                                         "expected vector of size 3" );
1655                         }
1656                         for( j = 0; j < 3; ++j )
1657                                 co[j] = ((VectorObject *)tmp)->vec[j];
1658                 } else if( PySequence_Check( tmp ) ) {
1659                         int ok=1;
1660                         PyObject *flt;
1661                         if( PySequence_Size( tmp ) != 3 )
1662                                 ok = 0;
1663                         else    
1664                                 for( j = 0; ok && j < 3; ++j ) {
1665                                         flt = PySequence_ITEM( tmp, j );
1666                                         if( !PyNumber_Check ( flt ) )
1667                                                 ok = 0;
1668                                         else
1669                                                 co[j] = (float)PyFloat_AsDouble( flt );
1670                                         Py_DECREF( flt );
1671                                 }
1672
1673                         if( !ok ) {
1674                                 MEM_freeN( newvert );
1675                                 Py_DECREF ( args );
1676                                 Py_DECREF ( tmp );
1677                                 return EXPP_ReturnPyObjError( PyExc_ValueError,
1678                                         "expected sequence triplet of floats" );
1679                         }
1680                 } else {
1681                         MEM_freeN( newvert );
1682                         Py_DECREF ( args );
1683                         Py_DECREF ( tmp );
1684                         return EXPP_ReturnPyObjError( PyExc_ValueError,
1685                                 "expected sequence triplet of floats" );
1686                 }
1687
1688                 Py_DECREF ( tmp );
1689
1690         /* add the coordinate to the new list */
1691                 memcpy( tmpvert->co, co, sizeof(co) );
1692
1693         /* TODO: anything else which needs to be done when we add a vert? */
1694         /* probably not: NMesh's newvert() doesn't */
1695                 ++tmpvert;
1696         }
1697
1698         /*
1699          * if we got here we've added all the new verts, so just copy the old
1700          * verts over and we're done
1701          */
1702
1703         if( mesh->mvert ) {
1704                 memcpy( newvert, mesh->mvert, mesh->totvert*sizeof(MVert) );
1705                 MEM_freeN( mesh->mvert );
1706         }
1707         mesh->mvert = newvert;
1708
1709         /*
1710          * maybe not quite done; if there are keys, have to fix those lists up
1711          */
1712
1713         if( mesh->key ) {
1714                 KeyBlock *currkey = mesh->key->block.first;
1715                 float *fp, *newkey;
1716
1717                 while( currkey ) {
1718
1719                         /* create key list, copy existing data if any */
1720                         newkey = MEM_callocN(mesh->key->elemsize*newlen, "keydata");
1721                         if( currkey->data ) {
1722                                 memcpy( newkey, currkey->data,
1723                                                 mesh->totvert*mesh->key->elemsize );
1724                                 MEM_freeN( currkey->data );
1725                                 currkey->data = newkey;
1726                         }
1727
1728                         /* add data for new vertices */
1729                         fp = (float *)((char *)currkey->data +
1730                                         (mesh->key->elemsize*mesh->totvert));
1731                         tmpvert = mesh->mvert + mesh->totvert;
1732                         for( i = newlen - mesh->totvert; i > 0; --i ) {
1733                                 VECCOPY(fp, tmpvert->co);
1734                                 fp += 3;
1735                                 tmpvert++;
1736                         }
1737                         currkey->totelem = newlen;
1738                         currkey = currkey->next;
1739                 }
1740         }
1741
1742         /*
1743          * if there are vertex groups, also have to fix them
1744          */
1745
1746         if( mesh->dvert ) {
1747                 MDeformVert *newdvert;
1748                 newdvert = MEM_callocN( sizeof(MDeformVert)*newlen , "mesh defVert" );
1749                 memcpy( newdvert, mesh->dvert, sizeof(MDeformVert)*mesh->totvert );
1750                 MEM_freeN( mesh->dvert );
1751                 mesh->dvert = newdvert;
1752         }
1753
1754         /* set final vertex list size */
1755         mesh->totvert = newlen;
1756
1757         mesh_update( mesh );
1758
1759         Py_DECREF ( args );
1760         Py_RETURN_NONE;
1761 }
1762
1763 static PyObject *MVertSeq_delete( BPy_MVertSeq * self, PyObject *args )
1764 {
1765         unsigned int *vert_table;
1766         int vert_delete, face_count;
1767         int i;
1768         Mesh *mesh = self->mesh;
1769         MFace *tmpface;
1770
1771         /*
1772          * if input tuple contains a single sequence, use it as input instead;
1773          * otherwise use the sequence as-is and check later that it contains
1774          * one or more integers or MVerts
1775          */
1776         if( PySequence_Size( args ) == 1 ) {
1777                 PyObject *tmp = PyTuple_GET_ITEM( args, 0 );
1778                 if( PySequence_Check( tmp ) ) 
1779                         args = tmp;
1780         }
1781
1782         /* if sequence is empty, do nothing */
1783         if( PySequence_Size( args ) == 0 ) {
1784                 Py_RETURN_NONE;
1785         }
1786
1787         /* allocate vertex lookup table */
1788         vert_table = (unsigned int *)MEM_callocN( 
1789                         mesh->totvert*sizeof( unsigned int ), "vert_table" );
1790
1791         /* get the indices of vertices to be removed */
1792         for( i = PySequence_Size( args ); i--; ) {
1793                 PyObject *tmp = PySequence_GetItem( args, i );
1794                 int index;
1795                 if( BPy_MVert_Check( tmp ) ) {
1796                         if( (void *)self->mesh != ((BPy_MVert*)tmp)->data ) {
1797                                 MEM_freeN( vert_table );
1798                                 Py_DECREF( tmp );
1799                                 return EXPP_ReturnPyObjError( PyExc_ValueError,
1800                                                 "MVert belongs to a different mesh" );
1801                         }
1802                         index = ((BPy_MVert*)tmp)->index;
1803                 } else if( PyInt_CheckExact( tmp ) ) {
1804                         index = PyInt_AsLong ( tmp );
1805                 } else {
1806                         MEM_freeN( vert_table );
1807                         Py_DECREF( tmp );
1808                         return EXPP_ReturnPyObjError( PyExc_TypeError,
1809                                         "expected a sequence of ints or MVerts" );
1810                 }
1811                 Py_DECREF( tmp );
1812                 if( index < 0 || index >= mesh->totvert ) {
1813                         MEM_freeN( vert_table );
1814                         return EXPP_ReturnPyObjError( PyExc_IndexError,
1815                                         "array index out of range" );
1816                 }
1817                 vert_table[index] = UINT_MAX;
1818         }
1819
1820         /* delete things, then clean up and return */
1821
1822         vert_delete = make_vertex_table( vert_table, mesh->totvert );
1823         if( vert_delete )
1824                 delete_verts( mesh, vert_table, vert_delete );
1825
1826         /* calculate edges to delete, fix vertex indices */
1827         delete_edges( mesh, vert_table, 0 );
1828
1829         /*
1830          * find number of faces which contain any of the deleted vertices,
1831          * and mark them, then delete them
1832          */
1833         tmpface = mesh->mface;
1834         face_count=0;
1835         for( i = mesh->totface; i--; ++tmpface ) {
1836                 if( vert_table[tmpface->v1] == UINT_MAX ||
1837                                 vert_table[tmpface->v2] == UINT_MAX ||
1838                                 vert_table[tmpface->v3] == UINT_MAX ||
1839                                 vert_table[tmpface->v4] == UINT_MAX ) {
1840                         tmpface->v1 = UINT_MAX;
1841                         ++face_count;
1842                 }
1843         }
1844         delete_faces( mesh, vert_table, face_count );
1845
1846         /* clean up and exit */
1847         MEM_freeN( vert_table );
1848         mesh_update ( mesh );
1849         Py_RETURN_NONE;
1850 }
1851
1852 static PyObject *MVertSeq_selected( BPy_MVertSeq * self )
1853 {
1854         int i, count;
1855         Mesh *mesh = self->mesh;
1856         MVert *tmpvert;
1857         PyObject *list;
1858
1859         /* first count selected edges (quicker than appending to PyList?) */
1860         count = 0;
1861         tmpvert = mesh->mvert;
1862         for( i = 0; i < mesh->totvert; ++i, ++tmpvert )
1863                 if( tmpvert->flag & SELECT )
1864                         ++count;
1865
1866         list = PyList_New( count );
1867         if( !list )
1868                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1869                                 "PyList_New() failed" );
1870
1871         /* next, insert selected edges into list */
1872         count = 0;
1873         tmpvert = mesh->mvert;
1874         for( i = 0; i < mesh->totvert; ++i, ++tmpvert ) {
1875                 if( tmpvert->flag & SELECT ) {
1876                         PyObject *tmp = PyInt_FromLong( i );
1877                         if( !tmp ) {
1878                                 Py_DECREF( list );
1879                                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1880                                                 "PyInt_FromLong() failed" );
1881                         }
1882                         PyList_SET_ITEM( list, count, tmp );
1883                         ++count;
1884                 }
1885         }
1886         return list;
1887 }
1888
1889 static struct PyMethodDef BPy_MVertSeq_methods[] = {
1890         {"extend", (PyCFunction)MVertSeq_extend, METH_VARARGS,
1891                 "add vertices to mesh"},
1892         {"delete", (PyCFunction)MVertSeq_delete, METH_VARARGS,
1893                 "delete vertices from mesh"},
1894         {"selected", (PyCFunction)MVertSeq_selected, METH_NOARGS,
1895                 "returns a list containing indices of selected vertices"},
1896         {NULL, NULL, 0, NULL}
1897 };
1898
1899 /************************************************************************
1900  *
1901  * Python MVertSeq_Type standard operations
1902  *
1903  ************************************************************************/
1904
1905 static void MVertSeq_dealloc( BPy_MVertSeq * self )
1906 {
1907         PyObject_DEL( self );
1908 }
1909
1910 /*****************************************************************************/
1911 /* Python MVertSeq_Type structure definition:                               */
1912 /*****************************************************************************/
1913 PyTypeObject MVertSeq_Type = {
1914         PyObject_HEAD_INIT( NULL )  /* required py macro */
1915         0,                          /* ob_size */
1916         /*  For printing, in format "<module>.<name>" */
1917         "Blender MVertSeq",           /* char *tp_name; */
1918         sizeof( BPy_MVertSeq ),       /* int tp_basicsize; */
1919         0,                          /* tp_itemsize;  For allocation */
1920
1921         /* Methods to implement standard operations */
1922
1923         ( destructor ) MVertSeq_dealloc,/* destructor tp_dealloc; */
1924         NULL,                       /* printfunc tp_print; */
1925         NULL,                       /* getattrfunc tp_getattr; */
1926         NULL,                       /* setattrfunc tp_setattr; */
1927         NULL,                       /* cmpfunc tp_compare; */
1928         NULL,                       /* reprfunc tp_repr; */
1929
1930         /* Method suites for standard classes */
1931
1932         NULL,                       /* PyNumberMethods *tp_as_number; */
1933         &MVertSeq_as_sequence,      /* PySequenceMethods *tp_as_sequence; */
1934         NULL,                       /* PyMappingMethods *tp_as_mapping; */
1935
1936         /* More standard operations (here for binary compatibility) */
1937
1938         NULL,                       /* hashfunc tp_hash; */
1939         NULL,                       /* ternaryfunc tp_call; */
1940         NULL,                       /* reprfunc tp_str; */
1941         NULL,                       /* getattrofunc tp_getattro; */
1942         NULL,                       /* setattrofunc tp_setattro; */
1943
1944         /* Functions to access object as input/output buffer */
1945         NULL,                       /* PyBufferProcs *tp_as_buffer; */
1946
1947   /*** Flags to define presence of optional/expanded features ***/
1948         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
1949
1950         NULL,                       /*  char *tp_doc;  Documentation string */
1951   /*** Assigned meaning in release 2.0 ***/
1952         /* call function for all accessible objects */
1953         NULL,                       /* traverseproc tp_traverse; */
1954
1955         /* delete references to contained objects */
1956         NULL,                       /* inquiry tp_clear; */
1957
1958   /***  Assigned meaning in release 2.1 ***/
1959   /*** rich comparisons ***/
1960         NULL,                       /* richcmpfunc tp_richcompare; */
1961
1962   /***  weak reference enabler ***/
1963         0,                          /* long tp_weaklistoffset; */
1964
1965   /*** Added in release 2.2 ***/
1966         /*   Iterators */
1967         ( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
1968         ( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
1969
1970   /*** Attribute descriptor and subclassing stuff ***/
1971         BPy_MVertSeq_methods,       /* struct PyMethodDef *tp_methods; */
1972         NULL,                       /* struct PyMemberDef *tp_members; */
1973         NULL,                       /* struct PyGetSetDef *tp_getset; */
1974         NULL,                       /* struct _typeobject *tp_base; */
1975         NULL,                       /* PyObject *tp_dict; */
1976         NULL,                       /* descrgetfunc tp_descr_get; */
1977         NULL,                       /* descrsetfunc tp_descr_set; */
1978         0,                          /* long tp_dictoffset; */
1979         NULL,                       /* initproc tp_init; */
1980         NULL,                       /* allocfunc tp_alloc; */
1981         NULL,                       /* newfunc tp_new; */
1982         /*  Low-level free-memory routine */
1983         NULL,                       /* freefunc tp_free;  */
1984         /* For PyObject_IS_GC */
1985         NULL,                       /* inquiry tp_is_gc;  */
1986         NULL,                       /* PyObject *tp_bases; */
1987         /* method resolution order */
1988         NULL,                       /* PyObject *tp_mro;  */
1989         NULL,                       /* PyObject *tp_cache; */
1990         NULL,                       /* PyObject *tp_subclasses; */
1991         NULL,                       /* PyObject *tp_weaklist; */
1992         NULL
1993 };
1994
1995 /************************************************************************
1996  *
1997  * Edge attributes
1998  *
1999  ************************************************************************/
2000
2001 static MEdge * MEdge_get_pointer( BPy_MEdge * self )
2002 {
2003         if( self->index >= self->mesh->totedge )
2004                 return (MEdge *)EXPP_ReturnPyObjError( PyExc_RuntimeError,
2005                                 "MEdge is no longer valid" );
2006         return &self->mesh->medge[self->index];
2007 }
2008
2009 /*
2010  * get an edge's crease value
2011  */
2012
2013 static PyObject *MEdge_getCrease( BPy_MEdge * self )
2014 {
2015         PyObject *attr;
2016         MEdge *edge = MEdge_get_pointer( self );
2017
2018         if( !edge )
2019                 return NULL;
2020
2021         attr = PyInt_FromLong( edge->crease );
2022         if( attr )
2023                 return attr;
2024
2025         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2026                         "PyInt_FromLong() failed" );
2027 }
2028
2029 /*
2030  * set an edge's crease value
2031  */
2032
2033 static int MEdge_setCrease( BPy_MEdge * self, PyObject * value )
2034 {
2035         MEdge *edge = MEdge_get_pointer( self );
2036
2037         if( !edge )
2038                 return -1;
2039
2040         return EXPP_setIValueClamped( value, &edge->crease, 0, 255, 'b' );
2041 }
2042
2043 /*
2044  * get an edge's flag
2045  */
2046
2047 static PyObject *MEdge_getFlag( BPy_MEdge * self )
2048 {
2049         PyObject *attr;
2050         MEdge *edge = MEdge_get_pointer( self );
2051
2052         if( !edge )
2053                 return NULL;
2054
2055         attr = PyInt_FromLong( edge->flag );
2056
2057         if( attr )
2058                 return attr;
2059
2060         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2061                         "PyInt_FromLong() failed" );
2062 }
2063
2064 /*
2065  * set an edge's flag
2066  */
2067
2068 static int MEdge_setFlag( BPy_MEdge * self, PyObject * value )
2069 {
2070         short param;
2071         static short bitmask = 1                /* 1=select */
2072                                 | ME_EDGEDRAW
2073                                 | ME_EDGERENDER
2074                                 | ME_SEAM
2075                                 | ME_FGON;
2076         MEdge *edge = MEdge_get_pointer( self );
2077
2078         if( !edge )
2079                 return -1;
2080
2081         if( !PyInt_CheckExact ( value ) ) {
2082                 char errstr[128];
2083                 sprintf ( errstr , "expected int bitmask of 0x%04x", bitmask );
2084                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
2085         }
2086         param = (short)PyInt_AS_LONG ( value );
2087
2088         if ( ( param & bitmask ) != param )
2089                 return EXPP_ReturnIntError( PyExc_ValueError,
2090                                                 "invalid bit(s) set in mask" );
2091
2092         edge->flag = param;
2093
2094         return 0;
2095 }
2096
2097 /*
2098  * get an edge's first vertex
2099  */
2100
2101 static PyObject *MEdge_getV1( BPy_MEdge * self )
2102 {
2103         MEdge *edge = MEdge_get_pointer( self );
2104
2105         if( !edge )
2106                 return NULL;
2107
2108         return MVert_CreatePyObject( self->mesh, edge->v1 );
2109 }
2110
2111 /*
2112  * set an edge's first vertex
2113  */
2114
2115 static int MEdge_setV1( BPy_MEdge * self, BPy_MVert * value )
2116 {
2117         MEdge *edge = MEdge_get_pointer( self );
2118
2119         if( !edge )
2120                 return -1;
2121         if( !BPy_MVert_Check( value ) )
2122                 return EXPP_ReturnIntError( PyExc_TypeError, "expected an MVert" );
2123
2124         edge->v1 = value->index;
2125         return 0;
2126 }
2127
2128 /*
2129  * get an edge's second vertex
2130  */
2131
2132 static PyObject *MEdge_getV2( BPy_MEdge * self )
2133 {
2134         MEdge *edge = MEdge_get_pointer( self );
2135
2136         if( !edge )
2137                 return NULL;
2138
2139         return MVert_CreatePyObject( self->mesh, edge->v2 );
2140 }
2141
2142 /*
2143  * set an edge's second vertex
2144  */
2145
2146 static int MEdge_setV2( BPy_MEdge * self, BPy_MVert * value )
2147 {
2148         MEdge *edge = MEdge_get_pointer( self );
2149
2150         if( !edge )
2151                 return -1;
2152         if( !BPy_MVert_Check( value ) )
2153                 return EXPP_ReturnIntError( PyExc_TypeError, "expected an MVert" );
2154
2155         edge->v2 = value->index;
2156         return 0;
2157 }
2158
2159 /*
2160  * get an edges's index
2161  */
2162
2163 static PyObject *MEdge_getIndex( BPy_MEdge * self )
2164 {
2165         PyObject *attr;
2166
2167         if( !MEdge_get_pointer( self ) )
2168                 return NULL;
2169
2170         attr = PyInt_FromLong( self->index );
2171
2172         if( attr )
2173                 return attr;
2174
2175         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2176                         "PyInt_FromLong() failed" );
2177 }
2178
2179 /************************************************************************
2180  *
2181  * Python MEdge_Type attributes get/set structure
2182  *
2183  ************************************************************************/
2184
2185 static PyGetSetDef BPy_MEdge_getseters[] = {
2186         {"crease",
2187          (getter)MEdge_getCrease, (setter)MEdge_setCrease,
2188          "edge's crease value",
2189          NULL},
2190         {"flag",
2191          (getter)MEdge_getFlag, (setter)MEdge_setFlag,
2192          "edge's flags",
2193          NULL},
2194         {"v1",
2195          (getter)MEdge_getV1, (setter)MEdge_setV1,
2196          "edge's first vertex",
2197          NULL},
2198         {"v2",
2199          (getter)MEdge_getV2, (setter)MEdge_setV2,
2200          "edge's second vertex",
2201          NULL},
2202         {"index",
2203          (getter)MEdge_getIndex, (setter)NULL,
2204          "edge's index",
2205          NULL},
2206         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
2207 };
2208
2209 /************************************************************************
2210  *
2211  * Python MEdge_Type iterator (iterates over vertices)
2212  *
2213  ************************************************************************/
2214
2215 /*
2216  * Initialize the interator index
2217  */
2218
2219 static PyObject *MEdge_getIter( BPy_MEdge * self )
2220 {
2221         self->iter = 0;
2222         return EXPP_incr_ret ( (PyObject *) self );
2223 }
2224
2225 /*
2226  * Return next MVert.  Throw an exception after the second vertex.
2227  */
2228
2229 static PyObject *MEdge_nextIter( BPy_MEdge * self )
2230 {
2231         if( self->iter == 2 )
2232                 return EXPP_ReturnPyObjError( PyExc_StopIteration,
2233                                 "iterator at end" );
2234
2235         self->iter++;
2236         if( self->iter == 1 )
2237                 return MEdge_getV1( self );
2238         else
2239                 return MEdge_getV2( self );
2240 }
2241
2242 /************************************************************************
2243  *
2244  * Python MEdge_Type standard operations
2245  *
2246  ************************************************************************/
2247
2248 static void MEdge_dealloc( BPy_MEdge * self )
2249 {
2250         PyObject_DEL( self );
2251 }
2252
2253 static int MEdge_compare( BPy_MEdge * a, BPy_MEdge * b )
2254 {
2255         return( a->mesh == b->mesh && a->index == b->index ) ? 0 : -1;
2256 }
2257
2258 static PyObject *MEdge_repr( BPy_MEdge * self )
2259 {
2260         struct MEdge *edge = MEdge_get_pointer( self );
2261
2262         if( !edge )
2263                 return NULL;
2264
2265         return PyString_FromFormat( "[MEdge (%d %d) %d %d]",
2266                         (int)edge->v1, (int)edge->v2, (int)edge->crease,
2267                         (int)self->index );
2268 }
2269
2270 static long MEdge_hash( BPy_MEdge *self )
2271 {
2272         return (long)self->index;
2273 }
2274
2275 /************************************************************************
2276  *
2277  * Python MEdge_Type structure definition
2278  *
2279  ************************************************************************/
2280
2281 PyTypeObject MEdge_Type = {
2282         PyObject_HEAD_INIT( NULL )  /* required py macro */
2283         0,                          /* ob_size */
2284         /*  For printing, in format "<module>.<name>" */
2285         "Blender MEdge",           /* char *tp_name; */
2286         sizeof( BPy_MEdge ),       /* int tp_basicsize; */
2287         0,                          /* tp_itemsize;  For allocation */
2288
2289         /* Methods to implement standard operations */
2290
2291         ( destructor ) MEdge_dealloc,/* destructor tp_dealloc; */
2292         NULL,                       /* printfunc tp_print; */
2293         NULL,                       /* getattrfunc tp_getattr; */
2294         NULL,                       /* setattrfunc tp_setattr; */
2295         ( cmpfunc ) MEdge_compare,  /* cmpfunc tp_compare; */
2296         ( reprfunc ) MEdge_repr,    /* reprfunc tp_repr; */
2297
2298         /* Method suites for standard classes */
2299
2300         NULL,                       /* PyNumberMethods *tp_as_number; */
2301     NULL,                       /* PySequenceMethods *tp_as_sequence; */
2302         NULL,                       /* PyMappingMethods *tp_as_mapping; */
2303
2304         /* More standard operations (here for binary compatibility) */
2305
2306         ( hashfunc ) MEdge_hash,    /* hashfunc tp_hash; */
2307         NULL,                       /* ternaryfunc tp_call; */
2308         NULL,                       /* reprfunc tp_str; */
2309         NULL,                       /* getattrofunc tp_getattro; */
2310         NULL,                       /* setattrofunc tp_setattro; */
2311
2312         /* Functions to access object as input/output buffer */
2313         NULL,                       /* PyBufferProcs *tp_as_buffer; */
2314
2315   /*** Flags to define presence of optional/expanded features ***/
2316         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
2317
2318         NULL,                       /*  char *tp_doc;  Documentation string */
2319   /*** Assigned meaning in release 2.0 ***/
2320         /* call function for all accessible objects */
2321         NULL,                       /* traverseproc tp_traverse; */
2322
2323         /* delete references to contained objects */
2324         NULL,                       /* inquiry tp_clear; */
2325
2326   /***  Assigned meaning in release 2.1 ***/
2327   /*** rich comparisons ***/
2328         NULL,                       /* richcmpfunc tp_richcompare; */
2329
2330   /***  weak reference enabler ***/
2331         0,                          /* long tp_weaklistoffset; */
2332
2333   /*** Added in release 2.2 ***/
2334         /*   Iterators */
2335         ( getiterfunc) MEdge_getIter, /* getiterfunc tp_iter; */
2336         ( iternextfunc ) MEdge_nextIter, /* iternextfunc tp_iternext; */
2337
2338   /*** Attribute descriptor and subclassing stuff ***/
2339         NULL,                       /* struct PyMethodDef *tp_methods; */
2340         NULL,                       /* struct PyMemberDef *tp_members; */
2341         BPy_MEdge_getseters,        /* struct PyGetSetDef *tp_getset; */
2342         NULL,                       /* struct _typeobject *tp_base; */
2343         NULL,                       /* PyObject *tp_dict; */
2344         NULL,                       /* descrgetfunc tp_descr_get; */
2345         NULL,                       /* descrsetfunc tp_descr_set; */
2346         0,                          /* long tp_dictoffset; */
2347         NULL,                       /* initproc tp_init; */
2348         NULL,                       /* allocfunc tp_alloc; */
2349         NULL,                       /* newfunc tp_new; */
2350         /*  Low-level free-memory routine */
2351         NULL,                       /* freefunc tp_free;  */
2352         /* For PyObject_IS_GC */
2353         NULL,                       /* inquiry tp_is_gc;  */
2354         NULL,                       /* PyObject *tp_bases; */
2355         /* method resolution order */
2356         NULL,                       /* PyObject *tp_mro;  */
2357         NULL,                       /* PyObject *tp_cache; */
2358         NULL,                       /* PyObject *tp_subclasses; */
2359         NULL,                       /* PyObject *tp_weaklist; */
2360         NULL
2361 };
2362
2363 static PyObject *MEdge_CreatePyObject( Mesh * mesh, int i )
2364 {
2365         BPy_MEdge *obj = PyObject_NEW( BPy_MEdge, &MEdge_Type );
2366
2367         if( !obj )
2368                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2369                                 "PyObject_New() failed" );
2370
2371         obj->mesh = mesh;
2372         obj->index = i;
2373         return (PyObject *)obj;
2374 }
2375
2376 /************************************************************************
2377  *
2378  * Edge sequence 
2379  *
2380  ************************************************************************/
2381
2382 static int MEdgeSeq_len( BPy_MEdgeSeq * self )
2383 {
2384         return self->mesh->totedge;
2385 }
2386
2387 static PyObject *MEdgeSeq_item( BPy_MEdgeSeq * self, int i )
2388 {
2389         if( i < 0 || i >= self->mesh->totedge )
2390                 return EXPP_ReturnPyObjError( PyExc_IndexError,
2391                                               "array index out of range" );
2392
2393         return MEdge_CreatePyObject( self->mesh, i );
2394 }
2395
2396
2397 static PySequenceMethods MEdgeSeq_as_sequence = {
2398         ( inquiry ) MEdgeSeq_len,       /* sq_length */
2399         ( binaryfunc ) 0,       /* sq_concat */
2400         ( intargfunc ) 0,       /* sq_repeat */
2401         ( intargfunc ) MEdgeSeq_item,   /* sq_item */
2402         ( intintargfunc ) 0,    /* sq_slice */
2403         ( intobjargproc ) 0,    /* sq_ass_item */
2404         ( intintobjargproc ) 0, /* sq_ass_slice */
2405         0,0,0,
2406 };
2407
2408 /************************************************************************
2409  *
2410  * Python MEdgeSeq_Type iterator (iterates over edges)
2411  *
2412  ************************************************************************/
2413
2414 /*
2415  * Initialize the interator index
2416  */
2417
2418 static PyObject *MEdgeSeq_getIter( BPy_MEdgeSeq * self )
2419 {
2420         self->iter = 0;
2421         return EXPP_incr_ret ( (PyObject *) self );
2422 }
2423
2424 /*
2425  * Return next MEdge.
2426  */
2427
2428 static PyObject *MEdgeSeq_nextIter( BPy_MEdgeSeq * self )
2429 {
2430         if( self->iter == self->mesh->totedge )
2431                 return EXPP_ReturnPyObjError( PyExc_StopIteration,
2432                                 "iterator at end" );
2433
2434         return MEdge_CreatePyObject( self->mesh, self->iter++ );
2435 }
2436
2437 /************************************************************************
2438  *
2439  * Python MEdgeSeq_Type methods
2440  *
2441  ************************************************************************/
2442
2443 /*
2444  * Create edges from tuples of vertices.  Duplicate new edges, or
2445  * edges which already exist,
2446  */
2447
2448 static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
2449 {
2450         int len, nverts;
2451         int i, j;
2452         int new_edge_count, good_edges;
2453         SrchEdges *oldpair, *newpair, *tmppair, *tmppair2;
2454         PyObject *tmp;
2455         BPy_MVert *e[4];
2456         MEdge *tmpedge;
2457         Mesh *mesh = self->mesh;
2458
2459         /* make sure we get a tuple of sequences of something */
2460         switch( PySequence_Size( args ) ) {
2461         case 1:
2462                 /* if a sequence... */
2463                 tmp = PyTuple_GET_ITEM( args, 0 );
2464                 if( PySequence_Check( tmp ) && PySequence_Size( tmp ) == 1 ) {
2465                         /* if another sequence, use it */
2466                         PyObject *tmp2 = PySequence_ITEM( tmp, 0 );
2467                         if( PySequence_Check( tmp2 ) )
2468                                 args = tmp;
2469                         Py_INCREF( args );
2470                         Py_DECREF( tmp2 );
2471                 } else
2472                         return EXPP_ReturnPyObjError( PyExc_TypeError,
2473                                         "expected a sequence of sequence pairs" );
2474                 break;
2475         case 2: 
2476         case 3:
2477         case 4:         /* two to four args may be individual verts */
2478                 tmp = PyTuple_GET_ITEM( args, 0 );
2479                 /*
2480                  * if first item isn't a sequence, then assume it's a bunch of MVerts
2481                  * and wrap inside a tuple
2482                  */
2483                 if( !PySequence_Check( tmp ) ) {
2484                         args = Py_BuildValue( "(O)", args );
2485                         if( !args )
2486                                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2487                                                 "Py_BuildValue() failed" );
2488                 /*
2489                  * otherwise, assume it already a bunch of sequences so use as-is
2490                  */
2491                 } else { 
2492                         Py_INCREF( args );              /* so we can safely DECREF later */
2493                 }
2494                 break;
2495         default:        /* anything else is definitely wrong */
2496                 return EXPP_ReturnPyObjError( PyExc_TypeError,
2497                                 "expected a sequence of sequence pairs" );
2498         }
2499
2500         /* make sure there is something to add */
2501         len = PySequence_Size( args );
2502         if( len == 0 ) {
2503                 Py_DECREF ( args );
2504                 Py_RETURN_NONE;
2505         }
2506
2507         /* verify the param list and get a total count of number of edges */
2508         new_edge_count = 0;
2509         for( i = 0; i < len; ++i ) {
2510                 tmp = PySequence_GetItem( args, i );
2511
2512                 /* not a tuple of MVerts... error */
2513                 if( !PySequence_Check( tmp ) ||
2514                                 EXPP_check_sequence_consistency( tmp, &MVert_Type ) != 1 ) {
2515                         Py_DECREF( tmp );
2516                         Py_DECREF( args );
2517                         return EXPP_ReturnPyObjError( PyExc_ValueError,
2518                                 "expected sequence of MVert sequences" );
2519                 }
2520
2521                 /* not the right number of MVerts... error */
2522                 nverts = PySequence_Size( tmp );
2523                 if( nverts < 2 || nverts > 4 ) {
2524                         Py_DECREF( tmp );
2525                         Py_DECREF( args );
2526                         return EXPP_ReturnPyObjError( PyExc_ValueError,
2527                                 "expected 2 to 4 MVerts per sequence" );
2528                 }
2529                 Py_DECREF( tmp );
2530
2531                 if( nverts == 2 )
2532                         ++new_edge_count;       /* if only two vert, then add only edge */
2533                 else
2534                         new_edge_count += nverts;       /* otherwise, one edge per vert */
2535         }
2536
2537         /* OK, commit to allocating the search structures */
2538         newpair = (SrchEdges *)MEM_callocN( sizeof(SrchEdges)*new_edge_count,
2539                         "MEdgePairs" );
2540
2541         /* scan the input list and build the new edge pair list */
2542         len = PySequence_Size( args );
2543         tmppair = newpair;
2544         new_edge_count = 0;
2545         for( i = 0; i < len; ++i ) {
2546                 int edge_count;
2547                 tmp = PySequence_GetItem( args, i );
2548                 nverts = PySequence_Size( tmp );
2549
2550                 /* get new references for the vertices */
2551                 for(j = 0; j < nverts; ++j )
2552                         e[j] = (BPy_MVert *)PySequence_GetItem( tmp, j );
2553                 Py_DECREF( tmp );
2554
2555                 if( nverts == 2 )
2556                         edge_count = 1;  /* again, two verts give just one edge */
2557                 else
2558                         edge_count = nverts;    
2559
2560                 /* now add the edges to the search list */
2561                 for(j = 0; j < edge_count; ++j ) {
2562                         int k = j+1;
2563                         if( k == nverts )       /* final edge */ 
2564                                 k = 0;
2565
2566                         /* sort verts into search list, abort if two are the same */
2567                         if( e[j]->index < e[k]->index ) {
2568                                 tmppair->v[0] = e[j]->index;
2569                                 tmppair->v[1] = e[k]->index;
2570                                 tmppair->swap = 0;
2571                         } else if( e[j]->index > e[k]->index ) {
2572                                 tmppair->v[0] = e[k]->index;
2573                                 tmppair->v[1] = e[j]->index;
2574                                 tmppair->swap = 1;
2575                         } else {
2576                                 MEM_freeN( newpair );
2577                                 for(j = 0; j < nverts; ++j )
2578                                         Py_DECREF( e[j] );
2579                                 Py_DECREF( args );
2580                                 return EXPP_ReturnPyObjError( PyExc_ValueError,
2581                                                 "tuple contains duplicate vertices" );
2582                         }
2583                         tmppair->index = new_edge_count;
2584                         ++new_edge_count;
2585                         tmppair++;
2586                 }
2587
2588                 /* free the new references */
2589                 for( j = 0; j < nverts; ++j )
2590                         Py_DECREF( e[j] );
2591         }
2592
2593         /* sort the new edge pairs */
2594         qsort( newpair, new_edge_count, sizeof(SrchEdges), medge_comp );
2595
2596         /*
2597          * find duplicates in the new list and mark.  if it's a duplicate,
2598          * then mark by setting second vert index to 0 (a real edge won't have
2599          * second vert index of 0 since verts are sorted)
2600          */
2601
2602         good_edges = new_edge_count;    /* all edges are good at this point */
2603
2604         tmppair = newpair;              /* "last good edge" */
2605         tmppair2 = &tmppair[1]; /* "current candidate edge" */
2606         for( i = 0; i < new_edge_count; ++i ) {
2607                 if( tmppair->v[0] != tmppair2->v[0] ||
2608                                 tmppair->v[1] != tmppair2->v[1] )
2609                         tmppair = tmppair2;     /* last != current, so current == last */
2610                 else {
2611                         tmppair2->v[1] = 0; /* last == current, so mark as duplicate */
2612                         --good_edges;           /* one less good edge */
2613                 }
2614                 tmppair2++;
2615         }
2616
2617         /* if mesh has edges, see if any of the new edges are already in it */
2618         if( mesh->totedge ) {
2619                 oldpair = (SrchEdges *)MEM_callocN( sizeof(SrchEdges)*mesh->totedge,
2620                                 "MEdgePairs" );
2621
2622                 /*
2623                  * build a search list of new edges (don't need to update "swap"
2624                  * field, since we're not creating edges here)
2625                  */
2626                 tmppair = oldpair;
2627                 tmpedge = mesh->medge;
2628                 for( i = 0; i < mesh->totedge; ++i ) {
2629                         if( tmpedge->v1 < tmpedge->v2 ) {
2630                                 tmppair->v[0] = tmpedge->v1;
2631                                 tmppair->v[1] = tmpedge->v2;
2632                         } else {
2633                                 tmppair->v[0] = tmpedge->v2;
2634                                 tmppair->v[1] = tmpedge->v1;
2635                         }
2636                         ++tmpedge;
2637                         ++tmppair;
2638                 }
2639
2640         /* sort the old edge pairs */
2641                 qsort( oldpair, mesh->totedge, sizeof(SrchEdges), medge_comp );
2642
2643         /* eliminate new edges already in the mesh */
2644                 tmppair = newpair;
2645                 for( i = new_edge_count; i-- ; ) {
2646                         if( tmppair->v[1] ) {
2647                                 if( bsearch( tmppair, oldpair, mesh->totedge,
2648                                                         sizeof(SrchEdges), medge_comp ) ) {
2649                                         tmppair->v[1] = 0;      /* mark as duplicate */
2650                                         --good_edges;
2651                                 } 
2652                         }
2653                         tmppair++;
2654                 }
2655                 MEM_freeN( oldpair );
2656         }
2657
2658         /* if any new edges are left, add to list */
2659         if( good_edges ) {
2660                 int totedge = mesh->totedge+good_edges; /* new edge count */
2661
2662         /* allocate new edge list */
2663                 tmpedge = MEM_callocN(totedge*sizeof(MEdge), "Mesh_addEdges");
2664
2665         /* if we're appending, copy the old edge list and delete it */
2666                 if( mesh->medge ) {
2667                         memcpy( tmpedge, mesh->medge, mesh->totedge*sizeof(MEdge));
2668                         MEM_freeN( mesh->medge );
2669                 }
2670                 mesh->medge = tmpedge;          /* point to the new edge list */
2671
2672         /* resort edges into original order */
2673                 qsort( newpair, new_edge_count, sizeof(SrchEdges), medge_index_comp );
2674
2675         /* point to the first edge we're going to add */
2676                 tmpedge = &mesh->medge[mesh->totedge];
2677                 tmppair = newpair;
2678
2679         /* as we find a good edge, add it */
2680                 while( good_edges ) {
2681                         if( tmppair->v[1] ) {   /* not marked as duplicate ! */
2682                                 if( !tmppair->swap ) {
2683                                         tmpedge->v1 = tmppair->v[0];
2684                                         tmpedge->v2 = tmppair->v[1];
2685                                 } else {
2686                                         tmpedge->v1 = tmppair->v[1];
2687                                         tmpedge->v2 = tmppair->v[0];
2688                                 }
2689                                 tmpedge->flag = ME_EDGEDRAW | ME_EDGERENDER;
2690                                 mesh->totedge++;
2691                                 --good_edges;
2692                                 ++tmpedge;
2693                         }
2694                         tmppair++;
2695                 }
2696         }
2697
2698         /* clean up and leave */
2699         mesh_update( mesh );
2700         MEM_freeN( newpair );
2701         Py_DECREF ( args );
2702         Py_RETURN_NONE;
2703 }
2704
2705 static PyObject *MEdgeSeq_delete( BPy_MEdgeSeq * self, PyObject *args )
2706 {
2707         Mesh *mesh = self->mesh;
2708         MEdge *srcedge;
2709         MFace *srcface;
2710         unsigned int *vert_table, *del_table, *edge_table;
2711         int i, len;
2712         int face_count, edge_count, vert_count;
2713
2714         /*
2715          * if input tuple contains a single sequence, use it as input instead;
2716          * otherwise use the sequence as-is and check later that it contains
2717          * one or more integers or MVerts
2718          */
2719         if( PySequence_Size( args ) == 1 ) {
2720                 PyObject *tmp = PyTuple_GET_ITEM( args, 0 );
2721                 if( PySequence_Check( tmp ) ) 
2722                         args = tmp;
2723         }
2724
2725         /* if sequence is empty, do nothing */
2726         len = PySequence_Size( args );
2727         if( len == 0 ) {
2728                 Py_RETURN_NONE;
2729         }
2730
2731         edge_table = (unsigned int *)MEM_callocN( len*sizeof( unsigned int ),
2732                         "edge_table" );
2733
2734         /* get the indices of edges to be removed */
2735         for( i = len; i--; ) {
2736                 PyObject *tmp = PySequence_GetItem( args, i );
2737                 if( BPy_MEdge_Check( tmp ) )
2738                         edge_table[i] = ((BPy_MEdge *)tmp)->index;
2739                 else if( PyInt_CheckExact( tmp ) )
2740                         edge_table[i] = PyInt_AsLong ( tmp );
2741                 else {
2742                         MEM_freeN( edge_table );
2743                         Py_DECREF( tmp );
2744                         return EXPP_ReturnPyObjError( PyExc_TypeError,
2745                                         "expected a sequence of ints or MEdges" );
2746                 }
2747                 Py_DECREF( tmp );
2748
2749                 /* if index out-of-range, throw exception */
2750                 if( edge_table[i] >= (unsigned int)mesh->totedge ) {
2751                         MEM_freeN( edge_table );
2752                         return EXPP_ReturnPyObjError( PyExc_ValueError,
2753                                         "array index out of range" );
2754                 }
2755         }
2756
2757         /*
2758          * build two tables: first table marks vertices which belong to an edge
2759          * which is being deleted
2760          */
2761         del_table = (unsigned int *)MEM_callocN( 
2762                         mesh->totvert*sizeof( unsigned int ), "vert_table" );
2763
2764         /*
2765          * Borrow a trick from editmesh code: for each edge to be deleted, mark
2766          * its vertices as well.  Then go through face list and look for two
2767          * consecutive marked vertices.
2768          */
2769
2770         /* mark each edge that's to be deleted */
2771         srcedge = mesh->medge;
2772         for( i = len; i--; ) {
2773                 unsigned int idx = edge_table[i];
2774                 del_table[srcedge[idx].v1] = UINT_MAX;
2775                 del_table[srcedge[idx].v2] = UINT_MAX;
2776                 srcedge[idx].v1 = UINT_MAX;
2777         }
2778
2779         /*
2780          * second table is used for vertices which become orphaned (belong to no
2781          * edges) and need to be deleted; it's also the normal lookup table for
2782          * old->new vertex indices
2783          */
2784
2785         vert_table = (unsigned int *)MEM_mallocN( 
2786                         mesh->totvert*sizeof( unsigned int ), "vert_table" );
2787
2788         /* assume all edges will be deleted (fills with UINT_MAX) */
2789         memset( vert_table, UCHAR_MAX, mesh->totvert*sizeof( unsigned int ) );
2790
2791         /* unmark vertices of each "good" edge; count each "bad" edge */
2792         edge_count = 0;
2793         for( i = mesh->totedge; i--; ++srcedge )
2794                 if( srcedge->v1 != UINT_MAX )
2795                         vert_table[srcedge->v1] = vert_table[srcedge->v2] = 0;
2796                 else
2797                         ++edge_count;
2798
2799         /*
2800          * find faces which no longer have all edges
2801          */
2802
2803         face_count = 0;
2804         srcface = mesh->mface;
2805         for( i = 0; i < mesh->totface; ++i, ++srcface ) {
2806                 int len = srcface->v4 ? 4 : 3;
2807                 unsigned int id[4];
2808                 int del;
2809
2810                 id[0] = del_table[srcface->v1];
2811                 id[1] = del_table[srcface->v2];
2812                 id[2] = del_table[srcface->v3];
2813                 id[3] = del_table[srcface->v4];
2814
2815                 del = ( id[0] == UINT_MAX && id[1] == UINT_MAX ) ||
2816                         ( id[1] == UINT_MAX && id[2] == UINT_MAX );
2817                 if( !del ) {
2818                         if( len == 3 )
2819                                 del = ( id[2] == UINT_MAX && id[0] == UINT_MAX );
2820                         else
2821                                 del = ( id[2] == UINT_MAX && id[3] == UINT_MAX ) ||
2822                                         ( id[3] == UINT_MAX && id[0] == UINT_MAX );
2823                 }
2824                 if( del ) {
2825                         srcface->v1 = UINT_MAX;
2826                         ++face_count;
2827                 } 
2828         }
2829
2830         /* fix the vertex lookup table, if any verts to delete, do so now */
2831         vert_count = make_vertex_table( vert_table, mesh->totvert );
2832         if( vert_count )
2833                 delete_verts( mesh, vert_table, vert_count );
2834
2835         /* delete faces which have a deleted edge */
2836         delete_faces( mesh, vert_table, face_count );
2837
2838         /* now delete the edges themselves */
2839         delete_edges( mesh, vert_table, edge_count );
2840
2841         /* clean up and return */
2842         MEM_freeN( del_table );
2843         MEM_freeN( vert_table );
2844         MEM_freeN( edge_table );
2845         mesh_update ( mesh );
2846         Py_RETURN_NONE;
2847 }
2848
2849 static PyObject *MEdgeSeq_selected( BPy_MEdgeSeq * self )
2850 {
2851         int i, count;
2852         Mesh *mesh = self->mesh;
2853         MEdge *tmpedge;
2854         PyObject *list;
2855
2856         /* first count selected edges (quicker than appending to PyList?) */
2857         count = 0;
2858         tmpedge = mesh->medge;
2859         for( i = 0; i < mesh->totedge; ++i, ++tmpedge )
2860                 if( (mesh->mvert[tmpedge->v1].flag & SELECT) &&
2861                                 (mesh->mvert[tmpedge->v2].flag & SELECT) )
2862                         ++count;
2863
2864         list = PyList_New( count );
2865         if( !list )
2866                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2867                                 "PyList_New() failed" );
2868
2869         /* next, insert selected edges into list */
2870         count = 0;
2871         tmpedge = mesh->medge;
2872         for( i = 0; i < mesh->totedge; ++i, ++tmpedge ) {
2873                 if( (mesh->mvert[tmpedge->v1].flag & SELECT) &&
2874                                 (mesh->mvert[tmpedge->v2].flag & SELECT) ) {
2875                         PyObject *tmp = PyInt_FromLong( i );
2876                         if( !tmp ) {
2877                                 Py_DECREF( list );
2878                                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2879                                                 "PyInt_FromLong() failed" );
2880                         }
2881                         PyList_SET_ITEM( list, count, tmp );
2882                         ++count;
2883                 }
2884         }
2885         return list;
2886 }
2887
2888 static struct PyMethodDef BPy_MEdgeSeq_methods[] = {
2889         {"extend", (PyCFunction)MEdgeSeq_extend, METH_VARARGS,
2890                 "add edges to mesh"},
2891         {"delete", (PyCFunction)MEdgeSeq_delete, METH_VARARGS,
2892                 "delete edges from mesh"},
2893         {"selected", (PyCFunction)MEdgeSeq_selected, METH_NOARGS,
2894                 "returns a list containing indices of selected edges"},
2895         {NULL, NULL, 0, NULL}
2896 };
2897
2898 /************************************************************************
2899  *
2900  * Python MEdgeSeq_Type standard operators
2901  *
2902  ************************************************************************/
2903
2904 static void MEdgeSeq_dealloc( BPy_MEdgeSeq * self )
2905 {
2906         PyObject_DEL( self );
2907 }
2908
2909 /*****************************************************************************/
2910 /* Python MEdgeSeq_Type structure definition:                               */
2911 /*****************************************************************************/
2912 PyTypeObject MEdgeSeq_Type = {
2913         PyObject_HEAD_INIT( NULL )  /* required py macro */
2914         0,                          /* ob_size */
2915         /*  For printing, in format "<module>.<name>" */
2916         "Blender MEdgeSeq",           /* char *tp_name; */
2917         sizeof( BPy_MEdgeSeq ),       /* int tp_basicsize; */
2918         0,                          /* tp_itemsize;  For allocation */
2919
2920         /* Methods to implement standard operations */
2921
2922         ( destructor ) MEdgeSeq_dealloc,/* destructor tp_dealloc; */
2923         NULL,                       /* printfunc tp_print; */
2924         NULL,                       /* getattrfunc tp_getattr; */
2925         NULL,                       /* setattrfunc tp_setattr; */
2926         NULL,                       /* cmpfunc tp_compare; */
2927         NULL,                       /* reprfunc tp_repr; */
2928
2929         /* Method suites for standard classes */
2930
2931         NULL,                       /* PyNumberMethods *tp_as_number; */
2932         &MEdgeSeq_as_sequence,      /* PySequenceMethods *tp_as_sequence; */
2933         NULL,                       /* PyMappingMethods *tp_as_mapping; */
2934
2935         /* More standard operations (here for binary compatibility) */
2936
2937         NULL,                       /* hashfunc tp_hash; */
2938         NULL,                       /* ternaryfunc tp_call; */
2939         NULL,                       /* reprfunc tp_str; */
2940         NULL,                       /* getattrofunc tp_getattro; */
2941         NULL,                       /* setattrofunc tp_setattro; */
2942
2943         /* Functions to access object as input/output buffer */
2944         NULL,                       /* PyBufferProcs *tp_as_buffer; */
2945
2946   /*** Flags to define presence of optional/expanded features ***/
2947         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
2948
2949         NULL,                       /*  char *tp_doc;  Documentation string */
2950   /*** Assigned meaning in release 2.0 ***/
2951         /* call function for all accessible objects */
2952         NULL,                       /* traverseproc tp_traverse; */
2953
2954         /* delete references to contained objects */
2955         NULL,                       /* inquiry tp_clear; */
2956
2957   /***  Assigned meaning in release 2.1 ***/
2958   /*** rich comparisons ***/
2959         NULL,                       /* richcmpfunc tp_richcompare; */
2960
2961   /***  weak reference enabler ***/
2962         0,                          /* long tp_weaklistoffset; */
2963
2964   /*** Added in release 2.2 ***/
2965         /*   Iterators */
2966         ( getiterfunc) MEdgeSeq_getIter, /* getiterfunc tp_iter; */
2967         ( iternextfunc ) MEdgeSeq_nextIter, /* iternextfunc tp_iternext; */
2968
2969   /*** Attribute descriptor and subclassing stuff ***/
2970         BPy_MEdgeSeq_methods,       /* struct PyMethodDef *tp_methods; */
2971         NULL,                       /* struct PyMemberDef *tp_members; */
2972         NULL,                       /* struct PyGetSetDef *tp_getset; */
2973         NULL,                       /* struct _typeobject *tp_base; */
2974         NULL,                       /* PyObject *tp_dict; */
2975         NULL,                       /* descrgetfunc tp_descr_get; */
2976         NULL,                       /* descrsetfunc tp_descr_set; */
2977         0,                          /* long tp_dictoffset; */
2978         NULL,                       /* initproc tp_init; */
2979         NULL,                       /* allocfunc tp_alloc; */
2980         NULL,                       /* newfunc tp_new; */
2981         /*  Low-level free-memory routine */
2982         NULL,                       /* freefunc tp_free;  */
2983         /* For PyObject_IS_GC */
2984         NULL,                       /* inquiry tp_is_gc;  */
2985         NULL,                       /* PyObject *tp_bases; */
2986         /* method resolution order */
2987         NULL,                       /* PyObject *tp_mro;  */
2988         NULL,                       /* PyObject *tp_cache; */
2989         NULL,                       /* PyObject *tp_subclasses; */
2990         NULL,                       /* PyObject *tp_weaklist; */
2991         NULL
2992 };
2993
2994 /************************************************************************
2995  *
2996  * Face attributes
2997  *
2998  ************************************************************************/
2999
3000 static MFace * MFace_get_pointer( BPy_MFace * self )
3001 {
3002         if( self->index >= self->mesh->totface )
3003                 return (MFace *)EXPP_ReturnPyObjError( PyExc_RuntimeError,
3004                                 "MFace is no longer valid" );
3005         return &self->mesh->mface[self->index];
3006 }
3007
3008 /*
3009  * get a face's vertices
3010  */
3011
3012 static PyObject *MFace_getVerts( BPy_MFace * self )
3013 {
3014         PyObject *attr;
3015         MFace *face = MFace_get_pointer( self );
3016
3017         if( !face )
3018                 return NULL;
3019
3020         attr = PyTuple_New( face->v4 ? 4 : 3 );
3021
3022         if( !attr )
3023                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
3024                                 "PyTuple_New() failed" );
3025
3026         PyTuple_SetItem( attr, 0, MVert_CreatePyObject( self->mesh, face->v1 ) );
3027         PyTuple_SetItem( attr, 1, MVert_CreatePyObject( self->mesh, face->v2 ) );
3028         PyTuple_SetItem( attr, 2, MVert_CreatePyObject( self->mesh, face->v3 ) );
3029         if( face->v4 )
3030                 PyTuple_SetItem( attr, 3, MVert_CreatePyObject( self->mesh,
3031                                         face->v4 ) );
3032
3033         return attr;
3034 }
3035
3036 /*
3037  * set a face's vertices
3038  */
3039
3040 static int MFace_setVerts( BPy_MFace * self, PyObject * args )
3041 {
3042         BPy_MVert *v1, *v2, *v3, *v4 = NULL;
3043         MFace *face = MFace_get_pointer( self );
3044
3045         if( !face )
3046                 return -1;
3047
3048         if( !PyArg_ParseTuple ( args, "O!O!O!|O!", &MVert_Type, &v1,
3049                                 &MVert_Type, &v2, &MVert_Type, &v3, &MVert_Type, &v4 ) )
3050                 return EXPP_ReturnIntError( PyExc_TypeError,
3051                         "expected tuple of 3 or 4 MVerts" );
3052
3053         face->v1 = v1->index;
3054         face->v2 = v2->index;
3055         face->v3 = v3->index;
3056         if( v4 )
3057                 face->v4 = v4->index;
3058         return 0;
3059 }
3060
3061 /*
3062  * get face's material index
3063  */
3064
3065 static PyObject *MFace_getMat( BPy_MFace * self )
3066 {
3067         PyObject *attr;
3068         MFace *face = MFace_get_pointer( self );
3069
3070         if( !face )
3071                 return NULL;
3072
3073         attr = PyInt_FromLong( face->mat_nr );
3074
3075         if( attr )
3076                 return attr;
3077
3078         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
3079                         "PyInt_FromLong() failed" );
3080 }
3081
3082 /*
3083  * set face's material index
3084  */
3085
3086 static int MFace_setMat( BPy_MFace * self, PyObject * value )
3087 {
3088         MFace *face = MFace_get_pointer( self );
3089
3090         if( !face )
3091                 return -1;
3092
3093         return EXPP_setIValueRange( value, &face->mat_nr, 0, 15, 'b' );
3094 }
3095
3096 /*
3097  * get a face's index
3098  */
3099
3100 static PyObject *MFace_getIndex( BPy_MFace * self )
3101 {
3102         PyObject *attr;
3103         MFace *face = MFace_get_pointer( self );
3104
3105         if( !face )
3106                 return NULL;
3107
3108         attr = PyInt_FromLong( self->index );
3109
3110         if( attr )
3111                 return attr;
3112
3113         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
3114                         "PyInt_FromLong() failed" );
3115 }
3116
3117 /*
3118  * get face's normal index
3119  */
3120
3121 static PyObject *MFace_getNormal( BPy_MFace * self )
3122 {
3123         float *vert[4];
3124         float no[3];
3125         MFace *face = MFace_get_pointer( self );
3126
3127         if( !face )
3128                 return NULL;
3129
3130         if( (int)face->v1 >= self->mesh->totvert ||
3131                         (int)face->v2 >= self->mesh->totvert ||
3132                         (int)face->v3 >= self->mesh->totvert ||
3133                         (int)face->v4 >= self->mesh->totvert )
3134                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
3135                                 "one or more MFace vertices are no longer valid" );
3136
3137         vert[0] = self->mesh->mvert[face->v1].co;
3138         vert[1] = self->mesh->mvert[face->v2].co;
3139         vert[2] = self->mesh->mvert[face->v3].co;
3140         vert[3] = self->mesh->mvert[face->v4].co;
3141         if( face->v4 )
3142                 CalcNormFloat4( vert[0], vert[1], vert[2], vert[3], no );
3143         else
3144                 CalcNormFloat( vert[0], vert[1], vert[2], no );
3145
3146         return newVectorObject( no, 3, Py_NEW );
3147 }
3148
3149 /*
3150  * get one of a face's mface flag bits
3151  */
3152
3153 static PyObject *MFace_getMFlagBits( BPy_MFace * self, void * type )
3154 {
3155         MFace *face = MFace_get_pointer( self );
3156
3157         if( !face )
3158                 return NULL;
3159
3160         return EXPP_getBitfield( &face->flag, (int)((long)type & 0xff), 'b' );
3161 }
3162
3163 /*
3164  * set one of a face's mface flag bits
3165  */
3166
3167 static int MFace_setMFlagBits( BPy_MFace * self, PyObject * value,
3168                 void * type )
3169 {
3170         MFace *face = MFace_get_pointer( self );
3171
3172         if( !face )
3173                 return -1;
3174
3175         return EXPP_setBitfield( value, &face->flag, (int)((long)type & 0xff), 'b' );
3176 }
3177
3178 /*
3179  * get face's texture image
3180  */
3181
3182 static PyObject *MFace_getImage( BPy_MFace *self )
3183 {
3184         TFace *face;
3185         if( !self->mesh->tface )
3186                 return EXPP_ReturnPyObjError( PyExc_ValueError,
3187                                 "face has no texture values" );
3188
3189         if( !MFace_get_pointer( self ) )
3190                 return NULL;
3191
3192         face = &self->mesh->tface[self->index];
3193
3194         if( face->tpage )
3195                 return Image_CreatePyObject( face->tpage );
3196         else
3197                 return EXPP_incr_ret( Py_None );
3198 }
3199
3200 /*
3201  * change or clear face's texture image
3202  */
3203
3204 static int MFace_setImage( BPy_MFace *self, PyObject *value )
3205 {
3206         TFace *face;
3207
3208         if( !MFace_get_pointer( self ) )
3209                 return -1;
3210
3211         if( !self->mesh->tface )
3212 #if 0
3213                 return EXPP_ReturnIntError( PyExc_ValueError,
3214                                 "face has no texture values" );
3215 #else
3216                 make_tfaces( self->mesh );
3217 #endif
3218
3219         face = &self->mesh->tface[self->index];
3220     if( value == Py_None )
3221         face->tpage = NULL;             /* should memory be freed? */
3222     else {
3223         if( !BPy_Image_Check( value ) )
3224             return EXPP_ReturnIntError( PyExc_TypeError,