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