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