4 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
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
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.
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.
23 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24 * All rights reserved.
26 * This is a new part of Blender, partially based on NMesh.c API.
28 * Contributor(s): Ken Hughes
30 * ***** END GPL/BL DUAL LICENSE BLOCK *****
33 #include "Mesh.h" /*This must come first*/
35 #include "MEM_guardedalloc.h"
37 #include "DNA_key_types.h"
38 #include "DNA_armature_types.h"
39 #include "DNA_scene_types.h"
40 #include "DNA_oops_types.h"
41 #include "DNA_space_types.h"
42 #include "DNA_curve_types.h"
43 #include "DNA_meta_types.h"
44 #include "DNA_modifier_types.h"
46 #include "BDR_editface.h" /* make_tfaces */
47 #include "BDR_vpaint.h"
48 #include "BDR_editobject.h"
50 #include "BIF_editdeform.h"
51 #include "BIF_editkey.h" /* insert_meshkey */
52 #include "BIF_space.h" /* REMAKEIPO - insert_meshkey */
53 #include "BIF_editview.h"
54 #include "BIF_editmesh.h"
55 #include "BIF_meshtools.h"
57 #include "BKE_customdata.h"
58 #include "BKE_deform.h"
59 #include "BKE_displist.h"
61 #include "BKE_material.h"
63 #include "BKE_global.h"
64 #include "BKE_library.h"
65 #include "BKE_DerivedMesh.h"
66 #include "BKE_object.h"
67 #include "BKE_mball.h"
68 #include "BKE_utildefines.h"
69 #include "BKE_depsgraph.h"
70 #include "BSE_edit.h" /* for countall(); */
71 #include "BKE_curve.h" /* for copy_curve(); */
72 #include "BKE_modifier.h" /* for modifier_new(), modifier_copyData(); */
73 #include "BKE_idprop.h"
75 #include "BLI_arithb.h"
76 #include "BLI_blenlib.h"
80 #include "butspace.h" /* for mesh tools */
85 #include "Mathutils.h"
87 #include "meshPrimitive.h"
89 #include "gen_utils.h"
90 #include "gen_library.h"
93 /* EXPP Mesh defines */
95 #define MESH_SMOOTHRESH 30
96 #define MESH_SMOOTHRESH_MIN 1
97 #define MESH_SMOOTHRESH_MAX 80
99 #define MESH_SUBDIV_MIN 0
100 #define MESH_SUBDIV_MAX 6
102 #define MESH_HASFACEUV 0
103 #define MESH_HASMCOL 1
104 #define MESH_HASVERTUV 2
105 #define MESH_HASMULTIRES 3
107 #define MESH_MULTIRES_LEVEL 0
108 #define MESH_MULTIRES_EDGE 1
109 #define MESH_MULTIRES_PIN 2
110 #define MESH_MULTIRES_RENDER 3
112 #define MESH_TOOL_TOSPHERE 0
113 #define MESH_TOOL_VERTEXSMOOTH 1
114 #define MESH_TOOL_FLIPNORM 2
115 #define MESH_TOOL_SUBDIV 3
116 #define MESH_TOOL_REMDOUB 4
117 #define MESH_TOOL_FILL 5
118 #define MESH_TOOL_RECALCNORM 6
119 #define MESH_TOOL_TRI2QUAD 7
120 #define MESH_TOOL_QUAD2TRI 8
122 static PyObject *MVertSeq_CreatePyObject( Mesh * mesh );
123 static PyObject *MFaceSeq_CreatePyObject( Mesh * mesh );
124 static PyObject *MEdgeSeq_CreatePyObject( Mesh * mesh );
125 static PyObject *MFace_CreatePyObject( Mesh * mesh, int i );
126 static PyObject *MEdge_CreatePyObject( Mesh * mesh, int i );
128 #define MFACE_VERT_BADRANGE_CHECK(me, face) ((int)face->v1 >= me->totvert || (int)face->v2 >= me->totvert || (int)face->v3 >= me->totvert || (int)face->v4 >= me->totvert)
129 #define MEDGE_VERT_BADRANGE_CHECK(me, edge) ((int)edge->v1 >= me->totvert || (int)edge->v2 >= me->totvert)
131 /************************************************************************
135 ************************************************************************/
138 * internal structures used for sorting edges and faces
141 typedef struct SrchEdges {
142 unsigned int v[2]; /* indices for verts */
143 unsigned char swap; /* non-zero if verts swapped */
144 unsigned int index; /* index in original param list of this edge */
145 /* (will be used by findEdges) */
148 typedef struct SrchFaces {
149 unsigned int v[4]; /* indices for verts */
150 unsigned int index; /* index in original param list of this edge */
151 unsigned char order; /* order of original verts, bitpacked */
154 typedef struct FaceEdges {
155 unsigned int v[2]; /* search key (vert indices) */
156 unsigned int index; /* location in edge list */
157 unsigned char sel; /* selection state */
161 * compare edges by vertex indices
164 int medge_comp( const void *va, const void *vb )
166 const unsigned int *a = ((SrchEdges *)va)->v;
167 const unsigned int *b = ((SrchEdges *)vb)->v;
169 /* compare first index for differences */
171 if (a[0] < b[0]) return -1;
172 else if (a[0] > b[0]) return 1;
174 /* if first indices equal, compare second index for differences */
176 else if (a[1] < b[1]) return -1;
177 else return (a[1] > b[1]);
181 * compare edges by insert list indices
184 int medge_index_comp( const void *va, const void *vb )
186 const SrchEdges *a = (SrchEdges *)va;
187 const SrchEdges *b = (SrchEdges *)vb;
189 /* compare list indices for differences */
191 if (a->index < b->index) return -1;
192 else return (a->index > b->index);
197 * compare faces by vertex indices
200 int mface_comp( const void *va, const void *vb )
202 const SrchFaces *a = va;
203 const SrchFaces *b = vb;
206 /* compare indices, first to last, for differences */
207 for( i = 0; i < 4; ++i ) {
208 if( a->v[i] < b->v[i] )
210 if( a->v[i] > b->v[i] )
215 * don't think this needs be done; if order is different then either
216 * (a) the face is good, just reversed or has a different starting
217 * vertex, or (b) face is bad (for 4 verts) and there's a "twist"
221 /* if all the same verts, compare their order */
222 if( a->order < b->order )
224 if( a->order > b->order )
232 * compare faces by insert list indices
235 int mface_index_comp( const void *va, const void *vb )
237 const SrchFaces *a = va;
238 const SrchFaces *b = vb;
240 /* compare indices, first to last, for differences */
241 if( a->index < b->index )
243 if( a->index > b->index )
249 * compare edges by vertex indices
252 int faceedge_comp( const void *va, const void *vb )
254 const unsigned int *a = ((FaceEdges *)va)->v;
255 const unsigned int *b = ((FaceEdges *)vb)->v;
257 /* compare first index for differences */
259 if (a[0] < b[0]) return -1;
260 else if (a[0] > b[0]) return 1;
262 /* if first indices equal, compare second index for differences */
264 else if (a[1] < b[1]) return -1;
265 else return (a[1] > b[1]);
269 * update the DAG for all objects linked to this mesh
272 static void mesh_update( Mesh * mesh )
274 Object_updateDag( (void *) mesh );
278 * delete vertices from mesh, then delete edges/keys/faces which used those
281 * Deletion is done by "smart compaction"; groups of verts/edges/faces which
282 * remain in the list are copied to new list instead of one at a time. Since
283 * Blender has no realloc we would have to copy things anyway, so there's no
284 * point trying to fill empty entries with data from the end of the lists.
286 * vert_table is a lookup table for mapping old verts to new verts (after the
287 * vextex list has deleted vertices removed). Each entry contains the
288 * vertex's new index.
291 static void delete_verts( Mesh *mesh, unsigned int *vert_table, int to_delete )
294 * (1) allocate vertex table (initialize contents to 0)
295 * (2) mark each vertex being deleted in vertex table (= UINT_MAX)
296 * (3) update remaining table entries with "new" vertex index (after
298 * (4) allocate new vertex list
299 * (5) do "smart copy" of vertices from old to new
300 * * each moved vertex is entered into vertex table: if vertex i is
301 * moving to index j in new list
303 * (6) if keys, do "smart copy" of keys
304 * (7) process edge list
306 * delete edges which delete verts
307 * (7) allocate new edge list
308 * (8) do "smart copy" of edges
309 * (9) allocate new face list
310 * (10) do "smart copy" of face
313 unsigned int *tmpvert;
315 int i, count, state, dstindex, totvert;
317 totvert = mesh->totvert - to_delete;
318 CustomData_copy( &mesh->vdata, &vdata, CD_MASK_MESH, CD_CALLOC, totvert );
321 * do "smart compaction" of the table; find and copy groups of vertices
322 * which are not being deleted
326 tmpvert = vert_table;
329 for( i = 0; i < mesh->totvert; ++i, ++tmpvert ) {
331 case 0: /* skipping verts */
332 if( *tmpvert == UINT_MAX ) {
339 case 1: /* gathering verts */
340 if( *tmpvert != UINT_MAX ) {
344 CustomData_copy_data( &mesh->vdata, &vdata, i-count,
354 /* if we were gathering verts at the end of the loop, copy those */
356 CustomData_copy_data( &mesh->vdata, &vdata, i-count, dstindex, count );
358 /* delete old vertex list, install the new one, update vertex count */
359 CustomData_free( &mesh->vdata, mesh->totvert );
361 mesh->totvert = totvert;
362 mesh_update_customdata_pointers( mesh );
365 static void delete_edges( Mesh *mesh, unsigned int *vert_table, int to_delete )
370 /* if not given, then mark and count edges to be deleted */
372 tmpedge = mesh->medge;
373 for( i = mesh->totedge; i-- ; ++tmpedge )
374 if( vert_table[tmpedge->v1] == UINT_MAX ||
375 vert_table[tmpedge->v2] == UINT_MAX ) {
376 tmpedge->v1 = UINT_MAX;
381 /* if there are edges to delete, handle it */
384 int count, state, dstindex, totedge;
386 /* allocate new edge list and populate */
387 totedge = mesh->totedge - to_delete;
388 CustomData_copy( &mesh->edata, &edata, CD_MASK_MESH, CD_CALLOC, totedge);
391 * do "smart compaction" of the edges; find and copy groups of edges
392 * which are not being deleted
396 tmpedge = mesh->medge;
399 for( i = 0; i < mesh->totedge; ++i, ++tmpedge ) {
401 case 0: /* skipping edges */
402 if( tmpedge->v1 == UINT_MAX ) {
409 case 1: /* gathering edges */
410 if( tmpedge->v1 != UINT_MAX ) {
414 CustomData_copy_data( &mesh->edata, &edata, i-count,
422 /* if edge is good, update vertex indices */
425 /* copy any pending good edges */
427 CustomData_copy_data( &mesh->edata, &edata, i-count, dstindex,
430 /* delete old edge list, install the new one, update vertex count */
431 CustomData_free( &mesh->edata, mesh->totedge );
433 mesh->totedge = totedge;
434 mesh_update_customdata_pointers( mesh );
437 /* if vertices were deleted, update edge's vertices */
439 tmpedge = mesh->medge;
440 for( i = mesh->totedge; i--; ++tmpedge ) {
441 tmpedge->v1 = vert_table[tmpedge->v1];
442 tmpedge->v2 = vert_table[tmpedge->v2];
448 * Since all faces must have 3 or 4 verts, we can't have v3 or v4 be zero.
449 * If that happens during the deletion, we have to shuffle the vertices
450 * around; otherwise it can cause an Eeekadoodle or worse. If there are
451 * texture faces as well, they have to be shuffled as well.
453 * (code borrowed from test_index_face() in mesh.c, but since we know the
454 * faces already have correct number of vertices, this is a little faster)
457 static void eeek_fix( MFace *mface, int len4 )
459 /* if 4 verts, then neither v3 nor v4 can be zero */
461 if( !mface->v3 || !mface->v4 ) {
462 SWAP( int, mface->v1, mface->v3 );
463 SWAP( int, mface->v2, mface->v4 );
465 } else if( !mface->v3 ) {
466 /* if 2 verts, then just v3 cannot be zero (v4 MUST be zero) */
467 SWAP( int, mface->v1, mface->v2 );
468 SWAP( int, mface->v2, mface->v3 );
472 static void delete_faces( Mesh *mesh, unsigned int *vert_table, int to_delete )
477 /* if there are faces to delete, handle it */
480 int count, state, dstindex, totface;
482 totface = mesh->totface - to_delete;
483 CustomData_copy( &mesh->fdata, &fdata, CD_MASK_MESH, CD_CALLOC, totface );
486 * do "smart compaction" of the faces; find and copy groups of faces
487 * which are not being deleted
491 tmpface = mesh->mface;
495 for( i = 0; i < mesh->totface; ++i ) {
497 case 0: /* skipping faces */
498 if( tmpface->v1 == UINT_MAX ) {
505 case 1: /* gathering faces */
506 if( tmpface->v1 != UINT_MAX ) {
510 CustomData_copy_data( &mesh->fdata, &fdata, i-count,
521 /* if we were gathering faces at the end of the loop, copy those */
522 if ( state && count )
523 CustomData_copy_data( &mesh->fdata, &fdata, i-count, dstindex,
526 /* delete old face list, install the new one, update face count */
528 CustomData_free( &mesh->fdata, mesh->totface );
530 mesh->totface = totface;
531 mesh_update_customdata_pointers( mesh );
534 /* if vertices were deleted, update face's vertices */
536 tmpface = mesh->mface;
538 for( i = 0; i<mesh->totface; ++i, ++tmpface ) {
539 int len4 = tmpface->v4;
540 tmpface->v1 = vert_table[tmpface->v1];
541 tmpface->v2 = vert_table[tmpface->v2];
542 tmpface->v3 = vert_table[tmpface->v3];
544 tmpface->v4 = vert_table[tmpface->v4];
548 test_index_face( tmpface, &mesh->fdata, i, len4? 4: 3);
554 * fill up vertex lookup table with old-to-new mappings
556 * returns the number of vertices marked for deletion
559 static unsigned int make_vertex_table( unsigned int *vert_table, int count )
562 unsigned int *tmpvert = vert_table;
563 unsigned int to_delete = 0;
564 unsigned int new_index = 0;
566 /* fill the lookup table with old->new index mappings */
567 for( i = count; i; --i, ++tmpvert ) {
568 if( *tmpvert == UINT_MAX ) {
571 *tmpvert = new_index;
579 /************************************************************************
583 ************************************************************************/
586 * get a color attribute
589 static PyObject *MCol_getAttr( BPy_MCol * self, void *type )
593 switch( (long)type ) {
594 case 'R': /* these are backwards, but that how it works */
595 param = self->color->b;
598 param = self->color->g;
600 case 'B': /* these are backwards, but that how it works */
601 param = self->color->r;
604 param = self->color->a;
609 sprintf( errstr, "undefined type '%d' in MCol_getAttr",
610 (int)((long)type & 0xff));
611 return EXPP_ReturnPyObjError( PyExc_RuntimeError, errstr );
615 return PyInt_FromLong( param );
619 * set a color attribute
622 static int MCol_setAttr( BPy_MCol * self, PyObject * value, void * type )
624 unsigned char *param;
626 switch( (long)type ) {
627 case 'R': /* these are backwards, but that how it works */
628 param = (unsigned char *)&self->color->b;
631 param = (unsigned char *)&self->color->g;
633 case 'B': /* these are backwards, but that how it works */
634 param = (unsigned char *)&self->color->r;
637 param = (unsigned char *)&self->color->a;
642 sprintf( errstr, "undefined type '%d' in MCol_setAttr",
643 (int)((long)type & 0xff));
644 return EXPP_ReturnIntError( PyExc_RuntimeError, errstr );
648 return EXPP_setIValueClamped( value, param, 0, 255, 'b' );
651 /************************************************************************
653 * Python MCol_Type attributes get/set structure
655 ************************************************************************/
657 static PyGetSetDef BPy_MCol_getseters[] = {
659 (getter)MCol_getAttr, (setter)MCol_setAttr,
663 (getter)MCol_getAttr, (setter)MCol_setAttr,
667 (getter)MCol_getAttr, (setter)MCol_setAttr,
671 (getter)MCol_getAttr, (setter)MCol_setAttr,
674 {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
678 /*----------------------------object[]---------------------------
679 sequence accessor (get)*/
680 static PyObject *MCol_item(BPy_MCol * self, int i)
685 param = self->color->b;
688 param = self->color->g;
691 param = self->color->r;
694 param = self->color->a;
697 return EXPP_ReturnPyObjError(PyExc_IndexError,
698 "vector[index] = x: assignment index out of range\n");
701 return PyInt_FromLong( param );
704 /*----------------------------object[]-------------------------
705 sequence accessor (set)*/
706 static int MCol_ass_item(BPy_MCol * self, int i, PyObject * value)
708 unsigned char *param;
712 param = (unsigned char *)&self->color->b; /* reversed? why */
715 param = (unsigned char *)&self->color->g;
718 param = (unsigned char *)&self->color->r; /* reversed? why */
721 param = (unsigned char *)&self->color->a;
725 return EXPP_ReturnIntError( PyExc_RuntimeError, "Index out of range" );
728 return EXPP_setIValueClamped( value, param, 0, 255, 'b' );
731 /************************************************************************
733 * Python MCol_Type methods
735 ************************************************************************/
737 static PyObject *MCol_repr( BPy_MCol * self )
739 return PyString_FromFormat( "[MCol %d %d %d %d]",
740 (int)self->color->b, (int)self->color->g,
741 (int)self->color->r, (int)self->color->a );
744 /*-----------------PROTCOL DECLARATIONS--------------------------*/
745 static PySequenceMethods MCol_SeqMethods = {
746 (inquiry) NULL, /* sq_length */
747 (binaryfunc) NULL, /* sq_concat */
748 (intargfunc) NULL, /* sq_repeat */
749 (intargfunc) MCol_item, /* sq_item */
750 (intintargfunc) NULL, /* sq_slice */
751 (intobjargproc) MCol_ass_item, /* sq_ass_item */
752 (intintobjargproc) NULL, /* sq_ass_slice */
755 /************************************************************************
757 * Python MCol_Type structure definition
759 ************************************************************************/
761 PyTypeObject MCol_Type = {
762 PyObject_HEAD_INIT( NULL ) /* required py macro */
764 /* For printing, in format "<module>.<name>" */
765 "Blender MCol", /* char *tp_name; */
766 sizeof( BPy_MCol ), /* int tp_basicsize; */
767 0, /* tp_itemsize; For allocation */
769 /* Methods to implement standard operations */
771 NULL, /* destructor tp_dealloc; */
772 NULL, /* printfunc tp_print; */
773 NULL, /* getattrfunc tp_getattr; */
774 NULL, /* setattrfunc tp_setattr; */
775 NULL, /* cmpfunc tp_compare; */
776 ( reprfunc ) MCol_repr, /* reprfunc tp_repr; */
778 /* Method suites for standard classes */
780 NULL, /* PyNumberMethods *tp_as_number; */
781 &MCol_SeqMethods, /* PySequenceMethods *tp_as_sequence; */
782 NULL, /* PyMappingMethods *tp_as_mapping; */
784 /* More standard operations (here for binary compatibility) */
786 NULL, /* hashfunc tp_hash; */
787 NULL, /* ternaryfunc tp_call; */
788 NULL, /* reprfunc tp_str; */
789 NULL, /* getattrofunc tp_getattro; */
790 NULL, /* setattrofunc tp_setattro; */
792 /* Functions to access object as input/output buffer */
793 NULL, /* PyBufferProcs *tp_as_buffer; */
795 /*** Flags to define presence of optional/expanded features ***/
796 Py_TPFLAGS_DEFAULT, /* long tp_flags; */
798 NULL, /* char *tp_doc; Documentation string */
799 /*** Assigned meaning in release 2.0 ***/
800 /* call function for all accessible objects */
801 NULL, /* traverseproc tp_traverse; */
803 /* delete references to contained objects */
804 NULL, /* inquiry tp_clear; */
806 /*** Assigned meaning in release 2.1 ***/
807 /*** rich comparisons ***/
808 NULL, /* richcmpfunc tp_richcompare; */
810 /*** weak reference enabler ***/
811 0, /* long tp_weaklistoffset; */
813 /*** Added in release 2.2 ***/
815 NULL, /* getiterfunc tp_iter; */
816 NULL, /* iternextfunc tp_iternext; */
818 /*** Attribute descriptor and subclassing stuff ***/
819 NULL, /* struct PyMethodDef *tp_methods; */
820 NULL, /* struct PyMemberDef *tp_members; */
821 BPy_MCol_getseters, /* struct PyGetSetDef *tp_getset; */
822 NULL, /* struct _typeobject *tp_base; */
823 NULL, /* PyObject *tp_dict; */
824 NULL, /* descrgetfunc tp_descr_get; */
825 NULL, /* descrsetfunc tp_descr_set; */
826 0, /* long tp_dictoffset; */
827 NULL, /* initproc tp_init; */
828 NULL, /* allocfunc tp_alloc; */
829 NULL, /* newfunc tp_new; */
830 /* Low-level free-memory routine */
831 NULL, /* freefunc tp_free; */
832 /* For PyObject_IS_GC */
833 NULL, /* inquiry tp_is_gc; */
834 NULL, /* PyObject *tp_bases; */
835 /* method resolution order */
836 NULL, /* PyObject *tp_mro; */
837 NULL, /* PyObject *tp_cache; */
838 NULL, /* PyObject *tp_subclasses; */
839 NULL, /* PyObject *tp_weaklist; */
843 static PyObject *MCol_CreatePyObject( MCol * color )
845 BPy_MCol *obj = PyObject_NEW( BPy_MCol, &MCol_Type );
848 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
849 "PyObject_New() failed" );
852 return (PyObject *)obj;
855 /************************************************************************
857 * BPy_MVert attributes
859 ************************************************************************/
861 static MVert * MVert_get_pointer( BPy_MVert * self )
863 if( BPy_MVert_Check( self ) ) {
864 if( self->index >= ((Mesh *)self->data)->totvert )
865 return (MVert *)EXPP_ReturnPyObjError( PyExc_RuntimeError,
866 "MVert is no longer valid" );
867 return &((Mesh *)self->data)->mvert[self->index];
870 return (MVert *)self->data;
874 * get a vertex's coordinate
877 static PyObject *MVert_getCoord( BPy_MVert * self )
881 v = MVert_get_pointer( self );
885 return newVectorObject( v->co, 3, Py_WRAP );
889 * set a vertex's coordinate
892 static int MVert_setCoord( BPy_MVert * self, VectorObject * value )
897 v = MVert_get_pointer( self );
901 if( !VectorObject_Check( value ) || value->size != 3 )
902 return EXPP_ReturnIntError( PyExc_TypeError,
903 "expected vector argument of size 3" );
906 v->co[i] = value->vec[i];
912 * get a vertex's index
915 static PyObject *MVert_getIndex( BPy_MVert * self )
917 if( self->index >= ((Mesh *)self->data)->totvert )
918 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
919 "MVert is no longer valid" );
921 return PyInt_FromLong( self->index );
926 * get a verts's hidden state
929 static PyObject *MVert_getMFlagBits( BPy_MVert * self, void * type )
933 v = MVert_get_pointer( self );
935 return NULL; /* error is set */
937 return EXPP_getBitfield( &v->flag, (int)((long)type & 0xff), 'b' );
942 * set a verts's hidden state
945 static int MVert_setMFlagBits( BPy_MVert * self, PyObject * value,
950 v = MVert_get_pointer( self );
953 return -1; /* error is set */
955 return EXPP_setBitfield( value, &v->flag,
956 (int)((long)type & 0xff), 'b' );
961 * get a vertex's normal
964 static PyObject *MVert_getNormal( BPy_MVert * self )
970 v = MVert_get_pointer( self );
972 return NULL; /* error set */
974 for( i = 0; i < 3; ++i )
975 no[i] = (float)(v->no[i] / 32767.0);
976 return newVectorObject( no, 3, Py_NEW );
980 * set a vertex's normal
983 static int MVert_setNormal( BPy_MVert * self, VectorObject * value )
989 v = MVert_get_pointer( self );
991 return -1; /* error set */
993 if( !VectorObject_Check( value ) || value->size != 3 )
994 return EXPP_ReturnIntError( PyExc_TypeError,
995 "expected vector argument of size 3" );
999 normal[i] = value->vec[i];
1003 for( i=0; i<3 ; ++i)
1004 v->no[i] = (short)(normal[i]*32767.0);
1011 * get a vertex's select status
1014 static PyObject *MVert_getSel( BPy_MVert *self )
1018 v = MVert_get_pointer( self );
1020 return NULL; /* error is set */
1022 return EXPP_getBitfield( &v->flag, SELECT, 'b' );
1026 * set a vertex's select status
1029 static int MVert_setSel( BPy_MVert *self, PyObject *value )
1031 MVert *v = MVert_get_pointer( self );
1032 Mesh *me = (Mesh *)self->data;
1034 return -1; /* error is set */
1037 * if vertex exists and setting status is OK, delete select storage
1038 * of the edges and faces as well
1041 if( v && !EXPP_setBitfield( value, &v->flag, SELECT, 'b' ) ) {
1042 if( me && me->mselect ) {
1043 MEM_freeN( me->mselect );
1052 * get a vertex's UV coordinates
1055 static PyObject *MVert_getUVco( BPy_MVert *self )
1057 Mesh *me = (Mesh *)self->data;
1060 return EXPP_ReturnPyObjError( PyExc_AttributeError,
1061 "mesh has no 'sticky' coordinates" );
1063 if( self->index >= ((Mesh *)self->data)->totvert )
1064 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1065 "MVert is no longer valid" );
1067 return newVectorObject( me->msticky[self->index].co, 2, Py_WRAP );
1071 * set a vertex's UV coordinates
1074 static int MVert_setUVco( BPy_MVert *self, PyObject *value )
1076 float uvco[3] = {0.0, 0.0};
1077 Mesh *me = (Mesh *)self->data;
1082 * at least for now, don't allow creation of sticky coordinates if they
1083 * don't already exist
1087 return EXPP_ReturnIntError( PyExc_AttributeError,
1088 "mesh has no 'sticky' coordinates" );
1090 if( self->index >= ((Mesh *)self->data)->totvert )
1091 return EXPP_ReturnIntError( PyExc_RuntimeError,
1092 "MVert is no longer valid" );
1094 if( VectorObject_Check( value ) ) {
1095 VectorObject *vect = (VectorObject *)value;
1096 if( vect->size != 2 )
1097 return EXPP_ReturnIntError( PyExc_AttributeError,
1098 "expected 2D vector" );
1099 for( i = 0; i < vect->size; ++i )
1100 uvco[i] = vect->vec[i];
1101 } else if( !PyArg_ParseTuple( value, "ff",
1102 &uvco[0], &uvco[1] ) )
1103 return EXPP_ReturnIntError( PyExc_TypeError,
1104 "expected 2D vector" );
1106 v = &me->msticky[self->index];
1108 for( i = 0; i < 2; ++i )
1114 /************************************************************************
1116 * Python MVert_Type attributes get/set structure
1118 ************************************************************************/
1120 static PyGetSetDef BPy_MVert_getseters[] = {
1122 (getter)MVert_getCoord, (setter)MVert_setCoord,
1123 "vertex's coordinate",
1126 (getter)MVert_getIndex, (setter)NULL,
1130 (getter)MVert_getNormal, (setter)MVert_setNormal,
1134 (getter)MVert_getSel, (setter)MVert_setSel,
1135 "vertex's select status",
1138 (getter)MVert_getMFlagBits, (setter)MVert_setMFlagBits,
1139 "vert hidden in edit mode",
1142 (getter)MVert_getUVco, (setter)MVert_setUVco,
1143 "vertex's UV coordinates",
1145 {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
1148 static PyGetSetDef BPy_PVert_getseters[] = {
1150 (getter)MVert_getCoord, (setter)MVert_setCoord,
1151 "vertex's coordinate",
1154 (getter)MVert_getNormal, (setter)MVert_setNormal,
1158 (getter)MVert_getSel, (setter)MVert_setSel,
1159 "vertex's select status",
1161 {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
1164 /************************************************************************
1166 * Python MVert_Type standard operations
1168 ************************************************************************/
1170 static void MVert_dealloc( BPy_MVert * self )
1172 if( BPy_PVert_Check( self ) ) /* free memory of thick objects */
1173 MEM_freeN ( self->data );
1175 PyObject_DEL( self );
1178 static int MVert_compare( BPy_MVert * a, BPy_MVert * b )
1180 return( a->data == b->data && a->index == b->index ) ? 0 : -1;
1183 static PyObject *MVert_repr( BPy_MVert * self )
1189 v = MVert_get_pointer( self );
1193 if( BPy_MVert_Check( self ) )
1194 sprintf( index, "%d", self->index );
1196 BLI_strncpy( index, "(None)", 24 );
1198 sprintf( format, "[MVert (%f %f %f) (%f %f %f) %s]",
1199 v->co[0], v->co[1], v->co[2], (float)(v->no[0] / 32767.0),
1200 (float)(v->no[1] / 32767.0), (float)(v->no[2] / 32767.0),
1203 return PyString_FromString( format );
1206 static long MVert_hash( BPy_MVert *self )
1208 return (long)self->index;
1211 static PyObject *Mesh_addPropLayer_internal(Mesh *mesh, CustomData *data, int tot, PyObject *args)
1216 if( !PyArg_ParseTuple( args, "si", &name, &type) )
1217 return EXPP_ReturnPyObjError( PyExc_TypeError,
1218 "expected a string and an int" );
1219 if (strlen(name)>31)
1220 return EXPP_ReturnPyObjError( PyExc_ValueError,
1221 "error, maximum name length is 31");
1222 if((type != CD_PROP_FLT) && (type != CD_PROP_INT) && (type != CD_PROP_STR))
1223 return EXPP_ReturnPyObjError( PyExc_ValueError,
1224 "error, unknown layer type");
1226 CustomData_add_layer_named(data, type, CD_DEFAULT, NULL,tot,name);
1228 mesh_update_customdata_pointers(mesh);
1232 static PyObject *Mesh_removePropLayer_internal(Mesh *mesh, CustomData *data, int tot,PyObject *value)
1234 CustomDataLayer *layer;
1235 char *name=PyString_AsString(value);
1239 return EXPP_ReturnPyObjError( PyExc_TypeError,
1240 "expected string argument" );
1242 if (strlen(name)>31)
1243 return EXPP_ReturnPyObjError( PyExc_ValueError,
1244 "error, maximum name length is 31" );
1246 i = CustomData_get_named_layer_index(data, CD_PROP_FLT, name);
1247 if(i == -1) i = CustomData_get_named_layer_index(data, CD_PROP_INT, name);
1248 if(i == -1) i = CustomData_get_named_layer_index(data, CD_PROP_STR, name);
1250 return EXPP_ReturnPyObjError(PyExc_ValueError,
1251 "No matching layers to remove" );
1252 layer = &data->layers[i];
1253 CustomData_free_layer(data, layer->type, tot, i);
1254 mesh_update_customdata_pointers(mesh);
1259 static PyObject *Mesh_renamePropLayer_internal(Mesh *mesh, CustomData *data, PyObject *args)
1261 CustomDataLayer *layer;
1263 char *name_from, *name_to;
1265 if( !PyArg_ParseTuple( args, "ss", &name_from, &name_to ) )
1266 return EXPP_ReturnPyObjError( PyExc_TypeError,
1267 "expected 2 strings" );
1269 if (strlen(name_from)>31 || strlen(name_to)>31)
1270 return EXPP_ReturnPyObjError( PyExc_ValueError,
1271 "error, maximum name length is 31" );
1273 i = CustomData_get_named_layer_index(data, CD_PROP_FLT, name_from);
1274 if(i == -1) i = CustomData_get_named_layer_index(data, CD_PROP_INT, name_from);
1275 if(i == -1) i = CustomData_get_named_layer_index(data, CD_PROP_STR, name_from);
1277 return EXPP_ReturnPyObjError(PyExc_ValueError,
1278 "No matching layers to rename" );
1280 layer = &data->layers[i];
1282 strcpy(layer->name, name_to); /* we alredy know the string sizes are under 32 */
1283 CustomData_set_layer_unique_name(data, i);
1287 static PyObject *Mesh_propList_internal(CustomData *data)
1289 CustomDataLayer *layer;
1290 PyObject *list = PyList_New( 0 ), *item;
1292 for(i=0; i<data->totlayer; i++) {
1293 layer = &data->layers[i];
1294 if( (layer->type == CD_PROP_FLT) || (layer->type == CD_PROP_INT) || (layer->type == CD_PROP_STR)) {
1295 item = PyString_FromString(layer->name);
1296 PyList_Append( list, item );
1303 static PyObject *Mesh_getProperty_internal(CustomData *data, int eindex, PyObject *value)
1305 CustomDataLayer *layer;
1306 char *name=PyString_AsString(value);
1310 MStringProperty *ps;
1313 return EXPP_ReturnPyObjError( PyExc_TypeError,
1314 "expected an string argument" );
1316 if (strlen(name)>31)
1317 return EXPP_ReturnPyObjError( PyExc_ValueError,
1318 "error, maximum name length is 31" );
1320 i = CustomData_get_named_layer_index(data, CD_PROP_FLT, name);
1321 if(i == -1) i = CustomData_get_named_layer_index(data, CD_PROP_INT, name);
1322 if(i == -1) i = CustomData_get_named_layer_index(data, CD_PROP_STR, name);
1324 return EXPP_ReturnPyObjError(PyExc_ValueError,
1325 "No matching layers" );
1327 layer = &data->layers[i];
1329 if(layer->type == CD_PROP_FLT){
1331 return PyFloat_FromDouble(pf[eindex].f);
1333 else if(layer->type == CD_PROP_INT){
1335 return PyInt_FromLong(pi[eindex].i);
1338 else if(layer->type == CD_PROP_STR){
1340 return PyString_FromString(ps[eindex].s);
1345 static PyObject *Mesh_setProperty_internal(CustomData *data, int eindex, PyObject *args)
1347 CustomDataLayer *layer;
1348 int i,index, type = -1;
1350 char *s=NULL, *name=NULL;
1353 MStringProperty *ps;
1356 if(PyArg_ParseTuple(args, "sO", &name, &val)){
1357 if (strlen(name)>31)
1358 return EXPP_ReturnPyObjError( PyExc_ValueError,
1359 "error, maximum name length is 31" );
1361 if(PyInt_Check(val)){
1363 i = (int)PyInt_AS_LONG(val);
1365 else if(PyFloat_Check(val)){
1367 f = (float)PyFloat_AsDouble(val);
1369 else if(PyString_Check(val)){
1371 s = PyString_AsString(val);
1374 return EXPP_ReturnPyObjError( PyExc_TypeError,
1375 "expected an name plus either float/int/string" );
1379 index = CustomData_get_named_layer_index(data, type, name);
1381 return EXPP_ReturnPyObjError(PyExc_ValueError,
1382 "No matching layers or type mismatch" );
1384 layer = &data->layers[index];
1386 if(type==CD_PROP_STR){
1388 return EXPP_ReturnPyObjError( PyExc_ValueError,
1389 "error, maximum string length is 255");
1393 strcpy(ps[eindex].s,s);
1396 else if(type==CD_PROP_FLT){
1407 static PyObject *MVert_getProp( BPy_MVert *self, PyObject *args)
1409 if( BPy_MVert_Check( self ) ){
1410 Mesh *me = (Mesh *)self->data;
1411 if(self->index >= me->totvert)
1412 return EXPP_ReturnPyObjError( PyExc_ValueError,
1413 "error, MVert is no longer valid part of mesh!");
1415 return Mesh_getProperty_internal(&(me->vdata), self->index, args);
1417 return EXPP_ReturnPyObjError( PyExc_ValueError,
1418 "error, Vertex not part of a mesh!");
1421 static PyObject *MVert_setProp( BPy_MVert *self, PyObject *args)
1423 if( BPy_MVert_Check( self ) ){
1424 Mesh *me = (Mesh *)self->data;
1425 if(self->index >= me->totvert)
1426 return EXPP_ReturnPyObjError( PyExc_ValueError,
1427 "error, MVert is no longer valid part of mesh!");
1429 return Mesh_setProperty_internal(&(me->vdata), self->index, args);
1431 return EXPP_ReturnPyObjError( PyExc_ValueError,
1432 "error, Vertex not part of a mesh!");
1435 static struct PyMethodDef BPy_MVert_methods[] = {
1436 {"getProperty", (PyCFunction)MVert_getProp, METH_O,
1437 "get property indicated by name"},
1438 {"setProperty", (PyCFunction)MVert_setProp, METH_VARARGS,
1439 "set property indicated by name"},
1440 {NULL, NULL, 0, NULL}
1444 /************************************************************************
1446 * Python MVert_Type structure definition
1448 ************************************************************************/
1450 PyTypeObject MVert_Type = {
1451 PyObject_HEAD_INIT( NULL ) /* required py macro */
1453 /* For printing, in format "<module>.<name>" */
1454 "Blender MVert", /* char *tp_name; */
1455 sizeof( BPy_MVert ), /* int tp_basicsize; */
1456 0, /* tp_itemsize; For allocation */
1458 /* Methods to implement standard operations */
1460 ( destructor ) MVert_dealloc,/* destructor tp_dealloc; */
1461 NULL, /* printfunc tp_print; */
1462 NULL, /* getattrfunc tp_getattr; */
1463 NULL, /* setattrfunc tp_setattr; */
1464 ( cmpfunc ) MVert_compare, /* cmpfunc tp_compare; */
1465 ( reprfunc ) MVert_repr, /* reprfunc tp_repr; */
1467 /* Method suites for standard classes */
1469 NULL, /* PyNumberMethods *tp_as_number; */
1470 NULL, /* PySequenceMethods *tp_as_sequence; */
1471 NULL, /* PyMappingMethods *tp_as_mapping; */
1473 /* More standard operations (here for binary compatibility) */
1475 ( hashfunc ) MVert_hash, /* hashfunc tp_hash; */
1476 NULL, /* ternaryfunc tp_call; */
1477 NULL, /* reprfunc tp_str; */
1478 NULL, /* getattrofunc tp_getattro; */
1479 NULL, /* setattrofunc tp_setattro; */
1481 /* Functions to access object as input/output buffer */
1482 NULL, /* PyBufferProcs *tp_as_buffer; */
1484 /*** Flags to define presence of optional/expanded features ***/
1485 Py_TPFLAGS_DEFAULT, /* long tp_flags; */
1487 NULL, /* char *tp_doc; Documentation string */
1488 /*** Assigned meaning in release 2.0 ***/
1489 /* call function for all accessible objects */
1490 NULL, /* traverseproc tp_traverse; */
1492 /* delete references to contained objects */
1493 NULL, /* inquiry tp_clear; */
1495 /*** Assigned meaning in release 2.1 ***/
1496 /*** rich comparisons ***/
1497 NULL, /* richcmpfunc tp_richcompare; */
1499 /*** weak reference enabler ***/
1500 0, /* long tp_weaklistoffset; */
1502 /*** Added in release 2.2 ***/
1504 NULL, /* getiterfunc tp_iter; */
1505 NULL, /* iternextfunc tp_iternext; */
1507 /*** Attribute descriptor and subclassing stuff ***/
1508 BPy_MVert_methods, /* struct PyMethodDef *tp_methods; */
1509 NULL, /* struct PyMemberDef *tp_members; */
1510 BPy_MVert_getseters, /* struct PyGetSetDef *tp_getset; */
1511 NULL, /* struct _typeobject *tp_base; */
1512 NULL, /* PyObject *tp_dict; */
1513 NULL, /* descrgetfunc tp_descr_get; */
1514 NULL, /* descrsetfunc tp_descr_set; */
1515 0, /* long tp_dictoffset; */
1516 NULL, /* initproc tp_init; */
1517 NULL, /* allocfunc tp_alloc; */
1518 NULL, /* newfunc tp_new; */
1519 /* Low-level free-memory routine */
1520 NULL, /* freefunc tp_free; */
1521 /* For PyObject_IS_GC */
1522 NULL, /* inquiry tp_is_gc; */
1523 NULL, /* PyObject *tp_bases; */
1524 /* method resolution order */
1525 NULL, /* PyObject *tp_mro; */
1526 NULL, /* PyObject *tp_cache; */
1527 NULL, /* PyObject *tp_subclasses; */
1528 NULL, /* PyObject *tp_weaklist; */
1532 /************************************************************************
1534 * Python PVert_Type standard operations
1536 ************************************************************************/
1538 static int PVert_compare( BPy_MVert * a, BPy_MVert * b )
1540 return( a->data == b->data ) ? 0 : -1;
1543 /************************************************************************
1545 * Python PVert_Type structure definition
1547 ************************************************************************/
1549 PyTypeObject PVert_Type = {
1550 PyObject_HEAD_INIT( NULL ) /* required py macro */
1552 /* For printing, in format "<module>.<name>" */
1553 "Blender PVert", /* char *tp_name; */
1554 sizeof( BPy_MVert ), /* int tp_basicsize; */
1555 0, /* tp_itemsize; For allocation */
1557 /* Methods to implement standard operations */
1559 ( destructor ) MVert_dealloc,/* destructor tp_dealloc; */
1560 NULL, /* printfunc tp_print; */
1561 NULL, /* getattrfunc tp_getattr; */
1562 NULL, /* setattrfunc tp_setattr; */
1563 ( cmpfunc ) PVert_compare, /* cmpfunc tp_compare; */
1564 ( reprfunc ) MVert_repr, /* reprfunc tp_repr; */
1566 /* Method suites for standard classes */
1568 NULL, /* PyNumberMethods *tp_as_number; */
1569 NULL, /* PySequenceMethods *tp_as_sequence; */
1570 NULL, /* PyMappingMethods *tp_as_mapping; */
1572 /* More standard operations (here for binary compatibility) */
1574 ( hashfunc ) MVert_hash, /* hashfunc tp_hash; */
1575 NULL, /* ternaryfunc tp_call; */
1576 NULL, /* reprfunc tp_str; */
1577 NULL, /* getattrofunc tp_getattro; */
1578 NULL, /* setattrofunc tp_setattro; */
1580 /* Functions to access object as input/output buffer */
1581 NULL, /* PyBufferProcs *tp_as_buffer; */
1583 /*** Flags to define presence of optional/expanded features ***/
1584 Py_TPFLAGS_DEFAULT, /* long tp_flags; */
1586 NULL, /* char *tp_doc; Documentation string */
1587 /*** Assigned meaning in release 2.0 ***/
1588 /* call function for all accessible objects */
1589 NULL, /* traverseproc tp_traverse; */
1591 /* delete references to contained objects */
1592 NULL, /* inquiry tp_clear; */
1594 /*** Assigned meaning in release 2.1 ***/
1595 /*** rich comparisons ***/
1596 NULL, /* richcmpfunc tp_richcompare; */
1598 /*** weak reference enabler ***/
1599 0, /* long tp_weaklistoffset; */
1601 /*** Added in release 2.2 ***/
1603 NULL, /* getiterfunc tp_iter; */
1604 NULL, /* iternextfunc tp_iternext; */
1606 /*** Attribute descriptor and subclassing stuff ***/
1607 NULL, /* struct PyMethodDef *tp_methods; */
1608 NULL, /* struct PyMemberDef *tp_members; */
1609 BPy_PVert_getseters, /* struct PyGetSetDef *tp_getset; */
1610 NULL, /* struct _typeobject *tp_base; */
1611 NULL, /* PyObject *tp_dict; */
1612 NULL, /* descrgetfunc tp_descr_get; */
1613 NULL, /* descrsetfunc tp_descr_set; */
1614 0, /* long tp_dictoffset; */
1615 NULL, /* initproc tp_init; */
1616 NULL, /* allocfunc tp_alloc; */
1617 NULL, /* newfunc tp_new; */
1618 /* Low-level free-memory routine */
1619 NULL, /* freefunc tp_free; */
1620 /* For PyObject_IS_GC */
1621 NULL, /* inquiry tp_is_gc; */
1622 NULL, /* PyObject *tp_bases; */
1623 /* method resolution order */
1624 NULL, /* PyObject *tp_mro; */
1625 NULL, /* PyObject *tp_cache; */
1626 NULL, /* PyObject *tp_subclasses; */
1627 NULL, /* PyObject *tp_weaklist; */
1632 * create 'thin' or 'thick' MVert objects
1634 * there are two types of objects; thin (wrappers for mesh vertex) and thick
1635 * (not contains in mesh). Thin objects are MVert_Type and thick are
1636 * PVert_Type. For thin objects, data is a pointer to a Mesh and index
1637 * is the vertex's index in mesh->mvert. For thick objects, data is a
1638 * pointer to an MVert; index is unused.
1642 * create a thin MVert object
1645 static PyObject *MVert_CreatePyObject( Mesh *mesh, int i )
1647 BPy_MVert *obj = (BPy_MVert *)PyObject_NEW( BPy_MVert, &MVert_Type );
1650 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1651 "PyObject_New() failed" );
1655 return (PyObject *)obj;
1659 * create a thick MVert object
1662 static PyObject *PVert_CreatePyObject( MVert *vert )
1665 BPy_MVert *obj = (BPy_MVert *)PyObject_NEW( BPy_MVert, &PVert_Type );
1668 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1669 "PyObject_New() failed" );
1671 newvert = (MVert *)MEM_callocN( sizeof( MVert ), "MVert" );
1673 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1674 "MEM_callocN() failed" );
1676 memcpy( newvert, vert, sizeof( MVert ) );
1677 obj->data = newvert;
1678 return (PyObject *)obj;
1681 /************************************************************************
1685 ************************************************************************/
1687 static int MVertSeq_len( BPy_MVertSeq * self )
1689 return self->mesh->totvert;
1693 * retrive a single MVert from somewhere in the vertex list
1696 static PyObject *MVertSeq_item( BPy_MVertSeq * self, int i )
1698 if( i < 0 || i >= self->mesh->totvert )
1699 return EXPP_ReturnPyObjError( PyExc_IndexError,
1700 "array index out of range" );
1702 return MVert_CreatePyObject( self->mesh, i );
1706 * retrieve a slice of the vertex list (as a Python list)
1708 * Python is nice enough to handle negative indices for us: if the user
1709 * specifies -1, Python will pass us len()-1. So we can just check for
1710 * indices in the range 0:len()-1. Of course, we should never actually
1711 * return the high index, but up to one less.
1714 static PyObject *MVertSeq_slice( BPy_MVertSeq *self, int low, int high )
1720 * Python list slice operator returns empty list when asked for a slice
1721 * outside the list, or if indices are reversed (low > high). Clamp
1722 * our input to do the same.
1725 if( low < 0 ) low = 0;
1726 if( high > self->mesh->totvert ) high = self->mesh->totvert;
1727 if( low > high ) low = high;
1729 list = PyList_New( high-low );
1731 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1732 "PyList_New() failed" );
1735 * return Py_NEW copies of requested vertices
1738 for( i = low; i < high; ++i )
1739 PyList_SET_ITEM( list, i-low,
1740 PVert_CreatePyObject( (void *)&self->mesh->mvert[i] ) );
1745 * assign a single MVert to somewhere in the vertex list
1748 static int MVertSeq_assign_item( BPy_MVertSeq * self, int i,
1751 MVert *dst = &self->mesh->mvert[i];
1755 return EXPP_ReturnIntError( PyExc_IndexError,
1756 "del() not supported" );
1758 if( i < 0 || i >= self->mesh->totvert )
1759 return EXPP_ReturnIntError( PyExc_IndexError,
1760 "array index out of range" );
1762 if( BPy_MVert_Check( v ) )
1763 src = &((Mesh *)v->data)->mvert[v->index];
1765 src = (MVert *)v->data;
1767 memcpy( dst, src, sizeof(MVert) );
1768 /* mesh_update( self->mesh );*/
1772 static int MVertSeq_assign_slice( BPy_MVertSeq *self, int low, int high,
1777 if( !PyList_Check( args ) )
1778 return EXPP_ReturnIntError( PyExc_IndexError,
1779 "can only assign lists of MVerts" );
1781 len = PyList_Size( args );
1784 * Python list slice assign operator allows for changing the size of the
1785 * destination list, by replacement and appending....
1788 * >>> m=[11,12,13,14]
1791 * [1, 2, 3, 4, 11, 12, 13, 14]
1795 * [1, 2, 11, 12, 13, 14, 4]
1797 * We don't want the size of the list to change (at least not at time
1798 * point in development) so we are a little more strict:
1799 * - low and high indices must be in range [0:len()]
1800 * - high-low == PyList_Size(v)
1803 if( low < 0 || high > self->mesh->totvert || low > high )
1804 return EXPP_ReturnIntError( PyExc_IndexError,
1805 "invalid slice range" );
1807 if( high-low != len )
1808 return EXPP_ReturnIntError( PyExc_IndexError,
1809 "slice range and input list sizes must be equal" );
1811 for( i = low; i < high; ++i )
1813 BPy_MVert *v = (BPy_MVert *)PyList_GET_ITEM( args, i-low );
1814 MVert *dst = &self->mesh->mvert[i];
1817 if( BPy_MVert_Check( v ) )
1818 src = &((Mesh *)v->data)->mvert[v->index];
1820 src = (MVert *)v->data;
1822 memcpy( dst, src, sizeof(MVert) );
1824 /* mesh_update( self->mesh );*/
1828 static PySequenceMethods MVertSeq_as_sequence = {
1829 ( inquiry ) MVertSeq_len, /* sq_length */
1830 ( binaryfunc ) 0, /* sq_concat */
1831 ( intargfunc ) 0, /* sq_repeat */
1832 ( intargfunc ) MVertSeq_item, /* sq_item */
1833 ( intintargfunc ) MVertSeq_slice, /* sq_slice */
1834 ( intobjargproc ) MVertSeq_assign_item, /* sq_ass_item */
1835 ( intintobjargproc ) MVertSeq_assign_slice, /* sq_ass_slice */
1839 /************************************************************************
1841 * Python MVertSeq_Type iterator (iterates over vertices)
1843 ************************************************************************/
1846 * Initialize the interator index
1849 static PyObject *MVertSeq_getIter( BPy_MVertSeq * self )
1851 if (self->iter==-1) { /* iteration for this pyobject is not yet used, just return self */
1853 return EXPP_incr_ret ( (PyObject *) self );
1855 /* were alredy using this as an iterator, make a copy to loop on */
1856 BPy_MVertSeq *seq = (BPy_MVertSeq *)MVertSeq_CreatePyObject(self->mesh);
1858 return (PyObject *)seq;
1863 * Return next MVert.
1866 static PyObject *MVertSeq_nextIter( BPy_MVertSeq * self )
1868 if( self->iter == self->mesh->totvert ) {
1869 self->iter= -1; /* allow it to be used as an iterator again without creating a new BPy_MVertSeq */
1870 return EXPP_ReturnPyObjError( PyExc_StopIteration,
1871 "iterator at end" );
1874 return MVert_CreatePyObject( self->mesh, self->iter++ );
1877 /************************************************************************
1879 * Python MVertSeq_Type methods
1881 ************************************************************************/
1883 static PyObject *MVertSeq_extend( BPy_MVertSeq * self, PyObject *args )
1888 MVert *newvert, *tmpvert;
1889 Mesh *mesh = self->mesh;
1891 /* make sure we get a sequence of tuples of something */
1893 switch( PySequence_Size( args ) ) {
1894 case 1: /* better be a list or a tuple */
1895 tmp = PyTuple_GET_ITEM( args, 0 );
1896 if( !VectorObject_Check ( tmp ) ) {
1897 if( !PySequence_Check ( tmp ) )
1898 return EXPP_ReturnPyObjError( PyExc_TypeError,
1899 "expected a sequence of sequence triplets" );
1900 else if( !PySequence_Size ( tmp ) ) {
1905 Py_INCREF( args ); /* so we can safely DECREF later */
1908 tmp = PyTuple_GET_ITEM( args, 0 );
1909 /* if first item is not a number, it's wrong */
1910 if( !PyNumber_Check( tmp ) )
1911 return EXPP_ReturnPyObjError( PyExc_TypeError,
1912 "expected a sequence of sequence triplets" );
1914 /* otherwise, put into a new tuple */
1915 args = Py_BuildValue( "((OOO))", tmp,
1916 PyTuple_GET_ITEM( args, 1 ), PyTuple_GET_ITEM( args, 2 ) );
1918 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1919 "Py_BuildValue() failed" );
1922 default: /* anything else is definitely wrong */
1923 return EXPP_ReturnPyObjError( PyExc_TypeError,
1924 "expected a sequence of sequence triplets" );
1927 /* if no verts given, return quietly */
1928 len = PySequence_Size( args );
1934 /* create custom vertex data arrays and copy existing vertices into it */
1936 newlen = mesh->totvert + len;
1937 CustomData_copy( &mesh->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, newlen );
1938 CustomData_copy_data( &mesh->vdata, &vdata, 0, 0, mesh->totvert );
1940 if ( !CustomData_has_layer( &vdata, CD_MVERT ) )
1941 CustomData_add_layer( &vdata, CD_MVERT, CD_CALLOC, NULL, newlen );
1943 newvert = CustomData_get_layer( &vdata, CD_MVERT );
1945 /* scan the input list and insert the new vertices */
1947 tmpvert = &newvert[mesh->totvert];
1948 for( i = 0; i < len; ++i ) {
1950 tmp = PySequence_GetItem( args, i );
1951 if( VectorObject_Check( tmp ) ) {
1952 if( ((VectorObject *)tmp)->size != 3 ) {
1953 CustomData_free( &vdata, newlen );
1956 return EXPP_ReturnPyObjError( PyExc_ValueError,
1957 "expected vector of size 3" );
1959 for( j = 0; j < 3; ++j )
1960 co[j] = ((VectorObject *)tmp)->vec[j];
1961 } else if( PySequence_Check( tmp ) ) {
1964 if( PySequence_Size( tmp ) != 3 )
1967 for( j = 0; ok && j < 3; ++j ) {
1968 flt = PySequence_ITEM( tmp, j );
1969 if( !PyNumber_Check ( flt ) )
1972 co[j] = (float)PyFloat_AsDouble( flt );
1977 CustomData_free( &vdata, newlen );
1980 return EXPP_ReturnPyObjError( PyExc_ValueError,
1981 "expected sequence triplet of floats" );
1984 CustomData_free( &vdata, newlen );
1987 return EXPP_ReturnPyObjError( PyExc_ValueError,
1988 "expected sequence triplet of floats" );
1993 /* add the coordinate to the new list */
1994 memcpy( tmpvert->co, co, sizeof(co) );
1996 tmpvert->flag |= SELECT;
1997 /* TODO: anything else which needs to be done when we add a vert? */
1998 /* probably not: NMesh's newvert() doesn't */
2002 CustomData_free( &mesh->vdata, mesh->totvert );
2003 mesh->vdata = vdata;
2004 mesh_update_customdata_pointers( mesh );
2007 * if there are keys, have to fix those lists up
2011 KeyBlock *currkey = mesh->key->block.first;
2016 /* create key list, copy existing data if any */
2017 newkey = MEM_callocN(mesh->key->elemsize*newlen, "keydata");
2018 if( currkey->data ) {
2019 memcpy( newkey, currkey->data,
2020 mesh->totvert*mesh->key->elemsize );
2021 MEM_freeN( currkey->data );
2022 currkey->data = newkey;
2025 /* add data for new vertices */
2026 fp = (float *)((char *)currkey->data +
2027 (mesh->key->elemsize*mesh->totvert));
2028 tmpvert = mesh->mvert + mesh->totvert;
2029 for( i = newlen - mesh->totvert; i > 0; --i ) {
2030 VECCOPY(fp, tmpvert->co);
2034 currkey->totelem = newlen;
2035 currkey = currkey->next;
2039 /* set final vertex list size */
2040 mesh->totvert = newlen;
2042 mesh_update( mesh );
2048 static PyObject *MVertSeq_delete( BPy_MVertSeq * self, PyObject *args )
2050 unsigned int *vert_table;
2051 int vert_delete, face_count;
2053 Mesh *mesh = self->mesh;
2057 * if input tuple contains a single sequence, use it as input instead;
2058 * otherwise use the sequence as-is and check later that it contains
2059 * one or more integers or MVerts
2061 if( PySequence_Size( args ) == 1 ) {
2062 PyObject *tmp = PyTuple_GET_ITEM( args, 0 );
2063 if( PySequence_Check( tmp ) )
2067 /* if sequence is empty, do nothing */
2068 if( PySequence_Size( args ) == 0 ) {
2072 /* allocate vertex lookup table */
2073 vert_table = (unsigned int *)MEM_callocN(
2074 mesh->totvert*sizeof( unsigned int ), "vert_table" );
2076 /* get the indices of vertices to be removed */
2077 for( i = PySequence_Size( args ); i--; ) {
2078 PyObject *tmp = PySequence_GetItem( args, i );
2080 if( BPy_MVert_Check( tmp ) ) {
2081 if( (void *)self->mesh != ((BPy_MVert*)tmp)->data ) {
2082 MEM_freeN( vert_table );
2084 return EXPP_ReturnPyObjError( PyExc_ValueError,
2085 "MVert belongs to a different mesh" );
2087 index = ((BPy_MVert*)tmp)->index;
2088 } else if( PyInt_Check( tmp ) ) {
2089 index = PyInt_AsLong ( tmp );
2091 MEM_freeN( vert_table );
2093 return EXPP_ReturnPyObjError( PyExc_TypeError,
2094 "expected a sequence of ints or MVerts" );
2097 if( index < 0 || index >= mesh->totvert ) {
2098 MEM_freeN( vert_table );
2099 return EXPP_ReturnPyObjError( PyExc_IndexError,
2100 "array index out of range" );
2102 vert_table[index] = UINT_MAX;
2105 /* delete things, then clean up and return */
2107 vert_delete = make_vertex_table( vert_table, mesh->totvert );
2109 delete_verts( mesh, vert_table, vert_delete );
2111 /* calculate edges to delete, fix vertex indices */
2112 delete_edges( mesh, vert_table, 0 );
2115 * find number of faces which contain any of the deleted vertices,
2116 * and mark them, then delete them
2118 tmpface = mesh->mface;
2120 for( i = mesh->totface; i--; ++tmpface ) {
2121 if( vert_table[tmpface->v1] == UINT_MAX ||
2122 vert_table[tmpface->v2] == UINT_MAX ||
2123 vert_table[tmpface->v3] == UINT_MAX ||
2124 ( tmpface->v4 && vert_table[tmpface->v4] == UINT_MAX ) ) {
2125 tmpface->v1 = UINT_MAX;
2129 delete_faces( mesh, vert_table, face_count );
2131 /* clean up and exit */
2132 MEM_freeN( vert_table );
2133 mesh_update ( mesh );
2137 static PyObject *MVertSeq_selected( BPy_MVertSeq * self )
2140 Mesh *mesh = self->mesh;
2144 /* first count selected edges (quicker than appending to PyList?) */
2146 tmpvert = mesh->mvert;
2147 for( i = 0; i < mesh->totvert; ++i, ++tmpvert )
2148 if( tmpvert->flag & SELECT )
2151 list = PyList_New( count );
2153 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2154 "PyList_New() failed" );
2156 /* next, insert selected edges into list */
2158 tmpvert = mesh->mvert;
2159 for( i = 0; i < mesh->totvert; ++i, ++tmpvert ) {
2160 if( tmpvert->flag & SELECT ) {
2161 PyObject *tmp = PyInt_FromLong( i );
2164 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2165 "PyInt_FromLong() failed" );
2167 PyList_SET_ITEM( list, count, tmp );
2173 static PyObject *MVertSeq_add_layertype(BPy_MVertSeq *self, PyObject *args)
2175 Mesh *me = (Mesh*)self->mesh;
2176 return Mesh_addPropLayer_internal(me, &(me->vdata), me->totvert, args);
2178 static PyObject *MVertSeq_del_layertype(BPy_MVertSeq *self, PyObject *value)
2180 Mesh *me = (Mesh*)self->mesh;
2181 return Mesh_removePropLayer_internal(me, &(me->vdata), me->totvert, value);
2183 static PyObject *MVertSeq_rename_layertype(BPy_MVertSeq *self, PyObject *args)
2185 Mesh *me = (Mesh*)self->mesh;
2186 return Mesh_renamePropLayer_internal(me,&(me->vdata),args);
2188 static PyObject *MVertSeq_PropertyList(BPy_MVertSeq *self)
2190 Mesh *me = (Mesh*)self->mesh;
2191 return Mesh_propList_internal(&(me->vdata));
2193 static PyObject *M_Mesh_PropertiesTypeDict(void)
2195 PyObject *Types = PyConstant_New( );
2197 BPy_constant *d = (BPy_constant *) Types;
2198 PyConstant_Insert(d, "FLOAT", PyInt_FromLong(CD_PROP_FLT));
2199 PyConstant_Insert(d, "INT" , PyInt_FromLong(CD_PROP_INT));
2200 PyConstant_Insert(d, "STRING", PyInt_FromLong(CD_PROP_STR));
2205 static struct PyMethodDef BPy_MVertSeq_methods[] = {
2206 {"extend", (PyCFunction)MVertSeq_extend, METH_VARARGS,
2207 "add vertices to mesh"},
2208 {"delete", (PyCFunction)MVertSeq_delete, METH_VARARGS,
2209 "delete vertices from mesh"},
2210 {"selected", (PyCFunction)MVertSeq_selected, METH_NOARGS,
2211 "returns a list containing indices of selected vertices"},
2212 {"addPropertyLayer",(PyCFunction)MVertSeq_add_layertype, METH_VARARGS,
2213 "add a new property layer"},
2214 {"removePropertyLayer",(PyCFunction)MVertSeq_del_layertype, METH_O,
2215 "removes a property layer"},
2216 {"renamePropertyLayer",(PyCFunction)MVertSeq_rename_layertype, METH_VARARGS,
2217 "renames an existing property layer"},
2218 {NULL, NULL, 0, NULL}
2221 static PyGetSetDef BPy_MVertSeq_getseters[] = {
2223 (getter)MVertSeq_PropertyList, (setter)NULL,
2224 "vertex property layers, read only",
2226 {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
2231 /************************************************************************
2233 * Python MVertSeq_Type standard operations
2235 ************************************************************************/
2237 /*****************************************************************************/
2238 /* Python MVertSeq_Type structure definition: */
2239 /*****************************************************************************/
2240 PyTypeObject MVertSeq_Type = {
2241 PyObject_HEAD_INIT( NULL ) /* required py macro */
2243 /* For printing, in format "<module>.<name>" */
2244 "Blender MVertSeq", /* char *tp_name; */
2245 sizeof( BPy_MVertSeq ), /* int tp_basicsize; */
2246 0, /* tp_itemsize; For allocation */
2248 /* Methods to implement standard operations */
2250 NULL, /* destructor tp_dealloc; */
2251 NULL, /* printfunc tp_print; */
2252 NULL, /* getattrfunc tp_getattr; */
2253 NULL, /* setattrfunc tp_setattr; */
2254 NULL, /* cmpfunc tp_compare; */
2255 NULL, /* reprfunc tp_repr; */
2257 /* Method suites for standard classes */
2259 NULL, /* PyNumberMethods *tp_as_number; */
2260 &MVertSeq_as_sequence, /* PySequenceMethods *tp_as_sequence; */
2261 NULL, /* PyMappingMethods *tp_as_mapping; */
2263 /* More standard operations (here for binary compatibility) */
2265 NULL, /* hashfunc tp_hash; */
2266 NULL, /* ternaryfunc tp_call; */
2267 NULL, /* reprfunc tp_str; */
2268 NULL, /* getattrofunc tp_getattro; */
2269 NULL, /* setattrofunc tp_setattro; */
2271 /* Functions to access object as input/output buffer */
2272 NULL, /* PyBufferProcs *tp_as_buffer; */
2274 /*** Flags to define presence of optional/expanded features ***/
2275 Py_TPFLAGS_DEFAULT, /* long tp_flags; */
2277 NULL, /* char *tp_doc; Documentation string */
2278 /*** Assigned meaning in release 2.0 ***/
2279 /* call function for all accessible objects */
2280 NULL, /* traverseproc tp_traverse; */
2282 /* delete references to contained objects */
2283 NULL, /* inquiry tp_clear; */
2285 /*** Assigned meaning in release 2.1 ***/
2286 /*** rich comparisons ***/
2287 NULL, /* richcmpfunc tp_richcompare; */
2289 /*** weak reference enabler ***/
2290 0, /* long tp_weaklistoffset; */
2292 /*** Added in release 2.2 ***/
2294 ( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
2295 ( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
2297 /*** Attribute descriptor and subclassing stuff ***/
2298 BPy_MVertSeq_methods, /* struct PyMethodDef *tp_methods; */
2299 NULL, /* struct PyMemberDef *tp_members; */
2300 BPy_MVertSeq_getseters, /* struct PyGetSetDef *tp_getset; */
2301 NULL, /* struct _typeobject *tp_base; */
2302 NULL, /* PyObject *tp_dict; */
2303 NULL, /* descrgetfunc tp_descr_get; */
2304 NULL, /* descrsetfunc tp_descr_set; */
2305 0, /* long tp_dictoffset; */
2306 NULL, /* initproc tp_init; */
2307 NULL, /* allocfunc tp_alloc; */
2308 NULL, /* newfunc tp_new; */
2309 /* Low-level free-memory routine */
2310 NULL, /* freefunc tp_free; */
2311 /* For PyObject_IS_GC */
2312 NULL, /* inquiry tp_is_gc; */
2313 NULL, /* PyObject *tp_bases; */
2314 /* method resolution order */
2315 NULL, /* PyObject *tp_mro; */
2316 NULL, /* PyObject *tp_cache; */
2317 NULL, /* PyObject *tp_subclasses; */
2318 NULL, /* PyObject *tp_weaklist; */
2322 /************************************************************************
2326 ************************************************************************/
2328 static MEdge * MEdge_get_pointer( BPy_MEdge * self )
2330 if( self->index >= self->mesh->totedge )
2331 return (MEdge *)EXPP_ReturnPyObjError( PyExc_RuntimeError,
2332 "MEdge is no longer valid" );
2333 return &self->mesh->medge[self->index];
2337 * get an edge's crease value
2340 static PyObject *MEdge_getCrease( BPy_MEdge * self )
2342 MEdge *edge = MEdge_get_pointer( self );
2347 return PyInt_FromLong( edge->crease );
2351 * set an edge's crease value
2354 static int MEdge_setCrease( BPy_MEdge * self, PyObject * value )
2356 MEdge *edge = MEdge_get_pointer( self );
2361 return EXPP_setIValueClamped( value, &edge->crease, 0, 255, 'b' );
2365 * get an edge's flag
2368 static PyObject *MEdge_getFlag( BPy_MEdge * self )
2370 MEdge *edge = MEdge_get_pointer( self );
2375 return PyInt_FromLong( edge->flag );
2379 * set an edge's flag
2382 static int MEdge_setFlag( BPy_MEdge * self, PyObject * value )
2385 static short bitmask = SELECT
2394 MEdge *edge = MEdge_get_pointer( self );
2399 if( !PyInt_Check ( value ) ) {
2401 sprintf ( errstr , "expected int bitmask of 0x%04x", bitmask );
2402 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
2404 param = (short)PyInt_AS_LONG ( value );
2406 if ( ( param & bitmask ) != param )
2407 return EXPP_ReturnIntError( PyExc_ValueError,
2408 "invalid bit(s) set in mask" );
2416 * get an edge's first vertex
2419 static PyObject *MEdge_getV1( BPy_MEdge * self )
2421 MEdge *edge = MEdge_get_pointer( self );
2426 return MVert_CreatePyObject( self->mesh, edge->v1 );
2430 * set an edge's first vertex
2433 static int MEdge_setV1( BPy_MEdge * self, BPy_MVert * value )
2435 MEdge *edge = MEdge_get_pointer( self );
2439 if( !BPy_MVert_Check( value ) )
2440 return EXPP_ReturnIntError( PyExc_TypeError, "expected an MVert" );
2442 edge->v1 = value->index;
2447 * get an edge's second vertex
2450 static PyObject *MEdge_getV2( BPy_MEdge * self )
2452 MEdge *edge = MEdge_get_pointer( self );
2455 return NULL; /* error is set */
2456 /* if v2 is out of range, the python mvert will complain, no need to check here */
2457 return MVert_CreatePyObject( self->mesh, edge->v2 );
2461 * set an edge's second vertex
2464 static int MEdge_setV2( BPy_MEdge * self, BPy_MVert * value )
2466 MEdge *edge = MEdge_get_pointer( self );
2469 return -1; /* error is set */
2470 if( !BPy_MVert_Check( value ) )
2471 return EXPP_ReturnIntError( PyExc_TypeError, "expected an MVert" );
2473 if ( edge->v1 == value->index )
2474 return EXPP_ReturnIntError( PyExc_ValueError, "an edge cant use the same vertex for each end" );
2476 edge->v2 = value->index;
2481 * get an edge's index
2484 static PyObject *MEdge_getIndex( BPy_MEdge * self )
2486 if( !MEdge_get_pointer( self ) )
2487 return NULL; /* error is set */
2489 return PyInt_FromLong( self->index );
2493 * get an edge's flag
2496 static PyObject *MEdge_getMFlagBits( BPy_MEdge * self, void * type )
2498 MEdge *edge = MEdge_get_pointer( self );
2501 return NULL; /* error is set */
2503 return EXPP_getBitfield( &edge->flag, (int)((long)type & 0xff), 'b' );
2507 * get an edge's length
2510 static PyObject *MEdge_getLength( BPy_MEdge * self )
2512 MEdge *edge = MEdge_get_pointer( self );
2519 return NULL; /* error is set */
2521 if MEDGE_VERT_BADRANGE_CHECK(self->mesh, edge)
2522 return EXPP_ReturnPyObjError( PyExc_RuntimeError, "This edge uses removed vert(s)" );
2524 /* get the 2 edges vert locations */
2525 v1= (&((Mesh *)self->mesh)->mvert[edge->v1])->co;
2526 v2= (&((Mesh *)self->mesh)->mvert[edge->v2])->co;
2531 for( i = 0; i < 3; i++ ) {
2532 tmpf = v1[i] - v2[i];
2535 return PyFloat_FromDouble( sqrt( dot ) );
2539 * get an key for using in a dictionary or set key
2542 static PyObject *MEdge_getKey( BPy_MEdge * self )
2545 MEdge *edge = MEdge_get_pointer( self );
2547 return NULL; /* error is set */
2549 attr = PyTuple_New( 2 );
2550 if (edge->v1 > edge->v2) {
2551 PyTuple_SET_ITEM( attr, 0, PyInt_FromLong(edge->v2) );
2552 PyTuple_SET_ITEM( attr, 1, PyInt_FromLong(edge->v1) );
2554 PyTuple_SET_ITEM( attr, 0, PyInt_FromLong(edge->v1) );
2555 PyTuple_SET_ITEM( attr, 1, PyInt_FromLong(edge->v2) );
2561 * set an edge's select state
2564 static int MEdge_setSel( BPy_MEdge * self,PyObject * value,
2565 void * type_unused )
2567 MEdge *edge = MEdge_get_pointer( self );
2568 int param = PyObject_IsTrue( value );
2569 Mesh *me = self->mesh;
2574 if MEDGE_VERT_BADRANGE_CHECK(me, edge)
2575 return EXPP_ReturnIntError( PyExc_RuntimeError, "This edge uses removed vert(s)" );
2578 return EXPP_ReturnIntError( PyExc_TypeError,
2579 "expected True/False or 0/1" );
2582 edge->flag |= SELECT;
2583 me->mvert[edge->v1].flag |= SELECT;
2584 me->mvert[edge->v2].flag |= SELECT;
2587 edge->flag &= ~SELECT;
2588 me->mvert[edge->v1].flag &= ~SELECT;
2589 me->mvert[edge->v2].flag &= ~SELECT;
2592 if( self->mesh->mselect ) {
2593 MEM_freeN( self->mesh->mselect );
2594 self->mesh->mselect = NULL;
2600 /************************************************************************
2602 * Python MEdge_Type attributes get/set structure
2604 ************************************************************************/
2606 static PyGetSetDef BPy_MEdge_getseters[] = {
2608 (getter)MEdge_getCrease, (setter)MEdge_setCrease,
2609 "edge's crease value",
2612 (getter)MEdge_getFlag, (setter)MEdge_setFlag,
2616 (getter)MEdge_getV1, (setter)MEdge_setV1,
2617 "edge's first vertex",
2620 (getter)MEdge_getV2, (setter)MEdge_setV2,
2621 "edge's second vertex",
2624 (getter)MEdge_getIndex, (setter)NULL,
2628 (getter)MEdge_getMFlagBits, (setter)MEdge_setSel,
2629 "edge selected in edit mode",
2632 (getter)MEdge_getLength, (setter)NULL,
2633 "edge's length, read only",
2636 (getter)MEdge_getKey, (setter)NULL,
2637 "edge's key for using with sets or dictionaries, read only",
2639 {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
2642 /************************************************************************
2644 * Python MEdge_Type iterator (iterates over vertices)
2646 ************************************************************************/
2649 * Initialize the interator index
2652 static PyObject *MEdge_getIter( BPy_MEdge * self )
2654 if (self->iter==-1) { /* not alredy used to iterator on, just use self */
2656 return EXPP_incr_ret ( (PyObject *) self );
2657 } else { /* alredy being iterated on, return a copy */
2658 BPy_MEdge *seq = (BPy_MEdge *)MEdge_CreatePyObject(self->mesh, self->index);
2660 return (PyObject *)seq;
2665 * Return next MVert. Throw an exception after the second vertex.
2668 static PyObject *MEdge_nextIter( BPy_MEdge * self )
2670 if( self->iter == 2 ) {
2672 return EXPP_ReturnPyObjError( PyExc_StopIteration,
2673 "iterator at end" );
2677 if( self->iter == 1 )
2678 return MEdge_getV1( self );
2680 return MEdge_getV2( self );
2683 /************************************************************************
2685 * Python MEdge_Type standard operations
2687 ************************************************************************/
2689 static int MEdge_compare( BPy_MEdge * a, BPy_MEdge * b )
2691 return( a->mesh == b->mesh && a->index == b->index ) ? 0 : -1;
2694 static PyObject *MEdge_repr( BPy_MEdge * self )
2696 struct MEdge *edge = MEdge_get_pointer( self );
2701 return PyString_FromFormat( "[MEdge (%d %d) %d %d]",
2702 (int)edge->v1, (int)edge->v2, (int)edge->crease,
2706 static long MEdge_hash( BPy_MEdge *self )
2708 return (long)self->index;
2710 static PyObject *MEdge_getProp( BPy_MEdge *self, PyObject *args)
2712 Mesh *me = (Mesh *)self->mesh;
2713 return Mesh_getProperty_internal(&(me->edata), self->index, args);
2716 static PyObject *MEdge_setProp( BPy_MEdge *self, PyObject *args)
2718 Mesh *me = (Mesh *)self->mesh;
2719 return Mesh_setProperty_internal(&(me->edata), self->index, args);
2722 static struct PyMethodDef BPy_MEdge_methods[] = {
2723 {"getProperty", (PyCFunction)MEdge_getProp, METH_O,
2724 "get property indicated by name"},
2725 {"setProperty", (PyCFunction)MEdge_setProp, METH_VARARGS,
2726 "set property indicated by name"},
2727 {NULL, NULL, 0, NULL}
2729 /************************************************************************
2731 * Python MEdge_Type structure definition
2733 ************************************************************************/
2735 PyTypeObject MEdge_Type = {
2736 PyObject_HEAD_INIT( NULL ) /* required py macro */
2738 /* For printing, in format "<module>.<name>" */
2739 "Blender MEdge", /* char *tp_name; */
2740 sizeof( BPy_MEdge ), /* int tp_basicsize; */
2741 0, /* tp_itemsize; For allocation */
2743 /* Methods to implement standard operations */
2745 NULL, /* destructor tp_dealloc; */
2746 NULL, /* printfunc tp_print; */
2747 NULL, /* getattrfunc tp_getattr; */
2748 NULL, /* setattrfunc tp_setattr; */
2749 ( cmpfunc ) MEdge_compare, /* cmpfunc tp_compare; */
2750 ( reprfunc ) MEdge_repr, /* reprfunc tp_repr; */
2752 /* Method suites for standard classes */
2754 NULL, /* PyNumberMethods *tp_as_number; */
2755 NULL, /* PySequenceMethods *tp_as_sequence; */
2756 NULL, /* PyMappingMethods *tp_as_mapping; */
2758 /* More standard operations (here for binary compatibility) */
2760 ( hashfunc ) MEdge_hash, /* hashfunc tp_hash; */
2761 NULL, /* ternaryfunc tp_call; */
2762 NULL, /* reprfunc tp_str; */
2763 NULL, /* getattrofunc tp_getattro; */
2764 NULL, /* setattrofunc tp_setattro; */
2766 /* Functions to access object as input/output buffer */
2767 NULL, /* PyBufferProcs *tp_as_buffer; */
2769 /*** Flags to define presence of optional/expanded features ***/
2770 Py_TPFLAGS_DEFAULT, /* long tp_flags; */
2772 NULL, /* char *tp_doc; Documentation string */
2773 /*** Assigned meaning in release 2.0 ***/
2774 /* call function for all accessible objects */
2775 NULL, /* traverseproc tp_traverse; */
2777 /* delete references to contained objects */
2778 NULL, /* inquiry tp_clear; */
2780 /*** Assigned meaning in release 2.1 ***/
2781 /*** rich comparisons ***/
2782 NULL, /* richcmpfunc tp_richcompare; */
2784 /*** weak reference enabler ***/
2785 0, /* long tp_weaklistoffset; */
2787 /*** Added in release 2.2 ***/
2789 ( getiterfunc) MEdge_getIter, /* getiterfunc tp_iter; */
2790 ( iternextfunc ) MEdge_nextIter, /* iternextfunc tp_iternext; */
2792 /*** Attribute descriptor and subclassing stuff ***/
2793 BPy_MEdge_methods, /* struct PyMethodDef *tp_methods; */
2794 NULL, /* struct PyMemberDef *tp_members; */
2795 BPy_MEdge_getseters, /* struct PyGetSetDef *tp_getset; */
2796 NULL, /* struct _typeobject *tp_base; */
2797 NULL, /* PyObject *tp_dict; */
2798 NULL, /* descrgetfunc tp_descr_get; */
2799 NULL, /* descrsetfunc tp_descr_set; */
2800 0, /* long tp_dictoffset; */
2801 NULL, /* initproc tp_init; */
2802 NULL, /* allocfunc tp_alloc; */
2803 NULL, /* newfunc tp_new; */
2804 /* Low-level free-memory routine */
2805 NULL, /* freefunc tp_free; */
2806 /* For PyObject_IS_GC */
2807 NULL, /* inquiry tp_is_gc; */
2808 NULL, /* PyObject *tp_bases; */
2809 /* method resolution order */
2810 NULL, /* PyObject *tp_mro; */
2811 NULL, /* PyObject *tp_cache; */
2812 NULL, /* PyObject *tp_subclasses; */
2813 NULL, /* PyObject *tp_weaklist; */
2817 static PyObject *MEdge_CreatePyObject( Mesh * mesh, int i )
2819 BPy_MEdge *obj = PyObject_NEW( BPy_MEdge, &MEdge_Type );
2822 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2823 "PyObject_New() failed" );
2828 return (PyObject *)obj;
2831 /************************************************************************
2835 ************************************************************************/
2837 static int MEdgeSeq_len( BPy_MEdgeSeq * self )
2839 return self->mesh->totedge;
2842 static PyObject *MEdgeSeq_item( BPy_MEdgeSeq * self, int i )
2844 if( i < 0 || i >= self->mesh->totedge )
2845 return EXPP_ReturnPyObjError( PyExc_IndexError,
2846 "array index out of range" );
2848 return MEdge_CreatePyObject( self->mesh, i );
2852 static PySequenceMethods MEdgeSeq_as_sequence = {
2853 ( inquiry ) MEdgeSeq_len, /* sq_length */
2854 ( binaryfunc ) 0, /* sq_concat */
2855 ( intargfunc ) 0, /* sq_repeat */
2856 ( intargfunc ) MEdgeSeq_item, /* sq_item */
2857 ( intintargfunc ) 0, /* sq_slice */
2858 ( intobjargproc ) 0, /* sq_ass_item */
2859 ( intintobjargproc ) 0, /* sq_ass_slice */
2863 /************************************************************************
2865 * Python MEdgeSeq_Type iterator (iterates over edges)
2867 ************************************************************************/
2870 * Initialize the interator index
2873 static PyObject *MEdgeSeq_getIter( BPy_MEdgeSeq * self )
2875 if (self->iter==-1) { /* iteration for this pyobject is not yet used, just return self */
2877 return EXPP_incr_ret ( (PyObject *) self );
2879 BPy_MEdgeSeq *seq = (BPy_MEdgeSeq *)MEdgeSeq_CreatePyObject(self->mesh);
2881 return (PyObject *)seq;
2886 * Return next MEdge.
2889 static PyObject *MEdgeSeq_nextIter( BPy_MEdgeSeq * self )
2891 if( self->iter == self->mesh->totedge ) {
2893 return EXPP_ReturnPyObjError( PyExc_StopIteration,
2894 "iterator at end" );
2897 return MEdge_CreatePyObject( self->mesh, self->iter++ );
2900 /************************************************************************
2902 * Python MEdgeSeq_Type methods
2904 ************************************************************************/
2907 * Create edges from tuples of vertices. Duplicate new edges, or
2908 * edges which already exist,
2911 static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args )
2915 int new_edge_count, good_edges;
2916 SrchEdges *oldpair, *newpair, *tmppair, *tmppair2;
2920 Mesh *mesh = self->mesh;
2922 /* make sure we get a tuple of sequences of something */
2923 switch( PySequence_Size( args ) ) {
2925 /* if a sequence... */
2926 tmp = PyTuple_GET_ITEM( args, 0 );
2927 if( PySequence_Check( tmp ) ) {
2930 /* ignore empty sequences */
2931 if( !PySequence_Size( tmp ) ) {
2935 /* if another sequence, use it */
2936 tmp2 = PySequence_ITEM( tmp, 0 );
2937 if( PySequence_Check( tmp2 ) )
2942 return EXPP_ReturnPyObjError( PyExc_TypeError,
2943 "expected a sequence of sequence pairs" );
2947 case 4: /* two to four args may be individual verts */
2948 tmp = PyTuple_GET_ITEM( args, 0 );
2950 * if first item isn't a sequence, then assume it's a bunch of MVerts
2951 * and wrap inside a tuple
2953 if( !PySequence_Check( tmp ) ) {
2954 args = Py_BuildValue( "(O)", args );
2956 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
2957 "Py_BuildValue() failed" );
2959 * otherwise, assume it already a bunch of sequences so use as-is
2962 Py_INCREF( args ); /* so we can safely DECREF later */
2965 default: /* anything else is definitely wrong */
2966 return EXPP_ReturnPyObjError( PyExc_TypeError,
2967 "expected a sequence of sequence pairs" );
2970 /* make sure there is something to add */
2971 len = PySequence_Size( args );
2977 /* verify the param list and get a total count of number of edges */
2979 for( i = 0; i < len; ++i ) {
2980 tmp = PySequence_GetItem( args, i );
2982 /* not a tuple of MVerts... error */
2983 if( !PySequence_Check( tmp ) ) {
2986 return EXPP_ReturnPyObjError( PyExc_ValueError,
2987 "expected sequence of MVert sequences" );
2990 /* not the right number of MVerts... error */
2991 nverts = PySequence_Size( tmp );
2992 if( nverts < 2 || nverts > 4 ) {
2995 return EXPP_ReturnPyObjError( PyExc_ValueError,
2996 "expected 2 to 4 MVerts per sequence" );
2999 if( EXPP_check_sequence_consistency( tmp, &MVert_Type ) == 1 ) {
3001 /* get MVerts, check they're from this mesh */
3003 for( j = 0; ok && j < nverts; ++j ) {
3004 e[0] = (BPy_MVert *)PySequence_GetItem( tmp, j );
3005 if( (void *)e[0]->data != (void *)self->mesh )
3011 /* not MVerts from another mesh ... error */
3014 return EXPP_ReturnPyObjError( PyExc_ValueError,
3015 "vertices are from a different mesh" );
3019 for( j = 0; ok == 0 && j < nverts; ++j ) {
3020 PyObject *item = PySequence_ITEM( tmp, j );
3021 if( !PyInt_Check( item ) )
3024 int index = PyInt_AsLong ( item );
3025 if( index < 0 || index >= self->mesh->totvert )
3032 /* not ints or outside of vertex list ... error */
3036 return EXPP_ReturnPyObjError( PyExc_TypeError,
3037 "expected an integer index" );
3039 return EXPP_ReturnPyObjError( PyExc_KeyError,
3040 "index out of range" );
3045 ++new_edge_count; /* if only two vert, then add only edge */
3047 new_edge_count += nverts; /* otherwise, one edge per vert */
3050 /* OK, commit to allocating the search structures */
3051 newpair = (SrchEdges *)MEM_callocN( sizeof(SrchEdges)*new_edge_count,
3054 /* scan the input list and build the new edge pair list */
3055 len = PySequence_Size( args );
3058 for( i = 0; i < len; ++i ) {
3061 tmp = PySequence_GetItem( args, i );
3062 nverts = PySequence_Size( tmp );
3064 /* get new references for the vertices */
3065 for(j = 0; j < nverts; ++j ) {
3066 PyObject *item = PySequence_ITEM( tmp, j );
3067 if( BPy_MVert_Check( item ) ) {
3068 eedges[j] = ((BPy_MVert *)item)->index;
3070 eedges[j] = PyInt_AsLong ( item );
3077 edge_count = 1; /* again, two verts give just one edge */
3079 edge_count = nverts;
3081 /* now add the edges to the search list */
3082 for( j = 0; j < edge_count; ++j ) {
3084 if( k == nverts ) /* final edge */
3087 /* sort verts into search list, skip if two are the same */
3088 if( eedges[j] != eedges[k] ) {
3089 if( eedges[j] < eedges[k] ) {
3090 tmppair->v[0] = eedges[j];
3091 tmppair->v[1] = eedges[k];
3094 tmppair->v[0] = eedges[k];
3095 tmppair->v[1] = eedges[j];
3098 tmppair->index = new_edge_count;
3106 /* sort the new edge pairs */
3107 qsort( newpair, new_edge_count, sizeof(SrchEdges), medge_comp );
3110 * find duplicates in the new list and mark. if it's a duplicate,
3111 * then mark by setting second vert index to 0 (a real edge won't have
3112 * second vert index of 0 since verts are sorted)
3115 good_edges = new_edge_count; /* all edges are good at this point */
3117 tmppair = newpair; /* "last good edge" */
3118 tmppair2 = &tmppair[1]; /* "current candidate edge" */
3119 for( i = 0; i < new_edge_count; ++i ) {
3120 if( tmppair->v[0] != tmppair2->v[0] ||
3121 tmppair->v[1] != tmppair2->v[1] )
3122 tmppair = tmppair2; /* last != current, so current == last */
3124 tmppair2->v[1] = 0; /* last == current, so mark as duplicate */
3125 --good_edges; /* one less good edge */
3130 /* if mesh has edges, see if any of the new edges are already in it */
3131 if( mesh->totedge ) {
3132 oldpair = (SrchEdges *)MEM_callocN( sizeof(SrchEdges)*mesh->totedge,
3136 * build a search list of new edges (don't need to update "swap"
3137 * field, since we're not creating edges here)
3140 tmpedge = mesh->medge;
3141 for( i = 0; i < mesh->totedge; ++i ) {
3142 if( tmpedge->v1 < tmpedge->v2 ) {
3143 tmppair->v[0] = tmpedge->v1;
3144 tmppair->v[1] = tmpedge->v2;
3146 tmppair->v[0] = tmpedge->v2;
3147 tmppair->v[1] = tmpedge->v1;
3153 /* sort the old edge pairs */
3154 qsort( oldpair, mesh->totedge, sizeof(SrchEdges), medge_comp );
3156 /* eliminate new edges already in the mesh */
3158 for( i = new_edge_count; i-- ; ) {
3159 if( tmppair->v[1] ) {
3160 if( bsearch( tmppair, oldpair, mesh->totedge,
3161 sizeof(SrchEdges), medge_comp ) ) {
3162 tmppair->v[1] = 0; /* mark as duplicate */
3168 MEM_freeN( oldpair );
3171 /* if any new edges are left, add to list */
3174 int totedge = mesh->totedge+good_edges;
3176 /* create custom edge data arrays and copy existing edges into it */
3177 CustomData_copy( &mesh->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge );
3178 CustomData_copy_data( &mesh->edata, &edata, 0, 0, mesh->totedge );
3180 if ( !CustomData_has_layer( &edata, CD_MEDGE ) )
3181 CustomData_add_layer( &edata, CD_MEDGE, CD_CALLOC, NULL, totedge );
3183 /* replace old with new data */
3184 CustomData_free( &mesh->edata, mesh->totedge );
3185 mesh->edata = edata;
3186 mesh_update_customdata_pointers( mesh );
3188 /* resort edges into original order */
3189 qsort( newpair, new_edge_count, sizeof(SrchEdges), medge_index_comp );
3191 /* point to the first edge we're going to add */
3192 tmpedge = &mesh->medge[mesh->totedge];
3195 /* as we find a good edge, add it */
3196 while( good_edges ) {
3197 if( tmppair->v[1] ) { /* not marked as duplicate ! */
3198 if( !tmppair->swap ) {
3199 tmpedge->v1 = tmppair->v[0];
3200 tmpedge->v2 = tmppair->v[1];
3202 tmpedge->v1 = tmppair->v[1];
3203 tmpedge->v2 = tmppair->v[0];
3205 tmpedge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT;
3214 /* clean up and leave */
3215 mesh_update( mesh );
3216 MEM_freeN( newpair );
3221 static PyObject *MEdgeSeq_delete( BPy_MEdgeSeq * self, PyObject *args )
3223 Mesh *mesh = self->mesh;
3226 unsigned int *vert_table, *del_table, *edge_table;
3228 int face_count, edge_count, vert_count;
3231 * if input tuple contains a single sequence, use it as input instead;
3232 * otherwise use the sequence as-is and check later that it contains
3233 * one or more integers or MVerts
3235 if( PySequence_Size( args ) == 1 ) {
3236 PyObject *tmp = PyTuple_GET_ITEM( args, 0 );
3237 if( PySequence_Check( tmp ) )
3241 /* if sequence is empty, do nothing */
3242 len = PySequence_Size( args );
3247 edge_table = (unsigned int *)MEM_callocN( len*sizeof( unsigned int ),
3250 /* get the indices of edges to be removed */
3251 for( i = len; i--; ) {
3252 PyObject *tmp = PySequence_GetItem( args, i );
3253 if( BPy_MEdge_Check( tmp ) )
3254 edge_table[i] = ((BPy_MEdge *)tmp)->index;
3255 else if( PyInt_Check( tmp ) )
3256 edge_table[i] = PyInt_AsLong ( tmp );
3258 MEM_freeN( edge_table );
3260 return EXPP_ReturnPyObjError( PyExc_TypeError,
3261 "expected a sequence of ints or MEdges" );
3265 /* if index out-of-range, throw exception */
3266 if( edge_table[i] >= (unsigned int)mesh->totedge ) {
3267 MEM_freeN( edge_table );
3268 return EXPP_ReturnPyObjError( PyExc_ValueError,
3269 "array index out of range" );
3274 * build two tables: first table marks vertices which belong to an edge
3275 * which is being deleted
3277 del_table = (unsigned int *)MEM_callocN(
3278 mesh->totvert*sizeof( unsigned int ), "vert_table" );
3281 * Borrow a trick from editmesh code: for each edge to be deleted, mark
3282 * its vertices as well. Then go through face list and look for two
3283 * consecutive marked vertices.
3286 /* mark each edge that's to be deleted */
3287 srcedge = mesh->medge;
3288 for( i = len; i--; ) {
3289 unsigned int idx = edge_table[i];
3290 del_table[srcedge[idx].v1] = UINT_MAX;
3291 del_table[srcedge[idx].v2] = UINT_MAX;
3292 srcedge[idx].v1 = UINT_MAX;
3296 * second table is used for vertices which become orphaned (belong to no
3297 * edges) and need to be deleted; it's also the normal lookup table for
3298 * old->new vertex indices