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