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