fix for own bugs in curves.
[blender.git] / source / blender / python / api2_2x / NMesh.c
1 /* 
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * This is a new part of Blender, but it borrows all the old NMesh code.
24  *
25  * Contributor(s): Willian P. Germano, Jordi Rovira i Bonet, Joseph Gilbert,
26  * Bala Gi, Alexander Szakaly, Stephane Soppera, Campbell Barton, Ken Hughes,
27  * Daniel Dunbar.
28  *
29  * ***** END GPL LICENSE BLOCK *****
30  */
31
32 #include "NMesh.h" /*This must come first*/
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_key_types.h"
37 #include "DNA_armature_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_space_types.h"
40 #include "DNA_curve_types.h"
41
42 #include "BDR_editface.h"       /* make_tfaces */
43 #include "BDR_vpaint.h"
44 #include "BDR_editobject.h"
45
46 #include "BIF_editdeform.h"
47 #include "BIF_editkey.h"        /* insert_meshkey */
48 #include "BIF_editview.h"
49 #include "BIF_space.h"
50
51 #include "BKE_customdata.h"
52 #include "BKE_deform.h"
53 #include "BKE_mesh.h"
54 #include "BKE_material.h"
55 #include "BKE_main.h"
56 #include "BKE_global.h"
57 #include "BKE_library.h"
58 #include "BKE_DerivedMesh.h"
59 #include "BKE_displist.h"
60 #include "BKE_object.h"
61 #include "BKE_mball.h"
62 #include "BKE_utildefines.h"
63 #include "BKE_depsgraph.h"
64 #include "BKE_idprop.h"
65
66 #include "BLI_arithb.h"
67 #include "BLI_blenlib.h"
68
69 #include "blendef.h"
70 #include "mydevice.h"
71 #include "Object.h"
72 #include "Key.h"
73 #include "Mathutils.h"
74 #include "IDProp.h"
75 #include "constant.h"
76 #include "gen_utils.h"
77 #include "gen_library.h"
78
79 extern void countall(void);
80
81 /* EXPP Mesh defines */
82
83 #define NMESH_FRAME_MAX                         30000
84 #define NMESH_SMOOTHRESH                        30
85 #define NMESH_SMOOTHRESH_MIN                    1
86 #define NMESH_SMOOTHRESH_MAX                    80
87 #define NMESH_SUBDIV                            1
88 #define NMESH_SUBDIV_MIN                        0
89 #define NMESH_SUBDIV_MAX                        6
90
91 static int unlink_existingMeshData( Mesh * mesh );
92 static int convert_NMeshToMesh( Mesh *mesh, BPy_NMesh *nmesh );
93 static void check_dverts(Mesh *me, int old_totverts);
94 static PyObject *NMesh_printDebug( PyObject * self );
95 static PyObject *NMesh_addEdge( PyObject * self, PyObject * args );
96 static PyObject *NMesh_findEdge( PyObject * self, PyObject * args );
97 static PyObject *NMesh_removeEdge( PyObject * self, PyObject * args );
98 static PyObject *NMesh_addFace( PyObject * self, PyObject * args );
99 static PyObject *NMesh_removeFace( PyObject * self, PyObject * args );
100 static PyObject *NMesh_addVertGroup( PyObject * self, PyObject * args );
101 static PyObject *NMesh_removeVertGroup( PyObject * self, PyObject * args );
102 static PyObject *NMesh_assignVertsToGroup( PyObject * self, PyObject * args );
103 static PyObject *NMesh_removeVertsFromGroup( PyObject * self,PyObject * args );
104 static PyObject *NMesh_getVertsFromGroup( PyObject * self, PyObject * args );
105 static PyObject *NMesh_renameVertGroup( PyObject * self, PyObject * args );
106 static PyObject *NMesh_getVertGroupNames( PyObject * self );
107 static PyObject *NMesh_transform (PyObject *self, PyObject *args);
108
109 static char NMesh_printDebug_doc[] =
110   "print debug info about the mesh.";
111
112 static char NMesh_getKey_doc[] =
113         "get the Key object linked to this mesh";
114
115 static char NMesh_addEdge_doc[] =
116   "create an edge between two vertices.\n\
117 If an edge already exists between those vertices, it is returned.\n\
118 (In Blender, only zero or one edge can link two vertices.)\n\
119 Created edge is automatically added to edges list.";
120
121 static char NMesh_findEdge_doc[] =
122   "find an edge between two vertices.";
123
124 static char NMesh_removeEdge_doc[] =
125   "remove an edge between two vertices.\n\
126 All faces using this edge are removed from faces list.";
127
128 static char NMesh_addFace_doc[] =
129   "add a face to face list and add to edge list (if edge data exists) necessary edges.";
130
131 static char NMesh_removeFace_doc[] =
132   "remove a face for face list and remove edges no more used by any other face (if \
133 edge data exists).";
134
135 static char NMesh_addVertGroup_doc[] =
136         "add a named and empty vertex(deform) Group to a mesh that has been linked\n\
137 to an object. ";
138
139 static char NMesh_removeVertGroup_doc[] =
140         "remove a named vertex(deform) Group from a mesh that has been linked\n\
141 to an object.  Will remove all verts assigned to group.";
142
143 static char NMesh_assignVertsToGroup_doc[] =
144         "Adds an array (a python list) of vertex points (by index) to a named\n\
145 vertex group.  The list will have an associated wieght assigned to them.\n\
146 The weight represents the amount of influence this group has over these\n\
147 vertex points. Weights should be in the range of 0.0 - 1.0.\n\
148 The assignmode can be either 'add', 'subtract', or 'replace'.  If this vertex\n\
149 is not assigned to the group 'add' creates a new association with the weight\n\
150 specified, otherwise the weight given is added to the current weight of the\n\
151 vertex.\n\
152 'subtract' will attempt to subtract the weight passed from a vertex already\n\
153 associated with a group, else it does nothing. 'replace' attempts to replace\n\
154 the weight with the new weight value for an already associated vertex/group,\n\
155 else it does nothing. The mesh must have all it's vertex points set before\n\
156 attempting to assign any vertex points to a vertex group.";
157
158 static char NMesh_removeVertsFromGroup_doc[] =
159         "Remove an array (a python list) of vertex points from a named group in a\n\
160 mesh that has been linked to an object. If no list is given this will remove\n\
161 all vertex point associations with the group passed";
162
163 static char NMesh_getVertsFromGroup_doc[] =
164         "By passing a python list of vertex indices and a named group, this will\n\
165 return a python list representing the indeces that are a part of this vertex.\n\
166 group. If no association was found for the index passed nothing will be\n\
167 return for the index. An optional flag will also return the weights as well";
168
169 static char NMesh_renameVertGroup_doc[] = "Renames a vertex group";
170
171 static char NMesh_getVertGroupNames_doc[] =
172         "Returns a list of all the vertex group names";
173
174 static char M_NMesh_doc[] = "The Blender.NMesh submodule";
175
176 static char M_NMesh_Col_doc[] = "([r, g, b, a]) - Get a new mesh color\n\n\
177 [r=255, g=255, b=255, a=255] Specify the color components";
178
179 static char M_NMesh_Face_doc[] =
180         "(vertexlist = None) - Get a new face, and pass optional vertex list";
181
182 static char NMFace_append_doc[] =
183         "(vert) - appends Vertex 'vert' to face vertex list";
184
185 static char M_NMesh_Vert_doc[] = "([x, y, z]) - Get a new vertex\n\n\
186 [x, y, z] Specify new coordinates";
187
188 static char NMesh_getMaterials_doc[] =
189         "(i = -1) - Get this mesh's list of materials.\n\
190 (i = -1) - int: determines the list's contents:\n\
191 -1: return the current list, possibly modified by the script (default);\n\
192  0: get a fresh list from the Blender mesh -- modifications not included,\n\
193     unless the script called mesh.update() first;\n\
194  1: like 0, but does not ignore empty slots, returns them as 'None'.";
195
196 static char NMesh_setMaterials_doc[] =
197         "(matlist) - Set this mesh's list of materials.  This method makes sure\n\
198 the passed matlist is valid (can only include up to 16 materials and None's).";
199
200 static char NMesh_addMaterial_doc[] =
201         "(material) - add a new Blender Material 'material' to this Mesh's materials\n\
202 list.";
203
204 static char NMesh_insertKey_doc[] =
205         "(frame = None, type = 'relative') - inserts a Mesh key at the given frame\n\
206 if called without arguments, it inserts the key at the current Scene frame.\n\
207 (type) - 'relative' or 'absolute'.  Only relevant on the first call to this\n\
208 function for each nmesh.";
209
210 static char NMesh_removeAllKeys_doc[] =
211         "() - removes all keys from this mesh\n\
212 returns True if successful or False if this NMesh wasn't linked to a real\n\
213 Blender Mesh yet or the Mesh had no keys";
214
215 static char NMesh_getSelectedFaces_doc[] =
216         "(flag = None) - returns list of selected Faces\n\
217 If flag = 1, return indices instead";
218
219 static char NMesh_getActiveFace_doc[] =
220         "returns the index of the active face ";
221
222 static char NMesh_hasVertexUV_doc[] =
223         "(flag = None) - returns 1 if Mesh has per vertex UVs ('Sticky')\n\
224 The optional argument sets the Sticky flag";
225
226 static char NMesh_hasFaceUV_doc[] =
227         "(flag = None) - returns 1 if Mesh has textured faces\n\
228 The optional argument sets the textured faces flag";
229
230 static char NMesh_hasVertexColours_doc[] =
231         "(flag = None) - returns 1 if Mesh has vertex colors.\n\
232 The optional argument sets the vertex color flag";
233
234 static char NMesh_getVertexInfluences_doc[] =
235         "Return a list of the influences of bones in the vertex \n\
236 specified by index. The list contains pairs with the \n\
237 bone name and the weight.";
238
239 static char NMesh_update_doc[] =
240 "(recalc_normals = 0, store_edges = 0, vertex_shade = 0) - Updates the Mesh.\n\
241 Optional arguments: if given and nonzero:\n\
242 'recalc_normals': normal vectors are recalculated;\n\
243 'store_edges': edges data is stored.\n\
244 'vertex_shade': vertex colors are added based on the current lamp setup.";
245
246 static char NMesh_getMode_doc[] =
247         "() - get the mode flags of this nmesh as an or'ed int value.";
248
249 static char NMesh_setMode_doc[] =
250         "(int or none to 5 strings) - set the mode flags of this nmesh.\n\
251 () - unset all flags.";
252
253 static char NMesh_getMaxSmoothAngle_doc[] =
254         "() - get the max smooth angle for mesh auto smoothing.";
255
256 static char NMesh_setMaxSmoothAngle_doc[] =
257         "(int) - set the max smooth angle for mesh auto smoothing in the range\n\
258 [1,80] in degrees.";
259
260 static char NMesh_getSubDivLevels_doc[] =
261         "() - get the subdivision levels for display and rendering: [display, render]";
262
263 static char NMesh_setSubDivLevels_doc[] =
264         "([int, int]) - set the subdivision levels for [display, render] -- they are\n\
265 clamped to the range [0,6].";
266
267 static char M_NMesh_New_doc[] =
268         "() - returns a new, empty NMesh mesh object\n";
269
270 static char M_NMesh_GetRaw_doc[] = "([name]) - Get a raw mesh from Blender\n\n\
271 [name] Name of the mesh to be returned\n\n\
272 If name is not specified a new empty mesh is\n\
273 returned, otherwise Blender returns an existing\n\
274 mesh.";
275
276 static char M_NMesh_GetNames_doc[] = "\
277 () - Get a list with the names of all available meshes in Blender\n\n\
278 Any of these names can be passed to NMesh.GetRaw() for the actual mesh data.";
279
280 static char M_NMesh_GetRawFromObject_doc[] =
281         "(name) - Get the raw mesh used by a Blender object\n\n\
282 (name) Name of the object to get the mesh from\n\n\
283 This returns the mesh as used by the object, which\n\
284 means it contains all deformations and modifications.";
285
286 static char M_NMesh_PutRaw_doc[] =
287         "(mesh, name = None, recalc_normals = 1, store_edges = 0]) -\n\
288 Return a raw mesh to Blender\n\n\
289 (mesh) The NMesh object to store\n\
290 [name] The mesh to replace\n\
291 [recalc_normals = 1] Flag to control vertex normal recalculation\n\
292 [store_edges=0] Store edges data in the blender mesh\n\
293 If the name of a mesh to replace is not given a new\n\
294 object is created and returned.";
295
296 static char NMesh_transform_doc[] =
297 "(matrix, recalc_normals = 0) - Transform the mesh by the supplied 4x4 matrix\n\
298 if recalc_normals is True, vertex normals are transformed along with \n\
299 vertex coordinatess.\n";
300
301
302 void mesh_update( Mesh * mesh, Object * ob )
303 {
304         if (ob) {
305                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
306         }
307         else {
308                 ob = G.main->object.first;
309                 while (ob) {
310                         if (ob->data == mesh) {
311                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
312                                 break;
313                         }
314                         ob = ob->id.next;
315                 }
316         }
317 }
318
319 /*
320  * before trying to convert NMesh data back to mesh, verify that the
321  * lists contain the right type of data
322  */
323
324 static int check_NMeshLists( BPy_NMesh *nmesh )
325 {
326         int i;
327
328         if( !PySequence_Check( nmesh->verts ) )
329                 return EXPP_ReturnIntError( PyExc_AttributeError,
330                                               "nmesh verts are not a sequence" );
331         if( !PySequence_Check( nmesh->edges ) )
332                 return EXPP_ReturnIntError( PyExc_AttributeError,
333                                               "nmesh edges are not a sequence" );
334         if( !PySequence_Check( nmesh->faces ) )
335                 return EXPP_ReturnIntError( PyExc_AttributeError,
336                                               "nmesh faces are not a sequence" );
337         if( !PySequence_Check( nmesh->materials ) )
338                 return EXPP_ReturnIntError( PyExc_AttributeError,
339                                               "nmesh materials are not a sequence" );
340
341         if( EXPP_check_sequence_consistency( nmesh->verts, &NMVert_Type ) != 1 )
342                 return EXPP_ReturnIntError( PyExc_AttributeError,
343                                               "nmesh vertices must be NMVerts" );
344         if( EXPP_check_sequence_consistency( nmesh->edges, &NMEdge_Type ) != 1 )
345                 return EXPP_ReturnIntError( PyExc_AttributeError,
346                                               "nmesh edges must be NMEdges" );
347         if( EXPP_check_sequence_consistency( nmesh->faces, &NMFace_Type ) != 1 )
348                 return EXPP_ReturnIntError( PyExc_AttributeError,
349                                               "nmesh faces must be NMFaces" );
350         for( i = 0 ; i < PySequence_Length(nmesh->faces); ++i ) {
351                 int j, err=0;
352                 PyObject *col, *v, *uv;
353         BPy_NMFace *face=(BPy_NMFace *)PySequence_GetItem(nmesh->faces, i);
354
355                 col = face->col;
356                 uv = face->uv;
357                 v = face->v;
358                 Py_DECREF( face );
359                 if( EXPP_check_sequence_consistency( face->col, &NMCol_Type ) != 1 ) {
360                         return EXPP_ReturnIntError( PyExc_AttributeError,
361                                               "nmesh face col must be NMCols" );
362                 }
363                 if( EXPP_check_sequence_consistency( face->v, &NMVert_Type ) != 1 )
364                         return EXPP_ReturnIntError( PyExc_AttributeError,
365                                               "nmesh face v must be NMVerts" );
366
367                 for( j = 0 ; !err && j < PySequence_Length( face->uv ); ++j ) {
368                         PyObject *uv = PySequence_GetItem( face->uv, j);
369                         if( PySequence_Check(uv) && PySequence_Length(uv) == 2 ) {
370                         PyObject *p1 = PySequence_GetItem(uv, 0);
371                         PyObject *p2 = PySequence_GetItem(uv, 1);
372                                 if( !PyNumber_Check(p1) || !PyNumber_Check(p2) )
373                                         err = 1;
374                                 Py_DECREF( p1 );
375                                 Py_DECREF( p2 );
376                         }
377                         else {
378                                 err = 1;
379                         }
380
381                         Py_DECREF( uv );
382                 }
383                 if( err )
384                         return EXPP_ReturnIntError( PyExc_AttributeError,
385                                               "nmesh face uv must contain sequence of 2 floats" );
386         }
387         return 0;
388 }
389
390
391 /*****************************/
392 /*                      Mesh Color Object                */
393 /*****************************/
394
395 static void NMCol_dealloc( PyObject * self )
396 {
397         PyObject_DEL( self );
398 }
399
400 static BPy_NMCol *newcol( char r, char g, char b, char a )
401 {
402         BPy_NMCol *mc = ( BPy_NMCol * ) PyObject_NEW( BPy_NMCol, &NMCol_Type );
403
404         mc->r = r;
405         mc->g = g;
406         mc->b = b;
407         mc->a = a;
408
409         return mc;
410 }
411
412 static PyObject *M_NMesh_Col( PyObject * self, PyObject * args )
413 {
414         char r = 255, g = 255, b = 255, a = 255;
415
416         if( PyArg_ParseTuple( args, "|bbbb", &r, &g, &b, &a ) )
417                 return ( PyObject * ) newcol( r, g, b, a );
418
419         return NULL;
420 }
421
422 static PyObject *NMCol_getattr( PyObject * self, char *name )
423 {
424         BPy_NMCol *mc = ( BPy_NMCol * ) self;
425
426         if( strcmp( name, "r" ) == 0 )
427                 return Py_BuildValue( "i", mc->r );
428         else if( strcmp( name, "g" ) == 0 )
429                 return Py_BuildValue( "i", mc->g );
430         else if( strcmp( name, "b" ) == 0 )
431                 return Py_BuildValue( "i", mc->b );
432         else if( strcmp( name, "a" ) == 0 )
433                 return Py_BuildValue( "i", mc->a );
434         else if( strcmp( name, "__members__" ) == 0 )
435                 return Py_BuildValue( "[s,s,s,s]", "r", "g", "b", "a" );
436
437         return EXPP_ReturnPyObjError( PyExc_AttributeError, name );
438 }
439
440 static int NMCol_setattr( PyObject * self, char *name, PyObject * v )
441 {
442         BPy_NMCol *mc = ( BPy_NMCol * ) self;
443         char ival;
444
445         if( !PyArg_Parse( v, "b", &ival ) )
446                 return -1;
447
448         ival = ( char ) EXPP_ClampInt( ival, 0, 255 );
449
450         if( strcmp( name, "r" ) == 0 )
451                 mc->r = (unsigned char)ival;
452         else if( strcmp( name, "g" ) == 0 )
453                 mc->g = (unsigned char)ival;
454         else if( strcmp( name, "b" ) == 0 )
455                 mc->b = (unsigned char)ival;
456         else if( strcmp( name, "a" ) == 0 )
457                 mc->a = (unsigned char)ival;
458         else
459                 return -1;
460
461         return 0;
462 }
463
464 static PyObject *NMCol_repr( BPy_NMCol * self )
465 {
466         static char s[256];
467         sprintf( s, "[NMCol - <%d, %d, %d, %d>]", self->r, self->g, self->b,
468                  self->a );
469         return Py_BuildValue( "s", s );
470 }
471
472 PyTypeObject NMCol_Type = {
473         PyObject_HEAD_INIT( NULL ) 0,   /* ob_size */
474         "Blender NMCol",        /* tp_name */
475         sizeof( BPy_NMCol ),    /* tp_basicsize */
476         0,                      /* tp_itemsize */
477         /* methods */
478         ( destructor ) NMCol_dealloc,   /* tp_dealloc */
479         ( printfunc ) 0,        /* tp_print */
480         ( getattrfunc ) NMCol_getattr,  /* tp_getattr */
481         ( setattrfunc ) NMCol_setattr,  /* tp_setattr */
482         0,                      /* tp_compare */
483         ( reprfunc ) NMCol_repr,        /* tp_repr */
484         0,                      /* tp_as_number */
485         0,                      /* tp_as_sequence */
486         0,                      /* tp_as_mapping */
487         0,                      /* tp_hash */
488         0,                      /* tp_as_number */
489         0,                      /* tp_as_sequence */
490         0,                      /* tp_as_mapping */
491         0,                      /* tp_hash */
492         0,0,0,0,0,0,0,0,0,0,0,0,0,0,
493         0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* up to tp_del to avoid a warning */
494 };
495
496 /*****************************/
497 /*              NMesh Python Object              */
498 /*****************************/
499 static void NMFace_dealloc( PyObject * self )
500 {
501         BPy_NMFace *mf = ( BPy_NMFace * ) self;
502
503         Py_DECREF( mf->v );
504         Py_DECREF( mf->uv );
505         Py_DECREF( mf->col );
506
507         PyObject_DEL( self );
508 }
509
510 static PyObject *new_NMFace( PyObject * vertexlist )
511 {
512         BPy_NMFace *mf = PyObject_NEW( BPy_NMFace, &NMFace_Type );
513         PyObject *vlcopy;
514
515         if( vertexlist ) {      /* create a copy of the given vertex list */
516                 PyObject *item;
517                 int i, len = PyList_Size( vertexlist );
518
519                 vlcopy = PyList_New( len );
520
521                 if( !vlcopy ) {
522                         Py_DECREF(mf);
523                         return EXPP_ReturnPyObjError( PyExc_MemoryError,
524                                                       "couldn't create PyList" );
525                 }
526                 for( i = 0; i < len; i++ ) {
527                         item = PySequence_GetItem( vertexlist, i );     /* PySequence increfs */
528
529                         if( item )
530                                 PyList_SET_ITEM( vlcopy, i, item );
531                         else {
532                                 Py_DECREF(mf);
533                                 Py_DECREF(vlcopy);
534                                 return EXPP_ReturnPyObjError
535                                         ( PyExc_RuntimeError,
536                                           "couldn't get vertex from a PyList" );
537                         }
538                 }
539         } else                  /* create an empty vertex list */
540                 vlcopy = PyList_New( 0 );
541
542         mf->v = vlcopy;
543         mf->uv = PyList_New( 0 );
544         mf->image = NULL;
545         mf->mode = TF_DYNAMIC + TF_TEX;
546         mf->flag = TF_SELECT;
547         mf->transp = TF_SOLID;
548         mf->col = PyList_New( 0 );
549
550         mf->mf_flag = 0;
551         mf->mat_nr = 0;
552         mf->orig_index = -1;
553
554         return ( PyObject * ) mf;
555 }
556
557 static PyObject *M_NMesh_Face( PyObject * self, PyObject * args )
558 {
559         PyObject *vertlist = NULL;
560
561         if( !PyArg_ParseTuple( args, "|O!", &PyList_Type, &vertlist ) )
562                 return EXPP_ReturnPyObjError( PyExc_TypeError,
563                                               "expected a list of vertices or nothing as argument" );
564
565 /*      if (!vertlist) vertlist = PyList_New(0); */
566
567         return new_NMFace( vertlist );
568 }
569
570 static PyObject *NMFace_append( PyObject * self, PyObject * args )
571 {
572         PyObject *vert;
573         BPy_NMFace *f = ( BPy_NMFace * ) self;
574
575         if( !PyArg_ParseTuple( args, "O!", &NMVert_Type, &vert ) )
576                 return EXPP_ReturnPyObjError( PyExc_TypeError,
577                                               "expected an NMVert object" );
578
579         PyList_Append( f->v, vert );
580
581         Py_RETURN_NONE;
582 }
583
584 #undef MethodDef
585 #define MethodDef(func) {#func, NMFace_##func, METH_VARARGS, NMFace_##func##_doc}
586
587 static struct PyMethodDef NMFace_methods[] = {
588         MethodDef( append ),
589         {NULL, NULL, 0, NULL}
590 };
591
592 static PyObject *NMFace_getattr( PyObject * self, char *name )
593 {
594         BPy_NMFace *mf = ( BPy_NMFace * ) self;
595
596         if( strcmp( name, "v" ) == 0 )
597                 return Py_BuildValue( "O", mf->v );
598         else if( strcmp( name, "col" ) == 0 )
599                 return Py_BuildValue( "O", mf->col );
600         else if( strcmp( name, "mat" ) == 0 )   // emulation XXX
601                 return Py_BuildValue( "i", mf->mat_nr );
602         else if( strcmp( name, "materialIndex" ) == 0 )
603                 return Py_BuildValue( "i", mf->mat_nr );
604         else if( strcmp( name, "smooth" ) == 0 )
605                 return Py_BuildValue( "i", (mf->mf_flag & ME_SMOOTH) ? 1:0 );
606         else if( strcmp( name, "sel" ) == 0 )
607                 return Py_BuildValue( "i", (mf->mf_flag & ME_FACE_SEL) ? 1:0 );
608         else if( strcmp( name, "hide" ) == 0 )
609                 return Py_BuildValue( "i", (mf->mf_flag & ME_HIDE) ? 1:0 );
610
611         else if( strcmp( name, "image" ) == 0 ) {
612                 if( mf->image )
613                         return Image_CreatePyObject( mf->image );
614                 else
615                         Py_RETURN_NONE;
616         }
617
618         else if( strcmp( name, "mode" ) == 0 )
619                 return Py_BuildValue( "i", mf->mode );
620         else if( strcmp( name, "flag" ) == 0 )
621                 return Py_BuildValue( "i", mf->flag );
622         else if( strcmp( name, "transp" ) == 0 )
623                 return Py_BuildValue( "i", mf->transp );
624         else if( strcmp( name, "uv" ) == 0 )
625                 return Py_BuildValue( "O", mf->uv );
626
627         else if( ( strcmp( name, "normal" ) == 0 )
628                  || ( strcmp( name, "no" ) == 0 ) ) {
629
630                 if( EXPP_check_sequence_consistency( mf->v, &NMVert_Type ) ==
631                     1 ) {
632
633                         float fNormal[3] = { 0.0, 0.0, 0.0 };
634                         float *vco[4] = { NULL, NULL, NULL, NULL };
635                         int nSize = PyList_Size( mf->v );
636                         int loop;
637
638                         if( nSize != 3 && nSize != 4 )
639                                 return EXPP_ReturnPyObjError
640                                         ( PyExc_AttributeError,
641                                           "face must contain either 3 or 4 verts" );
642
643                         for( loop = 0; loop < nSize; loop++ ) {
644                                 BPy_NMVert *v =
645                                         ( BPy_NMVert * ) PyList_GetItem( mf->v,
646                                                                          loop );
647                                 vco[loop] = ( float * ) v->co;
648                         }
649
650                         if( nSize == 4 )
651                                 CalcNormFloat4( vco[0], vco[1], vco[2], vco[3],
652                                                 fNormal );
653                         else
654                                 CalcNormFloat( vco[0], vco[1], vco[2],
655                                                fNormal );
656
657                         return Py_BuildValue( "[f,f,f]", fNormal[0],
658                                               fNormal[1], fNormal[2] );
659                 } else          // EXPP_check_sequence_consistency failed
660                         return EXPP_ReturnPyObjError( PyExc_AttributeError,
661                                                       "this face does not contain a series of NMVerts" );
662         }
663
664         else if( strcmp( name, "__members__" ) == 0 )
665                 return Py_BuildValue( "[s,s,s,s,s,s,s,s,s,s,s,s,s]",
666                                       "v", "col", "mat", "materialIndex",
667                                       "smooth", "image", "mode", "flag",
668                                       "transp", "uv", "normal", "sel", "hide");
669         return Py_FindMethod( NMFace_methods, ( PyObject * ) self, name );
670 }
671
672 static int NMFace_setattr( PyObject * self, char *name, PyObject * v )
673 {
674         BPy_NMFace *mf = ( BPy_NMFace * ) self;
675         short ival;
676         char cval;
677
678         if( strcmp( name, "v" ) == 0 ) {
679
680                 if( PySequence_Check( v ) ) {
681                         Py_DECREF( mf->v );
682                         mf->v = EXPP_incr_ret( v );
683
684                         return 0;
685                 }
686         } else if( strcmp( name, "col" ) == 0 ) {
687
688                 if( PySequence_Check( v ) ) {
689                         Py_DECREF( mf->col );
690                         mf->col = EXPP_incr_ret( v );
691
692                         return 0;
693                 }
694         } else if( !strcmp( name, "mat" ) || !strcmp( name, "materialIndex" ) ) {
695                 PyArg_Parse( v, "b", &cval );
696                 mf->mat_nr = cval;
697
698                 return 0;
699         } else if( strcmp( name, "smooth" ) == 0 ) {
700                 PyArg_Parse( v, "h", &ival );
701                 if (ival) mf->mf_flag |= ME_SMOOTH;
702                 else mf->mf_flag &= ~ME_SMOOTH;
703
704                 return 0;
705         } else if( strcmp( name, "sel" ) == 0 ) {
706                 PyArg_Parse( v, "h", &ival );
707                 if (ival) mf->mf_flag |= ME_FACE_SEL;
708                 else mf->mf_flag &= ~ME_FACE_SEL;
709
710                 return 0;
711         } else if( strcmp( name, "hide" ) == 0 ) {
712                 PyArg_Parse( v, "h", &ival );
713                 if (ival) mf->mf_flag |= ME_HIDE;
714                 else mf->mf_flag &= ~ME_HIDE;
715
716                 return 0;
717
718         } else if( strcmp( name, "uv" ) == 0 ) {
719
720                 if( PySequence_Check( v ) ) {
721                         Py_DECREF( mf->uv );
722                         mf->uv = EXPP_incr_ret( v );
723
724                         return 0;
725                 }
726         } else if( strcmp( name, "flag" ) == 0 ) {
727                 PyArg_Parse( v, "h", &ival );
728                 mf->flag = ival;
729
730                 return 0;
731         } else if( strcmp( name, "mode" ) == 0 ) {
732                 PyArg_Parse( v, "h", &ival );
733                 mf->mode = ival;
734
735                 return 0;
736         } else if( strcmp( name, "transp" ) == 0 ) {
737                 PyArg_Parse( v, "b", &cval );
738                 mf->transp = cval;
739
740                 return 0;
741         } else if( strcmp( name, "image" ) == 0 ) {
742                 PyObject *pyimg;
743                 if( !PyArg_Parse( v, "O!", &Image_Type, &pyimg ) )
744                         return EXPP_ReturnIntError( PyExc_TypeError,
745                                                     "expected image object" );
746
747                 if( pyimg == Py_None ) {
748                         mf->image = NULL;
749
750                         return 0;
751                 }
752
753                 mf->image = ( ( BPy_Image * ) pyimg )->image;
754
755                 return 0;
756         }
757
758         return EXPP_ReturnIntError( PyExc_AttributeError, name );
759 }
760
761 static PyObject *NMFace_repr( PyObject * self )
762 {
763         return PyString_FromString( "[NMFace]" );
764 }
765
766 static int NMFace_len( BPy_NMFace * self )
767 {
768         return PySequence_Length( self->v );
769 }
770
771 static PyObject *NMFace_item( BPy_NMFace * self, int i )
772 {
773         return PySequence_GetItem( self->v, i );        // new ref
774 }
775
776 static PyObject *NMFace_slice( BPy_NMFace * self, int begin, int end )
777 {
778         return PyList_GetSlice( self->v, begin, end );  // new ref
779 }
780
781 static PySequenceMethods NMFace_SeqMethods = {
782         ( inquiry ) NMFace_len, /* sq_length */
783         ( binaryfunc ) 0,       /* sq_concat */
784         ( intargfunc ) 0,       /* sq_repeat */
785         ( intargfunc ) NMFace_item,     /* sq_item */
786         ( intintargfunc ) NMFace_slice, /* sq_slice */
787         ( intobjargproc ) 0,    /* sq_ass_item */
788         ( intintobjargproc ) 0, /* sq_ass_slice */
789         0,0,0,
790 };
791
792 PyTypeObject NMFace_Type = {
793         PyObject_HEAD_INIT( NULL ) 0,   /*ob_size */
794         "Blender NMFace",       /*tp_name */
795         sizeof( BPy_NMFace ),   /*tp_basicsize */
796         0,                      /*tp_itemsize */
797         /* methods */
798         ( destructor ) NMFace_dealloc,  /*tp_dealloc */
799         ( printfunc ) 0,        /*tp_print */
800         ( getattrfunc ) NMFace_getattr, /*tp_getattr */
801         ( setattrfunc ) NMFace_setattr, /*tp_setattr */
802         0,                      /*tp_compare */
803         ( reprfunc ) NMFace_repr,       /*tp_repr */
804         0,                      /*tp_as_number */
805         &NMFace_SeqMethods,     /*tp_as_sequence */
806         0,                      /*tp_as_mapping */
807         0,                      /*tp_hash */
808         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
809         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* up to tp_del to avoid a warning */
810 };
811
812 static BPy_NMVert *newvert( float *co )
813 {
814         BPy_NMVert *mv = PyObject_NEW( BPy_NMVert, &NMVert_Type );
815
816         mv->co[0] = co[0];
817         mv->co[1] = co[1];
818         mv->co[2] = co[2];
819
820         mv->no[0] = mv->no[1] = mv->no[2] = 0.0;
821         mv->uvco[0] = mv->uvco[1] = mv->uvco[2] = 0.0;
822         mv->flag = 0;
823
824         return mv;
825 }
826
827 static PyObject *M_NMesh_Vert( PyObject * self, PyObject * args )
828 {
829         float co[3] = { 0.0, 0.0, 0.0 };
830
831         if( !PyArg_ParseTuple( args, "|fff", &co[0], &co[1], &co[2] ) )
832                 return EXPP_ReturnPyObjError( PyExc_TypeError,
833                                               "expected three floats (or nothing) as arguments" );
834
835         return ( PyObject * ) newvert( co );
836 }
837
838 static void NMVert_dealloc( PyObject * self )
839 {
840         PyObject_DEL( self );
841 }
842
843 static PyObject *NMVert_getattr( PyObject * self, char *name )
844 {
845         BPy_NMVert *mv = ( BPy_NMVert * ) self;
846
847         if( !strcmp( name, "co" ) || !strcmp( name, "loc" ) )
848                 return newVectorObject(mv->co,3,Py_WRAP);
849
850         else if( strcmp( name, "no" ) == 0 )
851                 return newVectorObject(mv->no,3,Py_WRAP);
852         else if( strcmp( name, "uvco" ) == 0 )
853                 return newVectorObject(mv->uvco,3,Py_WRAP);
854         else if( strcmp( name, "index" ) == 0 )
855                 return PyInt_FromLong( mv->index );
856         else if( strcmp( name, "sel" ) == 0 )
857                 return PyInt_FromLong( mv->flag & 1 );
858         else if( strcmp( name, "__members__" ) == 0 )
859                 return Py_BuildValue( "[s,s,s,s,s]", "co", "no", "uvco",
860                                       "index", "sel" );
861
862         return EXPP_ReturnPyObjError( PyExc_AttributeError, name );
863 }
864
865 static int NMVert_setattr( PyObject * self, char *name, PyObject * v )
866 {
867         BPy_NMVert *mv = ( BPy_NMVert * ) self;
868         int i;
869
870         if( strcmp( name, "index" ) == 0 ) {
871                 PyArg_Parse( v, "i", &i );
872                 mv->index = i;
873                 return 0;
874         } else if( strcmp( name, "sel" ) == 0 ) {
875                 PyArg_Parse( v, "i", &i );
876                 mv->flag = i ? 1 : 0;
877                 return 0;
878         } else if( strcmp( name, "uvco" ) == 0 ) {
879
880                 if( !PyArg_ParseTuple( v, "ff|f",
881                                        &( mv->uvco[0] ), &( mv->uvco[1] ),
882                                        &( mv->uvco[2] ) ) )
883                         return EXPP_ReturnIntError( PyExc_AttributeError,
884                                                     "Vector tuple or triple expected" );
885
886                 return 0;
887         }
888
889         return EXPP_ReturnIntError( PyExc_AttributeError, name );
890 }
891
892 static int NMVert_len( BPy_NMVert * self )
893 {
894         return 3;
895 }
896
897 static PyObject *NMVert_item( BPy_NMVert * self, int i )
898 {
899         if( i < 0 || i >= 3 )
900                 return EXPP_ReturnPyObjError( PyExc_IndexError,
901                                               "array index out of range" );
902
903         return Py_BuildValue( "f", self->co[i] );
904 }
905
906 static PyObject *NMVert_slice( BPy_NMVert * self, int begin, int end )
907 {
908         PyObject *list;
909         int count;
910
911         if( begin < 0 )
912                 begin = 0;
913         if( end > 3 )
914                 end = 3;
915         if( begin > end )
916                 begin = end;
917
918         list = PyList_New( end - begin );
919
920         for( count = begin; count < end; count++ )
921                 PyList_SetItem( list, count - begin,
922                                 PyFloat_FromDouble( self->co[count] ) );
923
924         return list;
925 }
926
927 static int NMVert_ass_item( BPy_NMVert * self, int i, PyObject * ob )
928 {
929         if( i < 0 || i >= 3 )
930                 return EXPP_ReturnIntError( PyExc_IndexError,
931                                             "array assignment index out of range" );
932
933         if( !PyNumber_Check( ob ) )
934                 return EXPP_ReturnIntError( PyExc_IndexError,
935                                             "NMVert member must be a number" );
936
937         self->co[i] = (float)PyFloat_AsDouble( ob );
938
939         return 0;
940 }
941
942 static int NMVert_ass_slice( BPy_NMVert * self, int begin, int end,
943                              PyObject * seq )
944 {
945         int count;
946
947         if( begin < 0 )
948                 begin = 0;
949         if( end > 3 )
950                 end = 3;
951         if( begin > end )
952                 begin = end;
953
954         if( !PySequence_Check( seq ) )
955                 EXPP_ReturnIntError( PyExc_TypeError,
956                                      "illegal argument type for built-in operation" );
957
958         if( PySequence_Length( seq ) != ( end - begin ) )
959                 EXPP_ReturnIntError( PyExc_TypeError,
960                                      "size mismatch in slice assignment" );
961
962         for( count = begin; count < end; count++ ) {
963                 PyObject *ob = PySequence_GetItem( seq, count );
964
965                 if( !PyArg_Parse( ob, "f", &self->co[count] ) ) {
966                         Py_DECREF( ob );
967                         return -1;
968                 }
969
970                 Py_DECREF( ob );
971         }
972
973         return 0;
974 }
975
976 static PySequenceMethods NMVert_SeqMethods = {
977         ( inquiry ) NMVert_len, /* sq_length */
978         ( binaryfunc ) 0,       /* sq_concat */
979         ( intargfunc ) 0,       /* sq_repeat */
980         ( intargfunc ) NMVert_item,     /* sq_item */
981         ( intintargfunc ) NMVert_slice, /* sq_slice */
982         ( intobjargproc ) NMVert_ass_item,      /* sq_ass_item */
983         ( intintobjargproc ) NMVert_ass_slice,  /* sq_ass_slice */
984         0,0,0,
985 };
986
987 PyTypeObject NMVert_Type = {
988         PyObject_HEAD_INIT( NULL ) 
989         0,      /*ob_size */
990         "Blender NMVert",       /*tp_name */
991         sizeof( BPy_NMVert ),   /*tp_basicsize */
992         0,                      /*tp_itemsize */
993         /* methods */
994         ( destructor ) NMVert_dealloc,  /*tp_dealloc */
995         ( printfunc ) 0,        /*tp_print */
996         ( getattrfunc ) NMVert_getattr, /*tp_getattr */
997         ( setattrfunc ) NMVert_setattr, /*tp_setattr */
998         0,                      /*tp_compare */
999         ( reprfunc ) 0,         /*tp_repr */
1000         0,                      /*tp_as_number */
1001         &NMVert_SeqMethods,     /*tp_as_sequence */
1002         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1003         0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_del */
1004 };
1005
1006
1007 /*****************************
1008  * NMEdge
1009  *****************************/
1010
1011 static BPy_NMEdge *new_NMEdge( BPy_NMVert * v1, BPy_NMVert * v2, char crease, short flag)
1012 {
1013   BPy_NMEdge *edge=NULL;
1014
1015   if (!v1 || !v2) return NULL;
1016   if (!BPy_NMVert_Check(v1) || !BPy_NMVert_Check(v2)) return NULL;
1017
1018   edge = PyObject_NEW( BPy_NMEdge, &NMEdge_Type );
1019
1020   edge->v1=EXPP_incr_ret((PyObject*)v1);
1021   edge->v2=EXPP_incr_ret((PyObject*)v2);
1022   edge->flag=flag;
1023   edge->crease=crease;
1024
1025   return edge;
1026 }
1027
1028 static void NMEdge_dealloc( PyObject * self )
1029 {
1030   BPy_NMEdge *edge=(BPy_NMEdge *)self;
1031
1032   Py_DECREF(edge->v1);
1033   Py_DECREF(edge->v2);
1034
1035   PyObject_DEL(self);
1036 }
1037
1038 static PyObject *NMEdge_getattr( PyObject * self, char *name )
1039 {
1040   BPy_NMEdge *edge=(BPy_NMEdge *)self;
1041
1042   if      ( strcmp( name, "v1" ) == 0 )
1043                 return EXPP_incr_ret( edge->v1 );
1044   else if ( strcmp( name, "v2" ) == 0 )
1045     return EXPP_incr_ret( edge->v2 );
1046   else if ( strcmp( name, "flag" ) == 0 )
1047     return PyInt_FromLong( edge->flag );
1048   else if ( strcmp( name, "crease" ) == 0 )
1049     return PyInt_FromLong( edge->crease );
1050   else if( strcmp( name, "__members__" ) == 0 )
1051     return Py_BuildValue( "[s,s,s,s]",
1052                           "v1", "v2", "flag", "crease" );
1053   
1054   return EXPP_ReturnPyObjError( PyExc_AttributeError, name );
1055 }
1056
1057 static int NMEdge_setattr( PyObject * self, char *name, PyObject * v )
1058 {
1059   BPy_NMEdge *edge=(BPy_NMEdge *)self;
1060
1061   if ( strcmp( name, "flag" ) == 0 )
1062   {
1063     short flag=0;
1064     if( !PyInt_Check( v ) )
1065       return EXPP_ReturnIntError( PyExc_TypeError,
1066                                   "expected int argument" );
1067
1068     flag = ( short ) PyInt_AsLong( v );
1069
1070     edge->flag = flag;
1071
1072     return 0;
1073   }
1074   else if ( strcmp( name, "crease" ) == 0 )
1075   {
1076     char crease=0;
1077     if( !PyInt_Check( v ) )
1078       return EXPP_ReturnIntError( PyExc_TypeError,
1079                                   "expected int argument" );
1080
1081     crease = ( char ) PyInt_AsLong( v );
1082
1083     edge->crease = crease;
1084
1085     return 0;
1086   }
1087
1088   return EXPP_ReturnIntError( PyExc_AttributeError, name );
1089 }
1090
1091 PyTypeObject NMEdge_Type = {
1092         PyObject_HEAD_INIT( NULL ) 
1093         0,      /*ob_size */
1094         "Blender NMEdge",       /*tp_name */
1095         sizeof( BPy_NMEdge ),   /*tp_basicsize */
1096         0,                      /*tp_itemsize */
1097         /* methods */
1098         ( destructor ) NMEdge_dealloc,  /*tp_dealloc */
1099         ( printfunc ) 0,        /*tp_print */
1100         ( getattrfunc ) NMEdge_getattr, /*tp_getattr */
1101         ( setattrfunc ) NMEdge_setattr, /*tp_setattr */
1102         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1103         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1104         0,0,0,0,0,0,
1105 };
1106
1107 static void NMesh_dealloc( PyObject * self )
1108 {
1109         BPy_NMesh *me = ( BPy_NMesh * ) self;
1110
1111         CustomData_free( &me->fdata, me->totfdata );
1112
1113         Py_DECREF( me->name );
1114         Py_DECREF( me->verts );
1115         Py_DECREF( me->faces );
1116         Py_DECREF( me->materials );
1117         Py_DECREF( me->edges );
1118
1119         PyObject_DEL( self );
1120 }
1121
1122 static PyObject *NMesh_getMaterials( PyObject * self, PyObject * args )
1123 {
1124         BPy_NMesh *nm = ( BPy_NMesh * ) self;
1125         PyObject *list = NULL;
1126         Mesh *me = nm->mesh;
1127         int all = -1;
1128
1129         if( !PyArg_ParseTuple( args, "|i", &all ) )
1130                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1131                                               "expected nothing or an int (bool) as argument" );
1132
1133         if( all >= 0 ) {
1134                 if (!me)
1135                         return EXPP_ReturnPyObjError(PyExc_TypeError,
1136                                         "meshes obtained with GetRawFromObject don't support this option");
1137
1138                 list = EXPP_PyList_fromMaterialList( me->mat, me->totcol,
1139                                                      all );
1140                 Py_DECREF( nm->materials );     /* update nmesh.materials attribute */
1141                 nm->materials = EXPP_incr_ret( list );
1142         } else
1143                 list = EXPP_incr_ret( nm->materials );
1144
1145         return list;
1146 }
1147
1148 static PyObject *NMesh_setMaterials( PyObject * self, PyObject * args )
1149 {
1150         BPy_NMesh *me = ( BPy_NMesh * ) self;
1151         PyObject *pymats = NULL;
1152
1153         if( !PyArg_ParseTuple( args, "O!", &PyList_Type, &pymats ) )
1154                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1155                                               "expected a list of materials (None's also accepted) as argument" );
1156
1157         if( !EXPP_check_sequence_consistency( pymats, &Material_Type ) )
1158                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1159                                               "list should only contain materials (None's also accepted)" );
1160
1161         if( PyList_Size( pymats ) > 16 )
1162                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1163                                               "list can't have more than 16 materials" );
1164
1165         Py_DECREF( me->materials );
1166         me->materials = EXPP_incr_ret( pymats );
1167
1168         Py_RETURN_NONE;
1169 }
1170
1171 static PyObject *NMesh_addMaterial( PyObject * self, PyObject * args )
1172 {
1173         BPy_NMesh *me = ( BPy_NMesh * ) self;
1174         BPy_Material *pymat;
1175         Material *mat;
1176         PyObject *iter;
1177         int i, len = 0;
1178
1179         if( !PyArg_ParseTuple( args, "O!", &Material_Type, &pymat ) )
1180                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1181                                               "expected Blender Material PyObject" );
1182
1183         mat = pymat->material;
1184         len = PyList_Size( me->materials );
1185
1186         if( len >= 16 )
1187                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1188                                               "object data material lists can't have more than 16 materials" );
1189
1190         for( i = 0; i < len; i++ ) {
1191                 iter = PyList_GetItem( me->materials, i );
1192                 if( mat == Material_FromPyObject( iter ) )
1193                         return EXPP_ReturnPyObjError( PyExc_AttributeError,
1194                                                       "material already in the list" );
1195         }
1196
1197         PyList_Append( me->materials, ( PyObject * ) pymat );
1198
1199         Py_RETURN_NONE;
1200 }
1201
1202 static PyObject *NMesh_getKey( BPy_NMesh * self )
1203 {
1204         PyObject *keyobj;
1205
1206         if( self->mesh->key )
1207                 keyobj = Key_CreatePyObject(self->mesh->key);
1208         else
1209                 keyobj = EXPP_incr_ret(Py_None);
1210         
1211         return keyobj;
1212 }
1213
1214 static PyObject *NMesh_removeAllKeys( PyObject * self, PyObject * args )
1215 {
1216         BPy_NMesh *nm = ( BPy_NMesh * ) self;
1217         Mesh *me = nm->mesh;
1218
1219         if( !PyArg_ParseTuple( args, "" ) )
1220                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1221                                               "this function expects no arguments" );
1222
1223         if( !me || !me->key )
1224                 return EXPP_incr_ret_False();
1225
1226         me->key->id.us--;
1227         me->key = 0;
1228
1229         return EXPP_incr_ret_True();
1230 }
1231
1232 static PyObject *NMesh_insertKey( PyObject * self, PyObject * args )
1233 {
1234         int fra = -1, oldfra = -1;
1235         char *type = NULL;
1236         short typenum;
1237         BPy_NMesh *nm = ( BPy_NMesh * ) self;
1238         Mesh *mesh = nm->mesh;
1239
1240         if( !PyArg_ParseTuple( args, "|is", &fra, &type ) )
1241                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1242                                               "expected nothing or an int and optionally a string as arguments" );
1243
1244         if( !type || !strcmp( type, "relative" ) )
1245                 typenum = 1;
1246         else if( !strcmp( type, "absolute" ) )
1247                 typenum = 2;
1248         else
1249                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
1250                                               "if given, type should be 'relative' or 'absolute'" );
1251
1252         if( fra > 0 ) {
1253                 fra = EXPP_ClampInt( fra, 1, NMESH_FRAME_MAX );
1254                 oldfra = G.scene->r.cfra;
1255                 G.scene->r.cfra = (int)fra;
1256         }
1257
1258         if( !mesh )
1259                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1260                                               "update this NMesh first with its .update() method" );
1261
1262         insert_meshkey( mesh, typenum );
1263         allspace(REMAKEIPO, 0);
1264
1265         if( fra > 0 )
1266                 G.scene->r.cfra = (int)oldfra;
1267
1268         Py_RETURN_NONE;
1269 }
1270
1271 static PyObject *NMesh_getSelectedFaces( PyObject * self, PyObject * args )
1272 {
1273         BPy_NMesh *nm = ( BPy_NMesh * ) self;
1274         Mesh *me = nm->mesh;
1275         int i, totfaces, flag = 0;
1276         PyObject *l, *pyval;
1277
1278         if( !PyArg_ParseTuple( args, "|i", &flag ) )
1279                 return EXPP_ReturnPyObjError( PyExc_ValueError,
1280                                               "expected int argument (or nothing)" );
1281         
1282         l = PyList_New( 0 );
1283         if( me == NULL || me->mface == NULL)
1284                 return l;
1285         
1286         /* make sure not to write more faces then we have */
1287         totfaces= MIN2(me->totface, PySequence_Length(nm->faces));
1288         
1289         if( flag ) {
1290                 for( i = 0; i < totfaces; i++ ) {
1291                         if( me->mface[i].flag & ME_FACE_SEL ) {
1292                                 pyval = PyInt_FromLong( i );
1293                                 PyList_Append( l, pyval );
1294                                 Py_DECREF(pyval);
1295                         }
1296                 }
1297         } else {
1298                 for( i = 0; i < totfaces; i++ ) {
1299                         if( me->mface[i].flag & ME_FACE_SEL )
1300                                 PyList_Append( l, PyList_GetItem( nm->faces, i ) );
1301                 }
1302         }
1303         return l;
1304 }
1305
1306 static PyObject *NMesh_getActiveFace( PyObject * self )
1307 {
1308         if( ( ( BPy_NMesh * ) self )->sel_face < 0 )
1309                 Py_RETURN_NONE;
1310
1311         return Py_BuildValue( "i", ( ( BPy_NMesh * ) self )->sel_face );
1312 }
1313
1314 static PyObject *NMesh_hasVertexUV( PyObject * self, PyObject * args )
1315 {
1316         BPy_NMesh *me = ( BPy_NMesh * ) self;
1317         int flag = -1;
1318
1319         if( !PyArg_ParseTuple( args, "|i", &flag ) )
1320                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1321                                               "expected int argument (or nothing)" );
1322
1323         switch ( flag ) {
1324         case 0:
1325                 me->flags &= ~NMESH_HASVERTUV;
1326                 break;
1327         case 1:
1328                 me->flags |= NMESH_HASVERTUV;
1329                 break;
1330         default:
1331                 break;
1332         }
1333
1334         if( me->flags & NMESH_HASVERTUV )
1335                 return EXPP_incr_ret_True();
1336         else
1337                 return EXPP_incr_ret_False();
1338 }
1339
1340 static PyObject *NMesh_hasFaceUV( PyObject * self, PyObject * args )
1341 {
1342         BPy_NMesh *me = ( BPy_NMesh * ) self;
1343         int flag = -1;
1344
1345         if( !PyArg_ParseTuple( args, "|i", &flag ) )
1346                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1347                                               "expected int argument (or nothing)" );
1348
1349         switch ( flag ) {
1350         case 0:
1351                 me->flags &= ~NMESH_HASFACEUV;
1352                 break;
1353         case 1:
1354                 me->flags |= NMESH_HASFACEUV;
1355                 break;
1356         default:
1357                 break;
1358         }
1359
1360         if( me->flags & NMESH_HASFACEUV )
1361                 return EXPP_incr_ret_True();
1362         else
1363                 return EXPP_incr_ret_False();
1364 }
1365
1366 static PyObject *NMesh_hasVertexColours( PyObject * self, PyObject * args )
1367 {
1368         BPy_NMesh *me = ( BPy_NMesh * ) self;
1369         int flag = -1;
1370
1371         if( !PyArg_ParseTuple( args, "|i", &flag ) )
1372                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1373                                               "expected int argument (or nothing)" );
1374
1375         switch ( flag ) {
1376         case 0:
1377                 me->flags &= ~NMESH_HASMCOL;
1378                 break;
1379         case 1:
1380                 me->flags |= NMESH_HASMCOL;
1381                 break;
1382         default:
1383                 break;
1384         }
1385
1386         if( me->flags & NMESH_HASMCOL )
1387                 return EXPP_incr_ret_True();
1388         else
1389                 return EXPP_incr_ret_False();
1390 }
1391
1392 static PyObject *NMesh_update( PyObject *self, PyObject *a, PyObject *kwd )
1393 {
1394         BPy_NMesh *nmesh = ( BPy_NMesh * ) self;
1395         Mesh *mesh = nmesh->mesh;
1396         int recalc_normals = 0, store_edges = 0, vertex_shade = 0;
1397         static char *kwlist[] = {"recalc_normals", "store_edges",
1398                 "vertex_shade", NULL};
1399         int needs_redraw = 1;
1400         int old_totvert = 0;
1401
1402         if (!PyArg_ParseTupleAndKeywords(a, kwd, "|iii", kwlist, &recalc_normals,
1403                 &store_edges, &vertex_shade ) )
1404                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
1405                                 "expected nothing or one to three bool(s) (0 or 1) as argument" );
1406
1407         if( check_NMeshLists( nmesh ) )
1408                 return NULL;
1409
1410         if( mesh ) {
1411                 old_totvert = mesh->totvert;
1412                 unlink_existingMeshData( mesh );
1413                 if( !convert_NMeshToMesh( mesh, nmesh ) )
1414                         return NULL;
1415                 if (mesh->dvert) check_dverts(mesh, old_totvert);
1416         } else {
1417                 mesh = Mesh_fromNMesh( nmesh );
1418                 /* if mesh is NULL, there was an error */
1419                 if( !mesh )
1420                         return NULL;
1421                 nmesh->mesh = mesh;
1422         }
1423
1424         if( recalc_normals )
1425                 mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mface, mesh->totface, NULL);
1426
1427         mesh_update( mesh, nmesh->object );
1428
1429         nmesh_updateMaterials( nmesh );
1430
1431         if( nmesh->name && nmesh->name != Py_None )
1432                 new_id( &( G.main->mesh ), &mesh->id,
1433                         PyString_AsString( nmesh->name ) );
1434
1435         if (vertex_shade) {
1436                 Base *base = FIRSTBASE;
1437
1438                 if (!nmesh->object)
1439                         return EXPP_ReturnPyObjError(PyExc_RuntimeError,
1440                 "link this mesh to an object first with ob.link(mesh)" );
1441
1442                 if (G.obedit)
1443                         return EXPP_ReturnPyObjError(PyExc_RuntimeError,
1444                 "can't shade vertices while in edit mode" );
1445
1446                 while (base) {
1447                         if (base->object == nmesh->object) {
1448                                 base->flag |= SELECT;
1449                                 nmesh->object->flag = (short)base->flag;
1450                                 set_active_base (base);
1451                                 needs_redraw = 0; /* already done in make_vertexcol */
1452                                 break;
1453                         }
1454                         base = base->next;
1455                 }
1456
1457                 /* recalculate the derived mesh before trying to use it */
1458                 makeDerivedMesh(nmesh->object, CD_MASK_BAREMESH);
1459                 make_vertexcol(1);
1460
1461                 countall();
1462         }
1463
1464         if( !during_script(  ) && needs_redraw)
1465                 EXPP_allqueue( REDRAWVIEW3D, 0 );
1466
1467         return PyInt_FromLong( 1 );
1468 }
1469
1470 /** Implementation of the python method getVertexInfluence for an NMesh object.
1471  * This method returns a list of pairs (string,float) with bone names and
1472  * influences that this vertex receives.
1473  * @author Jordi Rovira i Bonet
1474  */
1475
1476 static PyObject *NMesh_getVertexInfluences( PyObject * self, PyObject * args )
1477 {
1478         int index;
1479         PyObject *influence_list = NULL;
1480         Object *object = ( ( BPy_NMesh * ) self )->object;
1481         Mesh *me = ( ( BPy_NMesh * ) self )->mesh;
1482
1483         /* Get a reference to the mesh object wrapped in here. */
1484         if( !me )
1485                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1486                                 "unlinked nmesh: call its .update() method first" );
1487
1488         if( !object )
1489                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1490                                 "This mesh must be linked to an object" ); 
1491
1492         /* Parse the parameters: only on integer (vertex index) */
1493         if( !PyArg_ParseTuple( args, "i", &index ) )
1494                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1495                                 "expected int argument (index of the vertex)" );
1496
1497         /* check for valid index */
1498         if( index < 0 || index >= me->totvert )
1499                 return EXPP_ReturnPyObjError( PyExc_IndexError,
1500                                 "vertex index out of range" );
1501
1502         influence_list = PyList_New( 0 );
1503
1504         /* Proceed only if we have vertex deformation information */
1505         if( me->dvert ) {
1506                 int i;
1507                 MDeformWeight *sweight = NULL;
1508
1509                 /* Number of bones influencing the vertex */
1510                 int totinfluences = me->dvert[index].totweight;
1511
1512                 /* Get the reference of the first weight structure */
1513                 sweight = me->dvert[index].dw;
1514
1515                 /* Build the list only with weights and names of the influent bones */
1516                 for( i = 0; i < totinfluences; i++, sweight++ ) {
1517                         bDeformGroup *defgroup = (bDeformGroup *) BLI_findlink( &object->defbase,
1518                                         sweight->def_nr );
1519                         if( defgroup )
1520                                 PyList_Append( influence_list, Py_BuildValue( "[sf]",
1521                                                 defgroup->name, sweight->weight ) ); 
1522                 }
1523         }
1524
1525         return influence_list;
1526 }
1527
1528 Mesh *Mesh_fromNMesh( BPy_NMesh * nmesh )
1529 {
1530         Mesh *mesh = NULL;
1531         
1532         mesh = add_mesh( "Mesh" );
1533
1534         if( !mesh ) {
1535                 PyErr_SetString( PyExc_RuntimeError,
1536                                 "FATAL: could not create mesh object" );
1537                 return NULL;
1538         }
1539
1540         mesh->id.us = 0;        /* no user yet */
1541         G.totmesh++;
1542         
1543         if( !convert_NMeshToMesh( mesh, nmesh ) )
1544                 return NULL;
1545         
1546         return mesh;
1547 }
1548
1549 static PyObject *NMesh_getMaxSmoothAngle( BPy_NMesh * self )
1550 {
1551         return PyInt_FromLong( self->smoothresh );
1552 }
1553
1554 static PyObject *NMesh_setMaxSmoothAngle( PyObject * self, PyObject * args )
1555 {
1556         short value = 0;
1557         BPy_NMesh *nmesh = ( BPy_NMesh * ) self;
1558
1559         if( !PyArg_ParseTuple( args, "h", &value ) )
1560                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
1561                                               "expected an int in [1, 80] as argument" );
1562
1563         nmesh->smoothresh =
1564                 ( short ) EXPP_ClampInt( value, NMESH_SMOOTHRESH_MIN,
1565                                          NMESH_SMOOTHRESH_MAX );
1566
1567         Py_RETURN_NONE;
1568 }
1569
1570 static PyObject *NMesh_getSubDivLevels( BPy_NMesh * self )
1571 {
1572         return Py_BuildValue( "[h,h]", self->subdiv[0], self->subdiv[1] );
1573 }
1574
1575 static PyObject *NMesh_setSubDivLevels( PyObject * self, PyObject * args )
1576 {
1577         short display = 0, render = 0;
1578         BPy_NMesh *nmesh = ( BPy_NMesh * ) self;
1579
1580         if( !PyArg_ParseTuple( args, "(hh)", &display, &render ) )
1581                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
1582                                               "expected a sequence [int, int] as argument" );
1583
1584         nmesh->subdiv[0] =
1585                 ( short ) EXPP_ClampInt( display, NMESH_SUBDIV_MIN,
1586                                          NMESH_SUBDIV_MAX );
1587
1588         nmesh->subdiv[1] =
1589                 ( short ) EXPP_ClampInt( render, NMESH_SUBDIV_MIN,
1590                                          NMESH_SUBDIV_MAX );
1591
1592         Py_RETURN_NONE;
1593 }
1594
1595 static PyObject *NMesh_getMode( BPy_NMesh * self )
1596 {
1597         return PyInt_FromLong( self->mode );
1598 }
1599
1600 static PyObject *NMesh_setMode( PyObject * self, PyObject * args )
1601 {
1602         BPy_NMesh *nmesh = ( BPy_NMesh * ) self;
1603         PyObject *arg1 = NULL;
1604         char *m[5] = { NULL, NULL, NULL, NULL, NULL };
1605         short i, mode = 0;
1606
1607         if( !PyArg_ParseTuple ( args, "|Ossss", &arg1, &m[1], &m[2], &m[3], &m[4] ) )
1608                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
1609                         "expected an int or from none to 5 strings as argument(s)" );
1610
1611         if (arg1) {
1612                 if (PyInt_Check(arg1)) {
1613                         mode = (short)PyInt_AsLong(arg1);
1614                 }
1615                 else if (PyString_Check(arg1)) {
1616                         m[0] = PyString_AsString(arg1);
1617                         for( i = 0; i < 5; i++ ) {
1618                                 if( !m[i] ) break;
1619                                 else if( strcmp( m[i], "NoVNormalsFlip" ) == 0 )
1620                                         mode |= ME_NOPUNOFLIP;
1621                                 else if( strcmp( m[i], "TwoSided" ) == 0 )
1622                                         mode |= ME_TWOSIDED;
1623                                 else if( strcmp( m[i], "AutoSmooth" ) == 0 )
1624                                         mode |= ME_AUTOSMOOTH;
1625                                 else if( m[i][0] == '\0' )
1626                                         mode = 0;
1627                                 else
1628                                         return EXPP_ReturnPyObjError( PyExc_AttributeError,
1629                           "unknown NMesh mode" );
1630                         }
1631                 }
1632                 else return EXPP_ReturnPyObjError( PyExc_AttributeError,
1633                         "expected an int or from none to 5 strings as argument(s)" );
1634         }
1635
1636         nmesh->mode = mode;
1637
1638         Py_RETURN_NONE;
1639 }
1640
1641 /* METH_VARARGS: function(PyObject *self, PyObject *args) */
1642 #undef MethodDef
1643 #define MethodDef(func) {#func, NMesh_##func, METH_VARARGS, NMesh_##func##_doc}
1644
1645 static struct PyMethodDef NMesh_methods[] = {
1646         MethodDef( addEdge ),
1647         MethodDef( findEdge ),
1648         MethodDef( removeEdge ),
1649         MethodDef( addFace ),
1650         MethodDef( removeFace ),
1651         MethodDef( addVertGroup ),
1652         MethodDef( removeVertGroup ),
1653         MethodDef( assignVertsToGroup ),
1654         MethodDef( removeVertsFromGroup ),
1655         MethodDef( getVertsFromGroup ),
1656         MethodDef( renameVertGroup ),
1657         MethodDef( hasVertexColours ),
1658         MethodDef( hasFaceUV ),
1659         MethodDef( hasVertexUV ),
1660         MethodDef( getSelectedFaces ),
1661         MethodDef( getVertexInfluences ),
1662         MethodDef( getMaterials ),
1663         MethodDef( setMaterials ),
1664         MethodDef( addMaterial ),
1665         MethodDef( insertKey ),
1666         MethodDef( removeAllKeys ),
1667         MethodDef( setMode ),
1668         MethodDef( setMaxSmoothAngle ),
1669         MethodDef( setSubDivLevels ),
1670         MethodDef( transform ),
1671
1672 /* METH_NOARGS: function(PyObject *self) */
1673 #undef MethodDef
1674 #define MethodDef(func) {#func, (PyCFunction)NMesh_##func, METH_NOARGS,\
1675         NMesh_##func##_doc}
1676
1677         MethodDef( printDebug ),
1678         MethodDef( getVertGroupNames ),
1679         MethodDef( getActiveFace ),
1680         MethodDef( getKey ),
1681         MethodDef( getMode ),
1682         MethodDef( getMaxSmoothAngle ),
1683         MethodDef( getSubDivLevels ),
1684
1685 /* METH_VARARGS | METH_KEYWORDS:
1686  * function(PyObject *self, PyObject *args, PyObject *keywords) */
1687 #undef MethodDef
1688 #define MethodDef(func) {#func, (PyCFunction)NMesh_##func,\
1689         METH_VARARGS | METH_KEYWORDS, NMesh_##func##_doc}
1690
1691         MethodDef( update ),
1692         {NULL, NULL, 0, NULL}
1693 };
1694
1695 static PyObject *NMesh_getattr( PyObject * self, char *name )
1696 {
1697         BPy_NMesh *me = ( BPy_NMesh * ) self;
1698
1699         if( strcmp( name, "name" ) == 0 )
1700                 return EXPP_incr_ret( me->name );
1701
1702         else if ( strcmp( name, "properties" ) == 0 )
1703                 return BPy_Wrap_IDProperty( (ID*)me->mesh, IDP_GetProperties((ID*)me->mesh, 1), NULL );
1704
1705         else if( strcmp( name, "mode" ) == 0 )
1706                 return PyInt_FromLong( me->mode );
1707
1708         else if( strcmp( name, "block_type" ) == 0 )    /* for compatibility */
1709                 return PyString_FromString( "NMesh" );
1710
1711         else if( strcmp( name, "materials" ) == 0 )
1712                 return EXPP_incr_ret( me->materials );
1713
1714         else if( strcmp( name, "verts" ) == 0 )
1715                 return EXPP_incr_ret( me->verts );
1716
1717         else if( strcmp( name, "maxSmoothAngle" ) == 0 )
1718                 return PyInt_FromLong( me->smoothresh );
1719
1720         else if( strcmp( name, "subDivLevels" ) == 0 )
1721                 return Py_BuildValue( "[h,h]", me->subdiv[0], me->subdiv[1] );
1722
1723         else if( strcmp( name, "users" ) == 0 ) {
1724                 if( me->mesh ) {
1725                         return PyInt_FromLong( me->mesh->id.us );
1726                 } else {        /* it's a free mesh: */
1727                         return Py_BuildValue( "i", 0 );
1728                 }
1729         }
1730         else if (strcmp( name, "key") == 0)
1731                 return NMesh_getKey((BPy_NMesh*)self);
1732
1733         else if( strcmp( name, "faces" ) == 0 )
1734                 return EXPP_incr_ret( me->faces );
1735
1736   else if( strcmp( name, "edges" ) == 0 )
1737   {
1738     return EXPP_incr_ret( me->edges );
1739   }
1740         else if( strcmp( name, "__members__" ) == 0 )
1741                 return Py_BuildValue( "[s,s,s,s,s,s,s,s,s,s,s]",
1742                                       "name", "materials", "verts", "users",
1743                                       "faces", "maxSmoothAngle",
1744                                       "subdivLevels", "edges", "key" );
1745
1746         return Py_FindMethod( NMesh_methods, ( PyObject * ) self, name );
1747 }
1748
1749 static int NMesh_setattr( PyObject * self, char *name, PyObject * v )
1750 {
1751         BPy_NMesh *me = ( BPy_NMesh * ) self;
1752
1753         if( !strcmp( name, "name" ) ) {
1754
1755                 if( !PyString_Check( v ) )
1756                         return EXPP_ReturnIntError( PyExc_TypeError,
1757                                                     "expected string argument" );
1758
1759                 Py_DECREF( me->name );
1760                 me->name = EXPP_incr_ret( v );
1761         }
1762
1763         else if( !strcmp( name, "mode" ) ) {
1764                 short mode;
1765
1766                 if( !PyInt_Check( v ) )
1767                         return EXPP_ReturnIntError( PyExc_TypeError,
1768                                                     "expected int argument" );
1769
1770                 mode = ( short ) PyInt_AsLong( v );
1771                 if( mode >= 0 )
1772                         me->mode = mode;
1773                 else
1774                         return EXPP_ReturnIntError( PyExc_ValueError,
1775                                                     "expected positive int argument" );
1776         }
1777
1778         else if( !strcmp( name, "verts" ) || !strcmp( name, "faces" ) ||
1779                  !strcmp( name, "materials" ) ) {
1780
1781                 if( PySequence_Check( v ) ) {
1782
1783                         if( strcmp( name, "materials" ) == 0 ) {
1784                                 Py_DECREF( me->materials );
1785                                 me->materials = EXPP_incr_ret( v );
1786                         } else if( strcmp( name, "verts" ) == 0 ) {
1787                                 Py_DECREF( me->verts );
1788                                 me->verts = EXPP_incr_ret( v );
1789                         } else {
1790                                 Py_DECREF( me->faces );
1791                                 me->faces = EXPP_incr_ret( v );
1792                         }
1793                 }
1794
1795                 else
1796                         return EXPP_ReturnIntError( PyExc_TypeError,
1797                                                     "expected a list" );
1798         }
1799
1800         else if( !strcmp( name, "maxSmoothAngle" ) ) {
1801                 short smoothresh = 0;
1802
1803                 if( !PyInt_Check( v ) )
1804                         return EXPP_ReturnIntError( PyExc_TypeError,
1805                                                     "expected int argument" );
1806
1807                 smoothresh = ( short ) PyInt_AsLong( v );
1808
1809                 me->smoothresh =
1810                         (short)EXPP_ClampInt( smoothresh, NMESH_SMOOTHRESH_MIN,
1811                                        NMESH_SMOOTHRESH_MAX );
1812         }
1813
1814         else if( !strcmp( name, "subDivLevels" ) ) {
1815                 int subdiv[2] = { 0, 0 };
1816                 int i;
1817                 PyObject *tmp;
1818
1819                 if( !PySequence_Check( v ) || ( PySequence_Length( v ) != 2 ) )
1820                         return EXPP_ReturnIntError( PyExc_TypeError,
1821                                                     "expected a list [int, int] as argument" );
1822
1823                 for( i = 0; i < 2; i++ ) {
1824                         tmp = PySequence_GetItem( v, i );
1825                         if( tmp ) {
1826                                 if( !PyInt_Check( tmp ) ) {
1827                                         Py_DECREF( tmp );
1828                                         return EXPP_ReturnIntError
1829                                                 ( PyExc_TypeError,
1830                                                   "expected a list [int, int] as argument" );
1831                                 }
1832
1833                                 subdiv[i] = PyInt_AsLong( tmp );
1834                                 me->subdiv[i] =
1835                                         ( short ) EXPP_ClampInt( subdiv[i],
1836                                                                  NMESH_SUBDIV_MIN,
1837                                                                  NMESH_SUBDIV_MAX );
1838                                 Py_DECREF( tmp );
1839                         } else
1840                                 return EXPP_ReturnIntError( PyExc_RuntimeError,
1841                                                             "couldn't retrieve subdiv values from list" );
1842                 }
1843         }
1844   else if( strcmp( name, "edges" ) == 0 )
1845   {
1846     if (PySequence_Check(v))
1847     {
1848       Py_DECREF(me->edges);
1849       me->edges = EXPP_incr_ret( v );
1850     }
1851   }
1852         else
1853                 return EXPP_ReturnIntError( PyExc_AttributeError, name );
1854
1855         return 0;
1856 }
1857
1858 PyTypeObject NMesh_Type = {
1859         PyObject_HEAD_INIT( NULL ) 0,   /*ob_size */
1860         "Blender NMesh",        /*tp_name */
1861         sizeof( BPy_NMesh ),    /*tp_basicsize */
1862         0,                      /*tp_itemsize */
1863         /* methods */
1864         ( destructor ) NMesh_dealloc,   /*tp_dealloc */
1865         ( printfunc ) 0,        /*tp_print */
1866         ( getattrfunc ) NMesh_getattr,  /*tp_getattr */
1867         ( setattrfunc ) NMesh_setattr,  /*tp_setattr */
1868         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1869         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1870 };
1871
1872 static BPy_NMFace *nmface_from_data( BPy_NMesh * mesh, int vidxs[4],
1873         char mat_nr, char flag, MTFace * tface, MCol * col, int orig_index )
1874 {
1875         BPy_NMFace *newf = PyObject_NEW( BPy_NMFace, &NMFace_Type );
1876         int i, len;
1877
1878         if( vidxs[3] )
1879                 len = 4;
1880         else 
1881                 len = 3;
1882
1883         newf->v = PyList_New( len );
1884
1885         for( i = 0; i < len; i++ )
1886                 PyList_SetItem( newf->v, i,
1887                                 EXPP_incr_ret( PyList_GetItem
1888                                                ( mesh->verts, vidxs[i] ) ) );
1889
1890         if( tface ) {
1891                 newf->uv = PyList_New( len );   // per-face UV coordinates
1892
1893                 for( i = 0; i < len; i++ ) {
1894                         PyList_SetItem( newf->uv, i,
1895                                         Py_BuildValue( "(ff)", tface->uv[i][0],
1896                                                        tface->uv[i][1] ) );
1897                 }
1898
1899                 if( tface->tpage )      /* pointer to image per face: */
1900                         newf->image = ( Image * ) tface->tpage;
1901                 else
1902                         newf->image = NULL;
1903
1904                 newf->mode = tface->mode;       /* draw mode */
1905                 newf->flag = tface->flag;       /* select flag */
1906                 newf->transp = tface->transp;   /* transparency flag */
1907         } else {
1908                 newf->mode = TF_DYNAMIC;        /* just to initialize it to something meaninful, */
1909                 /* since without tfaces there are no tface->mode's, obviously. */
1910                 newf->image = NULL;
1911                 newf->uv = PyList_New( 0 );
1912         }
1913
1914         newf->mat_nr = mat_nr;
1915         newf->mf_flag = flag; /* MFace flag */
1916         newf->orig_index = orig_index;
1917
1918         if( col ) {
1919                 newf->col = PyList_New( 4 );
1920                 for( i = 0; i < 4; i++, col++ ) {
1921                         PyList_SetItem( newf->col, i,
1922                                         ( PyObject * ) newcol( col->b, col->g,
1923                                                                col->r,
1924                                                                col->a ) );
1925                 }
1926         } else
1927                 newf->col = PyList_New( 0 );
1928
1929         return newf;
1930 }
1931
1932 static BPy_NMEdge *nmedge_from_index( BPy_NMesh * mesh, int v0idx, int v1idx)
1933 {
1934   BPy_NMVert *v1=(BPy_NMVert *)PyList_GetItem( mesh->verts, v0idx);
1935   BPy_NMVert *v2=(BPy_NMVert *)PyList_GetItem( mesh->verts, v1idx);
1936   return new_NMEdge(v1, v2, (char)0.0, 0);
1937 }
1938
1939 static BPy_NMEdge *nmedge_from_data( BPy_NMesh * mesh, MEdge *edge )
1940 {
1941   BPy_NMVert *v1=(BPy_NMVert *)PyList_GetItem( mesh->verts, edge->v1 );
1942   BPy_NMVert *v2=(BPy_NMVert *)PyList_GetItem( mesh->verts, edge->v2 );
1943   return new_NMEdge(v1, v2, edge->crease, edge->flag);
1944 }
1945
1946 static BPy_NMVert *nmvert_from_data( MVert * vert, MSticky * st, float *co,
1947         int idx, char flag )
1948 {
1949         BPy_NMVert *mv = PyObject_NEW( BPy_NMVert, &NMVert_Type );
1950
1951         mv->co[0] = co[0];
1952         mv->co[1] = co[1];
1953         mv->co[2] = co[2];
1954
1955         mv->no[0] = (float)(vert->no[0] / 32767.0);
1956         mv->no[1] = (float)(vert->no[1] / 32767.0);
1957         mv->no[2] = (float)(vert->no[2] / 32767.0);
1958
1959         if( st ) {
1960                 mv->uvco[0] = st->co[0];
1961                 mv->uvco[1] = st->co[1];
1962                 mv->uvco[2] = 0.0;
1963
1964         } else
1965                 mv->uvco[0] = mv->uvco[1] = mv->uvco[2] = 0.0;
1966
1967         mv->index = idx;
1968         mv->flag = flag & 1;
1969
1970         return mv;
1971 }
1972
1973 static int get_active_faceindex( Mesh * me )
1974 {
1975         if( me == NULL )
1976                 return -1;
1977
1978         if (me->act_face != -1 && me->act_face < me->totface)
1979                 return me->act_face; 
1980         return -1;
1981 }
1982
1983 static BPy_NMVert *nmvert_from_float(float *co, float *no, int idx) {
1984         BPy_NMVert *mv;
1985
1986         mv = PyObject_NEW( BPy_NMVert, &NMVert_Type );
1987
1988         mv->index = idx;
1989
1990         mv->co[0] = co[0];
1991         mv->co[1] = co[1];
1992         mv->co[2] = co[2];
1993
1994         mv->no[0] = no[0];
1995         mv->no[1] = no[1];
1996         mv->no[2] = no[2];
1997
1998         mv->uvco[0] = mv->uvco[1] = mv->uvco[2] = 0.0;
1999
2000         mv->flag = 0;
2001
2002         return mv;
2003 }
2004
2005 static BPy_NMFace *nmface_from_index( BPy_NMesh * mesh, int vidxs[4], char mat_nr )
2006 {
2007         BPy_NMFace *newf = PyObject_NEW( BPy_NMFace, &NMFace_Type );
2008         int i, len;
2009
2010         if( vidxs[3] )
2011                 len = 4;
2012         else if( vidxs[2] )
2013                 len = 3;
2014         else
2015                 len = 2;
2016
2017         newf->v = PyList_New( len );
2018
2019         for( i = 0; i < len; i++ )
2020                 PyList_SetItem( newf->v, i,
2021                                 EXPP_incr_ret( PyList_GetItem
2022                                                ( mesh->verts, vidxs[i] ) ) );
2023
2024         newf->mode = TF_DYNAMIC;        /* just to initialize it to something meaninful, */
2025         /* since without tfaces there are no tface->mode's, obviously. */
2026         newf->image = NULL;
2027         newf->uv = PyList_New( 0 );
2028
2029         newf->mat_nr = mat_nr;
2030         newf->mf_flag = 0;
2031         newf->orig_index = -1;
2032
2033         newf->col = PyList_New( 0 );
2034
2035         return newf;
2036 }
2037
2038 /* RATHER EVIL FUNCTION BORROWED FROM fix_faceindices IN editmesh.c */
2039 static void correctFaceIndex(int vidx[4])
2040 {
2041         if (vidx[3]) {
2042                 if (vidx[1] == 0) {
2043                         vidx[1] = vidx[2];
2044                         vidx[2] = vidx[3];
2045                         vidx[3] = vidx[0];
2046                         vidx[0] = 0;
2047                 }
2048                 if (vidx[2] == 0) {
2049                         int t = vidx[1];
2050                         vidx[2] = vidx[0];
2051                         vidx[1] = vidx[3];
2052                         vidx[3] = t;
2053                         vidx[0] = 0;
2054                 }
2055                 if (vidx[3] == 0) {
2056                         vidx[3] = vidx[2];
2057                         vidx[2] = vidx[1];
2058                         vidx[1] = vidx[0];
2059                         vidx[0] = 0;
2060                 }
2061         }
2062         else if (vidx[1] == 0) {
2063                 vidx[1] = vidx[2];
2064                 vidx[2] = vidx[0];
2065                 vidx[0] = 0;
2066         }
2067         else if (vidx[2] == 0) {
2068                 vidx[2] = vidx[1];
2069                 vidx[1] = vidx[0];
2070                 vidx[0] = 0;
2071         }
2072 }
2073
2074 /*
2075         CREATES A NMESH FROM DISPLIST DATA. INSPIRED BY THE FUNCTIONS CALLED WHEN
2076         CONVERTING OBJECTS TO MESH.
2077  */
2078 static PyObject *new_NMesh_displist(ListBase *lb, Object *ob)
2079 {
2080         BPy_NMesh *me;
2081         DispList *dl;
2082         float *data, *ndata;
2083         float normal[3] = {1, 0, 0};
2084         int vidx[4];
2085         int parts, p1, p2, p3, p4, a, b, one_normal=0, ioffset=0;
2086         int *index;
2087
2088                 /* Note: This routine does not create new edges for the faces
2089                  * it adds... should be fixed for consistency.
2090                  */
2091
2092         if (ob->type == OB_CURVE || ob->type == OB_FONT)
2093                 one_normal = 1;
2094
2095         me = PyObject_NEW( BPy_NMesh, &NMesh_Type );
2096         me->name = EXPP_incr_ret( Py_None );
2097         me->flags = 0;
2098         me->mode = ME_TWOSIDED; /* default for new meshes */
2099         me->subdiv[0] = NMESH_SUBDIV;
2100         me->subdiv[1] = NMESH_SUBDIV;
2101         me->smoothresh = NMESH_SMOOTHRESH;
2102         me->edges = PyList_New( 0 );
2103
2104         me->object = ob;
2105         me->materials = EXPP_PyList_fromMaterialList( ob->mat, ob->totcol, 0 );
2106
2107         me->verts = PyList_New( 0 ); 
2108         me->faces = PyList_New( 0 );
2109
2110         memset(&me->fdata, 0, sizeof(me->fdata));
2111         me->totfdata = 0;
2112
2113         dl= lb->first;
2114         while(dl) {
2115                 parts= dl->parts;
2116                 index= dl->index;
2117                 data= dl->verts;
2118                 ndata= dl->nors;
2119
2120                 switch(dl->type) {
2121                 case DL_SEGM:
2122                         for(a=0; a<dl->parts*dl->nr; a++, data+=3) {
2123                                 PyList_Append(me->verts, ( PyObject * ) nmvert_from_float(data, normal, a));
2124                         }
2125
2126                         vidx[2] = vidx[3] = 0;
2127
2128                         for(a=0; a<dl->parts; a++) {
2129                                 for(b=1; b<dl->nr; b++) {
2130                                         int v0 = ioffset + a * dl->nr + b-1;
2131                                         int v1 = ioffset + a * dl->nr + b;
2132                                         PyList_Append(me->edges, ( PyObject * ) nmedge_from_index(me, v0, v1));
2133                                 }
2134                         }
2135                         ioffset += dl->parts * dl->nr;
2136                         break;
2137                 case DL_POLY:
2138                         for(a=0; a<dl->parts*dl->nr; a++, data+=3) {
2139                                 PyList_Append(me->verts, ( PyObject * ) nmvert_from_float(data, normal, a));
2140                         }
2141
2142                         vidx[2] = vidx[3] = 0;
2143
2144                         for(a=0; a<dl->parts; a++) {
2145                                 for(b=0; b<dl->nr; b++) {
2146                                         int v1, v0 = ioffset + a * dl->nr + b;
2147                                         if(b==dl->nr-1) v1 = ioffset + a * dl->nr;
2148                                         else v1= ioffset + a * dl->nr + b+1;
2149                                         PyList_Append(me->edges, ( PyObject * ) nmedge_from_index(me, v0, v1));
2150                                 }
2151                         }
2152                         ioffset += dl->parts * dl->nr;
2153                         break;
2154                 case DL_SURF:
2155                         for(a=0; a<dl->parts*dl->nr; a++, data+=3, ndata+=3) {
2156                                 PyList_Append(me->verts, ( PyObject * ) nmvert_from_float(data, ndata, a));
2157                         }
2158
2159                         for(a=0; a<dl->parts; a++) {
2160                                 
2161                                 if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0)
2162                                         break;
2163                                 
2164                                 for(; b<dl->nr; b++) {
2165                                         vidx[0] = p2 + ioffset;
2166                                         vidx[1] = p1 + ioffset;
2167                                         vidx[2] = p3 + ioffset;
2168                                         vidx[3] = p4 + ioffset;
2169                                         correctFaceIndex(vidx);
2170
2171                                         PyList_Append(me->faces, ( PyObject * ) nmface_from_index(me, vidx, (char)dl->col));
2172
2173                                         p2 = p1;
2174                                         p4 = p3;
2175                                         p1++;
2176                                         p3++;
2177                                 }
2178                         }
2179                         ioffset += dl->parts * dl->nr;
2180                         break;
2181
2182                 case DL_INDEX3:
2183                         if (one_normal)
2184                                 for(a=0; a<dl->nr; a++, data+=3)
2185                                         PyList_Append(me->verts, ( PyObject * ) nmvert_from_float(data, ndata, a));
2186                         else
2187                                 for(a=0; a<dl->nr; a++, data+=3, ndata+=3)
2188                                         PyList_Append(me->verts, ( PyObject * ) nmvert_from_float(data, ndata, a));
2189
2190                         while(parts--) {
2191                                 vidx[0] = index[0] + ioffset;
2192                                 vidx[1] = index[1] + ioffset;
2193                                 vidx[2] = index[2] + ioffset;
2194                                 vidx[3] = 0;
2195                                 correctFaceIndex(vidx);
2196
2197                                 PyList_Append(me->faces, ( PyObject * ) nmface_from_index(me, vidx, (char)dl->col));
2198                                 index+= 3;
2199                         }
2200                         ioffset += dl->nr;
2201
2202                         break;
2203
2204                 case DL_INDEX4:
2205                         for(a=0; a<dl->nr; a++, data+=3, ndata+=3) {
2206                                 PyList_Append(me->verts, ( PyObject * ) nmvert_from_float(data, ndata, a));
2207                         }
2208
2209                         while(parts--) {
2210                                 vidx[0] = index[0] + ioffset;
2211                                 vidx[1] = index[1] + ioffset;
2212                                 vidx[2] = index[2] + ioffset;
2213                                 vidx[3] = index[3] + ioffset;
2214                                 correctFaceIndex(vidx);
2215
2216                                 PyList_Append(me->faces, ( PyObject * ) nmface_from_index(me, vidx, (char)dl->col));
2217                                 index+= 4;
2218                         }
2219                         ioffset += dl->nr;
2220                         break;
2221                 }
2222                 dl= dl->next;
2223         }
2224
2225         return ( PyObject * ) me;
2226 }
2227
2228 static PyObject *new_NMesh_internal( Mesh * oldmesh,
2229                                      DerivedMesh *dm )
2230 {
2231         BPy_NMesh *me = PyObject_NEW( BPy_NMesh, &NMesh_Type );
2232         me->flags = 0;
2233         me->mode = ME_TWOSIDED; /* default for new meshes */
2234         me->subdiv[0] = NMESH_SUBDIV;
2235         me->subdiv[1] = NMESH_SUBDIV;
2236         me->smoothresh = NMESH_SMOOTHRESH;
2237
2238         me->object = NULL;      /* not linked to any object yet */
2239
2240         if( !oldmesh ) {
2241                 me->name = EXPP_incr_ret( Py_None );
2242                 me->materials = PyList_New( 0 );
2243                 me->verts = PyList_New( 0 );
2244                 me->edges = PyList_New( 0 );
2245                 me->faces = PyList_New( 0 );
2246                 me->mesh = 0;
2247                 memset(&me->fdata, 0, sizeof(me->fdata));
2248                 me->totfdata = 0;
2249         } else {
2250                 MVert *mverts;
2251                 MSticky *msticky;
2252                 MFace *mfaces;
2253                 MTFace *tfaces;
2254                 MCol *mcols;
2255                 MEdge *medges;
2256                 CustomData *fdata;
2257                 int i, totvert, totface, totedge;
2258
2259                 me->name = PyString_FromString( oldmesh->id.name + 2 );
2260                 me->mesh = oldmesh;
2261                 me->mode = oldmesh->flag;       /* yes, we save the mesh flags in nmesh->mode */
2262                 me->subdiv[0] = oldmesh->subdiv;
2263                 me->subdiv[1] = oldmesh->subdivr;
2264                 me->smoothresh = oldmesh->smoothresh;
2265
2266                 me->sel_face = get_active_faceindex( oldmesh );
2267
2268                 if( dm ) {
2269                         msticky = NULL;
2270                         mverts = dm->getVertArray(dm);
2271                         mfaces = dm->getFaceArray(dm);
2272                         tfaces = dm->getFaceDataArray(dm, CD_MTFACE);
2273                         mcols = dm->getFaceDataArray(dm, CD_MCOL);
2274                         medges = dm->getEdgeArray(dm);
2275                         fdata = &dm->faceData;
2276
2277                         totvert = dm->getNumVerts(dm);
2278                         totedge = dm->getNumEdges(dm);
2279                         totface = dm->getNumFaces(dm);;
2280                 } else {
2281                         msticky = oldmesh->msticky;
2282                         mverts = oldmesh->mvert;
2283                         mfaces = oldmesh->mface;
2284                         tfaces = oldmesh->mtface;
2285                         mcols = oldmesh->mcol;
2286                         medges = oldmesh->medge;
2287                         fdata = &oldmesh->fdata;
2288
2289                         totvert = oldmesh->totvert;
2290                         totface = oldmesh->totface;
2291                         totedge = oldmesh->totedge;
2292                 }
2293
2294                 /* copy non active mcol and mtface layers, these can't be edited
2295                    but will be preserved */
2296                 CustomData_copy( fdata, &me->fdata, CD_MASK_MCOL|CD_MASK_MTFACE,
2297                         CD_DUPLICATE, totface );
2298                 me->totfdata = totface;
2299
2300                 if( msticky )
2301                         me->flags |= NMESH_HASVERTUV;
2302                 if( tfaces )
2303                         me->flags |= NMESH_HASFACEUV;
2304                 if( mcols )
2305                         me->flags |= NMESH_HASMCOL;
2306
2307                 me->verts = PyList_New( totvert );
2308
2309                 for( i = 0; i < totvert; i++ ) {
2310                         MVert *oldmv = &mverts[i];
2311                         MSticky *oldst = msticky ? &msticky[i] : NULL;
2312
2313                         PyList_SetItem( me->verts, i,
2314                                         ( PyObject * ) nmvert_from_data( oldmv,
2315                                                                          oldst,
2316                                                                          oldmv->co,
2317                                                                          i,
2318                                                                          oldmv->flag ) );
2319                 }
2320
2321                 me->faces = PyList_New( totface );
2322                 for( i = 0; i < totface; i++ ) {
2323                         MTFace *oldtf = tfaces ? &tfaces[i] : NULL;
2324                         MCol *oldmc = mcols ? &mcols[i * 4] : NULL;
2325                         MFace *oldmf = &mfaces[i];
2326                         int vidxs[4];
2327                         vidxs[0] = oldmf->v1;
2328                         vidxs[1] = oldmf->v2;
2329                         vidxs[2] = oldmf->v3;
2330                         vidxs[3] = oldmf->v4;
2331
2332                         PyList_SetItem( me->faces, i,
2333                                         ( PyObject * ) nmface_from_data( me,
2334                                                                          vidxs,
2335                                                                          oldmf->
2336                                                                          mat_nr,
2337                                                                          oldmf->
2338                                                                          flag,
2339                                                                          oldtf,
2340                                                                          oldmc,
2341                                                                          i) );
2342                 }
2343
2344                 me->edges = PyList_New( totedge );
2345                 for( i = 0; i < totedge; i++ )
2346                 {
2347                         MEdge *edge = &medges[i];
2348                         PyList_SetItem( me->edges, i, (PyObject*)nmedge_from_data ( me, edge ) );
2349                 }
2350
2351                 me->materials = EXPP_PyList_fromMaterialList( oldmesh->mat, oldmesh->totcol, 0 );
2352         }
2353
2354         return ( PyObject * ) me;
2355 }
2356
2357 PyObject *new_NMesh( Mesh * oldmesh )
2358 {
2359         return new_NMesh_internal( oldmesh, NULL );
2360 }
2361
2362 static PyObject *M_NMesh_New( PyObject * self, PyObject * args )
2363 {
2364         char *name = NULL;
2365         PyObject *ret = NULL;
2366
2367         if( !PyArg_ParseTuple( args, "|s", &name ) )
2368                 return EXPP_ReturnPyObjError( PyExc_TypeError,
2369                                               "expected nothing or a string as argument" );
2370
2371         ret = new_NMesh( NULL );
2372
2373         if( ret && name ) {
2374                 BPy_NMesh *nmesh = ( BPy_NMesh * ) ret;
2375                 Py_DECREF( nmesh->name );
2376                 nmesh->name = PyString_FromString( name );
2377         }
2378
2379         return ret;
2380 }
2381
2382 static PyObject *M_NMesh_GetRaw( PyObject * self, PyObject * args )
2383 {
2384         char *name = NULL;
2385         Mesh *oldmesh = NULL;
2386
2387         if( !PyArg_ParseTuple( args, "|s", &name ) )
2388                 return EXPP_ReturnPyObjError( PyExc_TypeError,
2389                                               "expected string argument (or nothing)" );
2390
2391         if( name ) {
2392                 oldmesh = ( Mesh * ) GetIdFromList( &( G.main->mesh ), name );
2393
2394                 if( !oldmesh )
2395                         return EXPP_incr_ret( Py_None );
2396         }
2397
2398         return new_NMesh( oldmesh );
2399 }
2400
2401 static PyObject *M_NMesh_GetNames(PyObject *self)
2402 {
2403         PyObject *names = PyList_New(0), *tmpstr;
2404         Mesh *me = G.main->mesh.first;
2405
2406         while (me) {
2407                 tmpstr = PyString_FromString(me->id.name+2);
2408                 PyList_Append(names, tmpstr);
2409                 Py_DECREF(tmpstr);
2410                 me = me->id.next;
2411         }
2412
2413         return names;
2414 }
2415
2416 /* Note: NMesh.GetRawFromObject gets the display list mesh from Blender:
2417  * the vertices are already transformed / deformed. */
2418 static PyObject *M_NMesh_GetRawFromObject( PyObject * self, PyObject * args )
2419 {
2420         Object *ob;
2421         PyObject *nmesh;
2422         ListBase *lb=0;
2423         DispList *dl;
2424         char *name;
2425
2426         if( !PyArg_ParseTuple( args, "s", &name ) )
2427                 return EXPP_ReturnPyObjError( PyExc_TypeError,
2428                                               "expected string argument" );
2429
2430         ob = ( Object * ) GetIdFromList( &( G.main->object ), name );
2431
2432         if( !ob )
2433                 return EXPP_ReturnPyObjError( PyExc_AttributeError, name );
2434
2435  
2436         switch (ob->type) {
2437         case OB_MBALL:
2438                 if( is_basis_mball(ob)) {
2439                         lb= &ob->disp;
2440                         if(lb->first==0) makeDispListMBall(ob);
2441                         nmesh = new_NMesh_displist(lb, ob);
2442                 }
2443                 else {
2444                         return EXPP_ReturnPyObjError( PyExc_AttributeError, "Object does not have geometry data" );
2445                 }
2446                 break;
2447         case OB_FONT:
2448         case OB_CURVE:
2449                 {
2450                         Curve *cu= ob->data;
2451                         
2452                         lb= &cu->disp;
2453                         if(lb->first==0) makeDispListCurveTypes(ob, 0);
2454  
2455                         dl= lb->first;
2456                         if(dl==0)
2457                                 return EXPP_ReturnPyObjError( PyExc_AttributeError, "Object does not have geometry data" );
2458                         
2459                         if(dl->nors==0) addnormalsDispList(ob, lb);
2460  
2461                         nmesh = new_NMesh_displist(lb, ob);
2462                 }
2463                 break;
2464         case OB_SURF:
2465         
2466                 lb= &((Curve *)ob->data)->disp;
2467                 if(lb->first==0) makeDispListCurveTypes(ob, 0);
2468                 
2469                 dl= lb->first;
2470                 if(dl==0)
2471                         return EXPP_ReturnPyObjError( PyExc_AttributeError, "Object does not have geometry data" );
2472                 
2473                 if(dl->nors==0) addnormalsDispList(ob, lb);
2474                 nmesh = new_NMesh_displist(lb, ob);
2475  
2476                 break;
2477         case OB_MESH:
2478                 {
2479                         CustomDataMask dataMask = CD_MASK_BAREMESH | CD_MASK_MTFACE
2480                                                   | CD_MASK_MCOL;
2481                         DerivedMesh *dm = mesh_create_derived_render( ob, dataMask );
2482                         nmesh = new_NMesh_internal( ob->data, dm );
2483                         dm->release(dm);
2484                 }
2485                 break;
2486         default:
2487                 return EXPP_ReturnPyObjError( PyExc_AttributeError, "Object does not have geometry data" );
2488         }
2489
2490 /* @hack: to mark that (deformed) mesh is readonly, so the update function
2491  * will not try to write it. */
2492
2493         ( ( BPy_NMesh * ) nmesh )->mesh = 0;
2494
2495         return nmesh;
2496 }
2497
2498 static void mvert_from_data( MVert * mv, MSticky * st, BPy_NMVert * from )
2499 {
2500         mv->co[0] = from->co[0];
2501         mv->co[1] = from->co[1];
2502         mv->co[2] = from->co[2];
2503
2504         mv->no[0] = (short)(from->no[0] * 32767.0);
2505         mv->no[1] = (short)(from->no[1] * 32767.0);
2506         mv->no[2] = (short)(from->no[2] * 32767.0);
2507
2508         mv->flag = ( from->flag & 1 );
2509         mv->mat_nr = 0;
2510
2511         if( st ) {
2512                 st->co[0] = from->uvco[0];
2513                 st->co[1] = from->uvco[1];
2514         }
2515 }
2516
2517 static int assignFaceUV( MTFace * tf, BPy_NMFace * nmface )
2518 {
2519         PyObject *fuv, *tmp;
2520         int i;
2521         int len;
2522
2523         fuv = nmface->uv;
2524         /* if no UV info, allows things to proceed as normal */
2525         if( PySequence_Length( fuv ) == 0 ) {
2526                 tf->uv[0][0] = 0.0f; tf->uv[0][1] = 1.0f;
2527                 tf->uv[1][0] = 0.0f; tf->uv[1][1] = 0.0f;
2528                 tf->uv[2][0] = 1.0f; tf->uv[2][1] = 0.0f;
2529                 tf->uv[3][1] = 1.0f; tf->uv[3][1] = 1.0f;
2530                 return 1;
2531         }
2532
2533         /* if there are too many uv coordinates, only take the first 4 */
2534         len = PySequence_Length( fuv );
2535         if( len > 4 )
2536                 len = 4;
2537
2538         /* fuv = [(u_1, v_1), ... (u_n, v_n)] */
2539         for( i = 0; i < len; i++ ) {
2540                 tmp = PySequence_GetItem( fuv, i );     /* stolen reference ! */
2541                 if( !PyArg_ParseTuple
2542                     ( tmp, "ff", &( tf->uv[i][0] ), &( tf->uv[i][1] ) ) ) {
2543                                 PyErr_SetString ( PyExc_TypeError,
2544                                                       "expected tuple of two floats for uv" );
2545                                 Py_DECREF( tmp );
2546                                 return 0;
2547                 }
2548                 Py_DECREF( tmp );
2549         }
2550         if( nmface->image ) {   /* image assigned ? */
2551                 tf->tpage = ( void * ) nmface->image;
2552         } else
2553                 tf->tpage = 0;
2554
2555         tf->mode = nmface->mode;        /* copy mode */
2556         tf->flag = (char)nmface->flag;  /* copy flag */
2557         tf->transp = nmface->transp;    /* copy transp flag */
2558
2559         return 1;
2560 }
2561
2562 static int mface_from_data( MFace * mf, CustomData *fdata, int findex,
2563                              BPy_NMFace * from )
2564 {
2565         BPy_NMVert *nmv;
2566         MTFace *tf = CustomData_get(fdata, findex, CD_MTFACE);
2567         MCol *col = CustomData_get(fdata, findex, CD_MCOL);
2568
2569         int numverts = PyList_Size( from->v );
2570         if( numverts != 3 && numverts != 4 ) {  /* face can only have three or four verts */
2571                 PyErr_SetString ( PyExc_RuntimeError,
2572                                 "faces must have at 3 or 4 vertices" );
2573                 return 0;
2574         }
2575
2576         nmv = ( BPy_NMVert * ) PyList_GetItem( from->v, 0 );
2577         if( BPy_NMVert_Check( nmv ) && nmv->index != -1 )
2578                 mf->v1 = nmv->index;
2579         else 
2580                 return -1;
2581
2582         nmv = ( BPy_NMVert * ) PyList_GetItem( from->v, 1 );
2583         if( BPy_NMVert_Check( nmv ) && nmv->index != -1 )
2584                 mf->v2 = nmv->index;
2585         else
2586                 return -1;
2587
2588         nmv = ( BPy_NMVert * ) PyList_GetItem( from->v, 2 );
2589         if( BPy_NMVert_Check( nmv ) && nmv->index != -1 )
2590                 mf->v3 = nmv->index;
2591         else
2592                 return -1;
2593
2594         if( numverts == 4 ) {
2595                 nmv = ( BPy_NMVert * ) PyList_GetItem( from->v, 3 );
2596                 if( BPy_NMVert_Check( nmv ) && nmv->index != -1 )
2597                         mf->v4 = nmv->index;
2598                 else
2599                         return -1;
2600         }
2601
2602         if( tf )
2603                 if( !assignFaceUV( tf, from ) )
2604                         return 0;
2605
2606         mf->mat_nr = from->mat_nr;
2607         mf->flag = from->mf_flag;
2608
2609         if( col ) {
2610                 int i, len = PySequence_Length( from->col );
2611
2612                 if( len > 4 )
2613                         len = 4;
2614
2615                 for( i = 0; i < len; i++, col++ ) {
2616                         BPy_NMCol *mc =
2617                                 ( BPy_NMCol * ) PySequence_GetItem( from->col,
2618                                                                     i );
2619                         if( !BPy_NMCol_Check( mc ) ) {
2620                                 Py_DECREF( mc );
2621                                 continue;
2622                         }
2623
2624                         col->b = mc->r;
2625                         col->g = mc->g;
2626                         col->r = mc->b;
2627                         col->a = mc->a;
2628
2629                         Py_DECREF( mc );
2630                 }
2631         }
2632
2633         test_index_face(mf, fdata, findex, numverts);
2634
2635         return 1;
2636 }
2637
2638 /* check for a valid UV sequence */
2639 static int check_validFaceUV( BPy_NMesh * nmesh )
2640 {
2641         PyObject *faces;
2642         BPy_NMFace *nmface;
2643         int i, n;
2644
2645         faces = nmesh->faces;
2646         for( i = 0; i < PySequence_Length( faces ); i++ ) {
2647                 nmface = ( BPy_NMFace * ) PyList_GetItem( faces, i );
2648                 n = PySequence_Length( nmface->uv );
2649                 if( n != PySequence_Length( nmface->v ) ) {
2650                         if( n > 0 )
2651                                 printf( "Warning: different length of vertex and UV coordinate " "list in face!\n" );
2652                         return 0;
2653                 }
2654         }
2655         return 1;
2656 }
2657
2658 /* this is a copy of unlink_mesh in mesh.c, because ... */
2659 static void EXPP_unlink_mesh( Mesh * me )
2660 {
2661         int a;
2662
2663         if( me == 0 )
2664                 return;
2665
2666         for( a = 0; a < me->totcol; a++ ) {
2667                 if( me->mat[a] )
2668                         me->mat[a]->id.us--;
2669                 me->mat[a] = 0;
2670         }
2671
2672 /*      ... here we want to preserve mesh keys */
2673 /* if users want to get rid of them, they can use mesh.removeAllKeys() */
2674 /*
2675         if(me->key) me->key->id.us--;
2676         me->key= 0;
2677 */
2678         if( me->texcomesh )
2679                 me->texcomesh = 0;
2680
2681         me->totcol = 0;
2682 }
2683
2684 static int unlink_existingMeshData( Mesh * mesh )
2685 {
2686         MDeformVert *dvert= NULL;
2687
2688         EXPP_unlink_mesh( mesh );
2689
2690         if(mesh->dvert) {
2691                 /* we don't want to remove dvert here, check_dverts still needs it */
2692                 dvert= mesh->dvert;
2693                 CustomData_set_layer( &mesh->vdata, CD_MDEFORMVERT, NULL );
2694         }
2695
2696         CustomData_free( &mesh->vdata, mesh->totvert );
2697         CustomData_free( &mesh->edata, mesh->totedge );
2698         CustomData_free( &mesh->fdata, mesh->totface );
2699         mesh_update_customdata_pointers( mesh );
2700         
2701         if(dvert)
2702                 mesh->dvert= CustomData_add_layer( &mesh->vdata, CD_MDEFORMVERT,
2703                         CD_ASSIGN, dvert, mesh->totvert );
2704
2705         mesh->totedge = 0;
2706
2707         if( mesh->mat ) {
2708                 MEM_freeN( mesh->mat );
2709                 mesh->mat = NULL;
2710         }
2711
2712         return 1;
2713 }
2714
2715 Material **nmesh_updateMaterials( BPy_NMesh * nmesh )
2716 {
2717         Material **matlist;
2718         Mesh *mesh = nmesh->mesh;
2719         int len = PyList_Size( nmesh->materials );
2720
2721         if( !mesh ) {
2722                 printf( "FATAL INTERNAL ERROR: illegal call to updateMaterials()\n" );
2723                 return 0;
2724         }
2725
2726         if( len > 0 ) {
2727                 if (len>16) len = 16;
2728                 matlist = EXPP_newMaterialList_fromPyList( nmesh->materials );
2729                 EXPP_incr_mats_us( matlist, len );
2730
2731                 if( mesh->mat )
2732                         MEM_freeN( mesh->mat );
2733
2734                 mesh->mat = matlist;
2735
2736         } else {
2737                 matlist = 0;
2738         }
2739         mesh->totcol = (short)len;
2740
2741 /**@ This is another ugly fix due to the weird material handling of blender.
2742         * it makes sure that object material lists get updated (by their length)
2743         * according to their data material lists, otherwise blender crashes.
2744         * It just stupidly runs through all objects...BAD BAD BAD.
2745         */
2746         test_object_materials( ( ID * ) mesh );
2747
2748         return matlist;
2749 }
2750
2751 PyObject *NMesh_assignMaterials_toObject( BPy_NMesh * nmesh, Object * ob )
2752 {
2753         BPy_Material *pymat;
2754         Material *ma;
2755         int i;
2756         short old_matmask;
2757         Mesh *mesh = nmesh->mesh;
2758         int nmats;              /* number of mats == len(nmesh->materials) */
2759
2760         old_matmask = ob->colbits;      /*@ HACK: save previous colbits */
2761         ob->colbits = 0;        /* make assign_material work on mesh linked material */
2762
2763         nmats = PyList_Size( nmesh->materials );
2764
2765         if( nmats > 0 && !mesh->mat ) {
2766                 ob->totcol = (char)nmats;
2767                 mesh->totcol = (short)nmats;
2768                 mesh->mat =
2769                         MEM_callocN( sizeof( void * ) * nmats, "bpy_memats" );
2770
2771                 if( ob->mat )
2772                         MEM_freeN( ob->mat );
2773                 ob->mat =
2774                         MEM_callocN( sizeof( void * ) * nmats, "bpy_obmats" );
2775         }
2776
2777         for( i = 0; i < nmats; i++ ) {
2778                 pymat = ( BPy_Material * ) PySequence_GetItem( nmesh->
2779                                                                materials, i );
2780
2781                 if( BPy_Material_Check( ( PyObject * ) pymat ) ) {
2782                         ma = pymat->material;
2783                         assign_material( ob, ma, i + 1 );       /*@ XXX don't use this function anymore */
2784                 } else {
2785                         Py_DECREF( pymat );
2786                         return EXPP_ReturnPyObjError( PyExc_TypeError,
2787                                                       "expected Material type in attribute list 'materials'!" );
2788                 }
2789
2790                 Py_DECREF( pymat );
2791         }
2792
2793         ob->colbits = old_matmask;      /*@ HACK */
2794
2795         ob->actcol = 1;
2796         Py_RETURN_NONE;
2797 }
2798
2799 static void fill_medge_from_nmesh(Mesh * mesh, BPy_NMesh * nmesh)
2800 {
2801   int i,j;
2802   MEdge *faces_edges=NULL;
2803   int   tot_faces_edges=0;
2804   int tot_valid_faces_edges=0;
2805   int nmeshtotedges=PyList_Size(nmesh->edges);
2806   int tot_valid_nmedges=0;
2807   BPy_NMEdge **valid_nmedges=NULL;
2808
2809   valid_nmedges=MEM_callocN(nmeshtotedges*sizeof(BPy_NMEdge *), "make BPy_NMEdge");
2810
2811   /* First compute the list of edges that exists because faces exists */
2812   make_edges(mesh, 0);  /* 0 = draw all edges */
2813
2814   faces_edges=mesh->medge;
2815   tot_faces_edges=mesh->totedge;
2816   tot_valid_faces_edges=tot_faces_edges;
2817
2818   mesh->medge= CustomData_set_layer(&mesh->edata, CD_MEDGE, NULL);
2819   CustomData_free_layer_active(&mesh->edata, CD_MEDGE, mesh->totedge);
2820   mesh->totedge = 0;
2821
2822   /* Flag each edge in faces_edges that is already in nmesh->edges list.
2823    * Flaging an edge means MEdge v1=v2=0.
2824    * Each time an edge is flagged, tot_valid_faces_edges is decremented.
2825    *
2826    * Also store in valid_nmedges pointers to each valid NMEdge in nmesh->edges.
2827    * An invalid NMEdge is an edge that has a vertex that is not in the vertices 
2828    * list. Ie its index is -1. 
2829    * Each time an valid NMEdge is flagged, tot_valid_nmedges is incremented.
2830    */
2831   for( i = 0; i < nmeshtotedges; ++i )
2832   {
2833     int v1idx,v2idx;
2834     BPy_NMEdge *edge=( BPy_NMEdge *) PyList_GetItem(nmesh->edges, i);
2835     BPy_NMVert *v=(BPy_NMVert *)edge->v1;
2836     v1idx=v->index;
2837     v=(BPy_NMVert *)edge->v2;
2838     v2idx=v->index;
2839     if (-1 == v1idx || -1 == v2idx) continue;
2840     valid_nmedges[tot_valid_nmedges]=edge;
2841     ++tot_valid_nmedges;
2842     for( j = 0; j < tot_faces_edges; j++ )
2843     {
2844       MEdge *me=faces_edges+j;
2845       if ( ((int)me->v1==v1idx && (int)me->v2==v2idx) ||
2846            ((int)me->v1==v2idx && (int)me->v2==v1idx) )
2847       {
2848         me->v1=0; me->v2=0;
2849         --tot_valid_faces_edges;
2850       }
2851     }
2852   }
2853
2854   /* tot_valid_faces_edges < 0 causes a sigsegv crash, so we
2855    * clamp to prevent it
2856    * (this is related to faces (correctly) requiring at least 3 verts now,
2857    * which can break old scripts -- maybe we should also warn about the
2858    * 'broken' mesh the user created, but for now, until we investigate
2859    * better, this should do) */
2860   if (tot_valid_faces_edges < 0) tot_valid_faces_edges = 0;
2861
2862   /* Now we have the total count of valid edges */
2863   mesh->totedge=tot_valid_nmedges+tot_valid_faces_edges;
2864   mesh->medge= CustomData_add_layer( &mesh->edata, CD_MEDGE, CD_CALLOC, NULL,
2865         mesh->totedge );
2866
2867   for ( i = 0; i < tot_valid_nmedges; ++i )
2868   {
2869     BPy_NMEdge *edge=valid_nmedges[i];
2870     MEdge *medge=mesh->medge+i;
2871     int v1=((BPy_NMVert *)edge->v1)->index;
2872     int v2=((BPy_NMVert *)edge->v2)->index;
2873     medge->v1=v1;
2874     medge->v2=v2;
2875     medge->flag=edge->flag;
2876     medge->crease=edge->crease;
2877   }
2878   for ( i = 0, j = tot_valid_nmedges; i < tot_faces_edges; ++i )
2879   {
2880     MEdge *edge=faces_edges+i;
2881     if (edge->v1!=0 || edge->v2!=0)  // valid edge
2882     {
2883       MEdge *medge=mesh->medge+j;
2884       medge->v1=edge->v1;
2885       medge->v2=edge->v2;
2886       medge->flag=ME_EDGEDRAW|ME_EDGERENDER;
2887       medge->crease=0;
2888       ++j;
2889     }
2890   }
2891
2892   MEM_freeN( valid_nmedges );
2893   MEM_freeN( faces_edges );
2894 }
2895
2896 /* this should ensure meshes don't end up with wrongly sized
2897  * me->dvert arrays, which can cause hangs; it's not ideal,
2898  * it's better to wrap dverts in NMesh, but it should do for now
2899  * since there are also methods in NMesh to edit dverts in the actual
2900  * mesh in Blender and anyway this is memory friendly */
2901 static void check_dverts(Mesh *me, int old_totvert)
2902 {
2903         int totvert = me->totvert;
2904
2905         /* if vert count didn't change or there are no dverts, all is fine */
2906         if ((totvert == old_totvert) || (!me->dvert)) return;
2907         /* if all verts have been deleted, free old dverts */
2908         else if (totvert == 0) {
2909                 CustomData_free_layer_active( &me->vdata, CD_MDEFORMVERT, old_totvert );
2910                 me->dvert= NULL;
2911         }
2912         else {
2913                 /* verts added or removed, make new me->dvert */
2914                 MDeformVert *mdv = MEM_callocN( sizeof(MDeformVert)*totvert, "mdv" );
2915                 copy_dverts( mdv, me->dvert, MIN2( old_totvert, totvert ) );
2916                 free_dverts( me->dvert, old_totvert );
2917                 me->dvert= CustomData_set_layer( &me->vdata, CD_MDEFORMVERT, mdv );
2918         }
2919 }
2920
2921 static void check_mtface_mcols( BPy_NMesh *nmesh, Mesh *mesh )
2922 {
2923         int i;
2924
2925         /* copy non-active mcol and mtface layers based on original index */
2926         CustomData_merge( &nmesh->fdata, &mesh->fdata, CD_MASK_MCOL|CD_MASK_MTFACE,
2927                 CD_DEFAULT, mesh->totface );
2928
2929         for( i = 0; i < mesh->totface; i++ ) {
2930                 BPy_NMFace *mf =
2931                         ( BPy_NMFace * ) PySequence_GetItem( nmesh->faces, i );
2932
2933                 if ( mf->orig_index != -1 )
2934                         CustomData_copy_data( &nmesh->fdata, &mesh->fdata, mf->orig_index,
2935                                 i, 1 );
2936
2937                 Py_DECREF( mf );
2938         }
2939
2940         /* add new layers if needed */
2941         if( ( nmesh->flags & NMESH_HASMCOL ) &&
2942                 !CustomData_has_layer( &mesh->fdata, CD_MCOL ) ) {
2943                 mesh->mcol = CustomData_add_layer( &mesh->fdata, CD_MCOL,
2944                         CD_DEFAULT, NULL, mesh->totface );
2945         }
2946
2947         if( ( nmesh->flags & NMESH_HASFACEUV ) || check_validFaceUV( nmesh ) ) {
2948                 if ( !CustomData_has_layer( &mesh->fdata, CD_MTFACE) )
2949                         make_tfaces( mesh );
2950                 nmesh->flags |= NMESH_HASFACEUV;
2951         }
2952         else
2953                 CustomData_free_layers( &mesh->fdata, CD_MTFACE, mesh->totface );
2954
2955         /* active uvs and colors from NMFace will be written in mface_from_data */
2956 }
2957
2958 static int convert_NMeshToMesh( Mesh * mesh, BPy_NMesh * nmesh)
2959 {
2960         MFace *newmf;
2961         MVert *newmv;
2962         MSticky *newst;
2963         int nmeshtotedges;
2964         int badfaces;
2965         int i, j, ok;
2966
2967         /* Minor note: we used 'mode' because 'flag' was already used internally
2968          * by nmesh */
2969         mesh->flag = nmesh->mode;
2970         mesh->smoothresh = nmesh->smoothresh;
2971         mesh->subdiv = nmesh->subdiv[0];
2972         mesh->subdivr = nmesh->subdiv[1];
2973
2974         /*@ material assignment moved to PutRaw */
2975         mesh->totvert = PySequence_Length( nmesh->verts );
2976         if( mesh->totvert ) {
2977                 if( nmesh->flags & NMESH_HASVERTUV )
2978                         mesh->msticky = CustomData_add_layer( &mesh->vdata, CD_MSTICKY,
2979                                 CD_CALLOC, NULL, mesh->totvert );
2980
2981                 mesh->mvert = CustomData_add_layer( &mesh->vdata, CD_MVERT, CD_CALLOC,
2982                         NULL, mesh->totvert );
2983         }
2984
2985         if( mesh->totvert )
2986                 mesh->totface = PySequence_Length( nmesh->faces );
2987         else
2988                 mesh->totface = 0;
2989
2990         if( mesh->totface ) {
2991                 check_mtface_mcols( nmesh, mesh );
2992
2993                 mesh->mface = CustomData_add_layer( &mesh->fdata, CD_MFACE, CD_CALLOC,
2994                         NULL, mesh->totface );
2995         }
2996
2997         mesh_update_customdata_pointers( mesh );
2998
2999         /*@ This stuff here is to tag all the vertices referenced
3000          * by faces, then untag the vertices which are actually
3001          * in the vert list. Any vertices untagged will be ignored
3002          * by the mface_from_data function. It comes from my
3003          * screwed up decision to not make faces only store the
3004          * index. - Zr
3005          */
3006         for( i = 0; i < mesh->totface; i++ ) {
3007                 BPy_NMFace *mf =
3008                         ( BPy_NMFace * ) PySequence_GetItem( nmesh->faces, i );
3009
3010                 j = PySequence_Length( mf->v );
3011                 while( j-- ) {
3012                         BPy_NMVert *mv =
3013                                 ( BPy_NMVert * ) PySequence_GetItem( mf->v,
3014                                                                      j );
3015                         if( BPy_NMVert_Check( mv ) )
3016                                 mv->index = -1;
3017                         Py_DECREF( mv );
3018                 }
3019
3020                 Py_DECREF( mf );
3021         }
3022   /* do the same for edges if there is edge data */
3023     nmeshtotedges=PyList_Size(nmesh->edges);
3024     for( i = 0; i < nmeshtotedges; ++i )
3025     {
3026       BPy_NMEdge *edge=( BPy_NMEdge *) PyList_GetItem(nmesh->edges, i);
3027       BPy_NMVert *v=(BPy_NMVert *)edge->v1;
3028       v->index=-1;
3029       v=(BPy_NMVert *)edge->v2;
3030       v->index=-1;
3031     }
3032
3033         for( i = 0; i < mesh->totvert; i++ ) {
3034                 BPy_NMVert *mv =
3035                         ( BPy_NMVert * ) PySequence_GetItem( nmesh->verts, i );
3036                 mv->index = i;
3037                 Py_DECREF( mv );
3038         }
3039
3040         newmv = mesh->mvert;
3041         newst = mesh->msticky;
3042         for( i = 0; i < mesh->totvert; i++ ) {
3043                 PyObject *mv = PySequence_GetItem( nmesh->verts, i );
3044                 mvert_from_data( newmv, newst, ( BPy_NMVert * ) mv );
3045                 Py_DECREF( mv );
3046
3047                 newmv++;
3048                 if( newst )
3049                         newst++;
3050         }
3051
3052         newmf = mesh->mface;
3053         badfaces = 0;
3054         for( i = 0; i < mesh->totface; i++ ) {
3055                 PyObject *mf = PySequence_GetItem( nmesh->faces, i );
3056                 ok = mface_from_data( newmf, &mesh->fdata, i, ( BPy_NMFace * ) mf );
3057                 Py_DECREF( mf );
3058                 if( ok == 0)
3059                         return 0;
3060                 else if ( ok == -1 )
3061                         ++badfaces;
3062                 else
3063                         newmf++;
3064         }
3065         mesh->totface -= badfaces;
3066
3067                 /* Always do this to ensure no loose edges in faces */
3068     fill_medge_from_nmesh(mesh, nmesh);
3069
3070         return 1;
3071 }
3072
3073 static PyObject *M_NMesh_PutRaw( PyObject * self, PyObject * args )
3074 {
3075         char *name = NULL;
3076         Mesh *mesh = NULL;
3077         Object *ob = NULL;
3078         BPy_NMesh *nmesh;
3079         int recalc_normals = 1;
3080         int store_edges = 0;
3081         int old_totvert = 0;
3082
3083         if( !PyArg_ParseTuple( args, "O!|sii",
3084                                &NMesh_Type, &nmesh, &name, &recalc_normals, &store_edges ) )
3085                 return EXPP_ReturnPyObjError( PyExc_AttributeError,
3086                                               "expected an NMesh object and optionally also a string and two ints" );
3087
3088         if( check_NMeshLists( nmesh ) )
3089                 return NULL;
3090
3091         if( name )
3092                 mesh = ( Mesh * ) GetIdFromList( &( G.main->mesh ), name );
3093
3094         if( !mesh || mesh->id.us == 0 ) {
3095                 ob = add_object( OB_MESH );
3096                 if( !ob ) {
3097                         PyErr_SetString( PyExc_RuntimeError,
3098                                 "Fatal: could not create mesh object" );
3099                         return 0;
3100                 }
3101
3102                 if( !mesh )
3103                         mesh = ( Mesh * ) ob->data;
3104                 else
3105                         set_mesh( ob, mesh );   // also does id.us++
3106
3107                 nmesh->object = ob;     // linking so vgrouping methods know which obj to work on
3108         }
3109
3110         if( name )
3111                 new_id( &( G.main->mesh ), &mesh->id, name );
3112         else if( nmesh->name && nmesh->name != Py_None )
3113                 new_id( &( G.main->mesh ), &mesh->id,
3114                         PyString_AsString( nmesh->name ) );
3115
3116         old_totvert = mesh->totvert;
3117
3118         unlink_existingMeshData( mesh );
3119         if( !convert_NMeshToMesh( mesh, nmesh ) )
3120                 return NULL;
3121         nmesh->mesh = mesh;
3122
3123         if (mesh->dvert) check_dverts(mesh, old_totvert);
3124
3125         if( recalc_normals )
3126                 mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mface, mesh->totface, NULL);
3127
3128         mesh_update( mesh, nmesh->object );
3129
3130         if( !during_script(  ) )
3131                 EXPP_allqueue( REDRAWVIEW3D, 0 );
3132
3133         if (ob && G.obedit) { /* prevents a crash when a new object is created */
3134                 exit_editmode(EM_FREEDATA);
3135                 enter_editmode(0);
3136         }
3137
3138         // @OK...this requires some explanation:
3139         // Materials can be assigned two ways:
3140         // a) to the object data (in this case, the mesh)
3141         // b) to the Object
3142         //
3143         // Case a) is wanted, if Mesh data should be shared among objects,
3144         // as well as its materials (up to 16)
3145         // Case b) is wanted, when Mesh data should be shared, but not the
3146         // materials. For example, you want several checker boards sharing their
3147         // mesh data, but having different colors. So you would assign material
3148         // index 0 to all even, index 1 to all odd faces and bind the materials
3149         // to the Object instead (MaterialButtons: [OB] "link materials to object")
3150         //
3151         // This feature implies that pointers to materials can be stored in
3152         // an object or a mesh. The number of total materials MUST be
3153         // synchronized (ob->totcol <-> mesh->totcol). We avoid the dangerous
3154         // direct access by calling blenderkernel/material.c:assign_material().
3155
3156         // The flags setting the material binding is found in ob->colbits, where 
3157         // each bit indicates the binding PER MATERIAL 
3158
3159         if( ob ) {              // we created a new object
3160                 NMesh_assignMaterials_toObject( nmesh, ob );
3161                 EXPP_synchronizeMaterialLists( ob );
3162                 return Object_CreatePyObject( ob );
3163         } else {
3164                 mesh->mat =
3165                         EXPP_newMaterialList_fromPyList( nmesh->materials );
3166                 EXPP_incr_mats_us( mesh->mat,
3167                                    PyList_Size( nmesh->materials ) );
3168                 Py_RETURN_NONE;
3169         }
3170
3171 }
3172
3173 #undef MethodDef
3174 #define MethodDef(func) \
3175         {#func, M_NMesh_##func, METH_VARARGS, M_NMesh_##func##_doc}
3176
3177 static struct PyMethodDef M_NMesh_methods[] = {
3178         MethodDef( Col ),
3179         MethodDef( Vert ),
3180         MethodDef( Face ),
3181         MethodDef( New ),
3182         MethodDef( GetRaw ),
3183         MethodDef( GetRawFromObject ),
3184         MethodDef( PutRaw ),
3185         {"GetNames", (PyCFunction)M_NMesh_GetNames, METH_NOARGS,
3186                 M_NMesh_GetNames_doc},
3187         {NULL, NULL, 0, NULL}
3188 };
3189
3190 static PyObject *M_NMesh_Modes( void )
3191 {
3192         PyObject *Modes = PyConstant_New(  );
3193
3194         if( Modes ) {
3195                 BPy_constant *d = ( BPy_constant * ) Modes;
3196
3197                 PyConstant_Insert( d, "NOVNORMALSFLIP",
3198                                  PyInt_FromLong
3199                                  ( ME_NOPUNOFLIP ) );
3200                 PyConstant_Insert( d, "TWOSIDED",
3201                                  PyInt_FromLong( ME_TWOSIDED ) );
3202                 PyConstant_Insert( d, "AUTOSMOOTH",
3203                                  PyInt_FromLong
3204                                  ( ME_AUTOSMOOTH ) );
3205         }
3206
3207         return Modes;
3208 }
3209
3210 #undef EXPP_ADDCONST
3211 #define EXPP_ADDCONST(dict, name) \
3212                          PyConstant_Insert(dict, #name, PyInt_FromLong(TF_##name))
3213 /* Set constants for face drawing mode -- see drawmesh.c */
3214
3215 static PyObject *M_NMesh_FaceModesDict( void )
3216 {
3217         PyObject *FM = PyConstant_New(  );
3218
3219         if( FM ) {
3220                 BPy_constant *d = ( BPy_constant * ) FM;
3221
3222                 PyConstant_Insert( d, "BILLBOARD",
3223                                        PyInt_FromLong( TF_BILLBOARD2 ) );
3224                 PyConstant_Insert( d, "ALL", PyInt_FromLong( 0x7fff ) );
3225                 PyConstant_Insert( d, "HALO", PyInt_FromLong( TF_BILLBOARD ) );
3226                 PyConstant_Insert( d, "DYNAMIC", PyInt_FromLong( TF_DYNAMIC ) );
3227                 PyConstant_Insert( d, "INVISIBLE", PyInt_FromLong( TF_INVISIBLE ) );
3228                 PyConstant_Insert( d, "LIGHT", PyInt_FromLong( TF_LIGHT ) );
3229                 PyConstant_Insert( d, "OBCOL", PyInt_FromLong( TF_OBCOL ) );
3230                 PyConstant_Insert( d, "SHADOW", PyInt_FromLong( TF_SHADOW ) );
3231                 PyConstant_Insert( d, "TEXT", PyInt_FromLong( TF_BMFONT ) );
3232                 PyConstant_Insert( d, "SHAREDVERT", PyInt_FromLong( TF_SHAREDVERT ) );
3233                 PyConstant_Insert( d, "SHAREDCOL", PyInt_FromLong( TF_SHAREDCOL ) );
3234                 PyConstant_Insert( d, "TEX", PyInt_FromLong( TF_TEX ) );
3235                 PyConstant_Insert( d, "TILES", PyInt_FromLong( TF_TILES ) );
3236                 PyConstant_Insert( d, "TWOSIDE", PyInt_FromLong( TF_TWOSIDE ) );
3237         }
3238
3239         return FM;
3240 }
3241
3242 static PyObject *M_NMesh_FaceFlagsDict( void )
3243 {
3244         PyObject *FF = PyConstant_New(  );
3245
3246         if( FF ) {
3247                 BPy_constant *d = ( BPy_constant * ) FF;
3248
3249                 EXPP_ADDCONST( d, SELECT );
3250                 EXPP_ADDCONST( d, HIDE );
3251                 EXPP_ADDCONST( d, ACTIVE );
3252         }
3253
3254         return FF;
3255 }
3256
3257 static PyObject *M_NMesh_FaceTranspModesDict( void )
3258 {
3259         PyObject *FTM = PyConstant_New(  );
3260
3261         if( FTM ) {
3262                 BPy_constant *d = ( BPy_constant * ) FTM;
3263
3264                 EXPP_ADDCONST( d, SOLID );
3265                 EXPP_ADDCONST( d, ADD );
3266                 EXPP_ADDCONST( d, ALPHA );
3267                 EXPP_ADDCONST( d, SUB );
3268         }
3269
3270         return FTM;
3271 }
3272
3273 static PyObject *M_NMesh_EdgeFlagsDict( void )
3274 {
3275         PyObject *EF = PyConstant_New(  );
3276
3277         if( EF ) {
3278                 BPy_constant *d = ( BPy_constant * ) EF;
3279
3280                 PyConstant_Insert(d, "SELECT", PyInt_FromLong(1));
3281                 PyConstant_Insert(d, "EDGEDRAW", PyInt_FromLong(ME_EDGEDRAW));
3282                 PyConstant_Insert(d, "EDGERENDER", PyInt_FromLong(ME_EDGERENDER));
3283                 PyConstant_Insert(d, "SEAM", PyInt_FromLong(ME_SEAM));
3284                 PyConstant_Insert(d, "FGON", PyInt_FromLong(ME_FGON));
3285         }
3286
3287         return EF;
3288 }
3289
3290 PyObject *NMesh_Init( void )
3291 {
3292         PyObject *submodule;
3293
3294         PyObject *Modes = M_NMesh_Modes(  );