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