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