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