Python API
[blender.git] / source / blender / python / api2_2x / Mesh.c
1 /* 
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * This is a new part of Blender, partially based on NMesh.c API.
27  *
28  * Contributor(s): Ken Hughes
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include "Mesh.h" /*This must come first*/
34
35 #include "MEM_guardedalloc.h"
36
37 #include "DNA_key_types.h"
38 #include "DNA_armature_types.h"
39 #include "DNA_scene_types.h"
40 #include "DNA_oops_types.h"
41 #include "DNA_space_types.h"
42 #include "DNA_curve_types.h"
43 #include "DNA_meta_types.h"
44 #include "DNA_modifier_types.h"
45
46 #include "BDR_editface.h"       /* make_tfaces */
47 #include "BDR_vpaint.h"
48 #include "BDR_editobject.h"
49
50 #include "BIF_editdeform.h"
51 #include "BIF_editkey.h"        /* insert_meshkey */
52 #include "BIF_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 flag
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 length
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  * get an key for using in a dictionary or set key
2267  */
2268
2269 static PyObject *MEdge_getKey( BPy_MEdge * self )
2270 {
2271         MEdge *edge = MEdge_get_pointer( self );
2272         PyObject *attr = PyTuple_New( 2 );
2273         if (edge->v1 > edge->v2) {
2274                 PyTuple_SetItem( attr, 0, PyInt_FromLong(edge->v2) );
2275                 PyTuple_SetItem( attr, 1, PyInt_FromLong(edge->v1) );
2276         } else {
2277                 PyTuple_SetItem( attr, 0, PyInt_FromLong(edge->v1) );
2278                 PyTuple_SetItem( attr, 1, PyInt_FromLong(edge->v2) );
2279         }
2280         return attr;
2281 }
2282
2283 /*
2284  * set an edge's select state
2285  */
2286
2287 static int MEdge_setSel( BPy_MEdge * self,PyObject * value,
2288                 void * type_unused )
2289 {
2290         MEdge *edge = MEdge_get_pointer( self );
2291         int param = PyObject_IsTrue( value );
2292         Mesh *me;
2293
2294         if( !edge )
2295                 return -1;
2296
2297         if( param == -1 )
2298                 return EXPP_ReturnIntError( PyExc_TypeError,
2299                                 "expected true/false argument" );
2300
2301         me = self->mesh;
2302
2303         if( param ) {
2304                 edge->flag |= SELECT;
2305                 me->mvert[edge->v1].flag |= SELECT;
2306                 me->mvert[edge->v2].flag |= SELECT;
2307         }
2308         else {
2309                 edge->flag &= ~SELECT;
2310                 me->mvert[edge->v1].flag &= ~SELECT;
2311                 me->mvert[edge->v2].flag &= ~SELECT;
2312         }
2313
2314         if( self->mesh->mselect ) {
2315                 MEM_freeN( self->mesh->mselect );
2316                 self->mesh->mselect = NULL;
2317         }
2318
2319         return 0;
2320 }
2321
2322 /************************************************************************
2323  *
2324  * Python MEdge_Type attributes get/set structure
2325  *
2326  ************************************************************************/
2327
2328 static PyGetSetDef BPy_MEdge_getseters[] = {
2329         {"crease",
2330          (getter)MEdge_getCrease, (setter)MEdge_setCrease,
2331          "edge's crease value",
2332          NULL},
2333         {"flag",
2334          (getter)MEdge_getFlag, (setter)MEdge_setFlag,
2335          "edge's flags",
2336          NULL},
2337         {"v1",
2338          (getter)MEdge_getV1, (setter)MEdge_setV1,
2339          "edge's first vertex",
2340          NULL},
2341         {"v2",
2342          (getter)MEdge_getV2, (setter)MEdge_setV2,
2343          "edge's second vertex",
2344          NULL},
2345         {"index",
2346          (getter)MEdge_getIndex, (setter)NULL,
2347          "edge's index",
2348          NULL},
2349         {"sel",
2350          (getter)MEdge_getMFlagBits, (setter)MEdge_setSel,
2351      "edge selected in edit mode",
2352      (void *)SELECT},
2353         {"length",
2354          (getter)MEdge_getLength, (setter)NULL,
2355      "edge's length, read only",
2356      NULL},
2357         {"key",
2358          (getter)MEdge_getKey, (setter)NULL,
2359      "edge's key for using with sets or dictionaries, read only",
2360      NULL},
2361         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
2362 };
2363
2364 /************************************************************************
2365  *
2366  * Python MEdge_Type iterator (iterates over vertices)
2367  *
2368  ************************************************************************/
2369
2370 /*
2371  * Initialize the interator index
2372  */
2373
2374 static PyObject *MEdge_getIter( BPy_MEdge * self )
2375 {
2376         if (self->iter==-1) { /* not alredy used to iterator on, just use self */
2377                 self->iter = 0;
2378                 return EXPP_incr_ret ( (PyObject *) self );
2379         } else { /* alredy being iterated on, return a copy */
2380                 BPy_MEdge *seq = (BPy_MEdge *)MEdge_CreatePyObject(self->mesh, self->index);
2381                 seq->iter = 0;
2382                 return (PyObject *)seq;
2383         }
2384 }
2385
2386 /*
2387  * Return next MVert.  Throw an exception after the second vertex.
2388  */
2389
2390 static PyObject *MEdge_nextIter( BPy_MEdge * self )
2391 {
2392         if( self->iter == 2 ) {
2393                 self->iter = -1;
2394                 return EXPP_ReturnPyObjError( PyExc_StopIteration,
2395                                 "iterator at end" );
2396         }
2397         
2398         self->iter++;
2399         if( self->iter == 1 )
2400                 return MEdge_getV1( self );
2401         else
2402                 return MEdge_getV2( self );
2403 }
2404
2405 /************************************************************************
2406  *
2407  * Python MEdge_Type standard operations
2408  *
2409  ************************************************************************/
2410
2411 static void MEdge_dealloc( BPy_MEdge * self )
2412 {
2413         PyObject_DEL( self );
2414 }
2415
2416 static int MEdge_compare( BPy_MEdge * a, BPy_MEdge * b )
2417 {
2418         return( a->mesh == b->mesh && a->index == b->index ) ? 0 : -1;
2419 }
2420
2421 static PyObject *MEdge_repr( BPy_MEdge * self )
2422 {
2423         struct MEdge *edge = MEdge_get_pointer( self );
2424
2425         if( !edge )
2426                 return NULL;
2427
2428         return PyString_FromFormat( "[MEdge (%d %d) %d %d]",
2429                         (int)edge->v1, (int)edge->v2, (int)edge->crease,
2430                         (int)self->index );
2431 }
2432
2433 static long MEdge_hash( BPy_MEdge *self )
2434 {
2435         return (long)self->index;
2436 }
2437
2438 /************************************************************************
2439  *
2440  * Python MEdge_Type structure definition
2441  *
2442  ************************************************************************/
2443
2444 PyTypeObject MEdge_Type = {
2445         PyObject_HEAD_INIT( NULL )  /* required py macro */
2446         0,                          /* ob_size */
2447         /*  For printing, in format "<module>.<name>" */
2448         "Blender MEdge",           /* char *tp_name; */
2449         sizeof( BPy_MEdge ),       /* int tp_basicsize; */
2450         0,                          /* tp_itemsize;  For allocation */
2451
2452         /* Methods to implement standard operations */
2453
2454         ( destructor ) MEdge_dealloc,/* destructor tp_dealloc; */
2455         NULL,                       /* printfunc tp_print; */
2456         NULL,                       /* getattrfunc tp_getattr; */
2457         NULL,                       /* setattrfunc tp_setattr; */
2458         ( cmpfunc ) MEdge_compare,  /* cmpfunc tp_compare; */
2459         ( reprfunc ) MEdge_repr,    /* reprfunc tp_repr; */
2460
2461         /* Method suites for standard classes */
2462
2463         NULL,                       /* PyNumberMethods *tp_as_number; */
2464     NULL,                       /* PySequenceMethods *tp_as_sequence; */
2465         NULL,                       /* PyMappingMethods *tp_as_mapping; */
2466
2467         /* More standard operations (here for binary compatibility) */
2468
2469         ( hashfunc ) MEdge_hash,    /* hashfunc tp_hash; */
2470         NULL,                       /* ternaryfunc tp_call; */
2471         NULL,                       /* reprfunc tp_str; */
2472         NULL,                       /* getattrofunc tp_getattro; */
2473         NULL,                       /* setattrofunc tp_setattro; */
2474
2475         /* Functions to access object as input/output buffer */
2476         NULL,                       /* PyBufferProcs *tp_as_buffer; */
2477
2478   /*** Flags to define presence of optional/expanded features ***/
2479         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
2480
2481         NULL,                       /*  char *tp_doc;  Documentation string */
2482   /*** Assigned meaning in release 2.0 ***/
2483         /* call function for all accessible objects */
2484         NULL,                       /* traverseproc tp_traverse; */
2485
2486         /* delete references to contained objects */
2487         NULL,                       /* inquiry tp_clear; */
2488
2489   /***  Assigned meaning in release 2.1 ***/
2490   /*** rich comparisons ***/
2491         NULL,                       /* richcmpfunc tp_richcompare; */
2492
2493   /***  weak reference enabler ***/
2494         0,                          /* long tp_weaklistoffset; */
2495
2496   /*** Added in release 2.2 ***/
2497         /*   Iterators */
2498         ( getiterfunc) MEdge_getIter, /* getiterfunc tp_iter; */
2499         ( iternextfunc ) MEdge_nextIter, /* iternextfunc tp_iternext; */
2500
2501   /*** Attribute descriptor and subclassing stuff ***/
2502         NULL,                       /* struct PyMethodDef *tp_methods; */
2503         NULL,                       /* struct PyMemberDef *tp_members; */
2504         BPy_MEdge_getseters,        /* struct PyGetSetDef *tp_getset; */
2505         NULL,                       /* struct _typeobject *tp_base; */
2506         NULL,                       /* PyObject *tp_dict; */
2507         NULL,                       /* descrgetfunc tp_descr_get; */
2508         NULL,                       /* descrsetfunc tp_descr_set; */
2509         0,                          /* long tp_dictoffset; */
2510         NULL,                       /* initproc tp_init; */
2511         NULL,                       /* allocfunc tp_alloc; */
2512         NULL,                       /* newfunc tp_new; */
2513         /*  Low-level free-memory routine */
2514         NULL,                       /* freefunc tp_free;  */
2515         /* For PyObject_IS_GC */
2516         NULL,                       /* inquiry tp_is_gc;  */
2517         NULL,                       /* PyObject *tp_bases; */
2518         /* method resolution order */
2519         NULL,                       /* PyObject *tp_mro;  */
2520         NULL,                       /* PyObject *tp_cache; */
2521         NULL,                       /* PyObject *tp_subclasses; */
2522         NULL,                       /* PyObject *tp_weaklist; */
2523         NULL
2524 };
2525
2526 static PyObject *MEdge_CreatePyObject( Mesh * mesh, int i )
2527 {
2528         BPy_MEdge *obj = PyObject_NEW( BPy_MEdge, &MEdge_Type );
2529
2530         if( !obj )
2531                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2532                                 "PyObject_New() failed" );
2533
2534         obj->mesh = mesh;
2535         obj->index = i;
2536         obj->iter = -1;
2537         return (PyObject *)obj;
2538 }
2539
2540 /************************************************************************
2541  *
2542  * Edge sequence 
2543  *
2544  ************************************************************************/
2545
2546 static int MEdgeSeq_len( BPy_MEdgeSeq * self )
2547 {
2548         return self->mesh->totedge;
2549 }
2550
2551 static PyObject *MEdgeSeq_item( BPy_MEdgeSeq * self, int i )
2552 {
2553         if( i < 0 || i >= self->mesh->totedge )
2554                 return EXPP_ReturnPyObjError( PyExc_IndexError,
2555                                               "array index out of range" );
2556
2557         return MEdge_CreatePyObject( self->mesh, i );
2558 }
2559
2560
2561 static PySequenceMethods MEdgeSeq_as_sequence = {
2562         ( inquiry ) MEdgeSeq_len,       /* sq_length */
2563         ( binaryfunc ) 0,       /* sq_concat */
2564         ( intargfunc ) 0,       /* sq_repeat */
2565         ( intargfunc ) MEdgeSeq_item,   /* sq_item */
2566         ( intintargfunc ) 0,    /* sq_slice */
2567         ( intobjargproc ) 0,    /* sq_ass_item */
2568         ( intintobjargproc ) 0, /* sq_ass_slice */
2569         0,0,0,
2570 };
2571
2572 /************************************************************************
2573  *
2574  * Python MEdgeSeq_Type iterator (iterates over edges)
2575  *
2576  ************************************************************************/
2577
2578 /*
2579  * Initialize the interator index
2580  */
2581
2582 static PyObject *MEdgeSeq_getIter( BPy_MEdgeSeq * self )
2583 {
2584         if (self->iter==-1) { /* iteration for this pyobject is not yet used, just return self */
2585                 self->iter = 0;
2586                 return EXPP_incr_ret ( (PyObject *) self );
2587         } else {
2588                 BPy_MEdgeSeq *seq = (BPy_MEdgeSeq *)MEdgeSeq_CreatePyObject(self->mesh);
2589                 seq->iter = 0;
2590                 return (PyObject *)seq;
2591         }
2592 }
2593
2594 /*
2595  * Return next MEdge.
2596  */
2597
2598 static PyObject *MEdgeSeq_nextIter( BPy_MEdgeSeq * self )
2599 {
2600         if( self->iter == self->mesh->totedge ) {
2601                 self->iter= -1;
2602                 return EXPP_ReturnPyObjError( PyExc_StopIteration,
2603                                 "iterator at end" );
2604         }
2605
2606         return MEdge_CreatePyObject( self->mesh, self->iter++ );
2607 }
2608
2609 /************************************************************************
2610  *
2611  * Python MEdgeSeq_Type methods
2612  *
2613  ************************************************************************/
2614
2615 /*
2616  * Create edges from tuples of vertices.  Duplicate new edges, or
2617  * edges which already exist,
2618  */
2619
2620 static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
2621 {
2622         int len, nverts;
2623         int i, j, ok;
2624         int new_edge_count, good_edges;
2625         SrchEdges *oldpair, *newpair, *tmppair, *tmppair2;
2626         PyObject *tmp;
2627         BPy_MVert *e[4];
2628         MEdge *tmpedge;
2629         Mesh *mesh = self->mesh;
2630
2631         /* make sure we get a tuple of sequences of something */
2632         switch( PySequence_Size( args ) ) {
2633         case 1:
2634                 /* if a sequence... */
2635                 tmp = PyTuple_GET_ITEM( args, 0 );
2636                 if( PySequence_Check( tmp ) ) {
2637                         PyObject *tmp2;
2638
2639                         /* ignore empty sequences */
2640                         if( !PySequence_Size( tmp ) ) {
2641                                 Py_RETURN_NONE;
2642                         }
2643
2644                         /* if another sequence, use it */
2645                         tmp2 = PySequence_ITEM( tmp, 0 );
2646                         if( PySequence_Check( tmp2 ) )
2647                                 args = tmp;
2648                         Py_INCREF( args );
2649                         Py_DECREF( tmp2 );
2650                 } else
2651                         return EXPP_ReturnPyObjError( PyExc_TypeError,
2652                                         "expected a sequence of sequence pairs" );
2653                 break;
2654         case 2: 
2655         case 3:
2656         case 4:         /* two to four args may be individual verts */
2657                 tmp = PyTuple_GET_ITEM( args, 0 );
2658                 /*
2659                  * if first item isn't a sequence, then assume it's a bunch of MVerts
2660                  * and wrap inside a tuple
2661                  */
2662                 if( !PySequence_Check( tmp ) ) {
2663                         args = Py_BuildValue( "(O)", args );
2664                         if( !args )
2665                                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2666                                                 "Py_BuildValue() failed" );
2667                 /*
2668                  * otherwise, assume it already a bunch of sequences so use as-is
2669                  */
2670                 } else { 
2671                         Py_INCREF( args );              /* so we can safely DECREF later */
2672                 }
2673                 break;
2674         default:        /* anything else is definitely wrong */
2675                 return EXPP_ReturnPyObjError( PyExc_TypeError,
2676                                 "expected a sequence of sequence pairs" );
2677         }
2678
2679         /* make sure there is something to add */
2680         len = PySequence_Size( args );
2681         if( len == 0 ) {
2682                 Py_DECREF ( args );
2683                 Py_RETURN_NONE;
2684         }
2685
2686         /* verify the param list and get a total count of number of edges */
2687         new_edge_count = 0;
2688         for( i = 0; i < len; ++i ) {
2689                 tmp = PySequence_GetItem( args, i );
2690
2691                 /* not a tuple of MVerts... error */
2692                 if( !PySequence_Check( tmp ) ) {
2693                         Py_DECREF( tmp );
2694                         Py_DECREF( args );
2695                         return EXPP_ReturnPyObjError( PyExc_ValueError,
2696                                 "expected sequence of MVert sequences" );
2697                 }
2698
2699                 /* not the right number of MVerts... error */
2700                 nverts = PySequence_Size( tmp );
2701                 if( nverts < 2 || nverts > 4 ) {
2702                         Py_DECREF( tmp );
2703                         Py_DECREF( args );
2704                         return EXPP_ReturnPyObjError( PyExc_ValueError,
2705                                 "expected 2 to 4 MVerts per sequence" );
2706                 }
2707
2708                 if( EXPP_check_sequence_consistency( tmp, &MVert_Type ) == 1 ) {
2709
2710                         /* get MVerts, check they're from this mesh */
2711                         ok = 1;
2712                         for( j = 0; ok && j < nverts; ++j ) {
2713                                 e[0] = (BPy_MVert *)PySequence_GetItem( tmp, j );
2714                                 if( (void *)e[0]->data != (void *)self->mesh )
2715                                         ok = 0;
2716                                 Py_DECREF( e[0] );
2717                         }
2718                         Py_DECREF( tmp );
2719
2720                         /* not MVerts from another mesh ... error */
2721                         if( !ok ) {
2722                                 Py_DECREF( args );
2723                                 return EXPP_ReturnPyObjError( PyExc_ValueError,
2724                                         "vertices are from a different mesh" );
2725                         }
2726                 } else {
2727                         ok = 0; 
2728                         for( j = 0; ok == 0 && j < nverts; ++j ) {
2729                                 PyObject *item = PySequence_ITEM( tmp, j );
2730                                 if( !PyInt_CheckExact( item ) )
2731                                         ok = 1;
2732                                 else {
2733                                         int index = PyInt_AsLong ( item );
2734                                         if( index < 0 || index >= self->mesh->totvert )
2735                                                 ok = 2;
2736                                 }
2737                                 Py_DECREF( item );
2738                         }
2739                         Py_DECREF( tmp );
2740
2741                         /* not ints or outside of vertex list ... error */
2742                         if( ok ) {
2743                                 Py_DECREF( args );
2744                                 if( ok == 1 )
2745                                         return EXPP_ReturnPyObjError( PyExc_TypeError,
2746                                                 "expected an integer index" );
2747                                 else
2748                                         return EXPP_ReturnPyObjError( PyExc_KeyError,
2749                                                 "index out of range" );
2750                         }
2751                 }
2752
2753                 if( nverts == 2 )
2754                         ++new_edge_count;       /* if only two vert, then add only edge */
2755                 else
2756                         new_edge_count += nverts;       /* otherwise, one edge per vert */
2757         }
2758
2759         /* OK, commit to allocating the search structures */
2760         newpair = (SrchEdges *)MEM_callocN( sizeof(SrchEdges)*new_edge_count,
2761                         "MEdgePairs" );
2762
2763         /* scan the input list and build the new edge pair list */
2764         len = PySequence_Size( args );
2765         tmppair = newpair;
2766         new_edge_count = 0;
2767         for( i = 0; i < len; ++i ) {
2768                 int edge_count;
2769                 int eedges[4];
2770                 tmp = PySequence_GetItem( args, i );
2771                 nverts = PySequence_Size( tmp );
2772
2773                 /* get new references for the vertices */
2774                 for(j = 0; j < nverts; ++j ) {
2775                         PyObject *item = PySequence_ITEM( tmp, j );
2776                         if( BPy_MVert_Check( item ) ) {
2777                                 eedges[j] = ((BPy_MVert *)item)->index;
2778                         } else {
2779                                 eedges[j] = PyInt_AsLong ( item );
2780                         }
2781                         Py_DECREF( item );
2782                 }
2783                 Py_DECREF( tmp );
2784
2785                 if( nverts == 2 )
2786                         edge_count = 1;  /* again, two verts give just one edge */
2787                 else
2788                         edge_count = nverts;    
2789
2790                 /* now add the edges to the search list */
2791                 for( j = 0; j < edge_count; ++j ) {
2792                         int k = j+1;
2793                         if( k == nverts )       /* final edge */ 
2794                                 k = 0;
2795
2796                         /* sort verts into search list, skip if two are the same */
2797                         if( eedges[j] != eedges[k] ) {
2798                                 if( eedges[j] < eedges[k] ) {
2799                                         tmppair->v[0] = eedges[j];
2800                                         tmppair->v[1] = eedges[k];
2801                                         tmppair->swap = 0;
2802                                 } else {
2803                                         tmppair->v[0] = eedges[k];
2804                                         tmppair->v[1] = eedges[j];
2805                                         tmppair->swap = 1;
2806                                 } 
2807                                 tmppair->index = new_edge_count;
2808                                 ++new_edge_count;
2809                                 tmppair++;
2810                         }
2811                 }
2812
2813         }
2814
2815         /* sort the new edge pairs */
2816         qsort( newpair, new_edge_count, sizeof(SrchEdges), medge_comp );
2817
2818         /*
2819          * find duplicates in the new list and mark.  if it's a duplicate,
2820          * then mark by setting second vert index to 0 (a real edge won't have
2821          * second vert index of 0 since verts are sorted)
2822          */
2823
2824         good_edges = new_edge_count;    /* all edges are good at this point */
2825
2826         tmppair = newpair;              /* "last good edge" */
2827         tmppair2 = &tmppair[1]; /* "current candidate edge" */
2828         for( i = 0; i < new_edge_count; ++i ) {
2829                 if( tmppair->v[0] != tmppair2->v[0] ||
2830                                 tmppair->v[1] != tmppair2->v[1] )
2831                         tmppair = tmppair2;     /* last != current, so current == last */
2832                 else {
2833                         tmppair2->v[1] = 0; /* last == current, so mark as duplicate */
2834                         --good_edges;           /* one less good edge */
2835                 }
2836                 tmppair2++;
2837         }
2838
2839         /* if mesh has edges, see if any of the new edges are already in it */
2840         if( mesh->totedge ) {
2841                 oldpair = (SrchEdges *)MEM_callocN( sizeof(SrchEdges)*mesh->totedge,
2842                                 "MEdgePairs" );
2843
2844                 /*
2845                  * build a search list of new edges (don't need to update "swap"
2846                  * field, since we're not creating edges here)
2847                  */
2848                 tmppair = oldpair;
2849                 tmpedge = mesh->medge;
2850                 for( i = 0; i < mesh->totedge; ++i ) {
2851                         if( tmpedge->v1 < tmpedge->v2 ) {
2852                                 tmppair->v[0] = tmpedge->v1;
2853                                 tmppair->v[1] = tmpedge->v2;
2854                         } else {
2855                                 tmppair->v[0] = tmpedge->v2;
2856                                 tmppair->v[1] = tmpedge->v1;
2857                         }
2858                         ++tmpedge;
2859                         ++tmppair;
2860                 }
2861
2862         /* sort the old edge pairs */
2863                 qsort( oldpair, mesh->totedge, sizeof(SrchEdges), medge_comp );
2864
2865         /* eliminate new edges already in the mesh */
2866                 tmppair = newpair;
2867                 for( i = new_edge_count; i-- ; ) {
2868                         if( tmppair->v[1] ) {
2869                                 if( bsearch( tmppair, oldpair, mesh->totedge,
2870                                                         sizeof(SrchEdges), medge_comp ) ) {
2871                                         tmppair->v[1] = 0;      /* mark as duplicate */
2872                                         --good_edges;
2873                                 } 
2874                         }
2875                         tmppair++;
2876                 }
2877                 MEM_freeN( oldpair );
2878         }
2879
2880         /* if any new edges are left, add to list */
2881         if( good_edges ) {
2882                 CustomData edata;
2883                 int totedge = mesh->totedge+good_edges;
2884
2885         /* create custom edge data arrays and copy existing edges into it */
2886                 CustomData_copy( &mesh->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge );
2887                 CustomData_copy_data( &mesh->edata, &edata, 0, 0, mesh->totedge );
2888
2889                 if ( !CustomData_has_layer( &edata, CD_MEDGE ) )
2890                         CustomData_add_layer( &edata, CD_MEDGE, CD_CALLOC, NULL, totedge );
2891
2892         /* replace old with new data */
2893                 CustomData_free( &mesh->edata, mesh->totedge );
2894                 mesh->edata = edata;
2895                 mesh_update_customdata_pointers( mesh );
2896
2897         /* resort edges into original order */
2898                 qsort( newpair, new_edge_count, sizeof(SrchEdges), medge_index_comp );
2899
2900         /* point to the first edge we're going to add */
2901                 tmpedge = &mesh->medge[mesh->totedge];
2902                 tmppair = newpair;
2903
2904         /* as we find a good edge, add it */
2905                 while( good_edges ) {
2906                         if( tmppair->v[1] ) {   /* not marked as duplicate ! */
2907                                 if( !tmppair->swap ) {
2908                                         tmpedge->v1 = tmppair->v[0];
2909                                         tmpedge->v2 = tmppair->v[1];
2910                                 } else {
2911                                         tmpedge->v1 = tmppair->v[1];
2912                                         tmpedge->v2 = tmppair->v[0];
2913                                 }
2914                                 tmpedge->flag = ME_EDGEDRAW | ME_EDGERENDER;
2915                                 mesh->totedge++;
2916                                 --good_edges;
2917                                 ++tmpedge;
2918                         }
2919                         tmppair++;
2920                 }
2921         }
2922
2923         /* clean up and leave */
2924         mesh_update( mesh );
2925         MEM_freeN( newpair );
2926         Py_DECREF ( args );
2927         Py_RETURN_NONE;
2928 }
2929
2930 static PyObject *MEdgeSeq_delete( BPy_MEdgeSeq * self, PyObject *args )
2931 {
2932         Mesh *mesh = self->mesh;
2933         MEdge *srcedge;
2934         MFace *srcface;
2935         unsigned int *vert_table, *del_table, *edge_table;
2936         int i, len;
2937         int face_count, edge_count, vert_count;
2938
2939         /*
2940          * if input tuple contains a single sequence, use it as input instead;
2941          * otherwise use the sequence as-is and check later that it contains
2942          * one or more integers or MVerts
2943          */
2944         if( PySequence_Size( args ) == 1 ) {
2945                 PyObject *tmp = PyTuple_GET_ITEM( args, 0 );
2946                 if( PySequence_Check( tmp ) ) 
2947                         args = tmp;
2948         }
2949
2950         /* if sequence is empty, do nothing */
2951         len = PySequence_Size( args );
2952         if( len == 0 ) {
2953                 Py_RETURN_NONE;
2954         }
2955
2956         edge_table = (unsigned int *)MEM_callocN( len*sizeof( unsigned int ),
2957                         "edge_table" );
2958
2959         /* get the indices of edges to be removed */
2960         for( i = len; i--; ) {
2961                 PyObject *tmp = PySequence_GetItem( args, i );
2962                 if( BPy_MEdge_Check( tmp ) )
2963                         edge_table[i] = ((BPy_MEdge *)tmp)->index;
2964                 else if( PyInt_CheckExact( tmp ) )
2965                         edge_table[i] = PyInt_AsLong ( tmp );
2966                 else {
2967                         MEM_freeN( edge_table );
2968                         Py_DECREF( tmp );
2969                         return EXPP_ReturnPyObjError( PyExc_TypeError,
2970                                         "expected a sequence of ints or MEdges" );
2971                 }
2972                 Py_DECREF( tmp );
2973
2974                 /* if index out-of-range, throw exception */
2975                 if( edge_table[i] >= (unsigned int)mesh->totedge ) {
2976                         MEM_freeN( edge_table );
2977                         return EXPP_ReturnPyObjError( PyExc_ValueError,
2978                                         "array index out of range" );
2979                 }
2980         }
2981
2982         /*
2983          * build two tables: first table marks vertices which belong to an edge
2984          * which is being deleted
2985          */
2986         del_table = (unsigned int *)MEM_callocN( 
2987                         mesh->totvert*sizeof( unsigned int ), "vert_table" );
2988
2989         /*
2990          * Borrow a trick from editmesh code: for each edge to be deleted, mark
2991          * its vertices as well.  Then go through face list and look for two
2992          * consecutive marked vertices.
2993          */
2994
2995         /* mark each edge that's to be deleted */
2996         srcedge = mesh->medge;
2997         for( i = len; i--; ) {
2998                 unsigned int idx = edge_table[i];
2999                 del_table[srcedge[idx].v1] = UINT_MAX;
3000                 del_table[srcedge[idx].v2] = UINT_MAX;
3001                 srcedge[idx].v1 = UINT_MAX;
3002         }
3003
3004         /*
3005          * second table is used for vertices which become orphaned (belong to no
3006          * edges) and need to be deleted; it's also the normal lookup table for
3007          * old->new vertex indices
3008          */
3009
3010         vert_table = (unsigned int *)MEM_mallocN( 
3011                         mesh->totvert*sizeof( unsigned int ), "vert_table" );
3012
3013         /* assume all edges will be deleted (fills with UINT_MAX) */
3014         memset( vert_table, UCHAR_MAX, mesh->totvert*sizeof( unsigned int ) );
3015
3016         /* unmark vertices of each "good" edge; count each "bad" edge */
3017         edge_count = 0;
3018         for( i = mesh->totedge; i--; ++srcedge )
3019                 if( srcedge->v1 != UINT_MAX )
3020                         vert_table[srcedge->v1] = vert_table[srcedge->v2] = 0;
3021                 else
3022                         ++edge_count;
3023
3024         /*
3025          * find faces which no longer have all edges
3026          */
3027
3028         face_count = 0;
3029         srcface = mesh->mface;
3030         for( i = 0; i < mesh->totface; ++i, ++srcface ) {
3031                 int len = srcface->v4 ? 4 : 3;
3032                 unsigned int id[4];
3033                 int del;
3034
3035                 id[0] = del_table[srcface->v1];
3036                 id[1] = del_table[srcface->v2];
3037                 id[2] = del_table[srcface->v3];
3038                 id[3] = del_table[srcface->v4];
3039
3040                 del = ( id[0] == UINT_MAX && id[1] == UINT_MAX ) ||
3041                         ( id[1] == UINT_MAX && id[2] == UINT_MAX );
3042                 if( !del ) {
3043                         if( len == 3 )
3044                                 del = ( id[2] == UINT_MAX && id[0] == UINT_MAX );
3045                         else
3046                                 del = ( id[2] == UINT_MAX && id[3] == UINT_MAX ) ||
3047                                         ( id[3] == UINT_MAX && id[0] == UINT_MAX );
3048                 }
3049                 if( del ) {
3050                         srcface->v1 = UINT_MAX;
3051                         ++face_count;
3052                 } 
3053         }
3054
3055         /* fix the vertex lookup table, if any verts to delete, do so now */
3056         vert_count = make_vertex_table( vert_table, mesh->totvert );
3057         if( vert_count )
3058                 delete_verts( mesh, vert_table, vert_count );
3059
3060         /* delete faces which have a deleted edge */
3061         delete_faces( mesh, vert_table, face_count );
3062
3063         /* now delete the edges themselves */
3064         delete_edges( mesh, vert_table, edge_count );
3065
3066         /* clean up and return */
3067         MEM_freeN( del_table );
3068         MEM_freeN( vert_table );
3069         MEM_freeN( edge_table );
3070         mesh_update ( mesh );
3071         Py_RETURN_NONE;
3072 }
3073
3074 static PyObject *MEdgeSeq_collapse( BPy_MEdgeSeq * self, PyObject *args )
3075 {
3076         MEdge *srcedge;
3077         unsigned int *edge_table;
3078         float (*vert_list)[3];
3079         int i, len;
3080         Base *base, *basact;
3081         Mesh *mesh = self->mesh;
3082         Object *object = NULL; 
3083         PyObject *tmp;
3084
3085         /*
3086          * when using removedoublesflag(), we need to switch to editmode, so
3087          * nobody else can be using it
3088          */
3089
3090         if( G.obedit )
3091                 return EXPP_ReturnPyObjError(PyExc_RuntimeError,
3092                                 "can't use collapse() while in edit mode" );
3093
3094         /* make sure we get a tuple of sequences of something */
3095         switch( PySequence_Size( args ) ) {
3096         case 1:
3097                 /* if a sequence... */
3098                 tmp = PyTuple_GET_ITEM( args, 0 );
3099                 if( PySequence_Check( tmp ) ) {
3100                         PyObject *tmp2;
3101
3102                         /* ignore empty sequences */
3103                         if( !PySequence_Size( tmp ) ) {
3104                                 Py_RETURN_NONE;
3105                         }
3106
3107                         /* if another sequence, use it */
3108                         tmp2 = PySequence_ITEM( tmp, 0 );
3109                         if( PySequence_Check( tmp2 ) )
3110                                 args = tmp;
3111                         Py_INCREF( args );
3112                         Py_DECREF( tmp2 );
3113                 } else
3114                         return EXPP_ReturnPyObjError( PyExc_TypeError,
3115                                         "expected a sequence of sequence pairs" );
3116                 break;
3117         case 2: /* two args may be individual edges/verts */
3118                 tmp = PyTuple_GET_ITEM( args, 0 );
3119                 /*
3120                  * if first item isn't a sequence, then assume it's a bunch of MVerts
3121                  * and wrap inside a tuple
3122                  */
3123                 if( !PySequence_Check( tmp ) ) {
3124                         args = Py_BuildValue( "(O)", args );
3125                         if( !args )
3126                                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
3127                                                 "Py_BuildValue() failed" );
3128                 /*
3129                  * otherwise, assume it already a bunch of sequences so use as-is
3130                  */
3131                 } else { 
3132                         Py_INCREF( args );              /* so we can safely DECREF later */
3133                 }
3134                 break;
3135         default:        /* anything else is definitely wrong */
3136                 return EXPP_ReturnPyObjError( PyExc_TypeError,
3137                                 "expected a sequence of sequence pairs" );
3138         }
3139
3140         /* if sequence is empty, do nothing */
3141         len = PySequence_Size( args );
3142         if( len == 0 ) {
3143                 Py_RETURN_NONE;
3144         }
3145
3146         /* allocate table of edge indices and new vertex values */
3147
3148         edge_table = (unsigned int *)MEM_callocN( len*sizeof( unsigned int ),
3149                         "edge_table" );
3150         vert_list = (float (*)[3])MEM_callocN( 3*len*sizeof( float ),
3151                         "vert_list" );
3152
3153         /* get the indices of edges to be collapsed and new vert locations */
3154         for( i = len; i--; ) {
3155                 PyObject *tmp1;
3156                 PyObject *tmp2;
3157
3158                 tmp = PySequence_GetItem( args, i );
3159
3160                 /* if item isn't sequence of size 2, error */
3161                 if( !PySequence_Check( tmp ) || PySequence_Size( tmp ) != 2 ) {
3162                         MEM_freeN( edge_table );
3163                         MEM_freeN( vert_list );
3164                         Py_DECREF( tmp );
3165                         Py_DECREF( args );
3166                         return EXPP_ReturnPyObjError( PyExc_TypeError,
3167                                         "expected a sequence of (MEdges, vector)" );
3168                 }
3169
3170                 /* if items aren't a MEdge/int and vector, error */
3171                 tmp1 = PySequence_GetItem( tmp, 0 );
3172                 tmp2 = PySequence_GetItem( tmp, 1 );
3173                 Py_DECREF( tmp );
3174                 if( !(BPy_MEdge_Check( tmp1 ) || PyInt_CheckExact( tmp1 )) ||
3175                                 !VectorObject_Check ( tmp2 ) ) {
3176                         MEM_freeN( edge_table );
3177                         MEM_freeN( vert_list );
3178                         Py_DECREF( tmp1 );
3179                         Py_DECREF( tmp2 );
3180                         Py_DECREF( args );
3181                         return EXPP_ReturnPyObjError( PyExc_TypeError,
3182                                         "expected a sequence of (MEdges, vector)" );
3183                 }
3184
3185                 /* store edge index, new vertex location */
3186                 if( PyInt_CheckExact( tmp1 ) )
3187                         edge_table[i] = PyInt_AsLong ( tmp1 );
3188                 else
3189                         edge_table[i] = ((BPy_MEdge *)tmp1)->index;
3190                 memcpy( vert_list[i], ((VectorObject *)tmp2)->vec,
3191                                 3*sizeof( float ) );
3192                 Py_DECREF( tmp1 );
3193                 Py_DECREF( tmp2 );
3194
3195                 /* if index out-of-range, throw exception */
3196                 if( edge_table[i] >= (unsigned int)mesh->totedge ) {
3197                         MEM_freeN( edge_table );
3198                         MEM_freeN( vert_list );
3199                         return EXPP_ReturnPyObjError( PyExc_ValueError,
3200                                         "edge index out of range" );
3201                 }
3202         }
3203
3204         /*
3205          * simple algorithm:
3206          * (1) deselect all verts
3207          * (2) for each edge
3208          *   (2a) replace both verts with the new vert
3209          *   (2b) select both verts
3210          * (3) call removedoublesflag()
3211          */
3212
3213         /* (1) deselect all verts */
3214         for( i = mesh->totvert; i--; )
3215                 mesh->mvert[i].flag &= ~SELECT;
3216
3217         /* (2) replace edge's verts and select them */
3218         for( i = len; i--; ) {
3219                 srcedge = &mesh->medge[edge_table[i]];
3220                 memcpy( &mesh->mvert[srcedge->v1].co, vert_list[i], 3*sizeof( float ) );
3221                 memcpy( &mesh->mvert[srcedge->v2].co, vert_list[i], 3*sizeof( float ) );
3222                 mesh->mvert[srcedge->v1].flag |= SELECT;
3223                 mesh->mvert[srcedge->v2].flag |= SELECT;
3224         }
3225
3226         /* (3) call removedoublesflag() */
3227         for( base = FIRSTBASE; base; base = base->next ) {
3228                 if( base->object->type == OB_MESH && 
3229                                 base->object->data == self->mesh ) {
3230                         object = base->object;
3231                         break;
3232                 }
3233         }
3234
3235         basact = BASACT;
3236         BASACT = base;
3237         
3238         removedoublesflag( 1, 0.0 );
3239         /* make mesh's object active, enter mesh edit mode */
3240         G.obedit = object;
3241         
3242         /* exit edit mode, free edit mesh */
3243         load_editMesh();
3244         free_editMesh(G.editMesh);
3245         
3246         BASACT = basact;
3247
3248         /* clean up and exit */
3249         Py_DECREF( args );
3250         MEM_freeN( vert_list );
3251         MEM_freeN( edge_table );
3252         mesh_update ( mesh );
3253         Py_RETURN_NONE;
3254 }
3255
3256
3257 static PyObject *MEdgeSeq_selected( BPy_MEdgeSeq * self )
3258 {
3259         int i, count;
3260         Mesh *mesh = self->mesh;
3261         MEdge *tmpedge;
3262         PyObject *list;
3263
3264         /* first count selected edges (quicker than appending to PyList?) */
3265         count = 0;
3266         tmpedge = mesh->medge;
3267         for( i = 0; i < mesh->totedge; ++i, ++tmpedge )
3268                 if( (mesh->mvert[tmpedge->v1].flag & SELECT) &&
3269                                 (mesh->mvert[tmpedge->v2].flag & SELECT) )
3270                         ++count;
3271
3272         list = PyList_New( count );
3273         if( !list )
3274                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
3275                                 "PyList_New() failed" );
3276
3277         /* next, insert selected edges into list */
3278         count = 0;
3279         tmpedge = mesh->medge;
3280         for( i = 0; i < mesh->totedge; ++i, ++tmpedge ) {
3281                 if( (mesh->mvert[tmpedge->v1].flag & SELECT) &&
3282                                 (mesh->mvert[tmpedge->v2].flag & SELECT) ) {
3283                         PyObject *tmp = PyInt_FromLong( i );
3284                         if( !tmp ) {
3285                                 Py_DECREF( list );
3286                                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
3287                                                 "PyInt_FromLong() failed" );
3288                         }
3289                         PyList_SET_ITEM( list, count, tmp );
3290                         ++count;
3291                 }
3292         }