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