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