==Python API==
[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                         return EXPP_ReturnPyObjError( PyExc_TypeError,
1618                                         "expected a sequence of sequence triplets" );
1619                 args = Py_BuildValue( "((OOO))", tmp,
1620                                 PyTuple_GET_ITEM( args, 1 ), PyTuple_GET_ITEM( args, 2 ) );
1621                 if( !args )
1622                         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1623                                         "Py_BuildValue() failed" );
1624                 break;
1625         default:        /* anything else is definitely wrong */
1626                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1627                                 "expected a sequence of sequence triplets" );
1628         }
1629
1630         /* if no verts given, return quietly */
1631         len = PySequence_Size( args );
1632         if( len == 0 ) {
1633                 Py_DECREF ( args );
1634                 Py_RETURN_NONE;
1635         }
1636
1637         newlen = mesh->totvert + len;
1638         newvert = MEM_callocN( sizeof( MVert )*newlen, "MVerts" );
1639
1640         /* scan the input list and insert the new vertices */
1641
1642         tmpvert = &newvert[mesh->totvert];
1643         for( i = 0; i < len; ++i ) {
1644                 float co[3];
1645                 tmp = PySequence_GetItem( args, i );
1646                 if( VectorObject_Check( tmp ) ) {
1647                         if( ((VectorObject *)tmp)->size != 3 ) {
1648                                 MEM_freeN( newvert );
1649                                 Py_DECREF ( tmp );
1650                                 Py_DECREF ( args );
1651                                 return EXPP_ReturnPyObjError( PyExc_ValueError,
1652                                         "expected vector of size 3" );
1653                         }
1654                         for( j = 0; j < 3; ++j )
1655                                 co[j] = ((VectorObject *)tmp)->vec[j];
1656                 } else if( PySequence_Check( tmp ) ) {
1657                         int ok=1;
1658                         PyObject *flt;
1659                         if( PySequence_Size( tmp ) != 3 )
1660                                 ok = 0;
1661                         else    
1662                                 for( j = 0; ok && j < 3; ++j ) {
1663                                         flt = PySequence_ITEM( tmp, j );
1664                                         if( !PyNumber_Check ( flt ) )
1665                                                 ok = 0;
1666                                         else
1667                                                 co[j] = (float)PyFloat_AsDouble( flt );
1668                                         Py_DECREF( flt );
1669                                 }
1670
1671                         if( !ok ) {
1672                                 MEM_freeN( newvert );
1673                                 Py_DECREF ( args );
1674                                 Py_DECREF ( tmp );
1675                                 return EXPP_ReturnPyObjError( PyExc_ValueError,
1676                                         "expected sequence triplet of floats" );
1677                         }
1678                 } else {
1679                         MEM_freeN( newvert );
1680                         Py_DECREF ( args );
1681                         Py_DECREF ( tmp );
1682                         return EXPP_ReturnPyObjError( PyExc_ValueError,
1683                                 "expected sequence triplet of floats" );
1684                 }
1685
1686                 Py_DECREF ( tmp );
1687
1688         /* add the coordinate to the new list */
1689                 memcpy( tmpvert->co, co, sizeof(co) );
1690
1691         /* TODO: anything else which needs to be done when we add a vert? */
1692         /* probably not: NMesh's newvert() doesn't */
1693                 ++tmpvert;
1694         }
1695
1696         /*
1697          * if we got here we've added all the new verts, so just copy the old
1698          * verts over and we're done
1699          */
1700
1701         if( mesh->mvert ) {
1702                 memcpy( newvert, mesh->mvert, mesh->totvert*sizeof(MVert) );
1703                 MEM_freeN( mesh->mvert );
1704         }
1705         mesh->mvert = newvert;
1706
1707         /*
1708          * maybe not quite done; if there are keys, have to fix those lists up
1709          */
1710
1711         if( mesh->key ) {
1712                 KeyBlock *currkey = mesh->key->block.first;
1713                 float *fp, *newkey;
1714
1715                 while( currkey ) {
1716
1717                         /* create key list, copy existing data if any */
1718                         newkey = MEM_callocN(mesh->key->elemsize*newlen, "keydata");
1719                         if( currkey->data ) {
1720                                 memcpy( newkey, currkey->data,
1721                                                 mesh->totvert*mesh->key->elemsize );
1722                                 MEM_freeN( currkey->data );
1723                                 currkey->data = newkey;
1724                         }
1725
1726                         /* add data for new vertices */
1727                         fp = (float *)((char *)currkey->data +
1728                                         (mesh->key->elemsize*mesh->totvert));
1729                         tmpvert = mesh->mvert + mesh->totvert;
1730                         for( i = newlen - mesh->totvert; i > 0; --i ) {
1731                                 VECCOPY(fp, tmpvert->co);
1732                                 fp += 3;
1733                                 tmpvert++;
1734                         }
1735                         currkey->totelem = newlen;
1736                         currkey = currkey->next;
1737                 }
1738         }
1739
1740         /*
1741          * if there are vertex groups, also have to fix them
1742          */
1743
1744         if( mesh->dvert ) {
1745                 MDeformVert *newdvert;
1746                 newdvert = MEM_callocN( sizeof(MDeformVert)*newlen , "mesh defVert" );
1747                 memcpy( newdvert, mesh->dvert, sizeof(MDeformVert)*mesh->totvert );
1748                 MEM_freeN( mesh->dvert );
1749                 mesh->dvert = newdvert;
1750         }
1751
1752         /* set final vertex list size */
1753         mesh->totvert = newlen;
1754
1755         mesh_update( mesh );
1756
1757         Py_DECREF ( args );
1758         Py_RETURN_NONE;
1759 }
1760
1761 static PyObject *MVertSeq_delete( BPy_MVertSeq * self, PyObject *args )
1762 {
1763         unsigned int *vert_table;
1764         int vert_delete, face_count;
1765         int i;
1766         Mesh *mesh = self->mesh;
1767         MFace *tmpface;
1768
1769         /*
1770          * if input tuple contains a single sequence, use it as input instead;
1771          * otherwise use the sequence as-is and check later that it contains
1772          * one or more integers or MVerts
1773          */
1774         if( PySequence_Size( args ) == 1 ) {
1775                 PyObject *tmp = PyTuple_GET_ITEM( args, 0 );
1776                 if( PySequence_Check( tmp ) ) 
1777                         args = tmp;
1778         }
1779
1780         /* if sequence is empty, do nothing */
1781         if( PySequence_Size( args ) == 0 ) {
1782                 Py_RETURN_NONE;
1783         }
1784
1785         /* allocate vertex lookup table */
1786         vert_table = (unsigned int *)MEM_callocN( 
1787                         mesh->totvert*sizeof( unsigned int ), "vert_table" );
1788
1789         /* get the indices of vertices to be removed */
1790         for( i = PySequence_Size( args ); i--; ) {
1791                 PyObject *tmp = PySequence_GetItem( args, i );
1792                 int index;
1793                 if( BPy_MVert_Check( tmp ) ) {
1794                         if( (void *)self->mesh != ((BPy_MVert*)tmp)->data ) {
1795                                 MEM_freeN( vert_table );
1796                                 Py_DECREF( tmp );
1797                                 return EXPP_ReturnPyObjError( PyExc_ValueError,
1798                                                 "MVert belongs to a different mesh" );
1799                         }
1800                         index = ((BPy_MVert*)tmp)->index;
1801                 } else if( PyInt_CheckExact( tmp ) ) {
1802                         index = PyInt_AsLong ( tmp );
1803                 } else {
1804                         MEM_freeN( vert_table );
1805                         Py_DECREF( tmp );
1806                         return EXPP_ReturnPyObjError( PyExc_TypeError,
1807                                         "expected a sequence of ints or MVerts" );
1808                 }
1809                 Py_DECREF( tmp );
1810                 if( index < 0 || index >= mesh->totvert ) {
1811                         MEM_freeN( vert_table );
1812                         return EXPP_ReturnPyObjError( PyExc_IndexError,
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_RETURN_NONE;
1848 }
1849
1850 static PyObject *MVertSeq_selected( BPy_MVertSeq * self )
1851 {
1852         int i, count;
1853         Mesh *mesh = self->mesh;
1854         MVert *tmpvert;
1855         PyObject *list;
1856
1857         /* first count selected edges (quicker than appending to PyList?) */
1858         count = 0;
1859         tmpvert = mesh->mvert;
1860         for( i = 0; i < mesh->totvert; ++i, ++tmpvert )
1861                 if( tmpvert->flag & SELECT )
1862                         ++count;
1863
1864         list = PyList_New( count );
1865         if( !list )
1866                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1867                                 "PyList_New() failed" );
1868
1869         /* next, insert selected edges into list */
1870         count = 0;
1871         tmpvert = mesh->mvert;
1872         for( i = 0; i < mesh->totvert; ++i, ++tmpvert ) {
1873                 if( tmpvert->flag & SELECT ) {
1874                         PyObject *tmp = PyInt_FromLong( i );
1875                         if( !tmp ) {
1876                                 Py_DECREF( list );
1877                                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1878                                                 "PyInt_FromLong() failed" );
1879                         }
1880                         PyList_SET_ITEM( list, count, tmp );
1881                         ++count;
1882                 }
1883         }
1884         return list;
1885 }
1886
1887 static struct PyMethodDef BPy_MVertSeq_methods[] = {
1888         {"extend", (PyCFunction)MVertSeq_extend, METH_VARARGS,
1889                 "add vertices to mesh"},
1890         {"delete", (PyCFunction)MVertSeq_delete, METH_VARARGS,
1891                 "delete vertices from mesh"},
1892         {"selected", (PyCFunction)MVertSeq_selected, METH_NOARGS,
1893                 "returns a list containing indices of selected vertices"},
1894         {NULL, NULL, 0, NULL}
1895 };
1896
1897 /************************************************************************
1898  *
1899  * Python MVertSeq_Type standard operations
1900  *
1901  ************************************************************************/
1902
1903 static void MVertSeq_dealloc( BPy_MVertSeq * self )
1904 {
1905         PyObject_DEL( self );
1906 }
1907
1908 /*****************************************************************************/
1909 /* Python MVertSeq_Type structure definition:                               */
1910 /*****************************************************************************/
1911 PyTypeObject MVertSeq_Type = {
1912         PyObject_HEAD_INIT( NULL )  /* required py macro */
1913         0,                          /* ob_size */
1914         /*  For printing, in format "<module>.<name>" */
1915         "Blender MVertSeq",           /* char *tp_name; */
1916         sizeof( BPy_MVertSeq ),       /* int tp_basicsize; */
1917         0,                          /* tp_itemsize;  For allocation */
1918
1919         /* Methods to implement standard operations */
1920
1921         ( destructor ) MVertSeq_dealloc,/* destructor tp_dealloc; */
1922         NULL,                       /* printfunc tp_print; */
1923         NULL,                       /* getattrfunc tp_getattr; */
1924         NULL,                       /* setattrfunc tp_setattr; */
1925         NULL,                       /* cmpfunc tp_compare; */
1926         NULL,                       /* reprfunc tp_repr; */
1927
1928         /* Method suites for standard classes */
1929
1930         NULL,                       /* PyNumberMethods *tp_as_number; */
1931         &MVertSeq_as_sequence,      /* PySequenceMethods *tp_as_sequence; */
1932         NULL,                       /* PyMappingMethods *tp_as_mapping; */
1933
1934         /* More standard operations (here for binary compatibility) */
1935
1936         NULL,                       /* hashfunc tp_hash; */
1937         NULL,                       /* ternaryfunc tp_call; */
1938         NULL,                       /* reprfunc tp_str; */
1939         NULL,                       /* getattrofunc tp_getattro; */
1940         NULL,                       /* setattrofunc tp_setattro; */
1941
1942         /* Functions to access object as input/output buffer */
1943         NULL,                       /* PyBufferProcs *tp_as_buffer; */
1944
1945   /*** Flags to define presence of optional/expanded features ***/
1946         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
1947
1948         NULL,                       /*  char *tp_doc;  Documentation string */
1949   /*** Assigned meaning in release 2.0 ***/
1950         /* call function for all accessible objects */
1951         NULL,                       /* traverseproc tp_traverse; */
1952
1953         /* delete references to contained objects */
1954         NULL,                       /* inquiry tp_clear; */
1955
1956   /***  Assigned meaning in release 2.1 ***/
1957   /*** rich comparisons ***/
1958         NULL,                       /* richcmpfunc tp_richcompare; */
1959
1960   /***  weak reference enabler ***/
1961         0,                          /* long tp_weaklistoffset; */
1962
1963   /*** Added in release 2.2 ***/
1964         /*   Iterators */
1965         ( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
1966         ( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
1967
1968   /*** Attribute descriptor and subclassing stuff ***/
1969         BPy_MVertSeq_methods,       /* struct PyMethodDef *tp_methods; */
1970         NULL,                       /* struct PyMemberDef *tp_members; */
1971         NULL,                       /* struct PyGetSetDef *tp_getset; */
1972         NULL,                       /* struct _typeobject *tp_base; */
1973         NULL,                       /* PyObject *tp_dict; */
1974         NULL,                       /* descrgetfunc tp_descr_get; */
1975         NULL,                       /* descrsetfunc tp_descr_set; */
1976         0,                          /* long tp_dictoffset; */
1977         NULL,                       /* initproc tp_init; */
1978         NULL,                       /* allocfunc tp_alloc; */
1979         NULL,                       /* newfunc tp_new; */
1980         /*  Low-level free-memory routine */
1981         NULL,                       /* freefunc tp_free;  */
1982         /* For PyObject_IS_GC */
1983         NULL,                       /* inquiry tp_is_gc;  */
1984         NULL,                       /* PyObject *tp_bases; */
1985         /* method resolution order */
1986         NULL,                       /* PyObject *tp_mro;  */
1987         NULL,                       /* PyObject *tp_cache; */
1988         NULL,                       /* PyObject *tp_subclasses; */
1989         NULL,                       /* PyObject *tp_weaklist; */
1990         NULL
1991 };
1992
1993 /************************************************************************
1994  *
1995  * Edge attributes
1996  *
1997  ************************************************************************/
1998
1999 static MEdge * MEdge_get_pointer( BPy_MEdge * self )
2000 {
2001         if( self->index >= self->mesh->totedge )
2002                 return (MEdge *)EXPP_ReturnPyObjError( PyExc_RuntimeError,
2003                                 "MEdge is no longer valid" );
2004         return &self->mesh->medge[self->index];
2005 }
2006
2007 /*
2008  * get an edge's crease value
2009  */
2010
2011 static PyObject *MEdge_getCrease( BPy_MEdge * self )
2012 {
2013         PyObject *attr;
2014         MEdge *edge = MEdge_get_pointer( self );
2015
2016         if( !edge )
2017                 return NULL;
2018
2019         attr = PyInt_FromLong( edge->crease );
2020         if( attr )
2021                 return attr;
2022
2023         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2024                         "PyInt_FromLong() failed" );
2025 }
2026
2027 /*
2028  * set an edge's crease value
2029  */
2030
2031 static int MEdge_setCrease( BPy_MEdge * self, PyObject * value )
2032 {
2033         MEdge *edge = MEdge_get_pointer( self );
2034
2035         if( !edge )
2036                 return -1;
2037
2038         return EXPP_setIValueClamped( value, &edge->crease, 0, 255, 'b' );
2039 }
2040
2041 /*
2042  * get an edge's flag
2043  */
2044
2045 static PyObject *MEdge_getFlag( BPy_MEdge * self )
2046 {
2047         PyObject *attr;
2048         MEdge *edge = MEdge_get_pointer( self );
2049
2050         if( !edge )
2051                 return NULL;
2052
2053         attr = PyInt_FromLong( edge->flag );
2054
2055         if( attr )
2056                 return attr;
2057
2058         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2059                         "PyInt_FromLong() failed" );
2060 }
2061
2062 /*
2063  * set an edge's flag
2064  */
2065
2066 static int MEdge_setFlag( BPy_MEdge * self, PyObject * value )
2067 {
2068         short param;
2069         static short bitmask = 1                /* 1=select */
2070                                 | ME_EDGEDRAW
2071                                 | ME_EDGERENDER
2072                                 | ME_SEAM
2073                                 | ME_FGON;
2074         MEdge *edge = MEdge_get_pointer( self );
2075
2076         if( !edge )
2077                 return -1;
2078
2079         if( !PyInt_CheckExact ( value ) ) {
2080                 char errstr[128];
2081                 sprintf ( errstr , "expected int bitmask of 0x%04x", bitmask );
2082                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
2083         }
2084         param = (short)PyInt_AS_LONG ( value );
2085
2086         if ( ( param & bitmask ) != param )
2087                 return EXPP_ReturnIntError( PyExc_ValueError,
2088                                                 "invalid bit(s) set in mask" );
2089
2090         edge->flag = param;
2091
2092         return 0;
2093 }
2094
2095 /*
2096  * get an edge's first vertex
2097  */
2098
2099 static PyObject *MEdge_getV1( BPy_MEdge * self )
2100 {
2101         MEdge *edge = MEdge_get_pointer( self );
2102
2103         if( !edge )
2104                 return NULL;
2105
2106         return MVert_CreatePyObject( self->mesh, edge->v1 );
2107 }
2108
2109 /*
2110  * set an edge's first vertex
2111  */
2112
2113 static int MEdge_setV1( BPy_MEdge * self, BPy_MVert * value )
2114 {
2115         MEdge *edge = MEdge_get_pointer( self );
2116
2117         if( !edge )
2118                 return -1;
2119         if( !BPy_MVert_Check( value ) )
2120                 return EXPP_ReturnIntError( PyExc_TypeError, "expected an MVert" );
2121
2122         edge->v1 = value->index;
2123         return 0;
2124 }
2125
2126 /*
2127  * get an edge's second vertex
2128  */
2129
2130 static PyObject *MEdge_getV2( BPy_MEdge * self )
2131 {
2132         MEdge *edge = MEdge_get_pointer( self );
2133
2134         if( !edge )
2135                 return NULL;
2136
2137         return MVert_CreatePyObject( self->mesh, edge->v2 );
2138 }
2139
2140 /*
2141  * set an edge's second vertex
2142  */
2143
2144 static int MEdge_setV2( BPy_MEdge * self, BPy_MVert * value )
2145 {
2146         MEdge *edge = MEdge_get_pointer( self );
2147
2148         if( !edge )
2149                 return -1;
2150         if( !BPy_MVert_Check( value ) )
2151                 return EXPP_ReturnIntError( PyExc_TypeError, "expected an MVert" );
2152
2153         edge->v2 = value->index;
2154         return 0;
2155 }
2156
2157 /*
2158  * get an edges's index
2159  */
2160
2161 static PyObject *MEdge_getIndex( BPy_MEdge * self )
2162 {
2163         PyObject *attr;
2164
2165         if( !MEdge_get_pointer( self ) )
2166                 return NULL;
2167
2168         attr = PyInt_FromLong( self->index );
2169
2170         if( attr )
2171                 return attr;
2172
2173         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2174                         "PyInt_FromLong() failed" );
2175 }
2176
2177 /************************************************************************
2178  *
2179  * Python MEdge_Type attributes get/set structure
2180  *
2181  ************************************************************************/
2182
2183 static PyGetSetDef BPy_MEdge_getseters[] = {
2184         {"crease",
2185          (getter)MEdge_getCrease, (setter)MEdge_setCrease,
2186          "edge's crease value",
2187          NULL},
2188         {"flag",
2189          (getter)MEdge_getFlag, (setter)MEdge_setFlag,
2190          "edge's flags",
2191          NULL},
2192         {"v1",
2193          (getter)MEdge_getV1, (setter)MEdge_setV1,
2194          "edge's first vertex",
2195          NULL},
2196         {"v2",
2197          (getter)MEdge_getV2, (setter)MEdge_setV2,
2198          "edge's second vertex",
2199          NULL},
2200         {"index",
2201          (getter)MEdge_getIndex, (setter)NULL,
2202          "edge's index",
2203          NULL},
2204         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
2205 };
2206
2207 /************************************************************************
2208  *
2209  * Python MEdge_Type iterator (iterates over vertices)
2210  *
2211  ************************************************************************/
2212
2213 /*
2214  * Initialize the interator index
2215  */
2216
2217 static PyObject *MEdge_getIter( BPy_MEdge * self )
2218 {
2219         self->iter = 0;
2220         return EXPP_incr_ret ( (PyObject *) self );
2221 }
2222
2223 /*
2224  * Return next MVert.  Throw an exception after the second vertex.
2225  */
2226
2227 static PyObject *MEdge_nextIter( BPy_MEdge * self )
2228 {
2229         if( self->iter == 2 )
2230                 return EXPP_ReturnPyObjError( PyExc_StopIteration,
2231                                 "iterator at end" );
2232
2233         self->iter++;
2234         if( self->iter == 1 )
2235                 return MEdge_getV1( self );
2236         else
2237                 return MEdge_getV2( self );
2238 }
2239
2240 /************************************************************************
2241  *
2242  * Python MEdge_Type standard operations
2243  *
2244  ************************************************************************/
2245
2246 static void MEdge_dealloc( BPy_MEdge * self )
2247 {
2248         PyObject_DEL( self );
2249 }
2250
2251 static int MEdge_compare( BPy_MEdge * a, BPy_MEdge * b )
2252 {
2253         return( a->mesh == b->mesh && a->index == b->index ) ? 0 : -1;
2254 }
2255
2256 static PyObject *MEdge_repr( BPy_MEdge * self )
2257 {
2258         struct MEdge *edge = MEdge_get_pointer( self );
2259
2260         if( !edge )
2261                 return NULL;
2262
2263         return PyString_FromFormat( "[MEdge (%d %d) %d %d]",
2264                         (int)edge->v1, (int)edge->v2, (int)edge->crease,
2265                         (int)self->index );
2266 }
2267
2268 static long MEdge_hash( BPy_MEdge *self )
2269 {
2270         return (long)self->index;
2271 }
2272
2273 /************************************************************************
2274  *
2275  * Python MEdge_Type structure definition
2276  *
2277  ************************************************************************/
2278
2279 PyTypeObject MEdge_Type = {
2280         PyObject_HEAD_INIT( NULL )  /* required py macro */
2281         0,                          /* ob_size */
2282         /*  For printing, in format "<module>.<name>" */
2283         "Blender MEdge",           /* char *tp_name; */
2284         sizeof( BPy_MEdge ),       /* int tp_basicsize; */
2285         0,                          /* tp_itemsize;  For allocation */
2286
2287         /* Methods to implement standard operations */
2288
2289         ( destructor ) MEdge_dealloc,/* destructor tp_dealloc; */
2290         NULL,                       /* printfunc tp_print; */
2291         NULL,                       /* getattrfunc tp_getattr; */
2292         NULL,                       /* setattrfunc tp_setattr; */
2293         ( cmpfunc ) MEdge_compare,  /* cmpfunc tp_compare; */
2294         ( reprfunc ) MEdge_repr,    /* reprfunc tp_repr; */
2295
2296         /* Method suites for standard classes */
2297
2298         NULL,                       /* PyNumberMethods *tp_as_number; */
2299     NULL,                       /* PySequenceMethods *tp_as_sequence; */
2300         NULL,                       /* PyMappingMethods *tp_as_mapping; */
2301
2302         /* More standard operations (here for binary compatibility) */
2303
2304         ( hashfunc ) MEdge_hash,    /* hashfunc tp_hash; */
2305         NULL,                       /* ternaryfunc tp_call; */
2306         NULL,                       /* reprfunc tp_str; */
2307         NULL,                       /* getattrofunc tp_getattro; */
2308         NULL,                       /* setattrofunc tp_setattro; */
2309
2310         /* Functions to access object as input/output buffer */
2311         NULL,                       /* PyBufferProcs *tp_as_buffer; */
2312
2313   /*** Flags to define presence of optional/expanded features ***/
2314         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
2315
2316         NULL,                       /*  char *tp_doc;  Documentation string */
2317   /*** Assigned meaning in release 2.0 ***/
2318         /* call function for all accessible objects */
2319         NULL,                       /* traverseproc tp_traverse; */
2320
2321         /* delete references to contained objects */
2322         NULL,                       /* inquiry tp_clear; */
2323
2324   /***  Assigned meaning in release 2.1 ***/
2325   /*** rich comparisons ***/
2326         NULL,                       /* richcmpfunc tp_richcompare; */
2327
2328   /***  weak reference enabler ***/
2329         0,                          /* long tp_weaklistoffset; */
2330
2331   /*** Added in release 2.2 ***/
2332         /*   Iterators */
2333         ( getiterfunc) MEdge_getIter, /* getiterfunc tp_iter; */
2334         ( iternextfunc ) MEdge_nextIter, /* iternextfunc tp_iternext; */
2335
2336   /*** Attribute descriptor and subclassing stuff ***/
2337         NULL,                       /* struct PyMethodDef *tp_methods; */
2338         NULL,                       /* struct PyMemberDef *tp_members; */
2339         BPy_MEdge_getseters,        /* struct PyGetSetDef *tp_getset; */
2340         NULL,                       /* struct _typeobject *tp_base; */
2341         NULL,                       /* PyObject *tp_dict; */
2342         NULL,                       /* descrgetfunc tp_descr_get; */
2343         NULL,                       /* descrsetfunc tp_descr_set; */
2344         0,                          /* long tp_dictoffset; */
2345         NULL,                       /* initproc tp_init; */
2346         NULL,                       /* allocfunc tp_alloc; */
2347         NULL,                       /* newfunc tp_new; */
2348         /*  Low-level free-memory routine */
2349         NULL,                       /* freefunc tp_free;  */
2350         /* For PyObject_IS_GC */
2351         NULL,                       /* inquiry tp_is_gc;  */
2352         NULL,                       /* PyObject *tp_bases; */
2353         /* method resolution order */
2354         NULL,                       /* PyObject *tp_mro;  */
2355         NULL,                       /* PyObject *tp_cache; */
2356         NULL,                       /* PyObject *tp_subclasses; */
2357         NULL,                       /* PyObject *tp_weaklist; */
2358         NULL
2359 };
2360
2361 static PyObject *MEdge_CreatePyObject( Mesh * mesh, int i )
2362 {
2363         BPy_MEdge *obj = PyObject_NEW( BPy_MEdge, &MEdge_Type );
2364
2365         if( !obj )
2366                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2367                                 "PyObject_New() failed" );
2368
2369         obj->mesh = mesh;
2370         obj->index = i;
2371         return (PyObject *)obj;
2372 }
2373
2374 /************************************************************************
2375  *
2376  * Edge sequence 
2377  *
2378  ************************************************************************/
2379
2380 static int MEdgeSeq_len( BPy_MEdgeSeq * self )
2381 {
2382         return self->mesh->totedge;
2383 }
2384
2385 static PyObject *MEdgeSeq_item( BPy_MEdgeSeq * self, int i )
2386 {
2387         if( i < 0 || i >= self->mesh->totedge )
2388                 return EXPP_ReturnPyObjError( PyExc_IndexError,
2389                                               "array index out of range" );
2390
2391         return MEdge_CreatePyObject( self->mesh, i );
2392 }
2393
2394
2395 static PySequenceMethods MEdgeSeq_as_sequence = {
2396         ( inquiry ) MEdgeSeq_len,       /* sq_length */
2397         ( binaryfunc ) 0,       /* sq_concat */
2398         ( intargfunc ) 0,       /* sq_repeat */
2399         ( intargfunc ) MEdgeSeq_item,   /* sq_item */
2400         ( intintargfunc ) 0,    /* sq_slice */
2401         ( intobjargproc ) 0,    /* sq_ass_item */
2402         ( intintobjargproc ) 0, /* sq_ass_slice */
2403         0,0,0,
2404 };
2405
2406 /************************************************************************
2407  *
2408  * Python MEdgeSeq_Type iterator (iterates over edges)
2409  *
2410  ************************************************************************/
2411
2412 /*
2413  * Initialize the interator index
2414  */
2415
2416 static PyObject *MEdgeSeq_getIter( BPy_MEdgeSeq * self )
2417 {
2418         self->iter = 0;
2419         return EXPP_incr_ret ( (PyObject *) self );
2420 }
2421
2422 /*
2423  * Return next MEdge.
2424  */
2425
2426 static PyObject *MEdgeSeq_nextIter( BPy_MEdgeSeq * self )
2427 {
2428         if( self->iter == self->mesh->totedge )
2429                 return EXPP_ReturnPyObjError( PyExc_StopIteration,
2430                                 "iterator at end" );
2431
2432         return MEdge_CreatePyObject( self->mesh, self->iter++ );
2433 }
2434
2435 /************************************************************************
2436  *
2437  * Python MEdgeSeq_Type methods
2438  *
2439  ************************************************************************/
2440
2441 /*
2442  * Create edges from tuples of vertices.  Duplicate new edges, or
2443  * edges which already exist,
2444  */
2445
2446 static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
2447 {
2448         int len, nverts;
2449         int i, j;
2450         int new_edge_count, good_edges;
2451         SrchEdges *oldpair, *newpair, *tmppair, *tmppair2;
2452         PyObject *tmp;
2453         BPy_MVert *e[4];
2454         MEdge *tmpedge;
2455         Mesh *mesh = self->mesh;
2456
2457         /* make sure we get a tuple of sequences of something */
2458         switch( PySequence_Size( args ) ) {
2459         case 1:
2460                 /* if a sequence... */
2461                 tmp = PyTuple_GET_ITEM( args, 0 );
2462                 if( PySequence_Check( tmp ) ) {
2463                         /* if another sequence, use it */
2464                         PyObject *tmp2 = PySequence_ITEM( tmp, 0 );
2465                         if( PySequence_Check( tmp2 ) )
2466                                 args = tmp;
2467                         Py_INCREF( args );
2468                         Py_DECREF( tmp2 );
2469                 } else
2470                         return EXPP_ReturnPyObjError( PyExc_TypeError,
2471                                         "expected a sequence of sequence pairs" );
2472                 break;
2473         case 2: 
2474         case 3:
2475         case 4:         /* two to four args may be individual verts */
2476                 tmp = PyTuple_GET_ITEM( args, 0 );
2477                 /*
2478                  * if first item isn't a sequence, then assume it's a bunch of MVerts
2479                  * and wrap inside a tuple
2480                  */
2481                 if( !PySequence_Check( tmp ) ) {
2482                         args = Py_BuildValue( "(O)", args );
2483                         if( !args )
2484                                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2485                                                 "Py_BuildValue() failed" );
2486                 /*
2487                  * otherwise, assume it already a bunch of sequences so use as-is
2488                  */
2489                 } else { 
2490                         Py_INCREF( args );              /* so we can safely DECREF later */
2491                 }
2492                 break;
2493         default:        /* anything else is definitely wrong */
2494                 return EXPP_ReturnPyObjError( PyExc_TypeError,
2495                                 "expected a sequence of sequence pairs" );
2496         }
2497
2498         /* make sure there is something to add */
2499         len = PySequence_Size( args );
2500         if( len == 0 ) {
2501                 Py_DECREF ( args );
2502                 Py_RETURN_NONE;
2503         }
2504
2505         /* verify the param list and get a total count of number of edges */
2506         new_edge_count = 0;
2507         for( i = 0; i < len; ++i ) {
2508                 tmp = PySequence_GetItem( args, i );
2509
2510                 /* not a tuple of MVerts... error */
2511                 if( !PySequence_Check( tmp ) ||
2512                                 EXPP_check_sequence_consistency( tmp, &MVert_Type ) != 1 ) {
2513                         Py_DECREF( tmp );
2514                         Py_DECREF( args );
2515                         return EXPP_ReturnPyObjError( PyExc_ValueError,
2516                                 "expected sequence of MVert sequences" );
2517                 }
2518
2519                 /* not the right number of MVerts... error */
2520                 nverts = PySequence_Size( tmp );
2521                 if( nverts < 2 || nverts > 4 ) {
2522                         Py_DECREF( tmp );
2523                         Py_DECREF( args );
2524                         return EXPP_ReturnPyObjError( PyExc_ValueError,
2525                                 "expected 2 to 4 MVerts per sequence" );
2526                 }
2527                 Py_DECREF( tmp );
2528
2529                 if( nverts == 2 )
2530                         ++new_edge_count;       /* if only two vert, then add only edge */
2531                 else
2532                         new_edge_count += nverts;       /* otherwise, one edge per vert */
2533         }
2534
2535         /* OK, commit to allocating the search structures */
2536         newpair = (SrchEdges *)MEM_callocN( sizeof(SrchEdges)*new_edge_count,
2537                         "MEdgePairs" );
2538
2539         /* scan the input list and build the new edge pair list */
2540         len = PySequence_Size( args );
2541         tmppair = newpair;
2542         new_edge_count = 0;
2543         for( i = 0; i < len; ++i ) {
2544                 int edge_count;
2545                 tmp = PySequence_GetItem( args, i );
2546                 nverts = PySequence_Size( tmp );
2547
2548                 /* get new references for the vertices */
2549                 for(j = 0; j < nverts; ++j )
2550                         e[j] = (BPy_MVert *)PySequence_GetItem( tmp, j );
2551                 Py_DECREF( tmp );
2552
2553                 if( nverts == 2 )
2554                         edge_count = 1;  /* again, two verts give just one edge */
2555                 else
2556                         edge_count = nverts;    
2557
2558                 /* now add the edges to the search list */
2559                 for(j = 0; j < edge_count; ++j ) {
2560                         int k = j+1;
2561                         if( k == nverts )       /* final edge */ 
2562                                 k = 0;
2563
2564                         /* sort verts into search list, abort if two are the same */
2565                         if( e[j]->index < e[k]->index ) {
2566                                 tmppair->v[0] = e[j]->index;
2567                                 tmppair->v[1] = e[k]->index;
2568                                 tmppair->swap = 0;
2569                         } else if( e[j]->index > e[k]->index ) {
2570                                 tmppair->v[0] = e[k]->index;
2571                                 tmppair->v[1] = e[j]->index;
2572                                 tmppair->swap = 1;
2573                         } else {
2574                                 MEM_freeN( newpair );
2575                                 for(j = 0; j < nverts; ++j )
2576                                         Py_DECREF( e[j] );
2577                                 Py_DECREF( args );
2578                                 return EXPP_ReturnPyObjError( PyExc_ValueError,
2579                                                 "tuple contains duplicate vertices" );
2580                         }
2581                         tmppair->index = new_edge_count;
2582                         ++new_edge_count;
2583                         tmppair++;
2584                 }
2585
2586                 /* free the new references */
2587                 for( j = 0; j < nverts; ++j )
2588                         Py_DECREF( e[j] );
2589         }
2590
2591         /* sort the new edge pairs */
2592         qsort( newpair, new_edge_count, sizeof(SrchEdges), medge_comp );
2593
2594         /*
2595          * find duplicates in the new list and mark.  if it's a duplicate,
2596          * then mark by setting second vert index to 0 (a real edge won't have
2597          * second vert index of 0 since verts are sorted)
2598          */
2599
2600         good_edges = new_edge_count;    /* all edges are good at this point */
2601
2602         tmppair = newpair;              /* "last good edge" */
2603         tmppair2 = &tmppair[1]; /* "current candidate edge" */
2604         for( i = 0; i < new_edge_count; ++i ) {
2605                 if( tmppair->v[0] != tmppair2->v[0] ||
2606                                 tmppair->v[1] != tmppair2->v[1] )
2607                         tmppair = tmppair2;     /* last != current, so current == last */
2608                 else {
2609                         tmppair2->v[1] = 0; /* last == current, so mark as duplicate */
2610                         --good_edges;           /* one less good edge */
2611                 }
2612                 tmppair2++;
2613         }
2614
2615         /* if mesh has edges, see if any of the new edges are already in it */
2616         if( mesh->totedge ) {
2617                 oldpair = (SrchEdges *)MEM_callocN( sizeof(SrchEdges)*mesh->totedge,
2618                                 "MEdgePairs" );
2619
2620                 /*
2621                  * build a search list of new edges (don't need to update "swap"
2622                  * field, since we're not creating edges here)
2623                  */
2624                 tmppair = oldpair;
2625                 tmpedge = mesh->medge;
2626                 for( i = 0; i < mesh->totedge; ++i ) {
2627                         if( tmpedge->v1 < tmpedge->v2 ) {
2628                                 tmppair->v[0] = tmpedge->v1;
2629                                 tmppair->v[1] = tmpedge->v2;
2630                         } else {
2631                                 tmppair->v[0] = tmpedge->v2;
2632                                 tmppair->v[1] = tmpedge->v1;
2633                         }
2634                         ++tmpedge;
2635                         ++tmppair;
2636                 }
2637
2638         /* sort the old edge pairs */
2639                 qsort( oldpair, mesh->totedge, sizeof(SrchEdges), medge_comp );
2640
2641         /* eliminate new edges already in the mesh */
2642                 tmppair = newpair;
2643                 for( i = new_edge_count; i-- ; ) {
2644                         if( tmppair->v[1] ) {
2645                                 if( bsearch( tmppair, oldpair, mesh->totedge,
2646                                                         sizeof(SrchEdges), medge_comp ) ) {
2647                                         tmppair->v[1] = 0;      /* mark as duplicate */
2648                                         --good_edges;
2649                                 } 
2650                         }
2651                         tmppair++;
2652                 }
2653                 MEM_freeN( oldpair );
2654         }
2655
2656         /* if any new edges are left, add to list */
2657         if( good_edges ) {
2658                 int totedge = mesh->totedge+good_edges; /* new edge count */
2659
2660         /* allocate new edge list */
2661                 tmpedge = MEM_callocN(totedge*sizeof(MEdge), "Mesh_addEdges");
2662
2663         /* if we're appending, copy the old edge list and delete it */
2664                 if( mesh->medge ) {
2665                         memcpy( tmpedge, mesh->medge, mesh->totedge*sizeof(MEdge));
2666                         MEM_freeN( mesh->medge );
2667                 }
2668                 mesh->medge = tmpedge;          /* point to the new edge list */
2669
2670         /* resort edges into original order */
2671                 qsort( newpair, new_edge_count, sizeof(SrchEdges), medge_index_comp );
2672
2673         /* point to the first edge we're going to add */
2674                 tmpedge = &mesh->medge[mesh->totedge];
2675                 tmppair = newpair;
2676
2677         /* as we find a good edge, add it */
2678                 while( good_edges ) {
2679                         if( tmppair->v[1] ) {   /* not marked as duplicate ! */
2680                                 if( !tmppair->swap ) {
2681                                         tmpedge->v1 = tmppair->v[0];
2682                                         tmpedge->v2 = tmppair->v[1];
2683                                 } else {
2684                                         tmpedge->v1 = tmppair->v[1];
2685                                         tmpedge->v2 = tmppair->v[0];
2686                                 }
2687                                 tmpedge->flag = ME_EDGEDRAW | ME_EDGERENDER;
2688                                 mesh->totedge++;
2689                                 --good_edges;
2690                                 ++tmpedge;
2691                         }
2692                         tmppair++;
2693                 }
2694         }
2695
2696         /* clean up and leave */
2697         mesh_update( mesh );
2698         MEM_freeN( newpair );
2699         Py_DECREF ( args );
2700         Py_RETURN_NONE;
2701 }
2702
2703 static PyObject *MEdgeSeq_delete( BPy_MEdgeSeq * self, PyObject *args )
2704 {
2705         Mesh *mesh = self->mesh;
2706         MEdge *srcedge;
2707         MFace *srcface;
2708         unsigned int *vert_table, *del_table, *edge_table;
2709         int i, len;
2710         int face_count, edge_count, vert_count;
2711
2712         /*
2713          * if input tuple contains a single sequence, use it as input instead;
2714          * otherwise use the sequence as-is and check later that it contains
2715          * one or more integers or MVerts
2716          */
2717         if( PySequence_Size( args ) == 1 ) {
2718                 PyObject *tmp = PyTuple_GET_ITEM( args, 0 );
2719                 if( PySequence_Check( tmp ) ) 
2720                         args = tmp;
2721         }
2722
2723         /* if sequence is empty, do nothing */
2724         len = PySequence_Size( args );
2725         if( len == 0 ) {
2726                 Py_RETURN_NONE;
2727         }
2728
2729         edge_table = (unsigned int *)MEM_callocN( len*sizeof( unsigned int ),
2730                         "edge_table" );
2731
2732         /* get the indices of edges to be removed */
2733         for( i = len; i--; ) {
2734                 PyObject *tmp = PySequence_GetItem( args, i );
2735                 if( BPy_MEdge_Check( tmp ) )
2736                         edge_table[i] = ((BPy_MEdge *)tmp)->index;
2737                 else if( PyInt_CheckExact( tmp ) )
2738                         edge_table[i] = PyInt_AsLong ( tmp );
2739                 else {
2740                         MEM_freeN( edge_table );
2741                         Py_DECREF( tmp );
2742                         return EXPP_ReturnPyObjError( PyExc_TypeError,
2743                                         "expected a sequence of ints or MEdges" );
2744                 }
2745                 Py_DECREF( tmp );
2746
2747                 /* if index out-of-range, throw exception */
2748                 if( edge_table[i] >= (unsigned int)mesh->totedge ) {
2749                         MEM_freeN( edge_table );
2750                         return EXPP_ReturnPyObjError( PyExc_ValueError,
2751                                         "array index out of range" );
2752                 }
2753         }
2754
2755         /*
2756          * build two tables: first table marks vertices which belong to an edge
2757          * which is being deleted
2758          */
2759         del_table = (unsigned int *)MEM_callocN( 
2760                         mesh->totvert*sizeof( unsigned int ), "vert_table" );
2761
2762         /*
2763          * Borrow a trick from editmesh code: for each edge to be deleted, mark
2764          * its vertices as well.  Then go through face list and look for two
2765          * consecutive marked vertices.
2766          */
2767
2768         /* mark each edge that's to be deleted */
2769         srcedge = mesh->medge;
2770         for( i = len; i--; ) {
2771                 unsigned int idx = edge_table[i];
2772                 del_table[srcedge[idx].v1] = UINT_MAX;
2773                 del_table[srcedge[idx].v2] = UINT_MAX;
2774                 srcedge[idx].v1 = UINT_MAX;
2775         }
2776
2777         /*
2778          * second table is used for vertices which become orphaned (belong to no
2779          * edges) and need to be deleted; it's also the normal lookup table for
2780          * old->new vertex indices
2781          */
2782
2783         vert_table = (unsigned int *)MEM_mallocN( 
2784                         mesh->totvert*sizeof( unsigned int ), "vert_table" );
2785
2786         /* assume all edges will be deleted (fills with UINT_MAX) */
2787         memset( vert_table, UCHAR_MAX, mesh->totvert*sizeof( unsigned int ) );
2788
2789         /* unmark vertices of each "good" edge; count each "bad" edge */
2790         edge_count = 0;
2791         for( i = mesh->totedge; i--; ++srcedge )
2792                 if( srcedge->v1 != UINT_MAX )
2793                         vert_table[srcedge->v1] = vert_table[srcedge->v2] = 0;
2794                 else
2795                         ++edge_count;
2796
2797         /*
2798          * find faces which no longer have all edges
2799          */
2800
2801         face_count = 0;
2802         srcface = mesh->mface;
2803         for( i = 0; i < mesh->totface; ++i, ++srcface ) {
2804                 int len = srcface->v4 ? 4 : 3;
2805                 unsigned int id[4];
2806                 int del;
2807
2808                 id[0] = del_table[srcface->v1];
2809                 id[1] = del_table[srcface->v2];
2810                 id[2] = del_table[srcface->v3];
2811                 id[3] = del_table[srcface->v4];
2812
2813                 del = ( id[0] == UINT_MAX && id[1] == UINT_MAX ) ||
2814                         ( id[1] == UINT_MAX && id[2] == UINT_MAX );
2815                 if( !del ) {
2816                         if( len == 3 )
2817                                 del = ( id[2] == UINT_MAX && id[0] == UINT_MAX );
2818                         else
2819                                 del = ( id[2] == UINT_MAX && id[3] == UINT_MAX ) ||
2820                                         ( id[3] == UINT_MAX && id[0] == UINT_MAX );
2821                 }
2822                 if( del ) {
2823                         srcface->v1 = UINT_MAX;
2824                         ++face_count;
2825                 } 
2826         }
2827
2828         /* fix the vertex lookup table, if any verts to delete, do so now */
2829         vert_count = make_vertex_table( vert_table, mesh->totvert );
2830         if( vert_count )
2831                 delete_verts( mesh, vert_table, vert_count );
2832
2833         /* delete faces which have a deleted edge */
2834         delete_faces( mesh, vert_table, face_count );
2835
2836         /* now delete the edges themselves */
2837         delete_edges( mesh, vert_table, edge_count );
2838
2839         /* clean up and return */
2840         MEM_freeN( del_table );
2841         MEM_freeN( vert_table );
2842         MEM_freeN( edge_table );
2843         mesh_update ( mesh );
2844         Py_RETURN_NONE;
2845 }
2846
2847 static PyObject *MEdgeSeq_selected( BPy_MEdgeSeq * self )
2848 {
2849         int i, count;
2850         Mesh *mesh = self->mesh;
2851         MEdge *tmpedge;
2852         PyObject *list;
2853
2854         /* first count selected edges (quicker than appending to PyList?) */
2855         count = 0;
2856         tmpedge = mesh->medge;
2857         for( i = 0; i < mesh->totedge; ++i, ++tmpedge )
2858                 if( (mesh->mvert[tmpedge->v1].flag & SELECT) &&
2859                                 (mesh->mvert[tmpedge->v2].flag & SELECT) )
2860                         ++count;
2861
2862         list = PyList_New( count );
2863         if( !list )
2864                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2865                                 "PyList_New() failed" );
2866
2867         /* next, insert selected edges into list */
2868         count = 0;
2869         tmpedge = mesh->medge;
2870         for( i = 0; i < mesh->totedge; ++i, ++tmpedge ) {
2871                 if( (mesh->mvert[tmpedge->v1].flag & SELECT) &&
2872                                 (mesh->mvert[tmpedge->v2].flag & SELECT) ) {
2873                         PyObject *tmp = PyInt_FromLong( i );
2874                         if( !tmp ) {
2875                                 Py_DECREF( list );
2876                                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2877                                                 "PyInt_FromLong() failed" );
2878                         }
2879                         PyList_SET_ITEM( list, count, tmp );
2880                         ++count;
2881                 }
2882         }
2883         return list;
2884 }
2885
2886 static struct PyMethodDef BPy_MEdgeSeq_methods[] = {
2887         {"extend", (PyCFunction)MEdgeSeq_extend, METH_VARARGS,
2888                 "add edges to mesh"},
2889         {"delete", (PyCFunction)MEdgeSeq_delete, METH_VARARGS,
2890                 "delete edges from mesh"},
2891         {"selected", (PyCFunction)MEdgeSeq_selected, METH_NOARGS,
2892                 "returns a list containing indices of selected edges"},
2893         {NULL, NULL, 0, NULL}
2894 };
2895
2896 /************************************************************************
2897  *
2898  * Python MEdgeSeq_Type standard operators
2899  *
2900  ************************************************************************/
2901
2902 static void MEdgeSeq_dealloc( BPy_MEdgeSeq * self )
2903 {
2904         PyObject_DEL( self );
2905 }
2906
2907 /*****************************************************************************/
2908 /* Python MEdgeSeq_Type structure definition:                               */
2909 /*****************************************************************************/
2910 PyTypeObject MEdgeSeq_Type = {
2911         PyObject_HEAD_INIT( NULL )  /* required py macro */
2912         0,                          /* ob_size */
2913         /*  For printing, in format "<module>.<name>" */
2914         "Blender MEdgeSeq",           /* char *tp_name; */
2915         sizeof( BPy_MEdgeSeq ),       /* int tp_basicsize; */
2916         0,                          /* tp_itemsize;  For allocation */
2917
2918         /* Methods to implement standard operations */
2919
2920         ( destructor ) MEdgeSeq_dealloc,/* destructor tp_dealloc; */
2921         NULL,                       /* printfunc tp_print; */
2922         NULL,                       /* getattrfunc tp_getattr; */
2923         NULL,                       /* setattrfunc tp_setattr; */
2924         NULL,                       /* cmpfunc tp_compare; */
2925         NULL,                       /* reprfunc tp_repr; */
2926
2927         /* Method suites for standard classes */
2928
2929         NULL,                       /* PyNumberMethods *tp_as_number; */
2930         &MEdgeSeq_as_sequence,      /* PySequenceMethods *tp_as_sequence; */
2931         NULL,                       /* PyMappingMethods *tp_as_mapping; */
2932
2933         /* More standard operations (here for binary compatibility) */
2934
2935         NULL,                       /* hashfunc tp_hash; */
2936         NULL,                       /* ternaryfunc tp_call; */
2937         NULL,                       /* reprfunc tp_str; */
2938         NULL,                       /* getattrofunc tp_getattro; */
2939         NULL,                       /* setattrofunc tp_setattro; */
2940
2941         /* Functions to access object as input/output buffer */
2942         NULL,                       /* PyBufferProcs *tp_as_buffer; */
2943
2944   /*** Flags to define presence of optional/expanded features ***/
2945         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
2946
2947         NULL,                       /*  char *tp_doc;  Documentation string */
2948   /*** Assigned meaning in release 2.0 ***/
2949         /* call function for all accessible objects */
2950         NULL,                       /* traverseproc tp_traverse; */
2951
2952         /* delete references to contained objects */
2953         NULL,                       /* inquiry tp_clear; */
2954
2955   /***  Assigned meaning in release 2.1 ***/
2956   /*** rich comparisons ***/
2957         NULL,                       /* richcmpfunc tp_richcompare; */
2958
2959   /***  weak reference enabler ***/
2960         0,                          /* long tp_weaklistoffset; */
2961
2962   /*** Added in release 2.2 ***/
2963         /*   Iterators */
2964         ( getiterfunc) MEdgeSeq_getIter, /* getiterfunc tp_iter; */
2965         ( iternextfunc ) MEdgeSeq_nextIter, /* iternextfunc tp_iternext; */
2966
2967   /*** Attribute descriptor and subclassing stuff ***/
2968         BPy_MEdgeSeq_methods,       /* struct PyMethodDef *tp_methods; */
2969         NULL,                       /* struct PyMemberDef *tp_members; */
2970         NULL,                       /* struct PyGetSetDef *tp_getset; */
2971         NULL,                       /* struct _typeobject *tp_base; */
2972         NULL,                       /* PyObject *tp_dict; */
2973         NULL,                       /* descrgetfunc tp_descr_get; */
2974         NULL,                       /* descrsetfunc tp_descr_set; */
2975         0,                          /* long tp_dictoffset; */
2976         NULL,                       /* initproc tp_init; */
2977         NULL,                       /* allocfunc tp_alloc; */
2978         NULL,                       /* newfunc tp_new; */
2979         /*  Low-level free-memory routine */
2980         NULL,                       /* freefunc tp_free;  */
2981         /* For PyObject_IS_GC */
2982         NULL,                       /* inquiry tp_is_gc;  */
2983         NULL,                       /* PyObject *tp_bases; */
2984         /* method resolution order */
2985         NULL,                       /* PyObject *tp_mro;  */
2986         NULL,                       /* PyObject *tp_cache; */
2987         NULL,                       /* PyObject *tp_subclasses; */
2988         NULL,                       /* PyObject *tp_weaklist; */
2989         NULL
2990 };
2991
2992 /************************************************************************
2993  *
2994  * Face attributes
2995  *
2996  ************************************************************************/
2997
2998 static MFace * MFace_get_pointer( BPy_MFace * self )
2999 {
3000         if( self->index >= self->mesh->totface )
3001                 return (MFace *)EXPP_ReturnPyObjError( PyExc_RuntimeError,
3002                                 "MFace is no longer valid" );
3003         return &self->mesh->mface[self->index];
3004 }
3005
3006 /*
3007  * get a face's vertices
3008  */
3009
3010 static PyObject *MFace_getVerts( BPy_MFace * self )
3011 {
3012         PyObject *attr;
3013         MFace *face = MFace_get_pointer( self );
3014
3015         if( !face )
3016                 return NULL;
3017
3018         attr = PyTuple_New( face->v4 ? 4 : 3 );
3019
3020         if( !attr )
3021                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
3022                                 "PyTuple_New() failed" );
3023
3024         PyTuple_SetItem( attr, 0, MVert_CreatePyObject( self->mesh, face->v1 ) );
3025         PyTuple_SetItem( attr, 1, MVert_CreatePyObject( self->mesh, face->v2 ) );
3026         PyTuple_SetItem( attr, 2, MVert_CreatePyObject( self->mesh, face->v3 ) );
3027         if( face->v4 )
3028                 PyTuple_SetItem( attr, 3, MVert_CreatePyObject( self->mesh,
3029                                         face->v4 ) );
3030
3031         return attr;
3032 }
3033
3034 /*
3035  * set a face's vertices
3036  */
3037
3038 static int MFace_setVerts( BPy_MFace * self, PyObject * args )
3039 {
3040         BPy_MVert *v1, *v2, *v3, *v4 = NULL;
3041         MFace *face = MFace_get_pointer( self );
3042
3043         if( !face )
3044                 return -1;
3045
3046         if( !PyArg_ParseTuple ( args, "O!O!O!|O!", &MVert_Type, &v1,
3047                                 &MVert_Type, &v2, &MVert_Type, &v3, &MVert_Type, &v4 ) )
3048                 return EXPP_ReturnIntError( PyExc_TypeError,
3049                         "expected tuple of 3 or 4 MVerts" );
3050
3051         face->v1 = v1->index;
3052         face->v2 = v2->index;
3053         face->v3 = v3->index;
3054         if( v4 )
3055                 face->v4 = v4->index;
3056         return 0;
3057 }
3058
3059 /*
3060  * get face's material index
3061  */
3062
3063 static PyObject *MFace_getMat( BPy_MFace * self )
3064 {
3065         PyObject *attr;
3066         MFace *face = MFace_get_pointer( self );
3067
3068         if( !face )
3069                 return NULL;
3070
3071         attr = PyInt_FromLong( face->mat_nr );
3072
3073         if( attr )
3074                 return attr;
3075
3076         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
3077                         "PyInt_FromLong() failed" );
3078 }
3079
3080 /*
3081  * set face's material index
3082  */
3083
3084 static int MFace_setMat( BPy_MFace * self, PyObject * value )
3085 {
3086         MFace *face = MFace_get_pointer( self );
3087
3088         if( !face )
3089                 return -1;
3090
3091         return EXPP_setIValueRange( value, &face->mat_nr, 0, 15, 'b' );
3092 }
3093
3094 /*
3095  * get a face's index
3096  */
3097
3098 static PyObject *MFace_getIndex( BPy_MFace * self )
3099 {
3100         PyObject *attr;
3101         MFace *face = MFace_get_pointer( self );
3102
3103         if( !face )
3104                 return NULL;
3105
3106         attr = PyInt_FromLong( self->index );
3107
3108         if( attr )
3109                 return attr;
3110
3111         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
3112                         "PyInt_FromLong() failed" );
3113 }
3114
3115 /*
3116  * get face's normal index
3117  */
3118
3119 static PyObject *MFace_getNormal( BPy_MFace * self )
3120 {
3121         float *vert[4];
3122         float no[3];
3123         MFace *face = MFace_get_pointer( self );
3124
3125         if( !face )
3126                 return NULL;
3127
3128         if( (int)face->v1 >= self->mesh->totvert ||
3129                         (int)face->v2 >= self->mesh->totvert ||
3130                         (int)face->v3 >= self->mesh->totvert ||
3131                         (int)face->v4 >= self->mesh->totvert )
3132                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
3133                                 "one or more MFace vertices are no longer valid" );
3134
3135         vert[0] = self->mesh->mvert[face->v1].co;
3136         vert[1] = self->mesh->mvert[face->v2].co;
3137         vert[2] = self->mesh->mvert[face->v3].co;
3138         vert[3] = self->mesh->mvert[face->v4].co;
3139         if( face->v4 )
3140                 CalcNormFloat4( vert[0], vert[1], vert[2], vert[3], no );
3141         else
3142                 CalcNormFloat( vert[0], vert[1], vert[2], no );
3143
3144         return newVectorObject( no, 3, Py_NEW );
3145 }
3146
3147 /*
3148  * get one of a face's mface flag bits
3149  */
3150
3151 static PyObject *MFace_getMFlagBits( BPy_MFace * self, void * type )
3152 {
3153         MFace *face = MFace_get_pointer( self );
3154
3155         if( !face )
3156                 return NULL;
3157
3158         return EXPP_getBitfield( &face->flag, (int)((long)type & 0xff), 'b' );
3159 }
3160
3161 /*
3162  * set one of a face's mface flag bits
3163  */
3164
3165 static int MFace_setMFlagBits( BPy_MFace * self, PyObject * value,
3166                 void * type )
3167 {
3168         MFace *face = MFace_get_pointer( self );
3169
3170         if( !face )
3171                 return -1;
3172
3173         return EXPP_setBitfield( value, &face->flag, (int)((long)type & 0xff), 'b' );
3174 }
3175
3176 /*
3177  * get face's texture image
3178  */
3179
3180 static PyObject *MFace_getImage( BPy_MFace *self )
3181 {
3182         TFace *face;
3183         if( !self->mesh->tface )
3184                 return EXPP_ReturnPyObjError( PyExc_ValueError,
3185                                 "face has no texture values" );
3186
3187         if( !MFace_get_pointer( self ) )
3188                 return NULL;
3189
3190         face = &self->mesh->tface[self->index];
3191
3192         if( face->tpage )
3193                 return Image_CreatePyObject( face->tpage );
3194         else
3195                 return EXPP_incr_ret( Py_None );
3196 }
3197
3198 /*
3199  * change or clear face's texture image
3200  */
3201
3202 static int MFace_setImage( BPy_MFace *self, PyObject *value )
3203 {
3204         TFace *face;
3205         if( !self->mesh->tface )
3206                 return EXPP_ReturnIntError( PyExc_ValueError,
3207                                 "face has no texture values" );
3208
3209         if( !MFace_get_pointer( self ) )
3210                 return -1;
3211
3212         face = &self->mesh->tface[self->index];
3213     if( value == Py_None )
3214         face->tpage = NULL;             /* should memory be freed? */
3215     else {
3216         if( !BPy_Image_Check( value ) )
3217             return EXPP_ReturnIntError( PyExc_TypeError,
3218                                         "expected image object" );
3219         face->tpage = ( ( BPy_Image * ) value )->image;
3220     }
3221
3222     return 0;
3223 }
3224
3225 /*
3226  * get face's texture flag
3227  */
3228
3229 static PyObject *MFace_getFlag( BPy_MFace *self )
3230 {
3231         PyObject *attr;
3232
3233         if( !self->mesh->tface )
3234                 return EXPP_ReturnPyObjError( PyExc_ValueError,
3235                                 "face has no texture values" );
3236
3237         if( !MFace_get_pointer( self ) )
3238                 return NULL;
3239
3240         attr = PyInt_FromLong( self->mesh->tface[self->index].flag );
3241
3242         if( attr )
3243                 return attr;
3244
3245         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
3246                         "PyInt_FromLong() failed" );
3247 }
3248
3249 /*
3250  * set face's texture flag
3251  */
3252
3253 static int MFace_setFlag( BPy_MFace *self, PyObject *value )
3254 {
3255         int param;
3256         static short bitmask = TF_SELECT | TF_HIDE;
3257
3258         if( !self->mesh->tface )
3259                 return EXPP_ReturnIntError( PyExc_ValueError,
3260                                 "face has no texture values" );
3261
3262         if( !MFace_get_pointer( self ) )
3263                 return -1;
3264
3265         if( !PyInt_CheckExact ( value ) ) {
3266                 char errstr[128];
3267                 sprintf ( errstr , "expected int bitmask of 0x%04x", bitmask );
3268                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
3269         }
3270         param = PyInt_AS_LONG ( value );
3271
3272         /* only one face can be active, so don't allow that here */
3273
3274         if( ( param & bitmask ) == TF_ACTIVE )
3275                 return EXPP_ReturnIntError( PyExc_ValueError,
3276                                 "cannot make a face active; use 'activeFace' attribute" );
3277         
3278         if( ( param & bitmask ) != param )
3279                 return EXPP_ReturnIntError( PyExc_ValueError,
3280                                                 "invalid bit(s) set in mask" );
3281
3282         /* merge active setting with other new params */
3283         param |= (self->mesh->tface[self->index].flag & TF_ACTIVE);
3284         self->mesh->tface[self->index].flag = (char)param;
3285
3286         return 0;
3287 }
3288
3289 /*
3290  * get face's texture mode
3291  */
3292
3293 static PyObject *MFace_getMode( BPy_MFace *self )
3294 {
3295         PyObject *attr;
3296
3297         if( !self->mesh->tface )
3298                 return EXPP_ReturnPyObjError( PyExc_ValueError,
3299                                 "face has no texture values" );
3300
3301         if( !MFace_get_pointer( self ) )
3302                 return NULL;
3303
3304         attr = PyInt_FromLong( self->mesh->tface[self->index].mode );
3305
3306         if( attr )
3307                 return attr;
3308
3309         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
3310                         "PyInt_FromLong() failed" );
3311 }
3312