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