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