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