| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /* 
 | 
					
						
							|  |  |  |  * $Id$ | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. The Blender | 
					
						
							|  |  |  |  * Foundation also sells licenses for use in proprietary software under | 
					
						
							|  |  |  |  * the Blender License.  See http://www.blender.org/BL/ for information
 | 
					
						
							|  |  |  |  * about this. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 59 Temple Place - Suite 330, Boston, MA	02111-1307, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This is a new part of Blender, partially based on NMesh.c API. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): Ken Hughes | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL/BL DUAL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Mesh.h" /*This must come first*/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_key_types.h"
 | 
					
						
							|  |  |  | #include "DNA_armature_types.h"
 | 
					
						
							|  |  |  | #include "DNA_scene_types.h"
 | 
					
						
							|  |  |  | #include "DNA_oops_types.h"
 | 
					
						
							|  |  |  | #include "DNA_space_types.h"
 | 
					
						
							|  |  |  | #include "DNA_curve_types.h"
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | #include "DNA_meta_types.h"
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | #include "DNA_modifier_types.h"
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "BDR_editface.h"	/* make_tfaces */
 | 
					
						
							|  |  |  | #include "BDR_vpaint.h"
 | 
					
						
							|  |  |  | #include "BDR_editobject.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BIF_editdeform.h"
 | 
					
						
							|  |  |  | #include "BIF_editkey.h"	/* insert_meshkey */
 | 
					
						
							| 
									
										
										
										
											2006-09-27 16:33:02 +00:00
										 |  |  | #include "BIF_space.h"		/* REMAKEIPO - insert_meshkey */
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | #include "BIF_editview.h"
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | #include "BIF_editmesh.h"
 | 
					
						
							| 
									
										
										
										
											2006-05-08 05:37:00 +00:00
										 |  |  | #include "BIF_meshtools.h"
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_deform.h"
 | 
					
						
							|  |  |  | #include "BKE_mesh.h"
 | 
					
						
							|  |  |  | #include "BKE_material.h"
 | 
					
						
							|  |  |  | #include "BKE_main.h"
 | 
					
						
							|  |  |  | #include "BKE_global.h"
 | 
					
						
							|  |  |  | #include "BKE_library.h"
 | 
					
						
							|  |  |  | #include "BKE_displist.h"
 | 
					
						
							|  |  |  | #include "BKE_DerivedMesh.h"
 | 
					
						
							|  |  |  | #include "BKE_object.h"
 | 
					
						
							|  |  |  | #include "BKE_mball.h"
 | 
					
						
							|  |  |  | #include "BKE_utildefines.h"
 | 
					
						
							|  |  |  | #include "BKE_depsgraph.h"
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | #include "BSE_edit.h"		/* for countall(); */
 | 
					
						
							|  |  |  | #include "BKE_curve.h"		/* for copy_curve(); */
 | 
					
						
							|  |  |  | #include "BKE_modifier.h"	/* for modifier_new(), modifier_copyData(); */
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_arithb.h"
 | 
					
						
							|  |  |  | #include "BLI_blenlib.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "blendef.h"
 | 
					
						
							|  |  |  | #include "mydevice.h"
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | #include "butspace.h"		/* for mesh tools */
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | #include "Object.h"
 | 
					
						
							|  |  |  | #include "Key.h"
 | 
					
						
							|  |  |  | #include "Image.h"
 | 
					
						
							|  |  |  | #include "Material.h"
 | 
					
						
							|  |  |  | #include "Mathutils.h"
 | 
					
						
							| 
									
										
										
										
											2006-05-25 16:45:24 +00:00
										 |  |  | #include "meshPrimitive.h"
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | #include "constant.h"
 | 
					
						
							|  |  |  | #include "gen_utils.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* EXPP Mesh defines */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MESH_SMOOTHRESH               30
 | 
					
						
							|  |  |  | #define MESH_SMOOTHRESH_MIN            1
 | 
					
						
							|  |  |  | #define MESH_SMOOTHRESH_MAX           80
 | 
					
						
							|  |  |  | #define MESH_SUBDIV                    1
 | 
					
						
							|  |  |  | #define MESH_SUBDIV_MIN                0
 | 
					
						
							|  |  |  | #define MESH_SUBDIV_MAX                6
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MESH_HASFACEUV                 0
 | 
					
						
							|  |  |  | #define MESH_HASMCOL                   1
 | 
					
						
							|  |  |  | #define MESH_HASVERTUV                 2
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | #define MESH_TOOL_TOSPHERE             0
 | 
					
						
							|  |  |  | #define MESH_TOOL_VERTEXSMOOTH         1
 | 
					
						
							|  |  |  | #define MESH_TOOL_FLIPNORM             2
 | 
					
						
							|  |  |  | #define MESH_TOOL_SUBDIV               3
 | 
					
						
							|  |  |  | #define MESH_TOOL_REMDOUB              4
 | 
					
						
							|  |  |  | #define MESH_TOOL_FILL                 5
 | 
					
						
							|  |  |  | #define MESH_TOOL_RECALCNORM           6
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | #define MESH_TOOL_TRI2QUAD             7
 | 
					
						
							|  |  |  | #define MESH_TOOL_QUAD2TRI             8
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | static PyObject *MVertSeq_CreatePyObject( Mesh * mesh ); | 
					
						
							|  |  |  | static PyObject *MFaceSeq_CreatePyObject( Mesh * mesh ); | 
					
						
							|  |  |  | static PyObject *MEdgeSeq_CreatePyObject( Mesh * mesh ); | 
					
						
							|  |  |  | static PyObject *MFace_CreatePyObject( Mesh * mesh, int i ); | 
					
						
							|  |  |  | static PyObject *MEdge_CreatePyObject( Mesh * mesh, int i ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * internal utilities | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * internal structures used for sorting edges and faces | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct SrchEdges { | 
					
						
							|  |  |  | 	unsigned int v[2];		/* indices for verts */ | 
					
						
							|  |  |  | 	unsigned char swap;		/* non-zero if verts swapped */ | 
					
						
							|  |  |  | 	unsigned int index;		/* index in original param list of this edge */ | 
					
						
							|  |  |  | 							/* (will be used by findEdges) */ | 
					
						
							|  |  |  | } SrchEdges; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct SrchFaces { | 
					
						
							|  |  |  | 	unsigned int v[4];		/* indices for verts */ | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 	unsigned int index;		/* index in original param list of this edge */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	unsigned char order;	/* order of original verts, bitpacked */ | 
					
						
							|  |  |  | } SrchFaces; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | typedef struct FaceEdges { | 
					
						
							|  |  |  | 	unsigned int v[2];		/* search key (vert indices) */ | 
					
						
							|  |  |  | 	unsigned int index;		/* location in edge list */ | 
					
						
							|  |  |  | 	unsigned char sel;		/* selection state */ | 
					
						
							|  |  |  | } FaceEdges; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * compare edges by vertex indices | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int medge_comp( const void *va, const void *vb ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const unsigned int *a = ((SrchEdges *)va)->v; | 
					
						
							|  |  |  | 	const unsigned int *b = ((SrchEdges *)vb)->v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* compare first index for differences */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (a[0] < b[0]) return -1;	 | 
					
						
							|  |  |  | 	else if (a[0] > b[0]) return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if first indices equal, compare second index for differences */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	else if (a[1] < b[1]) return -1; | 
					
						
							|  |  |  | 	else return (a[1] > b[1]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * compare edges by insert list indices | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int medge_index_comp( const void *va, const void *vb ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const SrchEdges *a = (SrchEdges *)va; | 
					
						
							|  |  |  | 	const SrchEdges *b = (SrchEdges *)vb; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* compare list indices for differences */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (a->index < b->index) return -1; | 
					
						
							|  |  |  | 	else return (a->index > b->index); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * compare faces by vertex indices | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int mface_comp( const void *va, const void *vb ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const SrchFaces *a = va; | 
					
						
							|  |  |  | 	const SrchFaces *b = vb; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* compare indices, first to last, for differences */ | 
					
						
							|  |  |  | 	for( i = 0; i < 4; ++i ) { | 
					
						
							|  |  |  | 		if( a->v[i] < b->v[i] ) | 
					
						
							|  |  |  | 			return -1;	 | 
					
						
							|  |  |  | 		if( a->v[i] > b->v[i] ) | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * don't think this needs be done; if order is different then either | 
					
						
							|  |  |  | 	 * (a) the face is good, just reversed or has a different starting | 
					
						
							|  |  |  | 	 * vertex, or (b) face is bad (for 4 verts) and there's a "twist" | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 	/* if all the same verts, compare their order */ | 
					
						
							|  |  |  | 	if( a->order < b->order ) | 
					
						
							|  |  |  | 		return -1;	 | 
					
						
							|  |  |  | 	if( a->order > b->order ) | 
					
						
							|  |  |  | 		return 1;	 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * compare faces by insert list indices | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int mface_index_comp( const void *va, const void *vb ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const SrchFaces *a = va; | 
					
						
							|  |  |  | 	const SrchFaces *b = vb; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* compare indices, first to last, for differences */ | 
					
						
							|  |  |  | 	if( a->index < b->index ) | 
					
						
							|  |  |  | 		return -1;	 | 
					
						
							|  |  |  | 	if( a->index > b->index ) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  |  * compare edges by vertex indices | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | int faceedge_comp( const void *va, const void *vb ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	const unsigned int *a = ((FaceEdges *)va)->v; | 
					
						
							|  |  |  | 	const unsigned int *b = ((FaceEdges *)vb)->v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* compare first index for differences */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (a[0] < b[0]) return -1;	 | 
					
						
							|  |  |  | 	else if (a[0] > b[0]) return 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if first indices equal, compare second index for differences */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	else if (a[1] < b[1]) return -1; | 
					
						
							|  |  |  | 	else return (a[1] > b[1]); | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  |  * update the DAG for all objects linked to this mesh | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void mesh_update( Mesh * mesh ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object_updateDag( (void *) mesh ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | static void delete_dverts( Mesh *mesh, unsigned int *vert_table, int to_delete ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int *tmpvert; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	char state; | 
					
						
							|  |  |  | 	MDeformVert *newvert, *srcvert, *dstvert; | 
					
						
							|  |  |  | 	int count; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 	newvert = (MDeformVert *)MEM_mallocN( | 
					
						
							|  |  |  | 			sizeof( MDeformVert )*( mesh->totvert-to_delete ), "MDeformVerts" ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * do "smart compaction" of the table; find and copy groups of vertices | 
					
						
							|  |  |  | 	 * which are not being deleted | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 	dstvert = newvert; | 
					
						
							|  |  |  | 	srcvert = mesh->dvert; | 
					
						
							|  |  |  | 	tmpvert = vert_table; | 
					
						
							|  |  |  | 	count = 0; | 
					
						
							|  |  |  | 	state = 1; | 
					
						
							|  |  |  | 	for( i = 0; i < mesh->totvert; ++i, ++tmpvert ) { | 
					
						
							|  |  |  | 		switch( state ) { | 
					
						
							|  |  |  | 		case 0:		/* skipping verts */ | 
					
						
							|  |  |  | 			if( *tmpvert == UINT_MAX ) | 
					
						
							|  |  |  | 				++count; | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				srcvert = mesh->dvert + i; | 
					
						
							|  |  |  | 				count = 1; | 
					
						
							|  |  |  | 				state = 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 1:		/* gathering verts */ | 
					
						
							|  |  |  | 			if( *tmpvert != UINT_MAX ) { | 
					
						
							|  |  |  | 				++count; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				if( count ) { | 
					
						
							|  |  |  | 					memcpy( dstvert, srcvert, sizeof( MDeformVert ) * count ); | 
					
						
							|  |  |  | 					dstvert += count; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				count = 1; | 
					
						
							|  |  |  | 				state = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if( !state && mesh->dvert[i].dw ) | 
					
						
							|  |  |  | 			MEM_freeN( mesh->dvert[i].dw ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 	/* if we were gathering verts at the end of the loop, copy those */ | 
					
						
							|  |  |  | 	if( state && count ) | 
					
						
							|  |  |  | 		memcpy( dstvert, srcvert, sizeof( MDeformVert ) * count ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* delete old vertex list, install the new one */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MEM_freeN( mesh->dvert ); | 
					
						
							|  |  |  | 	mesh->dvert = newvert; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * delete vertices from mesh, then delete edges/keys/faces which used those | 
					
						
							|  |  |  |  * vertices | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Deletion is done by "smart compaction"; groups of verts/edges/faces which | 
					
						
							|  |  |  |  * remain in the list are copied to new list instead of one at a time.  Since | 
					
						
							|  |  |  |  * Blender has no realloc we would have to copy things anyway, so there's no | 
					
						
							|  |  |  |  * point trying to fill empty entries with data from the end of the lists. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * vert_table is a lookup table for mapping old verts to new verts (after the | 
					
						
							|  |  |  |  * vextex list has deleted vertices removed).  Each entry contains the | 
					
						
							|  |  |  |  * vertex's new index. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void delete_verts( Mesh *mesh, unsigned int *vert_table, int to_delete ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * (1) allocate vertex table (initialize contents to 0) | 
					
						
							|  |  |  | 	 * (2) mark each vertex being deleted in vertex table (= UINT_MAX) | 
					
						
							|  |  |  | 	 * (3) update remaining table entries with "new" vertex index (after | 
					
						
							|  |  |  | 	 *     compaction) | 
					
						
							|  |  |  | 	 * (4) allocate new vertex list | 
					
						
							|  |  |  | 	 * (5) do "smart copy" of vertices from old to new | 
					
						
							|  |  |  | 	 *     * each moved vertex is entered into vertex table: if vertex i is | 
					
						
							|  |  |  | 	 *       moving to index j in new list | 
					
						
							|  |  |  | 	 *       vert_table[i] = j; | 
					
						
							|  |  |  | 	 * (6) if keys, do "smart copy" of keys | 
					
						
							|  |  |  | 	 * (7) process edge list | 
					
						
							|  |  |  | 	 *      update vert index | 
					
						
							|  |  |  | 	 *      delete edges which delete verts | 
					
						
							|  |  |  | 	 * (7) allocate new edge list | 
					
						
							|  |  |  | 	 * (8) do "smart copy" of edges | 
					
						
							|  |  |  | 	 * (9) allocate new face list | 
					
						
							|  |  |  | 	 * (10) do "smart copy" of face | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	unsigned int *tmpvert; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	char state; | 
					
						
							|  |  |  | 	MVert *newvert, *srcvert, *dstvert; | 
					
						
							|  |  |  | 	int count; | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 	MSticky *newsticky = NULL, *srcsticky, *dststicky; | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* is there are deformed verts also, delete them first */ | 
					
						
							|  |  |  | 	if( mesh->dvert ) | 
					
						
							|  |  |  | 		delete_dverts( mesh, vert_table, to_delete ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	newvert = (MVert *)MEM_mallocN( | 
					
						
							|  |  |  | 			sizeof( MVert )*( mesh->totvert-to_delete ), "MVerts" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 	/* is there are UV verts, track them too */ | 
					
						
							|  |  |  | 	if( mesh->msticky ) | 
					
						
							|  |  |  | 	newsticky = (MSticky *)MEM_mallocN( | 
					
						
							|  |  |  | 			sizeof( MSticky )*( mesh->totvert-to_delete ), "MStickies" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * do "smart compaction" of the table; find and copy groups of vertices | 
					
						
							|  |  |  | 	 * which are not being deleted | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dstvert = newvert; | 
					
						
							|  |  |  | 	srcvert = mesh->mvert; | 
					
						
							|  |  |  | 	tmpvert = vert_table; | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 	dststicky = newsticky; | 
					
						
							|  |  |  | 	srcsticky = mesh->msticky; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	count = 0; | 
					
						
							|  |  |  | 	state = 1; | 
					
						
							|  |  |  | 	for( i = 0; i < mesh->totvert; ++i, ++tmpvert ) { | 
					
						
							|  |  |  | 		switch( state ) { | 
					
						
							|  |  |  | 		case 0:		/* skipping verts */ | 
					
						
							|  |  |  | 			if( *tmpvert == UINT_MAX ) { | 
					
						
							|  |  |  | 				++count; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				srcvert = mesh->mvert + i; | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 				srcsticky = mesh->msticky + i; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 				count = 1; | 
					
						
							|  |  |  | 				state = 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 1:		/* gathering verts */ | 
					
						
							|  |  |  | 			if( *tmpvert != UINT_MAX ) { | 
					
						
							|  |  |  | 				++count; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				if( count ) { | 
					
						
							|  |  |  | 					memcpy( dstvert, srcvert, sizeof( MVert ) * count ); | 
					
						
							|  |  |  | 					dstvert += count; | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 					if( newsticky ) { | 
					
						
							|  |  |  | 						memcpy( dststicky, srcsticky, sizeof( MSticky ) | 
					
						
							|  |  |  | 								* count ); | 
					
						
							|  |  |  | 						dststicky += count; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				count = 1; | 
					
						
							|  |  |  | 				state = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if we were gathering verts at the end of the loop, copy those */ | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 	if( state && count ) { | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		memcpy( dstvert, srcvert, sizeof( MVert ) * count ); | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 		if( newsticky ) | 
					
						
							|  |  |  | 			memcpy( dststicky, srcsticky, sizeof( MSticky ) * count ); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* delete old vertex list, install the new one, update vertex count */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MEM_freeN( mesh->mvert ); | 
					
						
							|  |  |  | 	mesh->mvert = newvert; | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 	if( newsticky ) { | 
					
						
							|  |  |  | 		MEM_freeN( mesh->msticky ); | 
					
						
							|  |  |  | 		mesh->msticky = newsticky; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	mesh->totvert -= to_delete; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void delete_edges( Mesh *mesh, unsigned int *vert_table, int to_delete ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	MEdge *tmpedge; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if not given, then mark and count edges to be deleted */ | 
					
						
							|  |  |  | 	if( !to_delete ) { | 
					
						
							|  |  |  | 		tmpedge = mesh->medge; | 
					
						
							|  |  |  | 		for( i = mesh->totedge; i-- ; ++tmpedge ) | 
					
						
							|  |  |  | 			if( vert_table[tmpedge->v1] == UINT_MAX || | 
					
						
							|  |  |  | 					vert_table[tmpedge->v2] == UINT_MAX ) { | 
					
						
							|  |  |  | 				tmpedge->v1 = UINT_MAX; | 
					
						
							|  |  |  | 				++to_delete; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if there are edges to delete, handle it */ | 
					
						
							|  |  |  | 	if( to_delete ) { | 
					
						
							|  |  |  | 		MEdge *newedge, *srcedge, *dstedge; | 
					
						
							|  |  |  | 		int count, state; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* allocate new edge list and populate */ | 
					
						
							|  |  |  | 		newedge = (MEdge *)MEM_mallocN( | 
					
						
							|  |  |  | 				sizeof( MEdge )*( mesh->totedge-to_delete ), "MEdges" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * do "smart compaction" of the edges; find and copy groups of edges | 
					
						
							|  |  |  | 	 * which are not being deleted | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		dstedge = newedge; | 
					
						
							|  |  |  | 		srcedge = mesh->medge; | 
					
						
							|  |  |  | 		tmpedge = srcedge; | 
					
						
							|  |  |  | 		count = 0; | 
					
						
							|  |  |  | 		state = 1; | 
					
						
							|  |  |  | 		for( i = 0; i < mesh->totedge; ++i, ++tmpedge ) { | 
					
						
							|  |  |  | 			switch( state ) { | 
					
						
							|  |  |  | 			case 0:		/* skipping edges */ | 
					
						
							|  |  |  | 				if( tmpedge->v1 == UINT_MAX ) { | 
					
						
							|  |  |  | 					++count; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					srcedge = tmpedge; | 
					
						
							|  |  |  | 					count = 1; | 
					
						
							|  |  |  | 					state = 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case 1:		/* gathering edges */ | 
					
						
							|  |  |  | 				if( tmpedge->v1 != UINT_MAX ) { | 
					
						
							|  |  |  | 					++count; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					if( count ) { | 
					
						
							|  |  |  | 						memcpy( dstedge, srcedge, sizeof( MEdge ) * count ); | 
					
						
							|  |  |  | 						dstedge += count; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					count = 1; | 
					
						
							|  |  |  | 					state = 0; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		/* if edge is good, update vertex indices */ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* copy any pending good edges */ | 
					
						
							|  |  |  | 		if( state && count ) | 
					
						
							|  |  |  | 			memcpy( dstedge, srcedge, sizeof( MEdge ) * count ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* delete old vertex list, install the new one, update vertex count */ | 
					
						
							|  |  |  | 		MEM_freeN( mesh->medge ); | 
					
						
							|  |  |  | 		mesh->medge = newedge; | 
					
						
							|  |  |  | 		mesh->totedge -= to_delete; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if vertices were deleted, update edge's vertices */ | 
					
						
							|  |  |  | 	if( vert_table ) { | 
					
						
							|  |  |  | 		tmpedge = mesh->medge; | 
					
						
							|  |  |  | 		for( i = mesh->totedge; i--; ++tmpedge ) { | 
					
						
							|  |  |  | 			tmpedge->v1 = vert_table[tmpedge->v1]; | 
					
						
							|  |  |  | 			tmpedge->v2 = vert_table[tmpedge->v2]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Since all faces must have 3 or 4 verts, we can't have v3 or v4 be zero. | 
					
						
							|  |  |  |  * If that happens during the deletion, we have to shuffle the vertices | 
					
						
							|  |  |  |  * around; otherwise it can cause an Eeekadoodle or worse.  If there are | 
					
						
							|  |  |  |  * texture faces as well, they have to be shuffled as well. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * (code borrowed from test_index_face() in mesh.c, but since we know the | 
					
						
							|  |  |  |  * faces already have correct number of vertices, this is a little faster) | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void eeek_fix( MFace *mface, TFace *tface, int len4 ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* if 4 verts, then neither v3 nor v4 can be zero */ | 
					
						
							|  |  |  | 	if( len4 ) { | 
					
						
							|  |  |  | 		if( !mface->v3 || !mface->v4 ) { | 
					
						
							|  |  |  | 			SWAP( int, mface->v1, mface->v3 ); | 
					
						
							|  |  |  | 			SWAP( int, mface->v2, mface->v4 ); | 
					
						
							|  |  |  | 			if( tface ) { | 
					
						
							|  |  |  | 				SWAP( float, tface->uv[0][0], tface->uv[2][0] ); | 
					
						
							|  |  |  | 				SWAP( float, tface->uv[0][1], tface->uv[2][1] ); | 
					
						
							|  |  |  | 				SWAP( float, tface->uv[1][0], tface->uv[3][0] ); | 
					
						
							|  |  |  | 				SWAP( float, tface->uv[1][1], tface->uv[3][1] ); | 
					
						
							|  |  |  | 				SWAP( unsigned int, tface->col[0], tface->col[2] ); | 
					
						
							|  |  |  | 				SWAP( unsigned int, tface->col[1], tface->col[3] ); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else if( !mface->v3 ) { | 
					
						
							|  |  |  | 	/* if 2 verts, then just v3 cannot be zero (v4 MUST be zero) */ | 
					
						
							|  |  |  | 		SWAP( int, mface->v1, mface->v2 ); | 
					
						
							|  |  |  | 		SWAP( int, mface->v2, mface->v3 ); | 
					
						
							|  |  |  | 		if( tface ) { | 
					
						
							|  |  |  | 			SWAP( float, tface->uv[0][0], tface->uv[1][0] ); | 
					
						
							|  |  |  | 			SWAP( float, tface->uv[0][1], tface->uv[1][1] ); | 
					
						
							|  |  |  | 			SWAP( float, tface->uv[2][0], tface->uv[1][0] ); | 
					
						
							|  |  |  | 			SWAP( float, tface->uv[2][1], tface->uv[1][1] ); | 
					
						
							|  |  |  | 			SWAP( unsigned int, tface->col[0], tface->col[1] ); | 
					
						
							|  |  |  | 			SWAP( unsigned int, tface->col[1], tface->col[2] ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void delete_faces( Mesh *mesh, unsigned int *vert_table, int to_delete ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	MFace *tmpface; | 
					
						
							|  |  |  | 	TFace *tmptface; | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 	MCol *tmpmcol; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* if there are faces to delete, handle it */ | 
					
						
							|  |  |  | 	if( to_delete ) { | 
					
						
							|  |  |  | 		MFace *newface, *srcface, *dstface; | 
					
						
							|  |  |  | 		TFace *newtface = NULL, *srctface, *dsttface; | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 		MCol *newmcol = NULL, *srcmcol, *dstmcol; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		char state; | 
					
						
							|  |  |  | 		int count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		newface = (MFace *)MEM_mallocN( ( mesh->totface-to_delete ) | 
					
						
							|  |  |  | 				* sizeof( MFace ), "MFace" ); | 
					
						
							|  |  |  | 		if( mesh->tface ) | 
					
						
							|  |  |  | 			newtface = (TFace *)MEM_mallocN( ( mesh->totface-to_delete ) | 
					
						
							|  |  |  | 					* sizeof( TFace ), "TFace" ); | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 		else if( mesh->mcol ) | 
					
						
							|  |  |  | 			newmcol = (MCol *)MEM_mallocN( ( mesh->totface-to_delete ) | 
					
						
							|  |  |  | 					* 4 * sizeof( MCol ), "MCol" ); | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * do "smart compaction" of the faces; find and copy groups of faces | 
					
						
							|  |  |  | 		 * which are not being deleted | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		dstface = newface; | 
					
						
							|  |  |  | 		srcface = mesh->mface; | 
					
						
							|  |  |  | 		tmpface = srcface; | 
					
						
							|  |  |  | 		dsttface = newtface; | 
					
						
							|  |  |  | 		srctface = mesh->tface; | 
					
						
							|  |  |  | 		tmptface = srctface; | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 		dstmcol = newmcol; | 
					
						
							|  |  |  | 		srcmcol = mesh->mcol; | 
					
						
							|  |  |  | 		tmpmcol = srcmcol; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		count = 0; | 
					
						
							|  |  |  | 		state = 1; | 
					
						
							|  |  |  | 		for( i = 0; i < mesh->totface; ++i ) { | 
					
						
							|  |  |  | 			switch( state ) { | 
					
						
							|  |  |  | 			case 0:		/* skipping faces */ | 
					
						
							|  |  |  | 				if( tmpface->v1 == UINT_MAX ) { | 
					
						
							|  |  |  | 					++count; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					srcface = tmpface; | 
					
						
							|  |  |  | 					srctface = tmptface; | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 					srcmcol = tmpmcol; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 					count = 1; | 
					
						
							|  |  |  | 					state = 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case 1:		/* gathering faces */ | 
					
						
							|  |  |  | 				if( tmpface->v1 != UINT_MAX ) { | 
					
						
							|  |  |  | 					++count; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					if( count ) { | 
					
						
							|  |  |  | 						memcpy( dstface, srcface, sizeof( MFace ) * count ); | 
					
						
							|  |  |  | 						dstface += count; | 
					
						
							|  |  |  | 						if( newtface ) { | 
					
						
							|  |  |  | 							memcpy( dsttface, srctface, sizeof( TFace ) | 
					
						
							|  |  |  | 									* count ); | 
					
						
							|  |  |  | 							dsttface += count; | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 						} else if( newmcol ) { | 
					
						
							|  |  |  | 							memcpy( dstmcol, srcmcol, sizeof( MCol ) | 
					
						
							|  |  |  | 									* 4 * count ); | 
					
						
							|  |  |  | 							dstmcol += count; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					count = 1; | 
					
						
							|  |  |  | 					state = 0; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			++tmpface;  | 
					
						
							|  |  |  | 			++tmptface;  | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 			++tmpmcol;  | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if we were gathering faces at the end of the loop, copy those */ | 
					
						
							|  |  |  | 		if ( state && count ) { | 
					
						
							|  |  |  | 			memcpy( dstface, srcface, sizeof( MFace ) * count ); | 
					
						
							|  |  |  | 			if( newtface ) | 
					
						
							|  |  |  | 				memcpy( dsttface, srctface, sizeof( TFace ) * count ); | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 			else if( newmcol ) | 
					
						
							|  |  |  | 				memcpy( dstmcol, srcmcol, sizeof( MCol ) * 4 * count ); | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* delete old face list, install the new one, update face count */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		MEM_freeN( mesh->mface ); | 
					
						
							|  |  |  | 		mesh->mface = newface; | 
					
						
							|  |  |  | 		mesh->totface -= to_delete; | 
					
						
							|  |  |  | 		if( newtface ) { | 
					
						
							|  |  |  | 			MEM_freeN( mesh->tface ); | 
					
						
							|  |  |  | 			mesh->tface = newtface; | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 		} else if( newmcol ) { | 
					
						
							|  |  |  | 			MEM_freeN( mesh->mcol ); | 
					
						
							|  |  |  | 			mesh->mcol = newmcol; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if vertices were deleted, update face's vertices */ | 
					
						
							|  |  |  | 	if( vert_table ) { | 
					
						
							|  |  |  | 		tmpface = mesh->mface; | 
					
						
							|  |  |  | 		tmptface = mesh->tface; | 
					
						
							|  |  |  | 		for( i = mesh->totface; i--; ) { | 
					
						
							|  |  |  | 			int len4 = tmpface->v4; | 
					
						
							|  |  |  | 			tmpface->v1 = vert_table[tmpface->v1]; | 
					
						
							|  |  |  | 			tmpface->v2 = vert_table[tmpface->v2]; | 
					
						
							|  |  |  | 			tmpface->v3 = vert_table[tmpface->v3]; | 
					
						
							| 
									
										
										
										
											2006-06-17 14:08:15 +00:00
										 |  |  | 			if(len4) | 
					
						
							|  |  |  | 				tmpface->v4 = vert_table[tmpface->v4]; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				tmpface->v4 = 0; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			eeek_fix( tmpface, tmptface, len4 ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			++tmpface; | 
					
						
							|  |  |  | 			if( mesh->tface ) | 
					
						
							|  |  |  | 				++tmptface; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * fill up vertex lookup table with old-to-new mappings | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * returns the number of vertices marked for deletion | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static unsigned int make_vertex_table( unsigned int *vert_table, int count ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	unsigned int *tmpvert = vert_table; | 
					
						
							|  |  |  | 	unsigned int to_delete = 0; | 
					
						
							|  |  |  | 	unsigned int new_index = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* fill the lookup table with old->new index mappings */ | 
					
						
							|  |  |  | 	for( i = count; i; --i, ++tmpvert ) { | 
					
						
							|  |  |  | 		if( *tmpvert == UINT_MAX ) { | 
					
						
							|  |  |  | 			++to_delete; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			*tmpvert = new_index; | 
					
						
							|  |  |  | 			++new_index; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return to_delete; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Color attributes | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * get a color attribute | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MCol_getAttr( BPy_MCol * self, void *type ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned char param; | 
					
						
							|  |  |  | 	PyObject *attr; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 	switch( (long)type ) { | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |     case 'R':	/* these are backwards, but that how it works */ | 
					
						
							|  |  |  | 		param = self->color->b; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |     case 'G': | 
					
						
							|  |  |  | 		param = self->color->g; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |     case 'B':	/* these are backwards, but that how it works */ | 
					
						
							|  |  |  | 		param = self->color->r; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  |     case 'A': | 
					
						
							|  |  |  | 		param = self->color->a; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			char errstr[1024]; | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 			sprintf( errstr, "undefined type '%d' in MCol_getAttr", | 
					
						
							|  |  |  | 					(int)((long)type & 0xff)); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			return EXPP_ReturnPyObjError( PyExc_RuntimeError, errstr ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	attr = PyInt_FromLong( param ); | 
					
						
							|  |  |  | 	if( attr ) | 
					
						
							|  |  |  | 		return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 			"PyInt_FromLong() failed");  | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * set a color attribute | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MCol_setAttr( BPy_MCol * self, PyObject * value, void * type ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned char *param; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 	switch( (long)type ) { | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |     case 'R':	/* these are backwards, but that how it works */ | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 		param = (unsigned char *)&self->color->b; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  |     case 'G': | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 		param = (unsigned char *)&self->color->g; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  |     case 'B':	/* these are backwards, but that how it works */ | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 		param = (unsigned char *)&self->color->r; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  |     case 'A': | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 		param = (unsigned char *)&self->color->a; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			char errstr[1024]; | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 			sprintf( errstr, "undefined type '%d' in MCol_setAttr", | 
					
						
							|  |  |  | 					(int)((long)type & 0xff)); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			return EXPP_ReturnIntError( PyExc_RuntimeError, errstr ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_setIValueClamped( value, param, 0, 255, 'b' ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MCol_Type attributes get/set structure | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyGetSetDef BPy_MCol_getseters[] = { | 
					
						
							|  |  |  | 	{"r", | 
					
						
							|  |  |  | 	 (getter)MCol_getAttr, (setter)MCol_setAttr, | 
					
						
							|  |  |  | 	 "red component", | 
					
						
							|  |  |  | 	 (void *)'R'}, | 
					
						
							|  |  |  | 	{"g", | 
					
						
							|  |  |  | 	 (getter)MCol_getAttr, (setter)MCol_setAttr, | 
					
						
							|  |  |  | 	 "green component", | 
					
						
							|  |  |  | 	 (void *)'G'}, | 
					
						
							|  |  |  | 	{"b", | 
					
						
							|  |  |  | 	 (getter)MCol_getAttr, (setter)MCol_setAttr, | 
					
						
							|  |  |  | 	 "blue component", | 
					
						
							|  |  |  | 	 (void *)'B'}, | 
					
						
							|  |  |  | 	{"a", | 
					
						
							|  |  |  | 	 (getter)MCol_getAttr, (setter)MCol_setAttr, | 
					
						
							|  |  |  | 	 "alpha component", | 
					
						
							|  |  |  | 	 (void *)'A'}, | 
					
						
							|  |  |  | 	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MCol_Type methods | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void MCol_dealloc( BPy_MCol * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject_DEL( self ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MCol_repr( BPy_MCol * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return PyString_FromFormat( "[MCol %d %d %d %d]", | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 			(int)self->color->b, (int)self->color->g,  | 
					
						
							|  |  |  | 			(int)self->color->r, (int)self->color->a );  | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MCol_Type structure definition | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyTypeObject MCol_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT( NULL )  /* required py macro */ | 
					
						
							|  |  |  | 	0,                          /* ob_size */ | 
					
						
							|  |  |  | 	/*  For printing, in format "<module>.<name>" */ | 
					
						
							|  |  |  | 	"Blender MCol",           /* char *tp_name; */ | 
					
						
							|  |  |  | 	sizeof( BPy_MCol ),       /* int tp_basicsize; */ | 
					
						
							|  |  |  | 	0,                          /* tp_itemsize;  For allocation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Methods to implement standard operations */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	( destructor ) MCol_dealloc,/* destructor tp_dealloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* printfunc tp_print; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrfunc tp_getattr; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrfunc tp_setattr; */ | 
					
						
							|  |  |  | 	NULL,                       /* cmpfunc tp_compare; */ | 
					
						
							|  |  |  | 	( reprfunc ) MCol_repr,     /* reprfunc tp_repr; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Method suites for standard classes */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /* PyNumberMethods *tp_as_number; */ | 
					
						
							|  |  |  | 	NULL,	        			/* PySequenceMethods *tp_as_sequence; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyMappingMethods *tp_as_mapping; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* More standard operations (here for binary compatibility) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /* hashfunc tp_hash; */ | 
					
						
							|  |  |  | 	NULL,                       /* ternaryfunc tp_call; */ | 
					
						
							|  |  |  | 	NULL,                       /* reprfunc tp_str; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrofunc tp_getattro; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrofunc tp_setattro; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Functions to access object as input/output buffer */ | 
					
						
							|  |  |  | 	NULL,                       /* PyBufferProcs *tp_as_buffer; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Flags to define presence of optional/expanded features ***/ | 
					
						
							|  |  |  | 	Py_TPFLAGS_DEFAULT,         /* long tp_flags; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /*  char *tp_doc;  Documentation string */ | 
					
						
							|  |  |  |   /*** Assigned meaning in release 2.0 ***/ | 
					
						
							|  |  |  | 	/* call function for all accessible objects */ | 
					
						
							|  |  |  | 	NULL,                       /* traverseproc tp_traverse; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* delete references to contained objects */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_clear; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  Assigned meaning in release 2.1 ***/ | 
					
						
							|  |  |  |   /*** rich comparisons ***/ | 
					
						
							|  |  |  | 	NULL,                       /* richcmpfunc tp_richcompare; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  weak reference enabler ***/ | 
					
						
							|  |  |  | 	0,                          /* long tp_weaklistoffset; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Added in release 2.2 ***/ | 
					
						
							|  |  |  | 	/*   Iterators */ | 
					
						
							|  |  |  | 	NULL,                       /* getiterfunc tp_iter; */ | 
					
						
							|  |  |  | 	NULL,                       /* iternextfunc tp_iternext; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Attribute descriptor and subclassing stuff ***/ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyMethodDef *tp_methods; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyMemberDef *tp_members; */ | 
					
						
							|  |  |  | 	BPy_MCol_getseters,       /* struct PyGetSetDef *tp_getset; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct _typeobject *tp_base; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_dict; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrgetfunc tp_descr_get; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrsetfunc tp_descr_set; */ | 
					
						
							|  |  |  | 	0,                          /* long tp_dictoffset; */ | 
					
						
							|  |  |  | 	NULL,                       /* initproc tp_init; */ | 
					
						
							|  |  |  | 	NULL,                       /* allocfunc tp_alloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* newfunc tp_new; */ | 
					
						
							|  |  |  | 	/*  Low-level free-memory routine */ | 
					
						
							|  |  |  | 	NULL,                       /* freefunc tp_free;  */ | 
					
						
							|  |  |  | 	/* For PyObject_IS_GC */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_is_gc;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_bases; */ | 
					
						
							|  |  |  | 	/* method resolution order */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_mro;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_cache; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_subclasses; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_weaklist; */ | 
					
						
							|  |  |  | 	NULL | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MCol_CreatePyObject( MCol * color ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BPy_MCol *obj = PyObject_NEW( BPy_MCol, &MCol_Type ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !obj ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"PyObject_New() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	obj->color = color; | 
					
						
							|  |  |  | 	return (PyObject *)obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  |  * BPy_MVert attributes | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | static MVert * MVert_get_pointer( BPy_MVert * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if( BPy_MVert_Check( self ) ) { | 
					
						
							|  |  |  | 		if( self->index >= ((Mesh *)self->data)->totvert ) | 
					
						
							|  |  |  | 			return (MVert *)EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					"MVert is no longer valid" ); | 
					
						
							|  |  |  | 		return &((Mesh *)self->data)->mvert[self->index]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return (MVert *)self->data; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * get a vertex's coordinate | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MVert_getCoord( BPy_MVert * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	MVert *v; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	v = MVert_get_pointer( self ); | 
					
						
							|  |  |  | 	if( !v ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	return newVectorObject( v->co, 3, Py_WRAP ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * set a vertex's coordinate | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MVert_setCoord( BPy_MVert * self, VectorObject * value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	MVert *v; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	v = MVert_get_pointer( self ); | 
					
						
							|  |  |  | 	if( !v ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( !VectorObject_Check( value ) || value->size != 3 ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected vector argument of size 3" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for( i=0; i<3 ; ++i) | 
					
						
							|  |  |  | 		v->co[i] = value->vec[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * get a vertex's index | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MVert_getIndex( BPy_MVert * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	PyObject *attr; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( self->index >= ((Mesh *)self->data)->totvert ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"MVert is no longer valid" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	attr = PyInt_FromLong( self->index ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	if( attr ) | 
					
						
							|  |  |  | 		return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 			"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-11 20:35:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * get a verts's hidden state | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MVert_getMFlagBits( BPy_MVert * self, void * type ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	MVert *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	v = MVert_get_pointer( self ); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if( self->index >= ((Mesh *)self->data)->totvert ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"MVert is no longer valid" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_getBitfield( &v->flag, (int)((long)type & 0xff), 'b' ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * set a verts's hidden state | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MVert_setMFlagBits( BPy_MVert * self, PyObject * value, | 
					
						
							|  |  |  | 		void * type ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	MVert *v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	v = MVert_get_pointer( self ); | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-11 20:35:43 +00:00
										 |  |  | 	if( self->index >= ((Mesh *)self->data)->totvert ) | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 		return EXPP_ReturnIntError( PyExc_RuntimeError, | 
					
						
							| 
									
										
										
										
											2006-05-11 20:35:43 +00:00
										 |  |  | 				"MVert is no longer valid" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_setBitfield( value, &v->flag,  | 
					
						
							|  |  |  | 			(int)((long)type & 0xff), 'b' ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * get a vertex's normal | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MVert_getNormal( BPy_MVert * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float no[3]; | 
					
						
							|  |  |  | 	int i; | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	MVert *v; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	v = MVert_get_pointer( self ); | 
					
						
							|  |  |  | 	if( !v ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	for( i = 0; i < 3; ++i ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		no[i] = (float)(v->no[i] / 32767.0); | 
					
						
							|  |  |  | 	return newVectorObject( no, 3, Py_NEW ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-10 12:12:21 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * set a vertex's normal | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MVert_setNormal( BPy_MVert * self, VectorObject * value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	MVert *v; | 
					
						
							|  |  |  | 	float normal[3]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	v = MVert_get_pointer( self ); | 
					
						
							|  |  |  | 	if( !v ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !VectorObject_Check( value ) || value->size != 3 ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected vector argument of size 3" ); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for( i=0; i<3 ; ++i) | 
					
						
							|  |  |  | 		normal[i] = value->vec[i]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	Normalise(normal); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for( i=0; i<3 ; ++i) | 
					
						
							|  |  |  | 		v->no[i] = (short)(normal[i]*32767.0); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * get a vertex's select status | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MVert_getSel( BPy_MVert *self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	MVert *v; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	v = MVert_get_pointer( self ); | 
					
						
							|  |  |  | 	if( !v ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	return EXPP_getBitfield( &v->flag, SELECT, 'b' ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * set a vertex's select status | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MVert_setSel( BPy_MVert *self, PyObject *value ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 	MVert *v = MVert_get_pointer( self ); | 
					
						
							|  |  |  | 	Mesh *me = (Mesh *)self->data; | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 	/* 
 | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 	 * if vertex exists and setting status is OK, delete select storage | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 	 * of the edges and faces as well | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 	if( v && !EXPP_setBitfield( value, &v->flag, SELECT, 'b' ) ) { | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 		if( me && me->mselect ) { | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 			MEM_freeN( me->mselect ); | 
					
						
							|  |  |  | 			me->mselect = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return -1; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * get a vertex's UV coordinates | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MVert_getUVco( BPy_MVert *self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	Mesh *me = (Mesh *)self->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !me->msticky ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 				"mesh has no 'sticky' coordinates" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( self->index >= ((Mesh *)self->data)->totvert ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"MVert is no longer valid" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	return newVectorObject( me->msticky[self->index].co, 2, Py_WRAP ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * set a vertex's UV coordinates | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MVert_setUVco( BPy_MVert *self, PyObject *value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float uvco[3] = {0.0, 0.0}; | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	Mesh *me = (Mesh *)self->data; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	struct MSticky *v; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* 
 | 
					
						
							|  |  |  | 	 * at least for now, don't allow creation of sticky coordinates if they | 
					
						
							|  |  |  | 	 * don't already exist | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	if( !me->msticky ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		return EXPP_ReturnIntError( PyExc_AttributeError, | 
					
						
							|  |  |  | 				"mesh has no 'sticky' coordinates" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( self->index >= ((Mesh *)self->data)->totvert ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"MVert is no longer valid" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	if( VectorObject_Check( value ) ) { | 
					
						
							|  |  |  | 		VectorObject *vect = (VectorObject *)value; | 
					
						
							|  |  |  | 		if( vect->size != 2 ) | 
					
						
							|  |  |  | 			return EXPP_ReturnIntError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					"expected 2D vector" ); | 
					
						
							|  |  |  | 		for( i = 0; i < vect->size; ++i ) | 
					
						
							|  |  |  | 			uvco[i] = vect->vec[i]; | 
					
						
							|  |  |  | 	} else if( !PyArg_ParseTuple( value, "ff", | 
					
						
							|  |  |  | 				&uvco[0], &uvco[1] ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected 2D vector" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	v = &me->msticky[self->index]; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for( i = 0; i < 2; ++i ) | 
					
						
							|  |  |  | 		v->co[i] = uvco[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MVert_Type attributes get/set structure | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyGetSetDef BPy_MVert_getseters[] = { | 
					
						
							|  |  |  | 	{"co", | 
					
						
							|  |  |  | 	 (getter)MVert_getCoord, (setter)MVert_setCoord, | 
					
						
							|  |  |  | 	 "vertex's coordinate", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"index", | 
					
						
							|  |  |  | 	 (getter)MVert_getIndex, (setter)NULL, | 
					
						
							|  |  |  | 	 "vertex's index", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"no", | 
					
						
							| 
									
										
										
										
											2006-05-10 12:12:21 +00:00
										 |  |  | 	 (getter)MVert_getNormal, (setter)MVert_setNormal, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	 "vertex's normal", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"sel", | 
					
						
							|  |  |  | 	 (getter)MVert_getSel, (setter)MVert_setSel, | 
					
						
							|  |  |  | 	 "vertex's select status", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							| 
									
										
										
										
											2006-05-11 20:35:43 +00:00
										 |  |  |     {"hide", | 
					
						
							|  |  |  |      (getter)MVert_getMFlagBits, (setter)MVert_setMFlagBits, | 
					
						
							|  |  |  |      "vert hidden in edit mode", | 
					
						
							|  |  |  |      (void *)ME_HIDE}, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	{"uvco", | 
					
						
							|  |  |  | 	 (getter)MVert_getUVco, (setter)MVert_setUVco, | 
					
						
							|  |  |  | 	 "vertex's UV coordinates", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | static PyGetSetDef BPy_PVert_getseters[] = { | 
					
						
							|  |  |  | 	{"co", | 
					
						
							|  |  |  | 	 (getter)MVert_getCoord, (setter)MVert_setCoord, | 
					
						
							|  |  |  | 	 "vertex's coordinate", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"no", | 
					
						
							| 
									
										
										
										
											2006-05-10 12:12:21 +00:00
										 |  |  | 	 (getter)MVert_getNormal, (setter)MVert_setNormal, | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	 "vertex's normal", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"sel", | 
					
						
							|  |  |  | 	 (getter)MVert_getSel, (setter)MVert_setSel, | 
					
						
							|  |  |  | 	 "vertex's select status", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MVert_Type standard operations | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void MVert_dealloc( BPy_MVert * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	if( BPy_PVert_Check( self ) ) /* free memory of thick objects */ | 
					
						
							|  |  |  | 		MEM_freeN ( self->data ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	PyObject_DEL( self ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MVert_compare( BPy_MVert * a, BPy_MVert * b ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	return( a->data == b->data && a->index == b->index ) ? 0 : -1; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MVert_repr( BPy_MVert * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char format[512]; | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	char index[24]; | 
					
						
							|  |  |  | 	MVert *v; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	v = MVert_get_pointer( self ); | 
					
						
							|  |  |  | 	if( !v ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( BPy_MVert_Check( self ) ) | 
					
						
							|  |  |  | 		sprintf( index, "%d", self->index ); | 
					
						
							|  |  |  | 	else | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 		BLI_strncpy( index, "(None)", 24 ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	sprintf( format, "[MVert (%f %f %f) (%f %f %f) %s]", | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			v->co[0], v->co[1], v->co[2], (float)(v->no[0] / 32767.0), | 
					
						
							|  |  |  | 			(float)(v->no[1] / 32767.0), (float)(v->no[2] / 32767.0), | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 			index ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return PyString_FromString( format ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 21:12:33 +00:00
										 |  |  | static long MVert_hash( BPy_MVert *self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return (long)self->index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MVert_Type structure definition | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyTypeObject MVert_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT( NULL )  /* required py macro */ | 
					
						
							|  |  |  | 	0,                          /* ob_size */ | 
					
						
							|  |  |  | 	/*  For printing, in format "<module>.<name>" */ | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	"Blender MVert",            /* char *tp_name; */ | 
					
						
							|  |  |  | 	sizeof( BPy_MVert ),        /* int tp_basicsize; */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	0,                          /* tp_itemsize;  For allocation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Methods to implement standard operations */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	( destructor ) MVert_dealloc,/* destructor tp_dealloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* printfunc tp_print; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrfunc tp_getattr; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrfunc tp_setattr; */ | 
					
						
							|  |  |  | 	( cmpfunc ) MVert_compare,  /* cmpfunc tp_compare; */ | 
					
						
							|  |  |  | 	( reprfunc ) MVert_repr,    /* reprfunc tp_repr; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Method suites for standard classes */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /* PyNumberMethods *tp_as_number; */ | 
					
						
							|  |  |  | 	NULL,	        			/* PySequenceMethods *tp_as_sequence; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyMappingMethods *tp_as_mapping; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* More standard operations (here for binary compatibility) */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 21:12:33 +00:00
										 |  |  | 	( hashfunc ) MVert_hash,    /* hashfunc tp_hash; */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	NULL,                       /* ternaryfunc tp_call; */ | 
					
						
							|  |  |  | 	NULL,                       /* reprfunc tp_str; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrofunc tp_getattro; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrofunc tp_setattro; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Functions to access object as input/output buffer */ | 
					
						
							|  |  |  | 	NULL,                       /* PyBufferProcs *tp_as_buffer; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Flags to define presence of optional/expanded features ***/ | 
					
						
							|  |  |  | 	Py_TPFLAGS_DEFAULT,         /* long tp_flags; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /*  char *tp_doc;  Documentation string */ | 
					
						
							|  |  |  |   /*** Assigned meaning in release 2.0 ***/ | 
					
						
							|  |  |  | 	/* call function for all accessible objects */ | 
					
						
							|  |  |  | 	NULL,                       /* traverseproc tp_traverse; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* delete references to contained objects */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_clear; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  Assigned meaning in release 2.1 ***/ | 
					
						
							|  |  |  |   /*** rich comparisons ***/ | 
					
						
							|  |  |  | 	NULL,                       /* richcmpfunc tp_richcompare; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  weak reference enabler ***/ | 
					
						
							|  |  |  | 	0,                          /* long tp_weaklistoffset; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Added in release 2.2 ***/ | 
					
						
							|  |  |  | 	/*   Iterators */ | 
					
						
							|  |  |  | 	NULL,                       /* getiterfunc tp_iter; */ | 
					
						
							|  |  |  | 	NULL,                       /* iternextfunc tp_iternext; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Attribute descriptor and subclassing stuff ***/ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyMethodDef *tp_methods; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyMemberDef *tp_members; */ | 
					
						
							|  |  |  | 	BPy_MVert_getseters,        /* struct PyGetSetDef *tp_getset; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct _typeobject *tp_base; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_dict; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrgetfunc tp_descr_get; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrsetfunc tp_descr_set; */ | 
					
						
							|  |  |  | 	0,                          /* long tp_dictoffset; */ | 
					
						
							|  |  |  | 	NULL,                       /* initproc tp_init; */ | 
					
						
							|  |  |  | 	NULL,                       /* allocfunc tp_alloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* newfunc tp_new; */ | 
					
						
							|  |  |  | 	/*  Low-level free-memory routine */ | 
					
						
							|  |  |  | 	NULL,                       /* freefunc tp_free;  */ | 
					
						
							|  |  |  | 	/* For PyObject_IS_GC */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_is_gc;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_bases; */ | 
					
						
							|  |  |  | 	/* method resolution order */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_mro;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_cache; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_subclasses; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_weaklist; */ | 
					
						
							|  |  |  | 	NULL | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python PVert_Type standard operations | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int PVert_compare( BPy_MVert * a, BPy_MVert * b ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return( a->data == b->data ) ? 0 : -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python PVert_Type structure definition | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyTypeObject PVert_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT( NULL )  /* required py macro */ | 
					
						
							|  |  |  | 	0,                          /* ob_size */ | 
					
						
							|  |  |  | 	/*  For printing, in format "<module>.<name>" */ | 
					
						
							|  |  |  | 	"Blender PVert",            /* char *tp_name; */ | 
					
						
							|  |  |  | 	sizeof( BPy_MVert ),        /* int tp_basicsize; */ | 
					
						
							|  |  |  | 	0,                          /* tp_itemsize;  For allocation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Methods to implement standard operations */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	( destructor ) MVert_dealloc,/* destructor tp_dealloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* printfunc tp_print; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrfunc tp_getattr; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrfunc tp_setattr; */ | 
					
						
							|  |  |  | 	( cmpfunc ) PVert_compare,  /* cmpfunc tp_compare; */ | 
					
						
							|  |  |  | 	( reprfunc ) MVert_repr,    /* reprfunc tp_repr; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Method suites for standard classes */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /* PyNumberMethods *tp_as_number; */ | 
					
						
							|  |  |  | 	NULL,	        			/* PySequenceMethods *tp_as_sequence; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyMappingMethods *tp_as_mapping; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* More standard operations (here for binary compatibility) */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 21:12:33 +00:00
										 |  |  | 	( hashfunc ) MVert_hash,    /* hashfunc tp_hash; */ | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	NULL,                       /* ternaryfunc tp_call; */ | 
					
						
							|  |  |  | 	NULL,                       /* reprfunc tp_str; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrofunc tp_getattro; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrofunc tp_setattro; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Functions to access object as input/output buffer */ | 
					
						
							|  |  |  | 	NULL,                       /* PyBufferProcs *tp_as_buffer; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Flags to define presence of optional/expanded features ***/ | 
					
						
							|  |  |  | 	Py_TPFLAGS_DEFAULT,         /* long tp_flags; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /*  char *tp_doc;  Documentation string */ | 
					
						
							|  |  |  |   /*** Assigned meaning in release 2.0 ***/ | 
					
						
							|  |  |  | 	/* call function for all accessible objects */ | 
					
						
							|  |  |  | 	NULL,                       /* traverseproc tp_traverse; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* delete references to contained objects */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_clear; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  Assigned meaning in release 2.1 ***/ | 
					
						
							|  |  |  |   /*** rich comparisons ***/ | 
					
						
							|  |  |  | 	NULL,                       /* richcmpfunc tp_richcompare; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  weak reference enabler ***/ | 
					
						
							|  |  |  | 	0,                          /* long tp_weaklistoffset; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Added in release 2.2 ***/ | 
					
						
							|  |  |  | 	/*   Iterators */ | 
					
						
							|  |  |  | 	NULL,                       /* getiterfunc tp_iter; */ | 
					
						
							|  |  |  | 	NULL,                       /* iternextfunc tp_iternext; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Attribute descriptor and subclassing stuff ***/ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyMethodDef *tp_methods; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyMemberDef *tp_members; */ | 
					
						
							|  |  |  | 	BPy_PVert_getseters,        /* struct PyGetSetDef *tp_getset; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct _typeobject *tp_base; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_dict; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrgetfunc tp_descr_get; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrsetfunc tp_descr_set; */ | 
					
						
							|  |  |  | 	0,                          /* long tp_dictoffset; */ | 
					
						
							|  |  |  | 	NULL,                       /* initproc tp_init; */ | 
					
						
							|  |  |  | 	NULL,                       /* allocfunc tp_alloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* newfunc tp_new; */ | 
					
						
							|  |  |  | 	/*  Low-level free-memory routine */ | 
					
						
							|  |  |  | 	NULL,                       /* freefunc tp_free;  */ | 
					
						
							|  |  |  | 	/* For PyObject_IS_GC */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_is_gc;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_bases; */ | 
					
						
							|  |  |  | 	/* method resolution order */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_mro;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_cache; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_subclasses; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_weaklist; */ | 
					
						
							|  |  |  | 	NULL | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * create 'thin' or 'thick' MVert objects | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * there are two types of objects; thin (wrappers for mesh vertex) and thick | 
					
						
							|  |  |  |  * (not contains in mesh).  Thin objects are MVert_Type and thick are | 
					
						
							|  |  |  |  * PVert_Type.  For thin objects, data is a pointer to a Mesh and index | 
					
						
							|  |  |  |  * is the vertex's index in mesh->mvert.  For thick objects, data is a | 
					
						
							|  |  |  |  * pointer to an MVert; index is unused. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * create a thin MVert object | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MVert_CreatePyObject( Mesh *mesh, int i ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-11 13:36:07 +00:00
										 |  |  | 	BPy_MVert *obj = (BPy_MVert *)PyObject_NEW( BPy_MVert, &MVert_Type ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( !obj ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"PyObject_New() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	obj->index = i; | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	obj->data = mesh; | 
					
						
							|  |  |  | 	return (PyObject *)obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * create a thick MVert object | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *PVert_CreatePyObject( MVert *vert ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-11 13:36:07 +00:00
										 |  |  | 	MVert *newvert; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	BPy_MVert *obj = (BPy_MVert *)PyObject_NEW( BPy_MVert, &PVert_Type ); | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( !obj ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"PyObject_New() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 13:36:07 +00:00
										 |  |  | 	newvert = (MVert *)MEM_callocN( sizeof( MVert ), "MVert" ); | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	if( !newvert ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"MEM_callocN() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memcpy( newvert, vert, sizeof( MVert ) ); | 
					
						
							|  |  |  | 	obj->data = newvert; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	return (PyObject *)obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Vertex sequence  | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MVertSeq_len( BPy_MVertSeq * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return self->mesh->totvert; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * retrive a single MVert from somewhere in the vertex list | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | static PyObject *MVertSeq_item( BPy_MVertSeq * self, int i ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if( i < 0 || i >= self->mesh->totvert ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_IndexError, | 
					
						
							|  |  |  | 					      "array index out of range" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return MVert_CreatePyObject( self->mesh, i ); | 
					
						
							| 
									
										
										
										
											2006-01-16 17:55:03 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * retrieve a slice of the vertex list (as a Python list) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python is nice enough to handle negative indices for us: if the user | 
					
						
							|  |  |  |  * specifies -1, Python will pass us len()-1.  So we can just check for | 
					
						
							|  |  |  |  * indices in the range 0:len()-1.  Of course, we should never actually | 
					
						
							|  |  |  |  * return the high index, but up to one less. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MVertSeq_slice( BPy_MVertSeq *self, int low, int high ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *list; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Python list slice operator returns empty list when asked for a slice | 
					
						
							|  |  |  | 	 * outside the list, or if indices are reversed (low > high).  Clamp | 
					
						
							|  |  |  | 	 * our input to do the same. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( low < 0 ) low = 0; | 
					
						
							|  |  |  | 	if( high > self->mesh->totvert ) high = self->mesh->totvert; | 
					
						
							|  |  |  | 	if( low > high ) low = high; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list = PyList_New( high-low ); | 
					
						
							|  |  |  | 	if( !list ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					      "PyList_New() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * return Py_NEW copies of requested vertices | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for( i = low; i < high; ++i ) | 
					
						
							|  |  |  | 		PyList_SET_ITEM( list, i-low, | 
					
						
							|  |  |  | 				PVert_CreatePyObject( (void *)&self->mesh->mvert[i] ) ); | 
					
						
							|  |  |  | 	return list; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * assign a single MVert to somewhere in the vertex list | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MVertSeq_assign_item( BPy_MVertSeq * self, int i, | 
					
						
							|  |  |  | 		BPy_MVert *v ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	MVert *dst = &self->mesh->mvert[i]; | 
					
						
							|  |  |  | 	MVert *src; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !v ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_IndexError, | 
					
						
							|  |  |  | 					      "del() not supported" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( i < 0 || i >= self->mesh->totvert ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_IndexError, | 
					
						
							|  |  |  | 					      "array index out of range" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( BPy_MVert_Check( v ) ) | 
					
						
							|  |  |  | 		src = &((Mesh *)v->data)->mvert[v->index]; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		src = (MVert *)v->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memcpy( dst, src, sizeof(MVert) ); | 
					
						
							| 
									
										
										
										
											2006-05-10 01:38:02 +00:00
										 |  |  | 	/* mesh_update( self->mesh );*/ | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2006-01-16 17:55:03 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int MVertSeq_assign_slice( BPy_MVertSeq *self, int low, int high, | 
					
						
							|  |  |  | 		   PyObject *args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int len, i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyList_Check( args ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_IndexError, | 
					
						
							|  |  |  | 					      "can only assign lists of MVerts" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	len = PyList_Size( args ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Python list slice assign operator allows for changing the size of the | 
					
						
							|  |  |  | 	 * destination list, by replacement and appending.... | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * >>> l=[1,2,3,4] | 
					
						
							|  |  |  | 	 * >>> m=[11,12,13,14] | 
					
						
							|  |  |  | 	 * >>> l[5:7]=m | 
					
						
							|  |  |  | 	 * >>> print l | 
					
						
							|  |  |  | 	 * [1, 2, 3, 4, 11, 12, 13, 14] | 
					
						
							|  |  |  | 	 * >>> l=[1,2,3,4] | 
					
						
							|  |  |  | 	 * >>> l[2:3]=m | 
					
						
							|  |  |  | 	 * >>> print l | 
					
						
							|  |  |  | 	 * [1, 2, 11, 12, 13, 14, 4] | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * We don't want the size of the list to change (at least not at time | 
					
						
							|  |  |  | 	 * point in development) so we are a little more strict: | 
					
						
							|  |  |  | 	 * - low and high indices must be in range [0:len()] | 
					
						
							|  |  |  | 	 * - high-low == PyList_Size(v) | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( low < 0 || high > self->mesh->totvert || low > high ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_IndexError, | 
					
						
							|  |  |  | 					      "invalid slice range" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( high-low != len ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_IndexError, | 
					
						
							|  |  |  | 					      "slice range and input list sizes must be equal" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for( i = low; i < high; ++i ) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		BPy_MVert *v = (BPy_MVert *)PyList_GET_ITEM( args, i-low ); | 
					
						
							|  |  |  | 		MVert *dst = &self->mesh->mvert[i]; | 
					
						
							|  |  |  | 		MVert *src; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if( BPy_MVert_Check( v ) ) | 
					
						
							|  |  |  | 			src = &((Mesh *)v->data)->mvert[v->index]; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			src = (MVert *)v->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		memcpy( dst, src, sizeof(MVert) ); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-05-10 01:38:02 +00:00
										 |  |  | 	/* mesh_update( self->mesh );*/ | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | static PySequenceMethods MVertSeq_as_sequence = { | 
					
						
							|  |  |  | 	( inquiry ) MVertSeq_len,	/* sq_length */ | 
					
						
							|  |  |  | 	( binaryfunc ) 0,	/* sq_concat */ | 
					
						
							|  |  |  | 	( intargfunc ) 0,	/* sq_repeat */ | 
					
						
							|  |  |  | 	( intargfunc ) MVertSeq_item,	/* sq_item */ | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	( intintargfunc ) MVertSeq_slice,	/* sq_slice */ | 
					
						
							|  |  |  | 	( intobjargproc ) MVertSeq_assign_item,	/* sq_ass_item */ | 
					
						
							|  |  |  | 	( intintobjargproc ) MVertSeq_assign_slice,	/* sq_ass_slice */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	0,0,0, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MVertSeq_Type iterator (iterates over vertices) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Initialize the interator index | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MVertSeq_getIter( BPy_MVertSeq * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	if (self->iter==-1) { /* iteration for this pyobject is not yet used, just return self */ | 
					
						
							|  |  |  | 		self->iter = 0; | 
					
						
							|  |  |  | 		return EXPP_incr_ret ( (PyObject *) self ); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		/* were alredy using this as an iterator, make a copy to loop on */ | 
					
						
							|  |  |  | 		BPy_MVertSeq *seq = (BPy_MVertSeq *)MVertSeq_CreatePyObject(self->mesh); | 
					
						
							|  |  |  | 		seq->iter = 0; | 
					
						
							|  |  |  | 		return (PyObject *)seq; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Return next MVert. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MVertSeq_nextIter( BPy_MVertSeq * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	if( self->iter == self->mesh->totvert ) { | 
					
						
							|  |  |  | 		self->iter= -1; /* allow it to be used as an iterator again without creating a new BPy_MVertSeq */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		return EXPP_ReturnPyObjError( PyExc_StopIteration, | 
					
						
							|  |  |  | 				"iterator at end" ); | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return MVert_CreatePyObject( self->mesh, self->iter++ ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MVertSeq_Type methods | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MVertSeq_extend( BPy_MVertSeq * self, PyObject *args ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	int len, newlen; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	int i,j; | 
					
						
							|  |  |  | 	PyObject *tmp; | 
					
						
							|  |  |  | 	MVert *newvert, *tmpvert; | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 	/* make sure we get a sequence of tuples of something */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 	switch( PySequence_Size( args ) ) { | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	case 1:		/* better be a list or a tuple */ | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 		tmp = PyTuple_GET_ITEM( args, 0 ); | 
					
						
							|  |  |  | 		if( !VectorObject_Check ( tmp ) ) { | 
					
						
							|  |  |  | 			if( !PySequence_Check ( tmp ) ) | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 						"expected a sequence of sequence triplets" ); | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 			else if( !PySequence_Size ( tmp ) ) { | 
					
						
							|  |  |  | 				Py_RETURN_NONE; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 			args = tmp; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		Py_INCREF( args );		/* so we can safely DECREF later */ | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2006-01-21 06:21:03 +00:00
										 |  |  | 	case 3: | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		tmp = PyTuple_GET_ITEM( args, 0 ); | 
					
						
							| 
									
										
										
										
											2006-01-21 06:21:03 +00:00
										 |  |  | 		/* if first item is not a number, it's wrong */ | 
					
						
							|  |  |  | 		if( !PyNumber_Check( tmp ) ) | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 			return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					"expected a sequence of sequence triplets" ); | 
					
						
							| 
									
										
										
										
											2006-01-21 06:21:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* otherwise, put into a new tuple */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		args = Py_BuildValue( "((OOO))", tmp, | 
					
						
							|  |  |  | 				PyTuple_GET_ITEM( args, 1 ), PyTuple_GET_ITEM( args, 2 ) ); | 
					
						
							|  |  |  | 		if( !args ) | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					"Py_BuildValue() failed" ); | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2006-01-21 06:21:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	default:	/* anything else is definitely wrong */ | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 				"expected a sequence of sequence triplets" ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 	/* if no verts given, return quietly */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	len = PySequence_Size( args ); | 
					
						
							|  |  |  | 	if( len == 0 ) { | 
					
						
							|  |  |  | 		Py_DECREF ( args ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 		Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	newlen = mesh->totvert + len; | 
					
						
							|  |  |  | 	newvert = MEM_callocN( sizeof( MVert )*newlen, "MVerts" ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* scan the input list and insert the new vertices */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmpvert = &newvert[mesh->totvert]; | 
					
						
							|  |  |  | 	for( i = 0; i < len; ++i ) { | 
					
						
							|  |  |  | 		float co[3]; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		tmp = PySequence_GetItem( args, i ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		if( VectorObject_Check( tmp ) ) { | 
					
						
							|  |  |  | 			if( ((VectorObject *)tmp)->size != 3 ) { | 
					
						
							|  |  |  | 				MEM_freeN( newvert ); | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 				Py_DECREF ( tmp ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 				Py_DECREF ( args ); | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 					"expected vector of size 3" ); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			for( j = 0; j < 3; ++j ) | 
					
						
							|  |  |  | 				co[j] = ((VectorObject *)tmp)->vec[j]; | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 		} else if( PySequence_Check( tmp ) ) { | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			int ok=1; | 
					
						
							|  |  |  | 			PyObject *flt; | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 			if( PySequence_Size( tmp ) != 3 ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 				ok = 0; | 
					
						
							|  |  |  | 			else	 | 
					
						
							|  |  |  | 				for( j = 0; ok && j < 3; ++j ) { | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 					flt = PySequence_ITEM( tmp, j ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 					if( !PyNumber_Check ( flt ) ) | 
					
						
							|  |  |  | 						ok = 0; | 
					
						
							|  |  |  | 					else | 
					
						
							| 
									
										
										
										
											2005-10-03 20:48:43 +00:00
										 |  |  | 						co[j] = (float)PyFloat_AsDouble( flt ); | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 					Py_DECREF( flt ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if( !ok ) { | 
					
						
							|  |  |  | 				MEM_freeN( newvert ); | 
					
						
							|  |  |  | 				Py_DECREF ( args ); | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 				Py_DECREF ( tmp ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 				return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 					"expected sequence triplet of floats" ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			MEM_freeN( newvert ); | 
					
						
							|  |  |  | 			Py_DECREF ( args ); | 
					
						
							|  |  |  | 			Py_DECREF ( tmp ); | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"expected sequence triplet of floats" ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		Py_DECREF ( tmp ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* add the coordinate to the new list */ | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 		memcpy( tmpvert->co, co, sizeof(co) ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO: anything else which needs to be done when we add a vert? */ | 
					
						
							|  |  |  | 	/* probably not: NMesh's newvert() doesn't */ | 
					
						
							|  |  |  | 		++tmpvert; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * if we got here we've added all the new verts, so just copy the old | 
					
						
							|  |  |  | 	 * verts over and we're done | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( mesh->mvert ) { | 
					
						
							|  |  |  | 		memcpy( newvert, mesh->mvert, mesh->totvert*sizeof(MVert) ); | 
					
						
							|  |  |  | 		MEM_freeN( mesh->mvert ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	mesh->mvert = newvert; | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 	 * if there are UV vertives, have to fix those | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( mesh->msticky ) { | 
					
						
							|  |  |  | 		MSticky *tmpsticky; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tmpsticky = MEM_mallocN( newlen*sizeof( MSticky ), "sticky" ); | 
					
						
							|  |  |  | 		memset( tmpsticky +mesh->totvert, 255, | 
					
						
							|  |  |  | 				(newlen-mesh->totvert)*sizeof( MSticky ) ); | 
					
						
							|  |  |  | 		memcpy( tmpsticky, mesh->msticky, mesh->totvert*sizeof( MSticky ) ); | 
					
						
							|  |  |  | 		MEM_freeN( mesh->msticky ); | 
					
						
							|  |  |  | 		mesh->msticky = tmpsticky; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * if there are keys, have to fix those lists up | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( mesh->key ) { | 
					
						
							|  |  |  | 		KeyBlock *currkey = mesh->key->block.first; | 
					
						
							|  |  |  | 		float *fp, *newkey; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		while( currkey ) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* create key list, copy existing data if any */ | 
					
						
							|  |  |  | 			newkey = MEM_callocN(mesh->key->elemsize*newlen, "keydata"); | 
					
						
							|  |  |  | 			if( currkey->data ) { | 
					
						
							|  |  |  | 				memcpy( newkey, currkey->data, | 
					
						
							|  |  |  | 						mesh->totvert*mesh->key->elemsize ); | 
					
						
							|  |  |  | 				MEM_freeN( currkey->data ); | 
					
						
							|  |  |  | 				currkey->data = newkey; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* add data for new vertices */ | 
					
						
							| 
									
										
										
										
											2005-10-11 13:36:07 +00:00
										 |  |  | 			fp = (float *)((char *)currkey->data + | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 					(mesh->key->elemsize*mesh->totvert)); | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 			tmpvert = mesh->mvert + mesh->totvert; | 
					
						
							|  |  |  | 			for( i = newlen - mesh->totvert; i > 0; --i ) { | 
					
						
							|  |  |  | 				VECCOPY(fp, tmpvert->co); | 
					
						
							|  |  |  | 				fp += 3; | 
					
						
							|  |  |  | 				tmpvert++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			currkey->totelem = newlen; | 
					
						
							|  |  |  | 			currkey = currkey->next; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-13 15:36:32 +00:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * if there are vertex groups, also have to fix them | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( mesh->dvert ) { | 
					
						
							|  |  |  | 		MDeformVert *newdvert; | 
					
						
							|  |  |  | 		newdvert = MEM_callocN( sizeof(MDeformVert)*newlen , "mesh defVert" ); | 
					
						
							|  |  |  | 		memcpy( newdvert, mesh->dvert, sizeof(MDeformVert)*mesh->totvert ); | 
					
						
							|  |  |  | 		MEM_freeN( mesh->dvert ); | 
					
						
							|  |  |  | 		mesh->dvert = newdvert; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	/* set final vertex list size */ | 
					
						
							|  |  |  | 	mesh->totvert = newlen; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mesh_update( mesh ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Py_DECREF ( args ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 	Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | static PyObject *MVertSeq_delete( BPy_MVertSeq * self, PyObject *args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int *vert_table; | 
					
						
							|  |  |  | 	int vert_delete, face_count; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 	MFace *tmpface; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * if input tuple contains a single sequence, use it as input instead; | 
					
						
							|  |  |  | 	 * otherwise use the sequence as-is and check later that it contains | 
					
						
							|  |  |  | 	 * one or more integers or MVerts | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	if( PySequence_Size( args ) == 1 ) { | 
					
						
							|  |  |  | 		PyObject *tmp = PyTuple_GET_ITEM( args, 0 ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 		if( PySequence_Check( tmp ) )  | 
					
						
							|  |  |  | 			args = tmp; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if sequence is empty, do nothing */ | 
					
						
							|  |  |  | 	if( PySequence_Size( args ) == 0 ) { | 
					
						
							|  |  |  | 		Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* allocate vertex lookup table */ | 
					
						
							|  |  |  | 	vert_table = (unsigned int *)MEM_callocN(  | 
					
						
							|  |  |  | 			mesh->totvert*sizeof( unsigned int ), "vert_table" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* get the indices of vertices to be removed */ | 
					
						
							|  |  |  | 	for( i = PySequence_Size( args ); i--; ) { | 
					
						
							|  |  |  | 		PyObject *tmp = PySequence_GetItem( args, i ); | 
					
						
							|  |  |  | 		int index; | 
					
						
							|  |  |  | 		if( BPy_MVert_Check( tmp ) ) { | 
					
						
							|  |  |  | 			if( (void *)self->mesh != ((BPy_MVert*)tmp)->data ) { | 
					
						
							|  |  |  | 				MEM_freeN( vert_table ); | 
					
						
							|  |  |  | 				Py_DECREF( tmp ); | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 						"MVert belongs to a different mesh" ); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			index = ((BPy_MVert*)tmp)->index; | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 		} else if( PyInt_CheckExact( tmp ) ) { | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 			index = PyInt_AsLong ( tmp ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 			MEM_freeN( vert_table ); | 
					
						
							|  |  |  | 			Py_DECREF( tmp ); | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					"expected a sequence of ints or MVerts" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		Py_DECREF( tmp ); | 
					
						
							|  |  |  | 		if( index < 0 || index >= mesh->totvert ) { | 
					
						
							|  |  |  | 			MEM_freeN( vert_table ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 			return EXPP_ReturnPyObjError( PyExc_IndexError, | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 					"array index out of range" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		vert_table[index] = UINT_MAX; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* delete things, then clean up and return */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vert_delete = make_vertex_table( vert_table, mesh->totvert ); | 
					
						
							|  |  |  | 	if( vert_delete ) | 
					
						
							|  |  |  | 		delete_verts( mesh, vert_table, vert_delete ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* calculate edges to delete, fix vertex indices */ | 
					
						
							|  |  |  | 	delete_edges( mesh, vert_table, 0 ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * find number of faces which contain any of the deleted vertices, | 
					
						
							|  |  |  | 	 * and mark them, then delete them | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	tmpface = mesh->mface; | 
					
						
							|  |  |  | 	face_count=0; | 
					
						
							|  |  |  | 	for( i = mesh->totface; i--; ++tmpface ) { | 
					
						
							|  |  |  | 		if( vert_table[tmpface->v1] == UINT_MAX || | 
					
						
							|  |  |  | 				vert_table[tmpface->v2] == UINT_MAX || | 
					
						
							|  |  |  | 				vert_table[tmpface->v3] == UINT_MAX || | 
					
						
							| 
									
										
										
										
											2006-06-17 14:08:15 +00:00
										 |  |  | 				( tmpface->v4 && vert_table[tmpface->v4] == UINT_MAX ) ) { | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 			tmpface->v1 = UINT_MAX; | 
					
						
							|  |  |  | 			++face_count; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	delete_faces( mesh, vert_table, face_count ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* clean up and exit */ | 
					
						
							|  |  |  | 	MEM_freeN( vert_table ); | 
					
						
							|  |  |  | 	mesh_update ( mesh ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 	Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | static PyObject *MVertSeq_selected( BPy_MVertSeq * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i, count; | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 	MVert *tmpvert; | 
					
						
							|  |  |  | 	PyObject *list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* first count selected edges (quicker than appending to PyList?) */ | 
					
						
							|  |  |  | 	count = 0; | 
					
						
							|  |  |  | 	tmpvert = mesh->mvert; | 
					
						
							|  |  |  | 	for( i = 0; i < mesh->totvert; ++i, ++tmpvert ) | 
					
						
							|  |  |  | 		if( tmpvert->flag & SELECT ) | 
					
						
							|  |  |  | 			++count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list = PyList_New( count ); | 
					
						
							|  |  |  | 	if( !list ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"PyList_New() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* next, insert selected edges into list */ | 
					
						
							|  |  |  | 	count = 0; | 
					
						
							|  |  |  | 	tmpvert = mesh->mvert; | 
					
						
							|  |  |  | 	for( i = 0; i < mesh->totvert; ++i, ++tmpvert ) { | 
					
						
							|  |  |  | 		if( tmpvert->flag & SELECT ) { | 
					
						
							|  |  |  | 			PyObject *tmp = PyInt_FromLong( i ); | 
					
						
							|  |  |  | 			if( !tmp ) { | 
					
						
							|  |  |  | 				Py_DECREF( list ); | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 						"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			PyList_SET_ITEM( list, count, tmp ); | 
					
						
							|  |  |  | 			++count; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return list; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | static struct PyMethodDef BPy_MVertSeq_methods[] = { | 
					
						
							|  |  |  | 	{"extend", (PyCFunction)MVertSeq_extend, METH_VARARGS, | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 		"add vertices to mesh"}, | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	{"delete", (PyCFunction)MVertSeq_delete, METH_VARARGS, | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		"delete vertices from mesh"}, | 
					
						
							|  |  |  | 	{"selected", (PyCFunction)MVertSeq_selected, METH_NOARGS, | 
					
						
							|  |  |  | 		"returns a list containing indices of selected vertices"}, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	{NULL, NULL, 0, NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MVertSeq_Type standard operations | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void MVertSeq_dealloc( BPy_MVertSeq * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject_DEL( self ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*****************************************************************************/ | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | /* Python MVertSeq_Type structure definition:                               */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /*****************************************************************************/ | 
					
						
							|  |  |  | PyTypeObject MVertSeq_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT( NULL )  /* required py macro */ | 
					
						
							|  |  |  | 	0,                          /* ob_size */ | 
					
						
							|  |  |  | 	/*  For printing, in format "<module>.<name>" */ | 
					
						
							|  |  |  | 	"Blender MVertSeq",           /* char *tp_name; */ | 
					
						
							|  |  |  | 	sizeof( BPy_MVertSeq ),       /* int tp_basicsize; */ | 
					
						
							|  |  |  | 	0,                          /* tp_itemsize;  For allocation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Methods to implement standard operations */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	( destructor ) MVertSeq_dealloc,/* destructor tp_dealloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* printfunc tp_print; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrfunc tp_getattr; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrfunc tp_setattr; */ | 
					
						
							|  |  |  | 	NULL,                       /* cmpfunc tp_compare; */ | 
					
						
							|  |  |  | 	NULL,                       /* reprfunc tp_repr; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Method suites for standard classes */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /* PyNumberMethods *tp_as_number; */ | 
					
						
							|  |  |  | 	&MVertSeq_as_sequence,	    /* PySequenceMethods *tp_as_sequence; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyMappingMethods *tp_as_mapping; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* More standard operations (here for binary compatibility) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /* hashfunc tp_hash; */ | 
					
						
							|  |  |  | 	NULL,                       /* ternaryfunc tp_call; */ | 
					
						
							|  |  |  | 	NULL,                       /* reprfunc tp_str; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrofunc tp_getattro; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrofunc tp_setattro; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Functions to access object as input/output buffer */ | 
					
						
							|  |  |  | 	NULL,                       /* PyBufferProcs *tp_as_buffer; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Flags to define presence of optional/expanded features ***/ | 
					
						
							|  |  |  | 	Py_TPFLAGS_DEFAULT,         /* long tp_flags; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /*  char *tp_doc;  Documentation string */ | 
					
						
							|  |  |  |   /*** Assigned meaning in release 2.0 ***/ | 
					
						
							|  |  |  | 	/* call function for all accessible objects */ | 
					
						
							|  |  |  | 	NULL,                       /* traverseproc tp_traverse; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* delete references to contained objects */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_clear; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  Assigned meaning in release 2.1 ***/ | 
					
						
							|  |  |  |   /*** rich comparisons ***/ | 
					
						
							|  |  |  | 	NULL,                       /* richcmpfunc tp_richcompare; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  weak reference enabler ***/ | 
					
						
							|  |  |  | 	0,                          /* long tp_weaklistoffset; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Added in release 2.2 ***/ | 
					
						
							|  |  |  | 	/*   Iterators */ | 
					
						
							|  |  |  | 	( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */ | 
					
						
							|  |  |  | 	( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Attribute descriptor and subclassing stuff ***/ | 
					
						
							|  |  |  | 	BPy_MVertSeq_methods,       /* struct PyMethodDef *tp_methods; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyMemberDef *tp_members; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyGetSetDef *tp_getset; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct _typeobject *tp_base; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_dict; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrgetfunc tp_descr_get; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrsetfunc tp_descr_set; */ | 
					
						
							|  |  |  | 	0,                          /* long tp_dictoffset; */ | 
					
						
							|  |  |  | 	NULL,                       /* initproc tp_init; */ | 
					
						
							|  |  |  | 	NULL,                       /* allocfunc tp_alloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* newfunc tp_new; */ | 
					
						
							|  |  |  | 	/*  Low-level free-memory routine */ | 
					
						
							|  |  |  | 	NULL,                       /* freefunc tp_free;  */ | 
					
						
							|  |  |  | 	/* For PyObject_IS_GC */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_is_gc;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_bases; */ | 
					
						
							|  |  |  | 	/* method resolution order */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_mro;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_cache; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_subclasses; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_weaklist; */ | 
					
						
							|  |  |  | 	NULL | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Edge attributes | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | static MEdge * MEdge_get_pointer( BPy_MEdge * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if( self->index >= self->mesh->totedge ) | 
					
						
							|  |  |  | 		return (MEdge *)EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"MEdge is no longer valid" ); | 
					
						
							|  |  |  | 	return &self->mesh->medge[self->index]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * get an edge's crease value | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MEdge_getCrease( BPy_MEdge * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	PyObject *attr; | 
					
						
							|  |  |  | 	MEdge *edge = MEdge_get_pointer( self ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( !edge ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	attr = PyInt_FromLong( edge->crease ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	if( attr ) | 
					
						
							|  |  |  | 		return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 			"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * set an edge's crease value | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MEdge_setCrease( BPy_MEdge * self, PyObject * value ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	MEdge *edge = MEdge_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !edge ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	return EXPP_setIValueClamped( value, &edge->crease, 0, 255, 'b' ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * get an edge's flag | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MEdge_getFlag( BPy_MEdge * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	PyObject *attr; | 
					
						
							|  |  |  | 	MEdge *edge = MEdge_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !edge ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	attr = PyInt_FromLong( edge->flag ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( attr ) | 
					
						
							|  |  |  | 		return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 			"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * set an edge's flag | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MEdge_setFlag( BPy_MEdge * self, PyObject * value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	short param; | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 	static short bitmask = SELECT | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 				| ME_EDGEDRAW | 
					
						
							|  |  |  | 				| ME_SEAM | 
					
						
							| 
									
										
										
										
											2006-06-26 04:14:12 +00:00
										 |  |  | 				| ME_FGON | 
					
						
							|  |  |  | 				| ME_HIDE | 
					
						
							|  |  |  | 				| ME_EDGERENDER | 
					
						
							|  |  |  | 				| ME_LOOSEEDGE | 
					
						
							| 
									
										
										
										
											2006-08-29 10:04:10 +00:00
										 |  |  | 				| ME_SEAM_LAST | 
					
						
							|  |  |  | 				| ME_SHARP; | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	MEdge *edge = MEdge_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !edge ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyInt_CheckExact ( value ) ) { | 
					
						
							|  |  |  | 		char errstr[128]; | 
					
						
							|  |  |  | 		sprintf ( errstr , "expected int bitmask of 0x%04x", bitmask ); | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, errstr ); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-03 20:48:43 +00:00
										 |  |  | 	param = (short)PyInt_AS_LONG ( value ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if ( ( param & bitmask ) != param ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 						"invalid bit(s) set in mask" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	edge->flag = param; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * get an edge's first vertex | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MEdge_getV1( BPy_MEdge * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	MEdge *edge = MEdge_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !edge ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	return MVert_CreatePyObject( self->mesh, edge->v1 ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * set an edge's first vertex | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MEdge_setV1( BPy_MEdge * self, BPy_MVert * value ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	MEdge *edge = MEdge_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !edge ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	if( !BPy_MVert_Check( value ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, "expected an MVert" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	edge->v1 = value->index; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * get an edge's second vertex | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MEdge_getV2( BPy_MEdge * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	MEdge *edge = MEdge_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !edge ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	return MVert_CreatePyObject( self->mesh, edge->v2 ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * set an edge's second vertex | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MEdge_setV2( BPy_MEdge * self, BPy_MVert * value ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	MEdge *edge = MEdge_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !edge ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	if( !BPy_MVert_Check( value ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, "expected an MVert" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	edge->v2 = value->index; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  |  * get an edge's index | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MEdge_getIndex( BPy_MEdge * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	PyObject *attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !MEdge_get_pointer( self ) ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	attr = PyInt_FromLong( self->index ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( attr ) | 
					
						
							|  |  |  | 		return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 			"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * get an edge's select state | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MEdge_getMFlagBits( BPy_MEdge * self, void * type ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	MEdge *edge = MEdge_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !edge ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_getBitfield( &edge->flag, (int)((long)type & 0xff), 'b' ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-11 10:06:15 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * get an edge's select state | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | static PyObject *MEdge_getLength( BPy_MEdge * self ) | 
					
						
							| 
									
										
										
										
											2006-05-11 10:06:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	MEdge *edge = MEdge_get_pointer( self ); | 
					
						
							|  |  |  | 	double dot = 0.0f; | 
					
						
							|  |  |  | 	float tmpf; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	float *v1, *v2; | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-11 10:06:15 +00:00
										 |  |  | 	/* get the 2 edges vert locations */ | 
					
						
							|  |  |  | 	v1= (&((Mesh *)self->mesh)->mvert[edge->v1])->co; | 
					
						
							|  |  |  | 	v2= (&((Mesh *)self->mesh)->mvert[edge->v2])->co; | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-11 10:06:15 +00:00
										 |  |  | 	if( !edge ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for( i = 0; i < 3; i++ ) { | 
					
						
							|  |  |  | 		tmpf = v1[i] - v2[i]; | 
					
						
							| 
									
										
										
										
											2006-05-11 10:06:15 +00:00
										 |  |  | 		dot += tmpf*tmpf; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 	return PyFloat_FromDouble( sqrt( dot ) ); | 
					
						
							| 
									
										
										
										
											2006-05-11 10:06:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * set an edge's select state | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MEdge_setSel( BPy_MEdge * self,PyObject * value, | 
					
						
							| 
									
										
										
										
											2006-05-08 05:37:00 +00:00
										 |  |  | 		void * type_unused ) | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	MEdge *edge = MEdge_get_pointer( self ); | 
					
						
							|  |  |  | 	int param = PyObject_IsTrue( value ); | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 	Mesh *me; | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( !edge ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( param == -1 ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected true/false argument" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 	me = self->mesh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( param ) { | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 		edge->flag |= SELECT; | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 		me->mvert[edge->v1].flag |= SELECT; | 
					
						
							|  |  |  | 		me->mvert[edge->v2].flag |= SELECT; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 		edge->flag &= ~SELECT; | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 		me->mvert[edge->v1].flag &= ~SELECT; | 
					
						
							|  |  |  | 		me->mvert[edge->v2].flag &= ~SELECT; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( self->mesh->mselect ) { | 
					
						
							|  |  |  | 		MEM_freeN( self->mesh->mselect ); | 
					
						
							|  |  |  | 		self->mesh->mselect = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MEdge_Type attributes get/set structure | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyGetSetDef BPy_MEdge_getseters[] = { | 
					
						
							|  |  |  | 	{"crease", | 
					
						
							|  |  |  | 	 (getter)MEdge_getCrease, (setter)MEdge_setCrease, | 
					
						
							|  |  |  | 	 "edge's crease value", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"flag", | 
					
						
							|  |  |  | 	 (getter)MEdge_getFlag, (setter)MEdge_setFlag, | 
					
						
							|  |  |  | 	 "edge's flags", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"v1", | 
					
						
							|  |  |  | 	 (getter)MEdge_getV1, (setter)MEdge_setV1, | 
					
						
							|  |  |  | 	 "edge's first vertex", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"v2", | 
					
						
							|  |  |  | 	 (getter)MEdge_getV2, (setter)MEdge_setV2, | 
					
						
							|  |  |  | 	 "edge's second vertex", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"index", | 
					
						
							|  |  |  | 	 (getter)MEdge_getIndex, (setter)NULL, | 
					
						
							|  |  |  | 	 "edge's index", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 	{"sel", | 
					
						
							|  |  |  | 	 (getter)MEdge_getMFlagBits, (setter)MEdge_setSel, | 
					
						
							|  |  |  |      "edge selected in edit mode", | 
					
						
							|  |  |  |      (void *)SELECT}, | 
					
						
							| 
									
										
										
										
											2006-05-11 10:06:15 +00:00
										 |  |  | 	{"length", | 
					
						
							|  |  |  | 	 (getter)MEdge_getLength, (setter)NULL, | 
					
						
							|  |  |  |      "edge's length, read only", | 
					
						
							|  |  |  |      NULL}, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MEdge_Type iterator (iterates over vertices) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Initialize the interator index | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MEdge_getIter( BPy_MEdge * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	if (self->iter==-1) { /* not alredy used to iterator on, just use self */ | 
					
						
							|  |  |  | 		self->iter = 0; | 
					
						
							|  |  |  | 		return EXPP_incr_ret ( (PyObject *) self ); | 
					
						
							|  |  |  | 	} else { /* alredy being iterated on, return a copy */ | 
					
						
							|  |  |  | 		BPy_MEdge *seq = (BPy_MEdge *)MEdge_CreatePyObject(self->mesh, self->index); | 
					
						
							|  |  |  | 		seq->iter = 0; | 
					
						
							|  |  |  | 		return (PyObject *)seq; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Return next MVert.  Throw an exception after the second vertex. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MEdge_nextIter( BPy_MEdge * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	if( self->iter == 2 ) { | 
					
						
							|  |  |  | 		self->iter = -1; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		return EXPP_ReturnPyObjError( PyExc_StopIteration, | 
					
						
							|  |  |  | 				"iterator at end" ); | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	self->iter++; | 
					
						
							|  |  |  | 	if( self->iter == 1 ) | 
					
						
							|  |  |  | 		return MEdge_getV1( self ); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return MEdge_getV2( self ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MEdge_Type standard operations | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void MEdge_dealloc( BPy_MEdge * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject_DEL( self ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MEdge_compare( BPy_MEdge * a, BPy_MEdge * b ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return( a->mesh == b->mesh && a->index == b->index ) ? 0 : -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MEdge_repr( BPy_MEdge * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	struct MEdge *edge = MEdge_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !edge ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return PyString_FromFormat( "[MEdge (%d %d) %d %d]", | 
					
						
							|  |  |  | 			(int)edge->v1, (int)edge->v2, (int)edge->crease, | 
					
						
							|  |  |  | 			(int)self->index ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 21:12:33 +00:00
										 |  |  | static long MEdge_hash( BPy_MEdge *self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return (long)self->index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MEdge_Type structure definition | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyTypeObject MEdge_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT( NULL )  /* required py macro */ | 
					
						
							|  |  |  | 	0,                          /* ob_size */ | 
					
						
							|  |  |  | 	/*  For printing, in format "<module>.<name>" */ | 
					
						
							|  |  |  | 	"Blender MEdge",           /* char *tp_name; */ | 
					
						
							|  |  |  | 	sizeof( BPy_MEdge ),       /* int tp_basicsize; */ | 
					
						
							|  |  |  | 	0,                          /* tp_itemsize;  For allocation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Methods to implement standard operations */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	( destructor ) MEdge_dealloc,/* destructor tp_dealloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* printfunc tp_print; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrfunc tp_getattr; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrfunc tp_setattr; */ | 
					
						
							|  |  |  | 	( cmpfunc ) MEdge_compare,  /* cmpfunc tp_compare; */ | 
					
						
							|  |  |  | 	( reprfunc ) MEdge_repr,    /* reprfunc tp_repr; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Method suites for standard classes */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /* PyNumberMethods *tp_as_number; */ | 
					
						
							|  |  |  |     NULL,                       /* PySequenceMethods *tp_as_sequence; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyMappingMethods *tp_as_mapping; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* More standard operations (here for binary compatibility) */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 21:12:33 +00:00
										 |  |  | 	( hashfunc ) MEdge_hash,    /* hashfunc tp_hash; */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	NULL,                       /* ternaryfunc tp_call; */ | 
					
						
							|  |  |  | 	NULL,                       /* reprfunc tp_str; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrofunc tp_getattro; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrofunc tp_setattro; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Functions to access object as input/output buffer */ | 
					
						
							|  |  |  | 	NULL,                       /* PyBufferProcs *tp_as_buffer; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Flags to define presence of optional/expanded features ***/ | 
					
						
							|  |  |  | 	Py_TPFLAGS_DEFAULT,         /* long tp_flags; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /*  char *tp_doc;  Documentation string */ | 
					
						
							|  |  |  |   /*** Assigned meaning in release 2.0 ***/ | 
					
						
							|  |  |  | 	/* call function for all accessible objects */ | 
					
						
							|  |  |  | 	NULL,                       /* traverseproc tp_traverse; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* delete references to contained objects */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_clear; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  Assigned meaning in release 2.1 ***/ | 
					
						
							|  |  |  |   /*** rich comparisons ***/ | 
					
						
							|  |  |  | 	NULL,                       /* richcmpfunc tp_richcompare; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  weak reference enabler ***/ | 
					
						
							|  |  |  | 	0,                          /* long tp_weaklistoffset; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Added in release 2.2 ***/ | 
					
						
							|  |  |  | 	/*   Iterators */ | 
					
						
							|  |  |  | 	( getiterfunc) MEdge_getIter, /* getiterfunc tp_iter; */ | 
					
						
							|  |  |  | 	( iternextfunc ) MEdge_nextIter, /* iternextfunc tp_iternext; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Attribute descriptor and subclassing stuff ***/ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyMethodDef *tp_methods; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyMemberDef *tp_members; */ | 
					
						
							|  |  |  | 	BPy_MEdge_getseters,        /* struct PyGetSetDef *tp_getset; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct _typeobject *tp_base; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_dict; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrgetfunc tp_descr_get; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrsetfunc tp_descr_set; */ | 
					
						
							|  |  |  | 	0,                          /* long tp_dictoffset; */ | 
					
						
							|  |  |  | 	NULL,                       /* initproc tp_init; */ | 
					
						
							|  |  |  | 	NULL,                       /* allocfunc tp_alloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* newfunc tp_new; */ | 
					
						
							|  |  |  | 	/*  Low-level free-memory routine */ | 
					
						
							|  |  |  | 	NULL,                       /* freefunc tp_free;  */ | 
					
						
							|  |  |  | 	/* For PyObject_IS_GC */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_is_gc;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_bases; */ | 
					
						
							|  |  |  | 	/* method resolution order */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_mro;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_cache; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_subclasses; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_weaklist; */ | 
					
						
							|  |  |  | 	NULL | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MEdge_CreatePyObject( Mesh * mesh, int i ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BPy_MEdge *obj = PyObject_NEW( BPy_MEdge, &MEdge_Type ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !obj ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"PyObject_New() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	obj->mesh = mesh; | 
					
						
							|  |  |  | 	obj->index = i; | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	obj->iter = -1; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	return (PyObject *)obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Edge sequence  | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MEdgeSeq_len( BPy_MEdgeSeq * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return self->mesh->totedge; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MEdgeSeq_item( BPy_MEdgeSeq * self, int i ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if( i < 0 || i >= self->mesh->totedge ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_IndexError, | 
					
						
							|  |  |  | 					      "array index out of range" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return MEdge_CreatePyObject( self->mesh, i ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | static PySequenceMethods MEdgeSeq_as_sequence = { | 
					
						
							|  |  |  | 	( inquiry ) MEdgeSeq_len,	/* sq_length */ | 
					
						
							|  |  |  | 	( binaryfunc ) 0,	/* sq_concat */ | 
					
						
							|  |  |  | 	( intargfunc ) 0,	/* sq_repeat */ | 
					
						
							|  |  |  | 	( intargfunc ) MEdgeSeq_item,	/* sq_item */ | 
					
						
							|  |  |  | 	( intintargfunc ) 0,	/* sq_slice */ | 
					
						
							|  |  |  | 	( intobjargproc ) 0,	/* sq_ass_item */ | 
					
						
							|  |  |  | 	( intintobjargproc ) 0,	/* sq_ass_slice */ | 
					
						
							|  |  |  | 	0,0,0, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MEdgeSeq_Type iterator (iterates over edges) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Initialize the interator index | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MEdgeSeq_getIter( BPy_MEdgeSeq * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	if (self->iter==-1) { /* iteration for this pyobject is not yet used, just return self */ | 
					
						
							|  |  |  | 		self->iter = 0; | 
					
						
							|  |  |  | 		return EXPP_incr_ret ( (PyObject *) self ); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		BPy_MEdgeSeq *seq = (BPy_MEdgeSeq *)MEdgeSeq_CreatePyObject(self->mesh); | 
					
						
							|  |  |  | 		seq->iter = 0; | 
					
						
							|  |  |  | 		return (PyObject *)seq; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Return next MEdge. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MEdgeSeq_nextIter( BPy_MEdgeSeq * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	if( self->iter == self->mesh->totedge ) { | 
					
						
							|  |  |  | 		self->iter= -1; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		return EXPP_ReturnPyObjError( PyExc_StopIteration, | 
					
						
							|  |  |  | 				"iterator at end" ); | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return MEdge_CreatePyObject( self->mesh, self->iter++ ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MEdgeSeq_Type methods | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Create edges from tuples of vertices.  Duplicate new edges, or | 
					
						
							|  |  |  |  * edges which already exist, | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MEdgeSeq_extend( BPy_MEdgeSeq * self, PyObject *args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int len, nverts; | 
					
						
							| 
									
										
										
										
											2006-02-17 17:50:54 +00:00
										 |  |  | 	int i, j, ok; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	int new_edge_count, good_edges; | 
					
						
							|  |  |  | 	SrchEdges *oldpair, *newpair, *tmppair, *tmppair2; | 
					
						
							|  |  |  | 	PyObject *tmp; | 
					
						
							|  |  |  | 	BPy_MVert *e[4]; | 
					
						
							|  |  |  | 	MEdge *tmpedge; | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-13 07:11:30 +00:00
										 |  |  | 	/* make sure we get a tuple of sequences of something */ | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 	switch( PySequence_Size( args ) ) { | 
					
						
							|  |  |  | 	case 1: | 
					
						
							|  |  |  | 		/* if a sequence... */ | 
					
						
							|  |  |  | 		tmp = PyTuple_GET_ITEM( args, 0 ); | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 		if( PySequence_Check( tmp ) ) { | 
					
						
							| 
									
										
										
										
											2006-02-17 17:50:54 +00:00
										 |  |  | 			PyObject *tmp2; | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* ignore empty sequences */ | 
					
						
							|  |  |  | 			if( !PySequence_Size( tmp ) ) { | 
					
						
							|  |  |  | 				Py_RETURN_NONE; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 			/* if another sequence, use it */ | 
					
						
							| 
									
										
										
										
											2006-02-10 21:10:58 +00:00
										 |  |  | 			tmp2 = PySequence_ITEM( tmp, 0 ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 			if( PySequence_Check( tmp2 ) ) | 
					
						
							|  |  |  | 				args = tmp; | 
					
						
							| 
									
										
										
										
											2006-01-13 07:11:30 +00:00
										 |  |  | 			Py_INCREF( args ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 			Py_DECREF( tmp2 ); | 
					
						
							|  |  |  | 		} else | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 					"expected a sequence of sequence pairs" ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case 2:	 | 
					
						
							|  |  |  | 	case 3: | 
					
						
							|  |  |  | 	case 4:		/* two to four args may be individual verts */ | 
					
						
							|  |  |  | 		tmp = PyTuple_GET_ITEM( args, 0 ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * if first item isn't a sequence, then assume it's a bunch of MVerts | 
					
						
							|  |  |  | 		 * and wrap inside a tuple | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		if( !PySequence_Check( tmp ) ) { | 
					
						
							|  |  |  | 			args = Py_BuildValue( "(O)", args ); | 
					
						
							|  |  |  | 			if( !args ) | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 						"Py_BuildValue() failed" ); | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * otherwise, assume it already a bunch of sequences so use as-is | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		} else {  | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			Py_INCREF( args );		/* so we can safely DECREF later */ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default:	/* anything else is definitely wrong */ | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 				"expected a sequence of sequence pairs" ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* make sure there is something to add */ | 
					
						
							|  |  |  | 	len = PySequence_Size( args ); | 
					
						
							|  |  |  | 	if( len == 0 ) { | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 		Py_DECREF ( args ); | 
					
						
							|  |  |  | 		Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* verify the param list and get a total count of number of edges */ | 
					
						
							|  |  |  | 	new_edge_count = 0; | 
					
						
							|  |  |  | 	for( i = 0; i < len; ++i ) { | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		tmp = PySequence_GetItem( args, i ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* not a tuple of MVerts... error */ | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 		if( !PySequence_Check( tmp ) ) { | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 			Py_DECREF( tmp ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			Py_DECREF( args ); | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 				"expected sequence of MVert sequences" ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* not the right number of MVerts... error */ | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 		nverts = PySequence_Size( tmp ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		if( nverts < 2 || nverts > 4 ) { | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 			Py_DECREF( tmp ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			Py_DECREF( args ); | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 				"expected 2 to 4 MVerts per sequence" ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 		if( EXPP_check_sequence_consistency( tmp, &MVert_Type ) == 1 ) { | 
					
						
							| 
									
										
										
										
											2006-02-17 17:50:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 			/* get MVerts, check they're from this mesh */ | 
					
						
							|  |  |  | 			ok = 1; | 
					
						
							|  |  |  | 			for( j = 0; ok && j < nverts; ++j ) { | 
					
						
							|  |  |  | 				e[0] = (BPy_MVert *)PySequence_GetItem( tmp, j ); | 
					
						
							|  |  |  | 				if( (void *)e[0]->data != (void *)self->mesh ) | 
					
						
							|  |  |  | 					ok = 0; | 
					
						
							|  |  |  | 				Py_DECREF( e[0] ); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			Py_DECREF( tmp ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* not MVerts from another mesh ... error */ | 
					
						
							|  |  |  | 			if( !ok ) { | 
					
						
							|  |  |  | 				Py_DECREF( args ); | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 					"vertices are from a different mesh" ); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ok = 0;  | 
					
						
							|  |  |  | 			for( j = 0; ok == 0 && j < nverts; ++j ) { | 
					
						
							|  |  |  | 				PyObject *item = PySequence_ITEM( tmp, j ); | 
					
						
							|  |  |  | 				if( !PyInt_CheckExact( item ) ) | 
					
						
							|  |  |  | 					ok = 1; | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					int index = PyInt_AsLong ( item ); | 
					
						
							|  |  |  | 					if( index < 0 || index >= self->mesh->totvert ) | 
					
						
							|  |  |  | 						ok = 2; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				Py_DECREF( item ); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			Py_DECREF( tmp ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* not ints or outside of vertex list ... error */ | 
					
						
							|  |  |  | 			if( ok ) { | 
					
						
							|  |  |  | 				Py_DECREF( args ); | 
					
						
							|  |  |  | 				if( ok == 1 ) | 
					
						
							|  |  |  | 					return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 						"expected an integer index" ); | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					return EXPP_ReturnPyObjError( PyExc_KeyError, | 
					
						
							|  |  |  | 						"index out of range" ); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-02-17 17:50:54 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		if( nverts == 2 ) | 
					
						
							|  |  |  | 			++new_edge_count;	/* if only two vert, then add only edge */ | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			new_edge_count += nverts;	/* otherwise, one edge per vert */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* OK, commit to allocating the search structures */ | 
					
						
							|  |  |  | 	newpair = (SrchEdges *)MEM_callocN( sizeof(SrchEdges)*new_edge_count, | 
					
						
							|  |  |  | 			"MEdgePairs" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* scan the input list and build the new edge pair list */ | 
					
						
							|  |  |  | 	len = PySequence_Size( args ); | 
					
						
							|  |  |  | 	tmppair = newpair; | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 	new_edge_count = 0; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	for( i = 0; i < len; ++i ) { | 
					
						
							| 
									
										
										
										
											2005-10-20 15:10:43 +00:00
										 |  |  | 		int edge_count; | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 		int eedges[4]; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		tmp = PySequence_GetItem( args, i ); | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 		nverts = PySequence_Size( tmp ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 		/* get new references for the vertices */ | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 		for(j = 0; j < nverts; ++j ) { | 
					
						
							|  |  |  | 			PyObject *item = PySequence_ITEM( tmp, j ); | 
					
						
							|  |  |  | 			if( BPy_MVert_Check( item ) ) { | 
					
						
							|  |  |  | 				eedges[j] = ((BPy_MVert *)item)->index; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				eedges[j] = PyInt_AsLong ( item ); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			Py_DECREF( item ); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		Py_DECREF( tmp ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if( nverts == 2 ) | 
					
						
							| 
									
										
										
										
											2005-10-20 15:10:43 +00:00
										 |  |  | 			edge_count = 1;	 /* again, two verts give just one edge */ | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			edge_count = nverts;	 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* now add the edges to the search list */ | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 		for( j = 0; j < edge_count; ++j ) { | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			int k = j+1; | 
					
						
							|  |  |  | 			if( k == nverts )	/* final edge */  | 
					
						
							|  |  |  | 				k = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 			/* sort verts into search list, skip if two are the same */ | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 			if( eedges[j] != eedges[k] ) { | 
					
						
							|  |  |  | 				if( eedges[j] < eedges[k] ) { | 
					
						
							|  |  |  | 					tmppair->v[0] = eedges[j]; | 
					
						
							|  |  |  | 					tmppair->v[1] = eedges[k]; | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 					tmppair->swap = 0; | 
					
						
							|  |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 					tmppair->v[0] = eedges[k]; | 
					
						
							|  |  |  | 					tmppair->v[1] = eedges[j]; | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 					tmppair->swap = 1; | 
					
						
							|  |  |  | 				}  | 
					
						
							|  |  |  | 				tmppair->index = new_edge_count; | 
					
						
							|  |  |  | 				++new_edge_count; | 
					
						
							|  |  |  | 				tmppair++; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* sort the new edge pairs */ | 
					
						
							|  |  |  | 	qsort( newpair, new_edge_count, sizeof(SrchEdges), medge_comp ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * find duplicates in the new list and mark.  if it's a duplicate, | 
					
						
							|  |  |  | 	 * then mark by setting second vert index to 0 (a real edge won't have | 
					
						
							|  |  |  | 	 * second vert index of 0 since verts are sorted) | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	good_edges = new_edge_count;	/* all edges are good at this point */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmppair = newpair;		/* "last good edge" */ | 
					
						
							|  |  |  | 	tmppair2 = &tmppair[1];	/* "current candidate edge" */ | 
					
						
							|  |  |  | 	for( i = 0; i < new_edge_count; ++i ) { | 
					
						
							|  |  |  | 		if( tmppair->v[0] != tmppair2->v[0] || | 
					
						
							|  |  |  | 				tmppair->v[1] != tmppair2->v[1] ) | 
					
						
							|  |  |  | 			tmppair = tmppair2;	/* last != current, so current == last */ | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			tmppair2->v[1] = 0; /* last == current, so mark as duplicate */ | 
					
						
							|  |  |  | 			--good_edges;		/* one less good edge */ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		tmppair2++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if mesh has edges, see if any of the new edges are already in it */ | 
					
						
							|  |  |  | 	if( mesh->totedge ) { | 
					
						
							|  |  |  | 		oldpair = (SrchEdges *)MEM_callocN( sizeof(SrchEdges)*mesh->totedge, | 
					
						
							|  |  |  | 				"MEdgePairs" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * build a search list of new edges (don't need to update "swap" | 
					
						
							|  |  |  | 		 * field, since we're not creating edges here) | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		tmppair = oldpair; | 
					
						
							|  |  |  | 		tmpedge = mesh->medge; | 
					
						
							|  |  |  | 		for( i = 0; i < mesh->totedge; ++i ) { | 
					
						
							|  |  |  | 			if( tmpedge->v1 < tmpedge->v2 ) { | 
					
						
							|  |  |  | 				tmppair->v[0] = tmpedge->v1; | 
					
						
							|  |  |  | 				tmppair->v[1] = tmpedge->v2; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				tmppair->v[0] = tmpedge->v2; | 
					
						
							|  |  |  | 				tmppair->v[1] = tmpedge->v1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			++tmpedge; | 
					
						
							|  |  |  | 			++tmppair; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* sort the old edge pairs */ | 
					
						
							|  |  |  | 		qsort( oldpair, mesh->totedge, sizeof(SrchEdges), medge_comp ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* eliminate new edges already in the mesh */ | 
					
						
							|  |  |  | 		tmppair = newpair; | 
					
						
							|  |  |  | 		for( i = new_edge_count; i-- ; ) { | 
					
						
							|  |  |  | 			if( tmppair->v[1] ) { | 
					
						
							|  |  |  | 				if( bsearch( tmppair, oldpair, mesh->totedge, | 
					
						
							|  |  |  | 							sizeof(SrchEdges), medge_comp ) ) { | 
					
						
							|  |  |  | 					tmppair->v[1] = 0;	/* mark as duplicate */ | 
					
						
							|  |  |  | 					--good_edges; | 
					
						
							|  |  |  | 				}  | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			tmppair++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		MEM_freeN( oldpair ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if any new edges are left, add to list */ | 
					
						
							|  |  |  | 	if( good_edges ) { | 
					
						
							|  |  |  | 		int totedge = mesh->totedge+good_edges;	/* new edge count */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* allocate new edge list */ | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		tmpedge = MEM_callocN(totedge*sizeof(MEdge), "Mesh_addEdges"); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* if we're appending, copy the old edge list and delete it */ | 
					
						
							|  |  |  | 		if( mesh->medge ) { | 
					
						
							|  |  |  | 			memcpy( tmpedge, mesh->medge, mesh->totedge*sizeof(MEdge)); | 
					
						
							|  |  |  | 			MEM_freeN( mesh->medge ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		mesh->medge = tmpedge;		/* point to the new edge list */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 	/* resort edges into original order */ | 
					
						
							|  |  |  | 		qsort( newpair, new_edge_count, sizeof(SrchEdges), medge_index_comp ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	/* point to the first edge we're going to add */ | 
					
						
							|  |  |  | 		tmpedge = &mesh->medge[mesh->totedge]; | 
					
						
							|  |  |  | 		tmppair = newpair; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* as we find a good edge, add it */ | 
					
						
							|  |  |  | 		while( good_edges ) { | 
					
						
							|  |  |  | 			if( tmppair->v[1] ) {	/* not marked as duplicate ! */ | 
					
						
							|  |  |  | 				if( !tmppair->swap ) { | 
					
						
							|  |  |  | 					tmpedge->v1 = tmppair->v[0]; | 
					
						
							|  |  |  | 					tmpedge->v2 = tmppair->v[1]; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					tmpedge->v1 = tmppair->v[1]; | 
					
						
							|  |  |  | 					tmpedge->v2 = tmppair->v[0]; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				tmpedge->flag = ME_EDGEDRAW | ME_EDGERENDER; | 
					
						
							|  |  |  | 				mesh->totedge++; | 
					
						
							|  |  |  | 				--good_edges; | 
					
						
							|  |  |  | 				++tmpedge; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			tmppair++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* clean up and leave */ | 
					
						
							|  |  |  | 	mesh_update( mesh ); | 
					
						
							|  |  |  | 	MEM_freeN( newpair ); | 
					
						
							|  |  |  | 	Py_DECREF ( args ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 	Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | static PyObject *MEdgeSeq_delete( BPy_MEdgeSeq * self, PyObject *args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 	MEdge *srcedge; | 
					
						
							|  |  |  | 	MFace *srcface; | 
					
						
							|  |  |  | 	unsigned int *vert_table, *del_table, *edge_table; | 
					
						
							|  |  |  | 	int i, len; | 
					
						
							|  |  |  | 	int face_count, edge_count, vert_count; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * if input tuple contains a single sequence, use it as input instead; | 
					
						
							|  |  |  | 	 * otherwise use the sequence as-is and check later that it contains | 
					
						
							|  |  |  | 	 * one or more integers or MVerts | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	if( PySequence_Size( args ) == 1 ) { | 
					
						
							|  |  |  | 		PyObject *tmp = PyTuple_GET_ITEM( args, 0 ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 		if( PySequence_Check( tmp ) )  | 
					
						
							|  |  |  | 			args = tmp; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 	/* if sequence is empty, do nothing */ | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	len = PySequence_Size( args ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 	if( len == 0 ) { | 
					
						
							|  |  |  | 		Py_RETURN_NONE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	edge_table = (unsigned int *)MEM_callocN( len*sizeof( unsigned int ), | 
					
						
							|  |  |  | 			"edge_table" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* get the indices of edges to be removed */ | 
					
						
							|  |  |  | 	for( i = len; i--; ) { | 
					
						
							|  |  |  | 		PyObject *tmp = PySequence_GetItem( args, i ); | 
					
						
							|  |  |  | 		if( BPy_MEdge_Check( tmp ) ) | 
					
						
							|  |  |  | 			edge_table[i] = ((BPy_MEdge *)tmp)->index; | 
					
						
							|  |  |  | 		else if( PyInt_CheckExact( tmp ) ) | 
					
						
							|  |  |  | 			edge_table[i] = PyInt_AsLong ( tmp ); | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			MEM_freeN( edge_table ); | 
					
						
							|  |  |  | 			Py_DECREF( tmp ); | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					"expected a sequence of ints or MEdges" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		Py_DECREF( tmp ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* if index out-of-range, throw exception */ | 
					
						
							|  |  |  | 		if( edge_table[i] >= (unsigned int)mesh->totedge ) { | 
					
						
							|  |  |  | 			MEM_freeN( edge_table ); | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 					"array index out of range" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * build two tables: first table marks vertices which belong to an edge | 
					
						
							|  |  |  | 	 * which is being deleted | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	del_table = (unsigned int *)MEM_callocN(  | 
					
						
							|  |  |  | 			mesh->totvert*sizeof( unsigned int ), "vert_table" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Borrow a trick from editmesh code: for each edge to be deleted, mark | 
					
						
							|  |  |  | 	 * its vertices as well.  Then go through face list and look for two | 
					
						
							|  |  |  | 	 * consecutive marked vertices. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* mark each edge that's to be deleted */ | 
					
						
							|  |  |  | 	srcedge = mesh->medge; | 
					
						
							|  |  |  | 	for( i = len; i--; ) { | 
					
						
							|  |  |  | 		unsigned int idx = edge_table[i]; | 
					
						
							|  |  |  | 		del_table[srcedge[idx].v1] = UINT_MAX; | 
					
						
							|  |  |  | 		del_table[srcedge[idx].v2] = UINT_MAX; | 
					
						
							|  |  |  | 		srcedge[idx].v1 = UINT_MAX; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * second table is used for vertices which become orphaned (belong to no | 
					
						
							|  |  |  | 	 * edges) and need to be deleted; it's also the normal lookup table for | 
					
						
							|  |  |  | 	 * old->new vertex indices | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vert_table = (unsigned int *)MEM_mallocN(  | 
					
						
							|  |  |  | 			mesh->totvert*sizeof( unsigned int ), "vert_table" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* assume all edges will be deleted (fills with UINT_MAX) */ | 
					
						
							|  |  |  | 	memset( vert_table, UCHAR_MAX, mesh->totvert*sizeof( unsigned int ) ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* unmark vertices of each "good" edge; count each "bad" edge */ | 
					
						
							|  |  |  | 	edge_count = 0; | 
					
						
							|  |  |  | 	for( i = mesh->totedge; i--; ++srcedge ) | 
					
						
							|  |  |  | 		if( srcedge->v1 != UINT_MAX ) | 
					
						
							|  |  |  | 			vert_table[srcedge->v1] = vert_table[srcedge->v2] = 0; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			++edge_count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * find faces which no longer have all edges | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	face_count = 0; | 
					
						
							|  |  |  | 	srcface = mesh->mface; | 
					
						
							|  |  |  | 	for( i = 0; i < mesh->totface; ++i, ++srcface ) { | 
					
						
							|  |  |  | 		int len = srcface->v4 ? 4 : 3; | 
					
						
							|  |  |  | 		unsigned int id[4]; | 
					
						
							|  |  |  | 		int del; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		id[0] = del_table[srcface->v1]; | 
					
						
							|  |  |  | 		id[1] = del_table[srcface->v2]; | 
					
						
							|  |  |  | 		id[2] = del_table[srcface->v3]; | 
					
						
							|  |  |  | 		id[3] = del_table[srcface->v4]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		del = ( id[0] == UINT_MAX && id[1] == UINT_MAX ) || | 
					
						
							|  |  |  | 			( id[1] == UINT_MAX && id[2] == UINT_MAX ); | 
					
						
							|  |  |  | 		if( !del ) { | 
					
						
							|  |  |  | 			if( len == 3 ) | 
					
						
							|  |  |  | 				del = ( id[2] == UINT_MAX && id[0] == UINT_MAX ); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				del = ( id[2] == UINT_MAX && id[3] == UINT_MAX ) || | 
					
						
							|  |  |  | 					( id[3] == UINT_MAX && id[0] == UINT_MAX ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if( del ) { | 
					
						
							|  |  |  | 			srcface->v1 = UINT_MAX; | 
					
						
							|  |  |  | 			++face_count; | 
					
						
							|  |  |  | 		}  | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* fix the vertex lookup table, if any verts to delete, do so now */ | 
					
						
							|  |  |  | 	vert_count = make_vertex_table( vert_table, mesh->totvert ); | 
					
						
							|  |  |  | 	if( vert_count ) | 
					
						
							|  |  |  | 		delete_verts( mesh, vert_table, vert_count ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* delete faces which have a deleted edge */ | 
					
						
							|  |  |  | 	delete_faces( mesh, vert_table, face_count ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* now delete the edges themselves */ | 
					
						
							|  |  |  | 	delete_edges( mesh, vert_table, edge_count ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* clean up and return */ | 
					
						
							|  |  |  | 	MEM_freeN( del_table ); | 
					
						
							|  |  |  | 	MEM_freeN( vert_table ); | 
					
						
							|  |  |  | 	MEM_freeN( edge_table ); | 
					
						
							|  |  |  | 	mesh_update ( mesh ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 	Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-10 12:12:21 +00:00
										 |  |  | static PyObject *MEdgeSeq_collapse( BPy_MEdgeSeq * self, PyObject *args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	MEdge *srcedge; | 
					
						
							|  |  |  | 	unsigned int *edge_table; | 
					
						
							|  |  |  | 	float (*vert_list)[3]; | 
					
						
							|  |  |  | 	int i, len; | 
					
						
							|  |  |  | 	Base *base, *basact; | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 	Object *object = NULL;  | 
					
						
							|  |  |  | 	PyObject *tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * when using removedoublesflag(), we need to switch to editmode, so | 
					
						
							|  |  |  | 	 * nobody else can be using it | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( G.obedit ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError(PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"can't use collapse() while in edit mode" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* make sure we get a tuple of sequences of something */ | 
					
						
							|  |  |  | 	switch( PySequence_Size( args ) ) { | 
					
						
							|  |  |  | 	case 1: | 
					
						
							|  |  |  | 		/* if a sequence... */ | 
					
						
							|  |  |  | 		tmp = PyTuple_GET_ITEM( args, 0 ); | 
					
						
							|  |  |  | 		if( PySequence_Check( tmp ) ) { | 
					
						
							|  |  |  | 			PyObject *tmp2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* ignore empty sequences */ | 
					
						
							|  |  |  | 			if( !PySequence_Size( tmp ) ) { | 
					
						
							|  |  |  | 				Py_RETURN_NONE; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* if another sequence, use it */ | 
					
						
							|  |  |  | 			tmp2 = PySequence_ITEM( tmp, 0 ); | 
					
						
							|  |  |  | 			if( PySequence_Check( tmp2 ) ) | 
					
						
							|  |  |  | 				args = tmp; | 
					
						
							|  |  |  | 			Py_INCREF( args ); | 
					
						
							|  |  |  | 			Py_DECREF( tmp2 ); | 
					
						
							|  |  |  | 		} else | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					"expected a sequence of sequence pairs" ); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 2:	/* two args may be individual edges/verts */ | 
					
						
							|  |  |  | 		tmp = PyTuple_GET_ITEM( args, 0 ); | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * if first item isn't a sequence, then assume it's a bunch of MVerts | 
					
						
							|  |  |  | 		 * and wrap inside a tuple | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		if( !PySequence_Check( tmp ) ) { | 
					
						
							|  |  |  | 			args = Py_BuildValue( "(O)", args ); | 
					
						
							|  |  |  | 			if( !args ) | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 						"Py_BuildValue() failed" ); | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * otherwise, assume it already a bunch of sequences so use as-is | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		} else {  | 
					
						
							|  |  |  | 			Py_INCREF( args );		/* so we can safely DECREF later */ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default:	/* anything else is definitely wrong */ | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected a sequence of sequence pairs" ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if sequence is empty, do nothing */ | 
					
						
							|  |  |  | 	len = PySequence_Size( args ); | 
					
						
							|  |  |  | 	if( len == 0 ) { | 
					
						
							|  |  |  | 		Py_RETURN_NONE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* allocate table of edge indices and new vertex values */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	edge_table = (unsigned int *)MEM_callocN( len*sizeof( unsigned int ), | 
					
						
							|  |  |  | 			"edge_table" ); | 
					
						
							|  |  |  | 	vert_list = (float (*)[3])MEM_callocN( 3*len*sizeof( float ), | 
					
						
							|  |  |  | 			"vert_list" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* get the indices of edges to be collapsed and new vert locations */ | 
					
						
							|  |  |  | 	for( i = len; i--; ) { | 
					
						
							|  |  |  | 		PyObject *tmp1; | 
					
						
							|  |  |  | 		PyObject *tmp2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tmp = PySequence_GetItem( args, i ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* if item isn't sequence of size 2, error */ | 
					
						
							|  |  |  | 		if( !PySequence_Check( tmp ) || PySequence_Size( tmp ) != 2 ) { | 
					
						
							|  |  |  | 			MEM_freeN( edge_table ); | 
					
						
							|  |  |  | 			MEM_freeN( vert_list ); | 
					
						
							|  |  |  | 			Py_DECREF( tmp ); | 
					
						
							|  |  |  | 			Py_DECREF( args ); | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					"expected a sequence of (MEdges, vector)" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* if items aren't a MEdge/int and vector, error */ | 
					
						
							|  |  |  | 		tmp1 = PySequence_GetItem( tmp, 0 ); | 
					
						
							|  |  |  | 		tmp2 = PySequence_GetItem( tmp, 1 ); | 
					
						
							|  |  |  | 		Py_DECREF( tmp ); | 
					
						
							|  |  |  | 		if( !(BPy_MEdge_Check( tmp1 ) || PyInt_CheckExact( tmp1 )) || | 
					
						
							|  |  |  | 				!VectorObject_Check ( tmp2 ) ) { | 
					
						
							|  |  |  | 			MEM_freeN( edge_table ); | 
					
						
							|  |  |  | 			MEM_freeN( vert_list ); | 
					
						
							|  |  |  | 			Py_DECREF( tmp1 ); | 
					
						
							|  |  |  | 			Py_DECREF( tmp2 ); | 
					
						
							|  |  |  | 			Py_DECREF( args ); | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					"expected a sequence of (MEdges, vector)" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* store edge index, new vertex location */ | 
					
						
							|  |  |  | 		if( PyInt_CheckExact( tmp1 ) ) | 
					
						
							|  |  |  | 			edge_table[i] = PyInt_AsLong ( tmp1 ); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			edge_table[i] = ((BPy_MEdge *)tmp1)->index; | 
					
						
							|  |  |  | 		memcpy( vert_list[i], ((VectorObject *)tmp2)->vec, | 
					
						
							|  |  |  | 				3*sizeof( float ) ); | 
					
						
							|  |  |  | 		Py_DECREF( tmp1 ); | 
					
						
							|  |  |  | 		Py_DECREF( tmp2 ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* if index out-of-range, throw exception */ | 
					
						
							|  |  |  | 		if( edge_table[i] >= (unsigned int)mesh->totedge ) { | 
					
						
							|  |  |  | 			MEM_freeN( edge_table ); | 
					
						
							|  |  |  | 			MEM_freeN( vert_list ); | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 					"edge index out of range" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * simple algorithm: | 
					
						
							|  |  |  | 	 * (1) deselect all verts | 
					
						
							|  |  |  | 	 * (2) for each edge | 
					
						
							|  |  |  | 	 *   (2a) replace both verts with the new vert | 
					
						
							|  |  |  | 	 *   (2b) select both verts | 
					
						
							|  |  |  | 	 * (3) call removedoublesflag() | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* (1) deselect all verts */ | 
					
						
							|  |  |  | 	for( i = mesh->totvert; i--; ) | 
					
						
							|  |  |  | 		mesh->mvert[i].flag &= ~SELECT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* (2) replace edge's verts and select them */ | 
					
						
							|  |  |  | 	for( i = len; i--; ) { | 
					
						
							|  |  |  | 		srcedge = &mesh->medge[edge_table[i]]; | 
					
						
							|  |  |  | 		memcpy( &mesh->mvert[srcedge->v1].co, vert_list[i], 3*sizeof( float ) ); | 
					
						
							|  |  |  | 		memcpy( &mesh->mvert[srcedge->v2].co, vert_list[i], 3*sizeof( float ) ); | 
					
						
							|  |  |  | 		mesh->mvert[srcedge->v1].flag |= SELECT; | 
					
						
							|  |  |  | 		mesh->mvert[srcedge->v2].flag |= SELECT; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* (3) call removedoublesflag() */ | 
					
						
							|  |  |  | 	for( base = FIRSTBASE; base; base = base->next ) { | 
					
						
							|  |  |  | 		if( base->object->type == OB_MESH &&  | 
					
						
							|  |  |  | 				base->object->data == self->mesh ) { | 
					
						
							|  |  |  | 			object = base->object; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	basact = BASACT; | 
					
						
							|  |  |  | 	BASACT = base; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	removedoublesflag( 1, 0.0 ); | 
					
						
							|  |  |  | 	/* make mesh's object active, enter mesh edit mode */ | 
					
						
							|  |  |  | 	G.obedit = object; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* exit edit mode, free edit mesh */ | 
					
						
							|  |  |  | 	load_editMesh(); | 
					
						
							|  |  |  | 	free_editMesh(G.editMesh); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	BASACT = basact; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* clean up and exit */ | 
					
						
							|  |  |  | 	Py_DECREF( args ); | 
					
						
							|  |  |  | 	MEM_freeN( vert_list ); | 
					
						
							|  |  |  | 	MEM_freeN( edge_table ); | 
					
						
							|  |  |  | 	mesh_update ( mesh ); | 
					
						
							|  |  |  | 	Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | static PyObject *MEdgeSeq_selected( BPy_MEdgeSeq * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i, count; | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 	MEdge *tmpedge; | 
					
						
							|  |  |  | 	PyObject *list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* first count selected edges (quicker than appending to PyList?) */ | 
					
						
							|  |  |  | 	count = 0; | 
					
						
							|  |  |  | 	tmpedge = mesh->medge; | 
					
						
							|  |  |  | 	for( i = 0; i < mesh->totedge; ++i, ++tmpedge ) | 
					
						
							|  |  |  | 		if( (mesh->mvert[tmpedge->v1].flag & SELECT) && | 
					
						
							|  |  |  | 				(mesh->mvert[tmpedge->v2].flag & SELECT) ) | 
					
						
							|  |  |  | 			++count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list = PyList_New( count ); | 
					
						
							|  |  |  | 	if( !list ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"PyList_New() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* next, insert selected edges into list */ | 
					
						
							|  |  |  | 	count = 0; | 
					
						
							|  |  |  | 	tmpedge = mesh->medge; | 
					
						
							|  |  |  | 	for( i = 0; i < mesh->totedge; ++i, ++tmpedge ) { | 
					
						
							|  |  |  | 		if( (mesh->mvert[tmpedge->v1].flag & SELECT) && | 
					
						
							|  |  |  | 				(mesh->mvert[tmpedge->v2].flag & SELECT) ) { | 
					
						
							|  |  |  | 			PyObject *tmp = PyInt_FromLong( i ); | 
					
						
							|  |  |  | 			if( !tmp ) { | 
					
						
							|  |  |  | 				Py_DECREF( list ); | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 						"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			PyList_SET_ITEM( list, count, tmp ); | 
					
						
							|  |  |  | 			++count; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return list; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | static struct PyMethodDef BPy_MEdgeSeq_methods[] = { | 
					
						
							|  |  |  | 	{"extend", (PyCFunction)MEdgeSeq_extend, METH_VARARGS, | 
					
						
							|  |  |  | 		"add edges to mesh"}, | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	{"delete", (PyCFunction)MEdgeSeq_delete, METH_VARARGS, | 
					
						
							|  |  |  | 		"delete edges from mesh"}, | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	{"selected", (PyCFunction)MEdgeSeq_selected, METH_NOARGS, | 
					
						
							|  |  |  | 		"returns a list containing indices of selected edges"}, | 
					
						
							| 
									
										
										
										
											2006-05-10 12:12:21 +00:00
										 |  |  | 	{"collapse", (PyCFunction)MEdgeSeq_collapse, METH_VARARGS, | 
					
						
							|  |  |  | 		"collapse one or more edges to a vertex"}, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	{NULL, NULL, 0, NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MEdgeSeq_Type standard operators | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void MEdgeSeq_dealloc( BPy_MEdgeSeq * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject_DEL( self ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*****************************************************************************/ | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | /* Python MEdgeSeq_Type structure definition:                               */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /*****************************************************************************/ | 
					
						
							|  |  |  | PyTypeObject MEdgeSeq_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT( NULL )  /* required py macro */ | 
					
						
							|  |  |  | 	0,                          /* ob_size */ | 
					
						
							|  |  |  | 	/*  For printing, in format "<module>.<name>" */ | 
					
						
							|  |  |  | 	"Blender MEdgeSeq",           /* char *tp_name; */ | 
					
						
							|  |  |  | 	sizeof( BPy_MEdgeSeq ),       /* int tp_basicsize; */ | 
					
						
							|  |  |  | 	0,                          /* tp_itemsize;  For allocation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Methods to implement standard operations */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	( destructor ) MEdgeSeq_dealloc,/* destructor tp_dealloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* printfunc tp_print; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrfunc tp_getattr; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrfunc tp_setattr; */ | 
					
						
							|  |  |  | 	NULL,                       /* cmpfunc tp_compare; */ | 
					
						
							|  |  |  | 	NULL,                       /* reprfunc tp_repr; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Method suites for standard classes */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /* PyNumberMethods *tp_as_number; */ | 
					
						
							|  |  |  | 	&MEdgeSeq_as_sequence,	    /* PySequenceMethods *tp_as_sequence; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyMappingMethods *tp_as_mapping; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* More standard operations (here for binary compatibility) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /* hashfunc tp_hash; */ | 
					
						
							|  |  |  | 	NULL,                       /* ternaryfunc tp_call; */ | 
					
						
							|  |  |  | 	NULL,                       /* reprfunc tp_str; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrofunc tp_getattro; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrofunc tp_setattro; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Functions to access object as input/output buffer */ | 
					
						
							|  |  |  | 	NULL,                       /* PyBufferProcs *tp_as_buffer; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Flags to define presence of optional/expanded features ***/ | 
					
						
							|  |  |  | 	Py_TPFLAGS_DEFAULT,         /* long tp_flags; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /*  char *tp_doc;  Documentation string */ | 
					
						
							|  |  |  |   /*** Assigned meaning in release 2.0 ***/ | 
					
						
							|  |  |  | 	/* call function for all accessible objects */ | 
					
						
							|  |  |  | 	NULL,                       /* traverseproc tp_traverse; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* delete references to contained objects */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_clear; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  Assigned meaning in release 2.1 ***/ | 
					
						
							|  |  |  |   /*** rich comparisons ***/ | 
					
						
							|  |  |  | 	NULL,                       /* richcmpfunc tp_richcompare; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  weak reference enabler ***/ | 
					
						
							|  |  |  | 	0,                          /* long tp_weaklistoffset; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Added in release 2.2 ***/ | 
					
						
							|  |  |  | 	/*   Iterators */ | 
					
						
							|  |  |  | 	( getiterfunc) MEdgeSeq_getIter, /* getiterfunc tp_iter; */ | 
					
						
							|  |  |  | 	( iternextfunc ) MEdgeSeq_nextIter, /* iternextfunc tp_iternext; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Attribute descriptor and subclassing stuff ***/ | 
					
						
							|  |  |  | 	BPy_MEdgeSeq_methods,       /* struct PyMethodDef *tp_methods; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyMemberDef *tp_members; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyGetSetDef *tp_getset; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct _typeobject *tp_base; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_dict; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrgetfunc tp_descr_get; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrsetfunc tp_descr_set; */ | 
					
						
							|  |  |  | 	0,                          /* long tp_dictoffset; */ | 
					
						
							|  |  |  | 	NULL,                       /* initproc tp_init; */ | 
					
						
							|  |  |  | 	NULL,                       /* allocfunc tp_alloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* newfunc tp_new; */ | 
					
						
							|  |  |  | 	/*  Low-level free-memory routine */ | 
					
						
							|  |  |  | 	NULL,                       /* freefunc tp_free;  */ | 
					
						
							|  |  |  | 	/* For PyObject_IS_GC */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_is_gc;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_bases; */ | 
					
						
							|  |  |  | 	/* method resolution order */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_mro;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_cache; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_subclasses; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_weaklist; */ | 
					
						
							|  |  |  | 	NULL | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Face attributes | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | static MFace * MFace_get_pointer( BPy_MFace * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if( self->index >= self->mesh->totface ) | 
					
						
							|  |  |  | 		return (MFace *)EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"MFace is no longer valid" ); | 
					
						
							|  |  |  | 	return &self->mesh->mface[self->index]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * get a face's vertices | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFace_getVerts( BPy_MFace * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	PyObject *attr; | 
					
						
							|  |  |  | 	MFace *face = MFace_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !face ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	attr = PyTuple_New( face->v4 ? 4 : 3 ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( !attr ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"PyTuple_New() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyTuple_SetItem( attr, 0, MVert_CreatePyObject( self->mesh, face->v1 ) ); | 
					
						
							|  |  |  | 	PyTuple_SetItem( attr, 1, MVert_CreatePyObject( self->mesh, face->v2 ) ); | 
					
						
							|  |  |  | 	PyTuple_SetItem( attr, 2, MVert_CreatePyObject( self->mesh, face->v3 ) ); | 
					
						
							|  |  |  | 	if( face->v4 ) | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 		PyTuple_SetItem( attr, 3, MVert_CreatePyObject( self->mesh, | 
					
						
							|  |  |  | 					face->v4 ) ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return attr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * set a face's vertices | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MFace_setVerts( BPy_MFace * self, PyObject * args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BPy_MVert *v1, *v2, *v3, *v4 = NULL; | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	MFace *face = MFace_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !face ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple ( args, "O!O!O!|O!", &MVert_Type, &v1, | 
					
						
							|  |  |  | 				&MVert_Type, &v2, &MVert_Type, &v3, &MVert_Type, &v4 ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 			"expected tuple of 3 or 4 MVerts" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	face->v1 = v1->index; | 
					
						
							|  |  |  | 	face->v2 = v2->index; | 
					
						
							|  |  |  | 	face->v3 = v3->index; | 
					
						
							|  |  |  | 	if( v4 ) | 
					
						
							|  |  |  | 		face->v4 = v4->index; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * get face's material index | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFace_getMat( BPy_MFace * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	PyObject *attr; | 
					
						
							|  |  |  | 	MFace *face = MFace_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !face ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	attr = PyInt_FromLong( face->mat_nr ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( attr ) | 
					
						
							|  |  |  | 		return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 			"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * set face's material index | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MFace_setMat( BPy_MFace * self, PyObject * value ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	MFace *face = MFace_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !face ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	return EXPP_setIValueRange( value, &face->mat_nr, 0, 15, 'b' ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * get a face's index | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFace_getIndex( BPy_MFace * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	PyObject *attr; | 
					
						
							|  |  |  | 	MFace *face = MFace_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !face ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	attr = PyInt_FromLong( self->index ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( attr ) | 
					
						
							|  |  |  | 		return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 			"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * get face's normal index | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFace_getNormal( BPy_MFace * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float *vert[4]; | 
					
						
							|  |  |  | 	float no[3]; | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	MFace *face = MFace_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !face ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( (int)face->v1 >= self->mesh->totvert || | 
					
						
							|  |  |  | 			(int)face->v2 >= self->mesh->totvert || | 
					
						
							|  |  |  | 			(int)face->v3 >= self->mesh->totvert || | 
					
						
							|  |  |  | 			(int)face->v4 >= self->mesh->totvert ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"one or more MFace vertices are no longer valid" ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	vert[0] = self->mesh->mvert[face->v1].co; | 
					
						
							|  |  |  | 	vert[1] = self->mesh->mvert[face->v2].co; | 
					
						
							|  |  |  | 	vert[2] = self->mesh->mvert[face->v3].co; | 
					
						
							| 
									
										
										
										
											2006-05-11 10:06:15 +00:00
										 |  |  | 	if( face->v4 ) { | 
					
						
							|  |  |  | 		vert[3] = self->mesh->mvert[face->v4].co; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		CalcNormFloat4( vert[0], vert[1], vert[2], vert[3], no ); | 
					
						
							| 
									
										
										
										
											2006-05-11 10:06:15 +00:00
										 |  |  | 	} else | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		CalcNormFloat( vert[0], vert[1], vert[2], no ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return newVectorObject( no, 3, Py_NEW ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-11 10:06:15 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * get face's center location | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFace_getCent( BPy_MFace * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float *vert[4]; | 
					
						
							|  |  |  | 	float cent[3]= {0,0,0}; | 
					
						
							|  |  |  | 	int i=3, j, k; | 
					
						
							|  |  |  | 	MFace *face = MFace_get_pointer( self ); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if( !face ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( (int)face->v1 >= self->mesh->totvert || | 
					
						
							|  |  |  | 			(int)face->v2 >= self->mesh->totvert || | 
					
						
							|  |  |  | 			(int)face->v3 >= self->mesh->totvert || | 
					
						
							|  |  |  | 			(int)face->v4 >= self->mesh->totvert ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"one or more MFace vertices are no longer valid" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vert[0] = self->mesh->mvert[face->v1].co; | 
					
						
							|  |  |  | 	vert[1] = self->mesh->mvert[face->v2].co; | 
					
						
							|  |  |  | 	vert[2] = self->mesh->mvert[face->v3].co; | 
					
						
							|  |  |  | 	if( face->v4 ) { | 
					
						
							|  |  |  | 		vert[3] = self->mesh->mvert[face->v4].co; | 
					
						
							|  |  |  | 		i=4; | 
					
						
							|  |  |  | 	}  | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for (j=0;j<i;j++) { | 
					
						
							|  |  |  | 		for (k=0;k<3;k++) { | 
					
						
							|  |  |  | 			cent[k]+=vert[j][k]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for (j=0;j<3;j++) { | 
					
						
							|  |  |  | 		cent[j]=cent[j]/i; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return newVectorObject( cent, 3, Py_NEW ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * get face's area | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static PyObject *MFace_getArea( BPy_MFace * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float *v1,*v2,*v3,*v4; | 
					
						
							|  |  |  | 	MFace *face = MFace_get_pointer( self ); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if( !face ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( (int)face->v1 >= self->mesh->totvert || | 
					
						
							|  |  |  | 			(int)face->v2 >= self->mesh->totvert || | 
					
						
							|  |  |  | 			(int)face->v3 >= self->mesh->totvert || | 
					
						
							|  |  |  | 			(int)face->v4 >= self->mesh->totvert ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"one or more MFace vertices are no longer valid" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	v1 = self->mesh->mvert[face->v1].co; | 
					
						
							|  |  |  | 	v2 = self->mesh->mvert[face->v2].co; | 
					
						
							|  |  |  | 	v3 = self->mesh->mvert[face->v3].co; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if( face->v4 ) { | 
					
						
							|  |  |  | 		v4 = self->mesh->mvert[face->v4].co; | 
					
						
							|  |  |  | 		return PyFloat_FromDouble( AreaQ3Dfl(v1, v2, v3, v4)); | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 		return PyFloat_FromDouble( AreaT3Dfl(v1, v2, v3)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * get one of a face's mface flag bits | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFace_getMFlagBits( BPy_MFace * self, void * type ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	MFace *face = MFace_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !face ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 	return EXPP_getBitfield( &face->flag, (int)((long)type & 0xff), 'b' ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * set one of a face's mface flag bits | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MFace_setMFlagBits( BPy_MFace * self, PyObject * value, | 
					
						
							|  |  |  | 		void * type ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	MFace *face = MFace_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !face ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 	return EXPP_setBitfield( value, &face->flag,  | 
					
						
							|  |  |  | 			(int)((long)type & 0xff), 'b' ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MFace_setSelect( BPy_MFace * self, PyObject * value, | 
					
						
							| 
									
										
										
										
											2006-05-08 05:37:00 +00:00
										 |  |  | 		void * type_unused ) | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	MFace *face = MFace_get_pointer( self ); | 
					
						
							|  |  |  | 	int param = PyObject_IsTrue( value ); | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 	Mesh *me; | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( !face ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( param == -1 ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected true/false argument" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 	me = self->mesh; | 
					
						
							|  |  |  | 	if( param ) { | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 		face->flag |= ME_FACE_SEL; | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 		me->mvert[face->v1].flag |= SELECT; | 
					
						
							|  |  |  | 		me->mvert[face->v2].flag |= SELECT; | 
					
						
							|  |  |  | 		me->mvert[face->v3].flag |= SELECT; | 
					
						
							|  |  |  | 		if( face->v4 ) | 
					
						
							|  |  |  | 			me->mvert[face->v4].flag |= SELECT; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 		face->flag &= ~ME_FACE_SEL; | 
					
						
							| 
									
										
										
										
											2006-05-14 14:12:45 +00:00
										 |  |  | 		me->mvert[face->v1].flag &= ~SELECT; | 
					
						
							|  |  |  | 		me->mvert[face->v2].flag &= ~SELECT; | 
					
						
							|  |  |  | 		me->mvert[face->v3].flag &= ~SELECT; | 
					
						
							|  |  |  | 		if( face->v4 ) | 
					
						
							|  |  |  | 			me->mvert[face->v4].flag &= ~SELECT; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( self->mesh->mselect ) { | 
					
						
							|  |  |  | 		MEM_freeN( self->mesh->mselect ); | 
					
						
							|  |  |  | 		self->mesh->mselect = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * get face's texture image | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFace_getImage( BPy_MFace *self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	TFace *face; | 
					
						
							|  |  |  | 	if( !self->mesh->tface ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no texture values" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( !MFace_get_pointer( self ) ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	face = &self->mesh->tface[self->index]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( face->tpage ) | 
					
						
							|  |  |  | 		return Image_CreatePyObject( face->tpage ); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * change or clear face's texture image | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MFace_setImage( BPy_MFace *self, PyObject *value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	TFace *face; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( !MFace_get_pointer( self ) ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-05 07:19:37 +00:00
										 |  |  | 	if( !self->mesh->tface ) | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no texture values" ); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 		make_tfaces( self->mesh ); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	face = &self->mesh->tface[self->index]; | 
					
						
							|  |  |  |     if( value == Py_None ) | 
					
						
							|  |  |  |         face->tpage = NULL;		/* should memory be freed? */ | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         if( !BPy_Image_Check( value ) ) | 
					
						
							|  |  |  |             return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 					"expected image object" ); | 
					
						
							|  |  |  |         face->tpage = ( ( BPy_Image * ) value )->image; | 
					
						
							| 
									
										
										
										
											2006-02-05 07:19:37 +00:00
										 |  |  | 		face->mode |= TF_TEX; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-07-06 16:40:49 +00:00
										 |  |  | #define MFACE_FLAG_BITMASK ( TF_SELECT | TF_ACTIVE | TF_SEL1 | \
 | 
					
						
							|  |  |  | 		TF_SEL2 | TF_SEL3 | TF_SEL4 | TF_HIDE ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2006-07-06 16:40:49 +00:00
										 |  |  | * get face's texture flag | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 23:18:53 +00:00
										 |  |  | static PyObject *MFace_getFlag( BPy_MFace *self ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if( !self->mesh->tface ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no texture values" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( !MFace_get_pointer( self ) ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-07-06 16:40:49 +00:00
										 |  |  | 	return PyInt_FromLong( (long) ( self->mesh->tface[self->index].flag | 
					
						
							|  |  |  | 			& MFACE_FLAG_BITMASK ) ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  |  * set face's texture flag | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 23:18:53 +00:00
										 |  |  | static int MFace_setFlag( BPy_MFace *self, PyObject *value ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int param; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !self->mesh->tface ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no texture values" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( !MFace_get_pointer( self ) ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	if( !PyInt_CheckExact ( value ) ) { | 
					
						
							|  |  |  | 		char errstr[128]; | 
					
						
							| 
									
										
										
										
											2006-07-06 16:40:49 +00:00
										 |  |  | 		sprintf ( errstr , "expected int bitmask of 0x%04x", MFACE_FLAG_BITMASK ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, errstr ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	param = PyInt_AS_LONG ( value ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* only one face can be active, so don't allow that here */ | 
					
						
							| 
									
										
										
										
											2006-06-27 02:49:55 +00:00
										 |  |  | 	if( param & TF_ACTIVE ) | 
					
						
							|  |  |  | 		param &= ~TF_ACTIVE; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2006-07-06 16:40:49 +00:00
										 |  |  | 	if( ( param & MFACE_FLAG_BITMASK ) != param ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 						"invalid bit(s) set in mask" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* merge active setting with other new params */ | 
					
						
							|  |  |  | 	param |= (self->mesh->tface[self->index].flag & TF_ACTIVE); | 
					
						
							| 
									
										
										
										
											2005-10-03 20:48:43 +00:00
										 |  |  | 	self->mesh->tface[self->index].flag = (char)param; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-10-11 23:18:53 +00:00
										 |  |  |  * get face's texture mode | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 23:18:53 +00:00
										 |  |  | static PyObject *MFace_getMode( BPy_MFace *self ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyObject *attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !self->mesh->tface ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no texture values" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( !MFace_get_pointer( self ) ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	attr = PyInt_FromLong( self->mesh->tface[self->index].mode ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( attr ) | 
					
						
							|  |  |  | 		return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 			"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-10-11 23:18:53 +00:00
										 |  |  |  * set face's texture mode | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 23:18:53 +00:00
										 |  |  | static int MFace_setMode( BPy_MFace *self, PyObject *value ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int param; | 
					
						
							|  |  |  | 	static short bitmask = TF_DYNAMIC | 
					
						
							|  |  |  | 				| TF_TEX | 
					
						
							|  |  |  | 				| TF_SHAREDVERT | 
					
						
							|  |  |  | 				| TF_LIGHT | 
					
						
							|  |  |  | 				| TF_SHAREDCOL | 
					
						
							|  |  |  | 				| TF_TILES | 
					
						
							|  |  |  | 				| TF_BILLBOARD | 
					
						
							|  |  |  | 				| TF_TWOSIDE | 
					
						
							|  |  |  | 				| TF_INVISIBLE | 
					
						
							|  |  |  | 				| TF_OBCOL | 
					
						
							|  |  |  | 				| TF_BILLBOARD2 | 
					
						
							|  |  |  | 				| TF_SHADOW | 
					
						
							|  |  |  | 				| TF_BMFONT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !self->mesh->tface ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no texture values" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( !MFace_get_pointer( self ) ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	if( !PyInt_CheckExact ( value ) ) { | 
					
						
							|  |  |  | 		char errstr[128]; | 
					
						
							|  |  |  | 		sprintf ( errstr , "expected int bitmask of 0x%04x", bitmask ); | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, errstr ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	param = PyInt_AS_LONG ( value ); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if( param == 0xffff )		/* if param is ALL, set everything but HALO */ | 
					
						
							|  |  |  | 		param = bitmask ^ TF_BILLBOARD; | 
					
						
							|  |  |  | 	else if( ( param & bitmask ) != param ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 						"invalid bit(s) set in mask" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Blender UI doesn't allow these on at the same time */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( ( param & (TF_BILLBOARD | TF_BILLBOARD2) ) ==  | 
					
						
							|  |  |  | 			(TF_BILLBOARD | TF_BILLBOARD2) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 						"HALO and BILLBOARD cannot be enabled simultaneously" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 20:48:43 +00:00
										 |  |  | 	self->mesh->tface[self->index].mode = (short)param; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * get face's texture transparency setting | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFace_getTransp( BPy_MFace *self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *attr; | 
					
						
							|  |  |  | 	if( !self->mesh->tface ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no texture values" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( !MFace_get_pointer( self ) ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	attr = PyInt_FromLong( self->mesh->tface[self->index].transp ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( attr ) | 
					
						
							|  |  |  | 		return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 			"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * set face's texture transparency setting | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MFace_setTransp( BPy_MFace *self, PyObject *value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if( !self->mesh->tface ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no texture values" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( !MFace_get_pointer( self ) ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	return EXPP_setIValueRange( value, | 
					
						
							|  |  |  | 			&self->mesh->tface[self->index].transp, TF_SOLID, TF_SUB, 'b' ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  |  * get a face's texture UV coord values | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFace_getUV( BPy_MFace * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	TFace *face; | 
					
						
							|  |  |  | 	PyObject *attr; | 
					
						
							|  |  |  | 	int length, i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !self->mesh->tface ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no texture values" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( !MFace_get_pointer( self ) ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	face = &self->mesh->tface[self->index]; | 
					
						
							|  |  |  | 	length = self->mesh->mface[self->index].v4 ? 4 : 3; | 
					
						
							|  |  |  | 	attr = PyTuple_New( length ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !attr ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"PyTuple_New() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for( i=0; i<length; ++i ) { | 
					
						
							|  |  |  | 		PyObject *vector = newVectorObject( face->uv[i], 2, Py_WRAP ); | 
					
						
							|  |  |  | 		if( !vector ) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		PyTuple_SetItem( attr, i, vector ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return attr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  |  * set a face's texture UV coord values | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MFace_setUV( BPy_MFace * self, PyObject * value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	TFace *face; | 
					
						
							|  |  |  | 	int length, i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( !MFace_get_pointer( self ) ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 	if( !PySequence_Check( value ) || | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | 			EXPP_check_sequence_consistency( value, &vector_Type ) != 1 ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 					    "expected sequence of vectors" ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	length = self->mesh->mface[self->index].v4 ? 4 : 3; | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 	if( length != PySequence_Size( value ) ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 					    "size of vertex and UV sequences differ" ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-05 07:19:37 +00:00
										 |  |  | 	if( !self->mesh->tface ) | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no texture values" ); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 		make_tfaces( self->mesh ); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	face = &self->mesh->tface[self->index]; | 
					
						
							|  |  |  | 	for( i=0; i<length; ++i ) { | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 		VectorObject *vector = (VectorObject *)PySequence_ITEM( value, i ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		face->uv[i][0] = vector->vec[0]; | 
					
						
							|  |  |  | 		face->uv[i][1] = vector->vec[1]; | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 		Py_DECREF( vector ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * get a face's texture UV coord select state | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFace_getUVSel( BPy_MFace * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	TFace *face; | 
					
						
							|  |  |  | 	PyObject *attr; | 
					
						
							|  |  |  | 	int length, i, mask; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !self->mesh->tface ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no texture values" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( !MFace_get_pointer( self ) ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	face = &self->mesh->tface[self->index]; | 
					
						
							|  |  |  | 	length = self->mesh->mface[self->index].v4 ? 4 : 3; | 
					
						
							|  |  |  | 	attr = PyTuple_New( length ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !attr ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"PyTuple_New() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* get coord select state, one bit at a time */ | 
					
						
							|  |  |  | 	mask = TF_SEL1; | 
					
						
							|  |  |  | 	for( i=0; i<length; ++i, mask <<= 1 ) { | 
					
						
							|  |  |  | 		PyObject *value = PyInt_FromLong( face->flag & mask ? 1 : 0 ); | 
					
						
							|  |  |  | 		if( !value ) { | 
					
						
							|  |  |  | 			Py_DECREF( attr ); | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		PyTuple_SetItem( attr, i, value ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return attr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * set a face's texture UV coord select state | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MFace_setUVSel( BPy_MFace * self, PyObject * value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	TFace *face; | 
					
						
							|  |  |  | 	int length, i, mask; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( !MFace_get_pointer( self ) ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	if( !PySequence_Check( value ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected a tuple of integers" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	length = self->mesh->mface[self->index].v4 ? 4 : 3; | 
					
						
							| 
									
										
										
										
											2006-06-06 17:04:00 +00:00
										 |  |  | 	if( length != PySequence_Size( value ) ) | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 					    "size of vertex and UV lists differ" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-05 07:19:37 +00:00
										 |  |  | 	if( !self->mesh->tface ) | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no texture values" ); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 		make_tfaces( self->mesh ); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	/* set coord select state, one bit at a time */ | 
					
						
							|  |  |  | 	face = &self->mesh->tface[self->index]; | 
					
						
							|  |  |  | 	mask = TF_SEL1; | 
					
						
							|  |  |  | 	for( i=0; i<length; ++i, mask <<= 1 ) { | 
					
						
							| 
									
										
										
										
											2006-06-06 17:28:39 +00:00
										 |  |  | 		PyObject *tmp = PySequence_GetItem( value, i ); /* adds a reference, remove below */ | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		if( !PyInt_CheckExact( tmp ) ) { | 
					
						
							| 
									
										
										
										
											2006-06-06 17:28:39 +00:00
										 |  |  | 			Py_DECREF(tmp); | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 			return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 					"expected a tuple of integers" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if( PyInt_AsLong( tmp ) ) | 
					
						
							|  |  |  | 			face->flag |= mask; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			face->flag &= ~mask; | 
					
						
							| 
									
										
										
										
											2006-06-06 17:28:39 +00:00
										 |  |  | 		Py_DECREF(tmp); | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * get a face's vertex colors. note that if mesh->tfaces is defined, then  | 
					
						
							|  |  |  |  * it takes precedent over mesh->mcol | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFace_getCol( BPy_MFace * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *attr; | 
					
						
							|  |  |  | 	int length, i; | 
					
						
							|  |  |  | 	MCol * mcol; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if there's no mesh color vectors or texture faces, nothing to do */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !self->mesh->mcol && !self->mesh->tface ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no vertex colors" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( !MFace_get_pointer( self ) ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	if( self->mesh->tface ) | 
					
						
							|  |  |  | 		mcol = (MCol *) self->mesh->tface[self->index].col; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		mcol = &self->mesh->mcol[self->index*4]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	length = self->mesh->mface[self->index].v4 ? 4 : 3; | 
					
						
							|  |  |  | 	attr = PyTuple_New( length ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !attr ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"PyTuple_New() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for( i=0; i<length; ++i ) { | 
					
						
							|  |  |  | 		PyObject *color = MCol_CreatePyObject( &mcol[i] ); | 
					
						
							|  |  |  | 		if( !color ) | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		PyTuple_SetItem( attr, i, color ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return attr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-13 17:22:53 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * set a face's vertex colors | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MFace_setCol( BPy_MFace * self, PyObject *value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int length, i; | 
					
						
							|  |  |  | 	MCol * mcol; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if there's no mesh color vectors or texture faces, nothing to do */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !self->mesh->mcol && !self->mesh->tface ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no vertex colors" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !MFace_get_pointer( self ) ) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( self->mesh->tface ) | 
					
						
							|  |  |  | 		mcol = (MCol *) self->mesh->tface[self->index].col; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		mcol = &self->mesh->mcol[self->index*4]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	length = self->mesh->mface[self->index].v4 ? 4 : 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyList_Check( value ) && !PyTuple_Check( value ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected a sequence of MCols" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( EXPP_check_sequence_consistency( value, &MCol_Type ) != 1 ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected a sequence of MCols" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( PySequence_Size( value ) != length ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"incorrect number of colors for this face" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for( i=0; i<length; ++i ) { | 
					
						
							|  |  |  | 		BPy_MCol *obj = (BPy_MCol *)PySequence_ITEM( value, i ); | 
					
						
							|  |  |  | 		mcol[i].r = obj->color->r; | 
					
						
							|  |  |  | 		mcol[i].g = obj->color->g; | 
					
						
							|  |  |  | 		mcol[i].b = obj->color->b; | 
					
						
							|  |  |  | 		mcol[i].a = obj->color->a; | 
					
						
							|  |  |  | 		Py_DECREF( obj ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MFace_Type attributes get/set structure | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyGetSetDef BPy_MFace_getseters[] = { | 
					
						
							|  |  |  |     {"verts", | 
					
						
							|  |  |  |      (getter)MFace_getVerts, (setter)MFace_setVerts, | 
					
						
							|  |  |  |      "face's vertices", | 
					
						
							|  |  |  |      NULL}, | 
					
						
							|  |  |  |     {"v", | 
					
						
							|  |  |  |      (getter)MFace_getVerts, (setter)MFace_setVerts, | 
					
						
							|  |  |  |      "deprecated: see 'verts'", | 
					
						
							|  |  |  |      NULL}, | 
					
						
							|  |  |  |     {"mat", | 
					
						
							|  |  |  |      (getter)MFace_getMat, (setter)MFace_setMat, | 
					
						
							|  |  |  |      "face's material index", | 
					
						
							|  |  |  |      NULL}, | 
					
						
							|  |  |  |     {"index", | 
					
						
							|  |  |  |      (getter)MFace_getIndex, (setter)NULL, | 
					
						
							|  |  |  |      "face's index", | 
					
						
							|  |  |  |      NULL}, | 
					
						
							|  |  |  |     {"no", | 
					
						
							|  |  |  |      (getter)MFace_getNormal, (setter)NULL, | 
					
						
							|  |  |  |      "face's normal", | 
					
						
							|  |  |  |      NULL}, | 
					
						
							| 
									
										
										
										
											2006-05-11 10:06:15 +00:00
										 |  |  |     {"cent", | 
					
						
							|  |  |  |      (getter)MFace_getCent, (setter)NULL, | 
					
						
							|  |  |  |      "face's center", | 
					
						
							|  |  |  |      NULL}, | 
					
						
							|  |  |  |     {"area", | 
					
						
							|  |  |  |      (getter)MFace_getArea, (setter)NULL, | 
					
						
							|  |  |  |      "face's 3D area", | 
					
						
							|  |  |  |      NULL}, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     {"hide", | 
					
						
							|  |  |  |      (getter)MFace_getMFlagBits, (setter)MFace_setMFlagBits, | 
					
						
							|  |  |  |      "face hidden in edit mode", | 
					
						
							|  |  |  |      (void *)ME_HIDE}, | 
					
						
							|  |  |  |     {"sel", | 
					
						
							| 
									
										
										
										
											2006-04-07 02:49:15 +00:00
										 |  |  |      (getter)MFace_getMFlagBits, (setter)MFace_setSelect, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |      "face selected in edit mode", | 
					
						
							|  |  |  |      (void *)ME_FACE_SEL}, | 
					
						
							|  |  |  |     {"smooth", | 
					
						
							|  |  |  |      (getter)MFace_getMFlagBits, (setter)MFace_setMFlagBits, | 
					
						
							|  |  |  |      "face smooth enabled", | 
					
						
							|  |  |  |      (void *)ME_SMOOTH}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* attributes for texture faces (mostly, I think) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     {"col", | 
					
						
							| 
									
										
										
										
											2006-01-13 17:22:53 +00:00
										 |  |  |      (getter)MFace_getCol, (setter)MFace_setCol, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |      "face's vertex colors", | 
					
						
							|  |  |  |      NULL}, | 
					
						
							|  |  |  |     {"flag", | 
					
						
							|  |  |  |      (getter)MFace_getFlag, (setter)MFace_setFlag, | 
					
						
							|  |  |  |      "flags associated with texture faces", | 
					
						
							|  |  |  |      NULL}, | 
					
						
							|  |  |  |     {"image", | 
					
						
							|  |  |  |      (getter)MFace_getImage, (setter)MFace_setImage, | 
					
						
							|  |  |  |      "image associated with texture faces", | 
					
						
							|  |  |  |      NULL}, | 
					
						
							|  |  |  |     {"mode", | 
					
						
							|  |  |  |      (getter)MFace_getMode, (setter)MFace_setMode, | 
					
						
							|  |  |  |      "modes associated with texture faces", | 
					
						
							|  |  |  |      NULL}, | 
					
						
							|  |  |  |     {"transp", | 
					
						
							|  |  |  |      (getter)MFace_getTransp, (setter)MFace_setTransp, | 
					
						
							|  |  |  |      "transparency of texture faces", | 
					
						
							|  |  |  |      NULL}, | 
					
						
							|  |  |  |     {"uv", | 
					
						
							|  |  |  |      (getter)MFace_getUV, (setter)MFace_setUV, | 
					
						
							|  |  |  |      "face's UV coordinates", | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  |      NULL}, | 
					
						
							|  |  |  |     {"uvSel", | 
					
						
							|  |  |  |      (getter)MFace_getUVSel, (setter)MFace_setUVSel, | 
					
						
							|  |  |  |      "face's UV coordinates select status", | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |      NULL}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MFace_Type iterator (iterates over vertices) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Initialize the interator index | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFace_getIter( BPy_MFace * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	if (self->iter==-1) { | 
					
						
							|  |  |  | 		self->iter = 0; | 
					
						
							|  |  |  | 		return EXPP_incr_ret ( (PyObject *) self ); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		BPy_MFace *seq= (BPy_MFace *)MFace_CreatePyObject(self->mesh, self->index); | 
					
						
							|  |  |  | 		seq->iter = 0; | 
					
						
							|  |  |  | 		return (PyObject *) seq; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Return next MVert.  Throw an exception after the final vertex. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFace_nextIter( BPy_MFace * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct MFace *face = &self->mesh->mface[self->index]; | 
					
						
							|  |  |  | 	int len = self->mesh->mface[self->index].v4 ? 4 : 3; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	if( self->iter == len ) { | 
					
						
							|  |  |  | 		self->iter = -1; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		return EXPP_ReturnPyObjError( PyExc_StopIteration, | 
					
						
							|  |  |  | 				"iterator at end" ); | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	++self->iter; | 
					
						
							|  |  |  | 	switch ( self->iter ) { | 
					
						
							|  |  |  | 	case 1: | 
					
						
							|  |  |  | 		return MVert_CreatePyObject( self->mesh, face->v1 ); | 
					
						
							|  |  |  | 	case 2: | 
					
						
							|  |  |  | 		return MVert_CreatePyObject( self->mesh, face->v2 ); | 
					
						
							|  |  |  | 	case 3: | 
					
						
							|  |  |  | 		return MVert_CreatePyObject( self->mesh, face->v3 ); | 
					
						
							|  |  |  | 	default : | 
					
						
							|  |  |  | 		return MVert_CreatePyObject( self->mesh, face->v4 ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MFace_Type methods | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MFace_Type standard operations | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void MFace_dealloc( BPy_MFace * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject_DEL( self ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MFace_compare( BPy_MFace * a, BPy_MFace * b ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return( a->mesh == b->mesh && a->index == b->index ) ? 0 : -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFace_repr( BPy_MFace* self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	MFace *face = MFace_get_pointer( self ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !face ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( face->v4 ) | 
					
						
							|  |  |  | 		return PyString_FromFormat( "[MFace (%d %d %d %d) %d]", | 
					
						
							|  |  |  | 				(int)face->v1, (int)face->v2,  | 
					
						
							|  |  |  | 				(int)face->v3, (int)face->v4, (int)self->index );  | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return PyString_FromFormat( "[MFace (%d %d %d) %d]", | 
					
						
							|  |  |  | 				(int)face->v1, (int)face->v2, | 
					
						
							|  |  |  | 				(int)face->v3, (int)self->index );  | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 21:12:33 +00:00
										 |  |  | static long MFace_hash( BPy_MFace *self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return (long)self->index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-06 18:14:31 +00:00
										 |  |  | static int MFace_len( BPy_MFace * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if( self->index >= self->mesh->totface ) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	return self->mesh->mface[self->index].v4 ? 4 : 3; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PySequenceMethods MFace_as_sequence = { | 
					
						
							|  |  |  | 	( inquiry ) MFace_len,         /* sq_length */ | 
					
						
							|  |  |  | 	( binaryfunc ) 0,	           /* sq_concat */ | 
					
						
							|  |  |  | 	( intargfunc ) 0,	           /* sq_repeat */ | 
					
						
							|  |  |  | 	( intargfunc ) 0,              /* sq_item */ | 
					
						
							|  |  |  | 	( intintargfunc ) 0,           /* sq_slice */ | 
					
						
							|  |  |  | 	( intobjargproc ) 0,           /* sq_ass_item */ | 
					
						
							|  |  |  | 	( intintobjargproc ) 0,        /* sq_ass_slice */ | 
					
						
							|  |  |  | 	0,0,0, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MFace_Type structure definition | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyTypeObject MFace_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT( NULL )  /* required py macro */ | 
					
						
							|  |  |  | 	0,                          /* ob_size */ | 
					
						
							|  |  |  | 	/*  For printing, in format "<module>.<name>" */ | 
					
						
							|  |  |  | 	"Blender MFace",            /* char *tp_name; */ | 
					
						
							|  |  |  | 	sizeof( BPy_MFace ),        /* int tp_basicsize; */ | 
					
						
							|  |  |  | 	0,                          /* tp_itemsize;  For allocation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Methods to implement standard operations */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	( destructor ) MFace_dealloc,/* destructor tp_dealloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* printfunc tp_print; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrfunc tp_getattr; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrfunc tp_setattr; */ | 
					
						
							|  |  |  | 	( cmpfunc ) MFace_compare,  /* cmpfunc tp_compare; */ | 
					
						
							|  |  |  | 	( reprfunc ) MFace_repr,    /* reprfunc tp_repr; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Method suites for standard classes */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /* PyNumberMethods *tp_as_number; */ | 
					
						
							| 
									
										
										
										
											2006-06-06 18:14:31 +00:00
										 |  |  | 	&MFace_as_sequence,         /* PySequenceMethods *tp_as_sequence; */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	NULL,                       /* PyMappingMethods *tp_as_mapping; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* More standard operations (here for binary compatibility) */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 21:12:33 +00:00
										 |  |  | 	( hashfunc ) MFace_hash,    /* hashfunc tp_hash; */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	NULL,                       /* ternaryfunc tp_call; */ | 
					
						
							|  |  |  | 	NULL,                       /* reprfunc tp_str; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrofunc tp_getattro; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrofunc tp_setattro; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Functions to access object as input/output buffer */ | 
					
						
							|  |  |  | 	NULL,                       /* PyBufferProcs *tp_as_buffer; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Flags to define presence of optional/expanded features ***/ | 
					
						
							|  |  |  | 	Py_TPFLAGS_DEFAULT,         /* long tp_flags; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /*  char *tp_doc;  Documentation string */ | 
					
						
							|  |  |  |   /*** Assigned meaning in release 2.0 ***/ | 
					
						
							|  |  |  | 	/* call function for all accessible objects */ | 
					
						
							|  |  |  | 	NULL,                       /* traverseproc tp_traverse; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* delete references to contained objects */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_clear; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  Assigned meaning in release 2.1 ***/ | 
					
						
							|  |  |  |   /*** rich comparisons ***/ | 
					
						
							|  |  |  | 	NULL,                       /* richcmpfunc tp_richcompare; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  weak reference enabler ***/ | 
					
						
							|  |  |  | 	0,                          /* long tp_weaklistoffset; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Added in release 2.2 ***/ | 
					
						
							|  |  |  | 	/*   Iterators */ | 
					
						
							|  |  |  | 	( getiterfunc ) MFace_getIter, /* getiterfunc tp_iter; */ | 
					
						
							|  |  |  | 	( iternextfunc ) MFace_nextIter, /* iternextfunc tp_iternext; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Attribute descriptor and subclassing stuff ***/ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyMethodDef *tp_methods; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyMemberDef *tp_members; */ | 
					
						
							|  |  |  | 	BPy_MFace_getseters,        /* struct PyGetSetDef *tp_getset; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct _typeobject *tp_base; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_dict; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrgetfunc tp_descr_get; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrsetfunc tp_descr_set; */ | 
					
						
							|  |  |  | 	0,                          /* long tp_dictoffset; */ | 
					
						
							|  |  |  | 	NULL,                       /* initproc tp_init; */ | 
					
						
							|  |  |  | 	NULL,                       /* allocfunc tp_alloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* newfunc tp_new; */ | 
					
						
							|  |  |  | 	/*  Low-level free-memory routine */ | 
					
						
							|  |  |  | 	NULL,                       /* freefunc tp_free;  */ | 
					
						
							|  |  |  | 	/* For PyObject_IS_GC */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_is_gc;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_bases; */ | 
					
						
							|  |  |  | 	/* method resolution order */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_mro;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_cache; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_subclasses; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_weaklist; */ | 
					
						
							|  |  |  | 	NULL | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFace_CreatePyObject( Mesh * mesh, int i ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BPy_MFace *obj = PyObject_NEW( BPy_MFace, &MFace_Type ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !obj ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"PyObject_New() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	obj->mesh = mesh; | 
					
						
							|  |  |  | 	obj->index = i; | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	obj->iter= -1; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	return (PyObject *)obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Face sequence  | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int MFaceSeq_len( BPy_MFaceSeq * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return self->mesh->totface; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFaceSeq_item( BPy_MFaceSeq * self, int i ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if( i < 0 || i >= self->mesh->totface ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_IndexError, | 
					
						
							|  |  |  | 					      "array index out of range" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return MFace_CreatePyObject( self->mesh, i ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PySequenceMethods MFaceSeq_as_sequence = { | 
					
						
							|  |  |  | 	( inquiry ) MFaceSeq_len,      /* sq_length */ | 
					
						
							|  |  |  | 	( binaryfunc ) 0,	           /* sq_concat */ | 
					
						
							|  |  |  | 	( intargfunc ) 0,	           /* sq_repeat */ | 
					
						
							|  |  |  | 	( intargfunc ) MFaceSeq_item,  /* sq_item */ | 
					
						
							|  |  |  | 	( intintargfunc ) 0,           /* sq_slice */ | 
					
						
							|  |  |  | 	( intobjargproc ) 0,           /* sq_ass_item */ | 
					
						
							|  |  |  | 	( intintobjargproc ) 0,        /* sq_ass_slice */ | 
					
						
							|  |  |  | 	0,0,0, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MFaceSeq_Type iterator (iterates over faces) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Initialize the interator index | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFaceSeq_getIter( BPy_MFaceSeq * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	if (self->iter==-1) { | 
					
						
							|  |  |  | 		self->iter = 0; | 
					
						
							|  |  |  | 		return EXPP_incr_ret ( (PyObject *) self ); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		BPy_MFaceSeq *seq = (BPy_MFaceSeq *)MFaceSeq_CreatePyObject(self->mesh); | 
					
						
							|  |  |  | 		seq->iter = 0; | 
					
						
							|  |  |  | 		return (PyObject *)seq; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Return next MFace. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFaceSeq_nextIter( BPy_MFaceSeq * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	if( self->iter == self->mesh->totface ) { | 
					
						
							|  |  |  | 		self->iter= -1; /* not being used in a seq */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		return EXPP_ReturnPyObjError( PyExc_StopIteration, | 
					
						
							|  |  |  | 				"iterator at end" ); | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	return MFace_CreatePyObject( self->mesh, self->iter++ ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MFaceSeq_Type methods | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-24 20:02:22 +00:00
										 |  |  | static PyObject *MFaceSeq_extend( BPy_MEdgeSeq * self, PyObject *args, | 
					
						
							|  |  |  | 	  PyObject *keywds ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * (a) check input for valid edge objects, faces which consist of | 
					
						
							|  |  |  | 	 *     only three or four edges | 
					
						
							|  |  |  | 	 * (b) check input to be sure edges form a closed face (each edge | 
					
						
							|  |  |  | 	 *     contains verts in two other different edges?) | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * (1) build list of new faces; remove duplicates | 
					
						
							|  |  |  | 	 *   * use existing "v4=0 rule" for 3-vert faces | 
					
						
							|  |  |  | 	 * (2) build list of existing faces for searching | 
					
						
							|  |  |  | 	 * (3) from new face list, remove existing faces: | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int len, nverts; | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 	int i, j, k, new_face_count; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	int good_faces; | 
					
						
							|  |  |  | 	SrchFaces *oldpair, *newpair, *tmppair, *tmppair2; | 
					
						
							|  |  |  | 	PyObject *tmp; | 
					
						
							|  |  |  | 	MFace *tmpface; | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							| 
									
										
										
										
											2006-08-24 20:02:22 +00:00
										 |  |  | 	int ignore_dups = 0; | 
					
						
							|  |  |  | 	PyObject *return_list = NULL; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 	/* before we try to add faces, add edges; if it fails; exit */ | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	tmp = MEdgeSeq_extend( self, args ); | 
					
						
							|  |  |  | 	if( !tmp ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	Py_DECREF( tmp ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-24 20:02:22 +00:00
										 |  |  | 	/* process any keyword arguments */ | 
					
						
							|  |  |  | 	if( keywds ) { | 
					
						
							|  |  |  | 		PyObject *res = PyDict_GetItemString( keywds, "ignoreDups" ); | 
					
						
							|  |  |  | 		if( res ) | 
					
						
							|  |  |  | 			ignore_dups = PyObject_IsTrue( res ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		res = PyDict_GetItemString( keywds, "indexList" ); | 
					
						
							|  |  |  | 		if( res && PyObject_IsTrue( res ) ) | 
					
						
							|  |  |  | 			return_list = PyList_New( 0 ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-13 07:11:30 +00:00
										 |  |  | 	/* make sure we get a tuple of sequences of something */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 	switch( PySequence_Size( args ) ) { | 
					
						
							|  |  |  | 	case 1:		/* better be a sequence or a tuple */ | 
					
						
							|  |  |  | 		/* if a sequence... */ | 
					
						
							|  |  |  | 		tmp = PyTuple_GET_ITEM( args, 0 ); | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 		if( PySequence_Check( tmp ) ) { | 
					
						
							| 
									
										
										
										
											2006-02-17 17:50:54 +00:00
										 |  |  | 			PyObject *tmp2; | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* ignore empty sequences */ | 
					
						
							|  |  |  | 			if( !PySequence_Size( tmp ) ) { | 
					
						
							|  |  |  | 				Py_RETURN_NONE; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 			/* if another sequence, use it */ | 
					
						
							| 
									
										
										
										
											2006-02-10 21:10:58 +00:00
										 |  |  | 			tmp2 = PySequence_ITEM( tmp, 0 ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 			if( PySequence_Check( tmp2 ) ) | 
					
						
							|  |  |  | 				args = tmp; | 
					
						
							| 
									
										
										
										
											2006-01-13 07:11:30 +00:00
										 |  |  | 			Py_INCREF( args ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 			Py_DECREF( tmp2 ); | 
					
						
							|  |  |  | 		} else | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 					"expected a sequence of sequence pairs" ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case 2:	 | 
					
						
							|  |  |  | 	case 3: | 
					
						
							|  |  |  | 	case 4:		/* two to four args may be individual verts */ | 
					
						
							|  |  |  | 		tmp = PyTuple_GET_ITEM( args, 0 ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * if first item isn't a sequence, then assume it's a bunch of MVerts | 
					
						
							|  |  |  | 		 * and wrap inside a tuple | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		if( !PySequence_Check( tmp ) ) { | 
					
						
							|  |  |  | 			args = Py_BuildValue( "(O)", args ); | 
					
						
							|  |  |  | 			if( !args ) | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 						"Py_BuildValue() failed" ); | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * otherwise, assume it already a bunch of sequences so use as-is | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		} else {  | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			Py_INCREF( args );		/* so we can safely DECREF later */ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default:	/* anything else is definitely wrong */ | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 				"expected a sequence of sequence pairs" ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 	/* if nothing to add, just exit */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	len = PySequence_Size( args ); | 
					
						
							|  |  |  | 	if( len == 0 ) { | 
					
						
							|  |  |  | 		Py_DECREF( args ); | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 		Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 	/* 
 | 
					
						
							|  |  |  | 	 * Since we call MEdgeSeq_extend first, we already know the input list | 
					
						
							|  |  |  | 	 * is valid.  Here we just need to count the total number of faces. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	new_face_count = 0; | 
					
						
							|  |  |  | 	for( i = 0; i < len; ++i ) { | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 		tmp = PySequence_ITEM( args, i ); | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 		nverts = PySequence_Size( tmp ); | 
					
						
							| 
									
										
										
										
											2006-08-25 16:01:16 +00:00
										 |  |  | 		if( return_list || nverts != 2 )		 | 
					
						
							|  |  |  | 			++new_face_count; /* new faces must have 3 or 4 verts */ | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 		Py_DECREF( tmp ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* OK, commit to allocating the search structures */ | 
					
						
							|  |  |  | 	newpair = (SrchFaces *)MEM_callocN( sizeof(SrchFaces)*new_face_count, | 
					
						
							|  |  |  | 			"MFacePairs" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* scan the input list and build the new face pair list */ | 
					
						
							|  |  |  | 	len = PySequence_Size( args ); | 
					
						
							|  |  |  | 	tmppair = newpair; | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	for( i = 0; i < len; ++i ) { | 
					
						
							| 
									
										
										
										
											2005-10-11 13:36:07 +00:00
										 |  |  | 		MFace tmpface; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		unsigned int vert[4]={0,0,0,0}; | 
					
						
							|  |  |  | 		unsigned char order[4]={0,1,2,3}; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		tmp = PySequence_GetItem( args, i ); | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 		nverts = PySequence_Size( tmp ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-05 19:15:58 +00:00
										 |  |  | 		if( nverts == 2 ) {	/* again, ignore 2-vert tuples */ | 
					
						
							| 
									
										
										
										
											2006-08-25 16:01:16 +00:00
										 |  |  | 			if( return_list )	/* if returning indices, mark as deleted */ | 
					
						
							|  |  |  | 				tmppair->v[1] = 0; | 
					
						
							| 
									
										
										
										
											2006-02-05 19:15:58 +00:00
										 |  |  | 			Py_DECREF( tmp ); | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 		/*
 | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 		 * get the face's vertices' indexes | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 		for( j = 0; j < nverts; ++j ) { | 
					
						
							|  |  |  | 			PyObject *item = PySequence_ITEM( tmp, j ); | 
					
						
							|  |  |  | 			if( BPy_MVert_Check( item ) ) | 
					
						
							|  |  |  | 				vert[j] = ((BPy_MVert *)item)->index; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				vert[j] = PyInt_AsLong( item ); | 
					
						
							|  |  |  | 			Py_DECREF( item ); | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		Py_DECREF( tmp ); | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 		tmpface.v1 = vert[0]; | 
					
						
							|  |  |  | 		tmpface.v2 = vert[1]; | 
					
						
							|  |  |  | 		tmpface.v3 = vert[2]; | 
					
						
							|  |  |  | 		tmpface.v4 = vert[3]; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * go through some contortions to guarantee the third and fourth | 
					
						
							|  |  |  | 		 * vertices are not index 0 | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		eeek_fix( &tmpface, NULL, nverts==4 ); | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 		vert[0] = tmpface.v1; | 
					
						
							|  |  |  | 		vert[1] = tmpface.v2; | 
					
						
							|  |  |  | 		vert[2] = tmpface.v3; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		if( nverts == 3 ) | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 			vert[3] = tmppair->v[3] = 0; | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 		else | 
					
						
							|  |  |  | 			vert[3] = tmpface.v4; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * sort the verts before placing in pair list.  the order of | 
					
						
							|  |  |  | 		 * vertices in the face is very important, so keep track of | 
					
						
							|  |  |  | 		 * the original order | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for( j = nverts-1; j >= 0; --j ) { | 
					
						
							|  |  |  | 			for( k = 0; k < j; ++k ) { | 
					
						
							|  |  |  | 				if( vert[k] > vert[k+1] ) { | 
					
						
							|  |  |  | 					SWAP( int, vert[k], vert[k+1] ); | 
					
						
							|  |  |  | 					SWAP( char, order[k], order[k+1] ); | 
					
						
							|  |  |  | 				} else if( vert[k] == vert[k+1] ) { | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 			if( k < j ) | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			tmppair->v[j] = vert[j]; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-08-25 16:01:16 +00:00
										 |  |  | 		if( j >= 0 ) {				/* a duplicate vertex found */ | 
					
						
							|  |  |  | 			if( return_list ) {		/* if returning index list */ | 
					
						
							|  |  |  | 				tmppair->v[1] = 0;	/*    mark as deleted */ | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				--new_face_count;	/* otherwise skip */ | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-02-10 00:08:06 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 		tmppair->index = i; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* pack order into a byte */ | 
					
						
							|  |  |  | 		tmppair->order = order[0]|(order[1]<<2)|(order[2]<<4)|(order[3]<<6); | 
					
						
							|  |  |  | 		++tmppair; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * find duplicates in the new list and mark.  if it's a duplicate, | 
					
						
							|  |  |  | 	 * then mark by setting second vert index to 0 (a real edge won't have | 
					
						
							|  |  |  | 	 * second vert index of 0 since verts are sorted) | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	good_faces = new_face_count;	/* assume all faces good to start */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmppair = newpair;	/* "last good edge" */ | 
					
						
							|  |  |  | 	tmppair2 = &tmppair[1];	/* "current candidate edge" */ | 
					
						
							| 
									
										
										
										
											2006-08-24 20:02:22 +00:00
										 |  |  | 	if( !ignore_dups ) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* sort the new face pairs */ | 
					
						
							|  |  |  | 		qsort( newpair, new_face_count, sizeof(SrchFaces), mface_comp ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for( i = 0; i < new_face_count; ++i ) { | 
					
						
							|  |  |  | 			if( mface_comp( tmppair, tmppair2 ) ) | 
					
						
							|  |  |  | 				tmppair = tmppair2;	/* last != current, so current == last */ | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				tmppair2->v[1] = 0; /* last == current, so mark as duplicate */ | 
					
						
							|  |  |  | 				--good_faces;		/* one less good face */ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			tmppair2++; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if mesh has faces, see if any of the new faces are already in it */ | 
					
						
							| 
									
										
										
										
											2006-08-24 20:02:22 +00:00
										 |  |  | 	if( mesh->totface && !ignore_dups ) { | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		oldpair = (SrchFaces *)MEM_callocN( sizeof(SrchFaces)*mesh->totface, | 
					
						
							|  |  |  | 				"MFacePairs" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tmppair = oldpair; | 
					
						
							|  |  |  | 		tmpface = mesh->mface; | 
					
						
							|  |  |  | 		for( i = 0; i < mesh->totface; ++i ) { | 
					
						
							|  |  |  | 			unsigned char order[4]={0,1,2,3}; | 
					
						
							| 
									
										
										
										
											2005-10-03 20:48:43 +00:00
										 |  |  | 			int verts[4]; | 
					
						
							|  |  |  | 			verts[0]=tmpface->v1; | 
					
						
							|  |  |  | 			verts[1]=tmpface->v2; | 
					
						
							|  |  |  | 			verts[2]=tmpface->v3; | 
					
						
							|  |  |  | 			verts[3]=tmpface->v4; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 			len = ( tmpface->v4 ) ? 3 : 2; | 
					
						
							|  |  |  | 			tmppair->v[3] = 0;	/* for triangular faces */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* sort the verts before placing in pair list here too */ | 
					
						
							|  |  |  | 			for( j = len; j >= 0; --j ) { | 
					
						
							|  |  |  | 				for( k = 0; k < j; ++k ) | 
					
						
							|  |  |  | 					if( verts[k] > verts[k+1] ) { | 
					
						
							|  |  |  | 						SWAP( int, verts[k], verts[k+1] ); | 
					
						
							|  |  |  | 						SWAP( unsigned char, order[k], order[k+1] ); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				tmppair->v[j] = verts[j]; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* pack order into a byte */ | 
					
						
							|  |  |  | 			tmppair->order = order[0]|(order[1]<<2)|(order[2]<<4)|(order[3]<<6); | 
					
						
							|  |  |  | 			++tmppair; | 
					
						
							|  |  |  | 			++tmpface; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* sort the old face pairs */ | 
					
						
							|  |  |  | 		qsort( oldpair, mesh->totface, sizeof(SrchFaces), mface_comp ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* eliminate new faces already in the mesh */ | 
					
						
							|  |  |  | 		tmppair = newpair; | 
					
						
							| 
									
										
										
										
											2006-08-24 20:02:22 +00:00
										 |  |  | 		for( i = good_faces; i ; ) { | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			if( tmppair->v[1] ) { | 
					
						
							|  |  |  | 				if( bsearch( tmppair, oldpair, mesh->totface,  | 
					
						
							|  |  |  | 						sizeof(SrchFaces), mface_comp ) ) { | 
					
						
							|  |  |  | 					tmppair->v[1] = 0;	/* mark as duplicate */ | 
					
						
							|  |  |  | 					--good_faces; | 
					
						
							| 
									
										
										
										
											2006-08-24 19:28:36 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				--i; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			tmppair++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		MEM_freeN( oldpair ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if any new faces are left, add to list */ | 
					
						
							| 
									
										
										
										
											2006-08-24 20:02:22 +00:00
										 |  |  | 	if( good_faces || return_list ) { | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 		int totface = mesh->totface+good_faces;	/* new face count */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-01 15:43:34 +00:00
										 |  |  | 	/* if mesh has tfaces, reallocate them first */ | 
					
						
							|  |  |  | 		if( mesh->tface ) { | 
					
						
							|  |  |  | 			TFace *tmptface; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			tmptface = MEM_callocN(totface*sizeof(TFace), "Mesh_addFaces"); | 
					
						
							|  |  |  | 			memcpy( tmptface, mesh->tface, mesh->totface*sizeof(TFace)); | 
					
						
							|  |  |  | 			MEM_freeN( mesh->tface ); | 
					
						
							|  |  |  | 			mesh->tface = tmptface; | 
					
						
							| 
									
										
										
										
											2006-07-28 07:08:27 +00:00
										 |  |  | 			 | 
					
						
							|  |  |  | 			/* make new faces tex faces have default tex values */ | 
					
						
							|  |  |  | 			tmptface= mesh->tface + mesh->totface; | 
					
						
							|  |  |  | 			for( i = good_faces; i-- ; ) { | 
					
						
							|  |  |  | 				default_tface(tmptface); | 
					
						
							|  |  |  | 				tmptface++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 		} else if( mesh->mcol ) { | 
					
						
							|  |  |  | 			MCol *tmpmcol; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			tmpmcol = MEM_callocN(totface*4*sizeof(MCol), "Mesh_addFaces"); | 
					
						
							|  |  |  | 			memcpy( tmpmcol, mesh->mcol, mesh->totface*4*sizeof(MCol)); | 
					
						
							|  |  |  | 			MEM_freeN( mesh->mcol ); | 
					
						
							|  |  |  | 			mesh->mcol = tmpmcol; | 
					
						
							| 
									
										
										
										
											2006-01-01 15:43:34 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 	/* sort the faces back into their original input list order */ | 
					
						
							| 
									
										
										
										
											2006-08-24 20:02:22 +00:00
										 |  |  | 		if( !ignore_dups ) | 
					
						
							|  |  |  | 			qsort( newpair, new_face_count, sizeof(SrchFaces), | 
					
						
							|  |  |  | 					mface_index_comp ); | 
					
						
							| 
									
										
										
										
											2006-01-11 18:37:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	/* allocate new face list */ | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		tmpface = MEM_callocN(totface*sizeof(MFace), "Mesh_addFaces"); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* if we're appending, copy the old face list and delete it */ | 
					
						
							|  |  |  | 		if( mesh->mface ) { | 
					
						
							|  |  |  | 			memcpy( tmpface, mesh->mface, mesh->totface*sizeof(MFace)); | 
					
						
							|  |  |  | 			MEM_freeN( mesh->mface ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		mesh->mface = tmpface;		/* point to the new face list */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* point to the first face we're going to add */ | 
					
						
							|  |  |  | 		tmpface = &mesh->mface[mesh->totface]; | 
					
						
							|  |  |  | 		tmppair = newpair; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-24 20:02:22 +00:00
										 |  |  | 		if( return_list ) | 
					
						
							|  |  |  | 			good_faces = new_face_count;	/* assume all faces good to start */ | 
					
						
							|  |  |  | 			 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	/* as we find a good face, add it */ | 
					
						
							|  |  |  | 		while ( good_faces ) { | 
					
						
							|  |  |  | 			if( tmppair->v[1] ) { | 
					
						
							|  |  |  | 				int i; | 
					
						
							|  |  |  | 				unsigned int index[4]; | 
					
						
							|  |  |  | 				unsigned char order = tmppair->order; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* unpack the order of the vertices */ | 
					
						
							|  |  |  | 				for( i = 0; i < 4; ++i ) { | 
					
						
							|  |  |  | 					index[(order & 0x03)] = i; | 
					
						
							|  |  |  | 					order >>= 2; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* now place vertices in the proper order */ | 
					
						
							|  |  |  | 				tmpface->v1 = tmppair->v[index[0]]; | 
					
						
							|  |  |  | 				tmpface->v2 = tmppair->v[index[1]]; | 
					
						
							|  |  |  | 				tmpface->v3 = tmppair->v[index[2]]; | 
					
						
							|  |  |  | 				tmpface->v4 = tmppair->v[index[3]]; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 				tmpface->flag = 0; | 
					
						
							| 
									
										
										
										
											2006-08-24 20:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				if( return_list ) | 
					
						
							|  |  |  | 					PyList_Append( return_list,  | 
					
						
							|  |  |  | 							PyInt_FromLong( mesh->totface ) ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 				mesh->totface++; | 
					
						
							|  |  |  | 				++tmpface; | 
					
						
							|  |  |  | 				--good_faces; | 
					
						
							| 
									
										
										
										
											2006-08-24 20:02:22 +00:00
										 |  |  | 			} else if( return_list ) { | 
					
						
							|  |  |  | 				Py_INCREF( Py_None ); | 
					
						
							|  |  |  | 				PyList_Append( return_list, Py_None ); | 
					
						
							|  |  |  | 				--good_faces; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			tmppair++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* clean up and leave */ | 
					
						
							|  |  |  | 	mesh_update( mesh ); | 
					
						
							|  |  |  | 	Py_DECREF ( args ); | 
					
						
							|  |  |  | 	MEM_freeN( newpair ); | 
					
						
							| 
									
										
										
										
											2006-08-24 20:02:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( return_list ) | 
					
						
							|  |  |  | 		return return_list; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		Py_RETURN_NONE; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | struct fourEdges | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	FaceEdges *v[4]; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFaceSeq_delete( BPy_MFaceSeq * self, PyObject *args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int *face_table; | 
					
						
							|  |  |  | 	int i, len; | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 	MFace *tmpface; | 
					
						
							|  |  |  | 	int face_count; | 
					
						
							|  |  |  | 	int edge_also = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* check for valid inputs */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( PySequence_Size( args ) != 2 || | 
					
						
							|  |  |  | 			!PyArg_ParseTuple( args, "iO", &edge_also, &args ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected and int and a sequence of ints or MFaces" ); | 
					
						
							| 
									
										
										
										
											2006-07-19 14:35:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyList_Check( args ) && !PyTuple_Check( args ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected and int and a sequence of ints or MFaces" ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	/* see how many args we need to parse */ | 
					
						
							|  |  |  | 	len = PySequence_Size( args ); | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 	if( len < 1 ) | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"sequence must contain at least one int or MFace" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	face_table = (unsigned int *)MEM_callocN( len*sizeof( unsigned int ), | 
					
						
							|  |  |  | 			"face_table" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* get the indices of faces to be removed */ | 
					
						
							|  |  |  | 	for( i = len; i--; ) { | 
					
						
							|  |  |  | 		PyObject *tmp = PySequence_GetItem( args, i ); | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  | 		if( BPy_MFace_Check( tmp ) ) | 
					
						
							|  |  |  | 			face_table[i] = ((BPy_MFace *)tmp)->index; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		else if( PyInt_CheckExact( tmp ) ) | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 			face_table[i] = PyInt_AsLong( tmp ); | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		else { | 
					
						
							|  |  |  | 			MEM_freeN( face_table ); | 
					
						
							|  |  |  | 			Py_DECREF( tmp ); | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					"expected a sequence of ints or MFaces" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		Py_DECREF( tmp ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* if index out-of-range, throw exception */ | 
					
						
							|  |  |  | 		if( face_table[i] >= (unsigned int)mesh->totface ) { | 
					
						
							|  |  |  | 			MEM_freeN( face_table ); | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 					"array index out of range" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( edge_also ) { | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * long version | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 * (1) build sorted table of all edges | 
					
						
							|  |  |  | 	 * (2) construct face->edge lookup table for all faces | 
					
						
							|  |  |  | 	 * 	   face->e1 = mesh->medge[i] | 
					
						
							|  |  |  | 	 * (3) (delete sorted table) | 
					
						
							|  |  |  | 	 * (4) mark all edges as live | 
					
						
							|  |  |  | 	 * (5) mark all edges for deleted faces as dead | 
					
						
							|  |  |  | 	 * (6) mark all edges for remaining faces as live | 
					
						
							|  |  |  | 	 * (7) delete all dead edges | 
					
						
							|  |  |  | 	 * (8) (delete face lookup table) | 
					
						
							|  |  |  | 	 * | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		FaceEdges *edge_table, *tmp_et; | 
					
						
							|  |  |  | 		MEdge *tmpedge; | 
					
						
							|  |  |  | 		FaceEdges **face_edges; | 
					
						
							|  |  |  | 		FaceEdges **tmp_fe; | 
					
						
							|  |  |  | 		struct fourEdges *fface; | 
					
						
							|  |  |  | 		int edge_count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		edge_table = MEM_mallocN( mesh->totedge*sizeof( FaceEdges ), | 
					
						
							|  |  |  | 			"edge_table" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tmpedge = mesh->medge; | 
					
						
							|  |  |  | 		tmp_et = edge_table; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for( i = 0; i < mesh->totedge; ++i ) { | 
					
						
							|  |  |  | 			if( tmpedge->v1 < tmpedge->v2 ) {  | 
					
						
							|  |  |  | 				tmp_et->v[0] = tmpedge->v1; | 
					
						
							|  |  |  | 				tmp_et->v[1] = tmpedge->v2; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				tmp_et->v[0] = tmpedge->v2; | 
					
						
							|  |  |  | 				tmp_et->v[1] = tmpedge->v1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			tmp_et->index = i; | 
					
						
							|  |  |  | 			tmp_et->sel = 1;		/* select each edge */ | 
					
						
							|  |  |  | 			++tmpedge;  | 
					
						
							|  |  |  | 			++tmp_et; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* sort the edge pairs */ | 
					
						
							|  |  |  | 		qsort( edge_table, mesh->totedge, sizeof(FaceEdges), faceedge_comp ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* build face translation table, lookup edges */ | 
					
						
							|  |  |  | 		face_edges = MEM_callocN( 4*sizeof(FaceEdges*)*mesh->totface, | 
					
						
							|  |  |  | 			"face_edges" );	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tmp_fe = face_edges; | 
					
						
							|  |  |  | 		tmpface = mesh->mface; | 
					
						
							|  |  |  | 		for( i = mesh->totface; i--; ++tmpface ) { | 
					
						
							|  |  |  | 			FaceEdges *ptrs[4]; | 
					
						
							|  |  |  | 			unsigned int verts[4]; | 
					
						
							|  |  |  | 			int j,k; | 
					
						
							|  |  |  | 			FaceEdges target; | 
					
						
							|  |  |  | 			int len=tmpface->v4 ? 4 : 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			ptrs[3] = NULL; | 
					
						
							|  |  |  | 			verts[0] = tmpface->v1; | 
					
						
							|  |  |  | 			verts[1] = tmpface->v2; | 
					
						
							|  |  |  | 			verts[2] = tmpface->v3; | 
					
						
							| 
									
										
										
										
											2006-01-12 07:51:19 +00:00
										 |  |  | 			if( len == 4 ) | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 				verts[3] = tmpface->v4; | 
					
						
							|  |  |  | 			for( j = 0; j < len; ++j ) { | 
					
						
							|  |  |  | 				k = (j+1) % len; | 
					
						
							|  |  |  | 				if( verts[j] < verts[k] ) {  | 
					
						
							|  |  |  | 					target.v[0] = verts[j]; | 
					
						
							|  |  |  | 					target.v[1] = verts[k]; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					target.v[0] = verts[k]; | 
					
						
							|  |  |  | 					target.v[1] = verts[j]; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				ptrs[j] = bsearch( &target, edge_table, mesh->totedge, | 
					
						
							|  |  |  | 							sizeof(FaceEdges), faceedge_comp ); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			for( j = 0; j < 4; ++j, ++tmp_fe ) | 
					
						
							|  |  |  | 				*tmp_fe = ptrs[j]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* for each face, deselect each edge */ | 
					
						
							|  |  |  | 		tmpface = mesh->mface; | 
					
						
							|  |  |  | 		face_count = 0; | 
					
						
							|  |  |  | 		for( i = len; i--; ) { | 
					
						
							|  |  |  | 			if( tmpface[face_table[i]].v1 != UINT_MAX ) { | 
					
						
							|  |  |  | 				fface = (void *)face_edges; | 
					
						
							|  |  |  | 				fface += face_table[i]; | 
					
						
							|  |  |  | 				fface->v[0]->sel = 0; | 
					
						
							|  |  |  | 				fface->v[1]->sel = 0; | 
					
						
							|  |  |  | 				fface->v[2]->sel = 0; | 
					
						
							|  |  |  | 				if( fface->v[3] ) | 
					
						
							|  |  |  | 					fface->v[3]->sel = 0; | 
					
						
							|  |  |  | 				tmpface[face_table[i]].v1 = UINT_MAX; | 
					
						
							|  |  |  | 				++face_count; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* for each face, deselect each edge */ | 
					
						
							|  |  |  | 		tmpface = mesh->mface; | 
					
						
							|  |  |  | 		fface = (struct fourEdges *)face_edges; | 
					
						
							|  |  |  | 		for( i = mesh->totface; i--; ++tmpface, ++fface ) { | 
					
						
							|  |  |  | 			if( tmpface->v1 != UINT_MAX ) { | 
					
						
							|  |  |  | 				FaceEdges (*face)[4]; | 
					
						
							|  |  |  | 				face = (void *)face_edges; | 
					
						
							|  |  |  | 				face += face_table[i]; | 
					
						
							|  |  |  | 				fface->v[0]->sel = 1; | 
					
						
							|  |  |  | 				fface->v[1]->sel = 1; | 
					
						
							|  |  |  | 				fface->v[2]->sel = 1; | 
					
						
							|  |  |  | 				if( fface->v[3] ) | 
					
						
							|  |  |  | 					fface->v[3]->sel = 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* now mark the selected edges for deletion */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		edge_count = 0; | 
					
						
							|  |  |  | 		for( i = 0; i < mesh->totedge; ++i ) { | 
					
						
							|  |  |  | 			if( !edge_table[i].sel ) { | 
					
						
							|  |  |  | 				mesh->medge[edge_table[i].index].v1 = UINT_MAX; | 
					
						
							|  |  |  | 				++edge_count; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if( edge_count ) | 
					
						
							|  |  |  | 			delete_edges( mesh, NULL, edge_count ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		MEM_freeN( face_edges ); | 
					
						
							|  |  |  | 		MEM_freeN( edge_table ); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 	/* mark faces to delete */ | 
					
						
							|  |  |  | 		tmpface = mesh->mface; | 
					
						
							|  |  |  | 		face_count = 0; | 
					
						
							|  |  |  | 		for( i = len; i--; ) | 
					
						
							|  |  |  | 			if( tmpface[face_table[i]].v1 != UINT_MAX ) { | 
					
						
							|  |  |  | 				tmpface[face_table[i]].v1 = UINT_MAX; | 
					
						
							|  |  |  | 				++face_count; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* delete faces which have a deleted edge */ | 
					
						
							|  |  |  | 	delete_faces( mesh, NULL, face_count ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* clean up and return */ | 
					
						
							|  |  |  | 	MEM_freeN( face_table ); | 
					
						
							|  |  |  | 	mesh_update ( mesh ); | 
					
						
							|  |  |  | 	return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | static PyObject *MFaceSeq_selected( BPy_MFaceSeq * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i, count; | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 	MFace *tmpface; | 
					
						
							|  |  |  | 	PyObject *list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* first count selected faces (quicker than appending to PyList?) */ | 
					
						
							|  |  |  | 	count = 0; | 
					
						
							|  |  |  | 	tmpface = mesh->mface; | 
					
						
							|  |  |  | 	for( i = 0; i < mesh->totface; ++i, ++tmpface ) | 
					
						
							|  |  |  | 		if( tmpface->flag & ME_FACE_SEL ) | 
					
						
							|  |  |  | 			++count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list = PyList_New( count ); | 
					
						
							|  |  |  | 	if( !list ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"PyList_New() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* next, insert selected faces into list */ | 
					
						
							|  |  |  | 	count = 0; | 
					
						
							|  |  |  | 	tmpface = mesh->mface; | 
					
						
							|  |  |  | 	for( i = 0; i < mesh->totface; ++i, ++tmpface ) { | 
					
						
							|  |  |  | 		if( tmpface->flag & ME_FACE_SEL ) { | 
					
						
							|  |  |  | 			PyObject *tmp = PyInt_FromLong( i ); | 
					
						
							|  |  |  | 			if( !tmp ) { | 
					
						
							|  |  |  | 				Py_DECREF( list ); | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 						"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			PyList_SET_ITEM( list, count, tmp ); | 
					
						
							|  |  |  | 			++count; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return list; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | static struct PyMethodDef BPy_MFaceSeq_methods[] = { | 
					
						
							| 
									
										
										
										
											2006-08-24 20:02:22 +00:00
										 |  |  | 	{"extend", (PyCFunction)MFaceSeq_extend, METH_VARARGS|METH_KEYWORDS, | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		"add faces to mesh"}, | 
					
						
							|  |  |  | 	{"delete", (PyCFunction)MFaceSeq_delete, METH_VARARGS, | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		"delete faces from mesh"}, | 
					
						
							|  |  |  | 	{"selected", (PyCFunction)MFaceSeq_selected, METH_NOARGS, | 
					
						
							|  |  |  | 		"returns a list containing indices of selected faces"}, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	{NULL, NULL, 0, NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python MFaceSeq_Type standard operations | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void MFaceSeq_dealloc( BPy_MFaceSeq * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject_DEL( self ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*****************************************************************************/ | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | /* Python MFaceSeq_Type structure definition:                               */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /*****************************************************************************/ | 
					
						
							|  |  |  | PyTypeObject MFaceSeq_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT( NULL )  /* required py macro */ | 
					
						
							|  |  |  | 	0,                          /* ob_size */ | 
					
						
							|  |  |  | 	/*  For printing, in format "<module>.<name>" */ | 
					
						
							|  |  |  | 	"Blender MFaceSeq",           /* char *tp_name; */ | 
					
						
							|  |  |  | 	sizeof( BPy_MFaceSeq ),       /* int tp_basicsize; */ | 
					
						
							|  |  |  | 	0,                          /* tp_itemsize;  For allocation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Methods to implement standard operations */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	( destructor ) MFaceSeq_dealloc,/* destructor tp_dealloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* printfunc tp_print; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrfunc tp_getattr; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrfunc tp_setattr; */ | 
					
						
							|  |  |  | 	NULL,                       /* cmpfunc tp_compare; */ | 
					
						
							|  |  |  | 	NULL,                       /* reprfunc tp_repr; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Method suites for standard classes */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /* PyNumberMethods *tp_as_number; */ | 
					
						
							|  |  |  | 	&MFaceSeq_as_sequence,	    /* PySequenceMethods *tp_as_sequence; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyMappingMethods *tp_as_mapping; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* More standard operations (here for binary compatibility) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /* hashfunc tp_hash; */ | 
					
						
							|  |  |  | 	NULL,                       /* ternaryfunc tp_call; */ | 
					
						
							|  |  |  | 	NULL,                       /* reprfunc tp_str; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrofunc tp_getattro; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrofunc tp_setattro; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Functions to access object as input/output buffer */ | 
					
						
							|  |  |  | 	NULL,                       /* PyBufferProcs *tp_as_buffer; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Flags to define presence of optional/expanded features ***/ | 
					
						
							|  |  |  | 	Py_TPFLAGS_DEFAULT,         /* long tp_flags; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /*  char *tp_doc;  Documentation string */ | 
					
						
							|  |  |  |   /*** Assigned meaning in release 2.0 ***/ | 
					
						
							|  |  |  | 	/* call function for all accessible objects */ | 
					
						
							|  |  |  | 	NULL,                       /* traverseproc tp_traverse; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* delete references to contained objects */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_clear; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  Assigned meaning in release 2.1 ***/ | 
					
						
							|  |  |  |   /*** rich comparisons ***/ | 
					
						
							|  |  |  | 	NULL,                       /* richcmpfunc tp_richcompare; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  weak reference enabler ***/ | 
					
						
							|  |  |  | 	0,                          /* long tp_weaklistoffset; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Added in release 2.2 ***/ | 
					
						
							|  |  |  | 	/*   Iterators */ | 
					
						
							|  |  |  | 	( getiterfunc )MFaceSeq_getIter, /* getiterfunc tp_iter; */ | 
					
						
							|  |  |  | 	( iternextfunc )MFaceSeq_nextIter, /* iternextfunc tp_iternext; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Attribute descriptor and subclassing stuff ***/ | 
					
						
							|  |  |  | 	BPy_MFaceSeq_methods,       /* struct PyMethodDef *tp_methods; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyMemberDef *tp_members; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyGetSetDef *tp_getset; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct _typeobject *tp_base; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_dict; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrgetfunc tp_descr_get; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrsetfunc tp_descr_set; */ | 
					
						
							|  |  |  | 	0,                          /* long tp_dictoffset; */ | 
					
						
							|  |  |  | 	NULL,                       /* initproc tp_init; */ | 
					
						
							|  |  |  | 	NULL,                       /* allocfunc tp_alloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* newfunc tp_new; */ | 
					
						
							|  |  |  | 	/*  Low-level free-memory routine */ | 
					
						
							|  |  |  | 	NULL,                       /* freefunc tp_free;  */ | 
					
						
							|  |  |  | 	/* For PyObject_IS_GC */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_is_gc;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_bases; */ | 
					
						
							|  |  |  | 	/* method resolution order */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_mro;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_cache; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_subclasses; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_weaklist; */ | 
					
						
							|  |  |  | 	NULL | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python BPy_Mesh methods | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_calcNormals( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mesh_calc_normals( mesh->mvert, mesh->totvert, mesh->mface, | 
					
						
							|  |  |  | 			mesh->totface, NULL ); | 
					
						
							|  |  |  | 	return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_vertexShade( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-03 20:24:10 +00:00
										 |  |  | 	Base *base = FIRSTBASE; | 
					
						
							| 
									
										
										
										
											2005-10-04 15:17:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	if( G.obedit ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError(PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"can't shade vertices while in edit mode" ); | 
					
						
							| 
									
										
										
										
											2005-10-04 15:17:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	while( base ) { | 
					
						
							|  |  |  | 		if( base->object->type == OB_MESH &&  | 
					
						
							|  |  |  | 				base->object->data == self->mesh ) { | 
					
						
							|  |  |  | 			base->flag |= SELECT; | 
					
						
							|  |  |  | 			set_active_base( base ); | 
					
						
							|  |  |  | 			make_vertexcol(); | 
					
						
							|  |  |  | 			countall(); | 
					
						
							|  |  |  | 			return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		base = base->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return EXPP_ReturnPyObjError(PyExc_RuntimeError, | 
					
						
							|  |  |  | 			"object not found in baselist!" ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * force display list update | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_Update( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	mesh_update( self->mesh ); | 
					
						
							|  |  |  | 	return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * search for a single edge in mesh's edge list | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_findEdge( BPy_Mesh * self, PyObject *args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	unsigned int v1, v2; | 
					
						
							|  |  |  | 	PyObject *tmp; | 
					
						
							|  |  |  | 	MEdge *edge = self->mesh->medge; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( EXPP_check_sequence_consistency( args, &MVert_Type ) == 1 && | 
					
						
							|  |  |  | 			PySequence_Size( args ) == 2 ) { | 
					
						
							|  |  |  | 		tmp = PyTuple_GET_ITEM( args, 0 ); | 
					
						
							|  |  |  | 		v1 = ((BPy_MVert *)tmp)->index; | 
					
						
							|  |  |  | 		tmp = PyTuple_GET_ITEM( args, 1 ); | 
					
						
							|  |  |  | 		v2 = ((BPy_MVert *)tmp)->index; | 
					
						
							|  |  |  | 	} else if( PyArg_ParseTuple( args, "ii", &v1, &v2 ) ) { | 
					
						
							|  |  |  | 		if( (int)v1 >= self->mesh->totvert || (int)v2 >= self->mesh->totvert ) | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_IndexError, | 
					
						
							|  |  |  | 					"index out of range" ); | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"expected tuple of two ints or MVerts" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for( i = 0; i < self->mesh->totedge; ++i ) { | 
					
						
							|  |  |  | 		if( ( edge->v1 == v1 && edge->v2 == v2 ) | 
					
						
							|  |  |  | 				|| ( edge->v1 == v2 && edge->v2 == v1 ) ) { | 
					
						
							|  |  |  | 			tmp = PyInt_FromLong( i ); | 
					
						
							|  |  |  | 			if( tmp ) | 
					
						
							|  |  |  | 				return tmp; | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		++edge; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * search for a group of edges in mesh's edge list | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_findEdges( PyObject * self, PyObject *args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int len; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	SrchEdges *oldpair, *tmppair, target, *result; | 
					
						
							|  |  |  | 	PyObject *list, *tmp; | 
					
						
							|  |  |  | 	BPy_MVert *v1, *v2; | 
					
						
							|  |  |  | 	unsigned int index1, index2; | 
					
						
							|  |  |  | 	MEdge *tmpedge; | 
					
						
							|  |  |  | 	Mesh *mesh = ((BPy_Mesh *)self)->mesh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if no edges, nothing to do */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !mesh->totedge ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"mesh has no edges" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* make sure we get a sequence of tuples of something */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmp = PyTuple_GET_ITEM( args, 0 ); | 
					
						
							|  |  |  | 	switch( PySequence_Size ( args ) ) { | 
					
						
							|  |  |  | 	case 1:		/* better be a list or a tuple */ | 
					
						
							|  |  |  | 		if( !PySequence_Check ( tmp ) ) | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					"expected a sequence of tuple int or MVert pairs" ); | 
					
						
							|  |  |  | 		args = tmp; | 
					
						
							|  |  |  | 		Py_INCREF( args );		/* so we can safely DECREF later */ | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case 2:		/* take any two args and put into a tuple */ | 
					
						
							|  |  |  | 		if( PyTuple_Check( tmp ) ) | 
					
						
							|  |  |  | 			Py_INCREF( args );	/* if first arg is a tuple, assume both are */ | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			args = Py_BuildValue( "((OO))", tmp, PyTuple_GET_ITEM( args, 1 ) ); | 
					
						
							|  |  |  | 			if( !args ) | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 						"Py_BuildValue() failed" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default:	/* anything else is definitely wrong */ | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected a sequence of tuple pairs" ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	len = PySequence_Size( args ); | 
					
						
							|  |  |  | 	if( len == 0 ) { | 
					
						
							|  |  |  | 		Py_DECREF( args ); | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"expected at least one tuple" ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if a single edge, handle the simpler way */ | 
					
						
							|  |  |  | 	if( len == 1 ) { | 
					
						
							|  |  |  | 		PyObject *result; | 
					
						
							|  |  |  | 		tmp = PySequence_GetItem( args, 0 ); | 
					
						
							|  |  |  | 		result = Mesh_findEdge( (BPy_Mesh *)self, tmp ); | 
					
						
							|  |  |  | 		Py_DECREF( tmp ); | 
					
						
							|  |  |  | 		Py_DECREF( args ); | 
					
						
							|  |  |  | 		return result; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* build a list of all edges so we can search */ | 
					
						
							|  |  |  | 	oldpair = (SrchEdges *)MEM_callocN( sizeof(SrchEdges)*mesh->totedge, | 
					
						
							|  |  |  | 			"MEdgePairs" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmppair = oldpair; | 
					
						
							|  |  |  | 	tmpedge = mesh->medge; | 
					
						
							|  |  |  | 	for( i = 0; i < mesh->totedge; ++i ) { | 
					
						
							|  |  |  | 		if( tmpedge->v1 < tmpedge->v2 ) { | 
					
						
							|  |  |  | 			tmppair->v[0] = tmpedge->v1; | 
					
						
							|  |  |  | 			tmppair->v[1] = tmpedge->v2; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			tmppair->v[0] = tmpedge->v2; | 
					
						
							|  |  |  | 			tmppair->v[1] = tmpedge->v1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		tmppair->index = i; | 
					
						
							|  |  |  | 		++tmpedge; | 
					
						
							|  |  |  | 		++tmppair; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* sort the old edge pairs */ | 
					
						
							|  |  |  | 	qsort( oldpair, mesh->totedge, sizeof(SrchEdges), medge_comp ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list = PyList_New( len ); | 
					
						
							|  |  |  | 	if( !len ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"PyList_New() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* scan the input list, find vert pairs, then search the edge list */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for( i = 0; i < len; ++i ) { | 
					
						
							|  |  |  | 		tmp = PySequence_GetItem( args, i ); | 
					
						
							|  |  |  | 		if( !PyTuple_Check( tmp ) || PyTuple_Size( tmp ) != 2 ) { | 
					
						
							|  |  |  | 			MEM_freeN( oldpair ); | 
					
						
							|  |  |  | 			Py_DECREF( tmp ); | 
					
						
							|  |  |  | 			Py_DECREF( args ); | 
					
						
							|  |  |  | 			Py_DECREF( list ); | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"expected tuple pair" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* get objects, check that they are both MVerts of this mesh */ | 
					
						
							|  |  |  | 		v1 = (BPy_MVert *)PyTuple_GET_ITEM( tmp, 0 ); | 
					
						
							|  |  |  | 		v2 = (BPy_MVert *)PyTuple_GET_ITEM( tmp, 1 ); | 
					
						
							|  |  |  | 		Py_DECREF ( tmp ); | 
					
						
							|  |  |  | 		if( BPy_MVert_Check( v1 ) && BPy_MVert_Check( v2 ) ) { | 
					
						
							|  |  |  | 			if( v1->data != (void *)mesh || v2->data != (void *)mesh ) { | 
					
						
							|  |  |  | 				MEM_freeN( oldpair ); | 
					
						
							|  |  |  | 				Py_DECREF( args ); | 
					
						
							|  |  |  | 				Py_DECREF( list ); | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 					"one or both MVerts do not belong to this mesh" ); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			index1 = v1->index; | 
					
						
							|  |  |  | 			index2 = v2->index; | 
					
						
							|  |  |  | 		} else if( PyInt_CheckExact( v1 ) && PyInt_CheckExact( v2 ) ) { | 
					
						
							|  |  |  | 			index1 = PyInt_AsLong( (PyObject *)v1 ); | 
					
						
							|  |  |  | 			index2 = PyInt_AsLong( (PyObject *)v2 ); | 
					
						
							|  |  |  | 			if( (int)index1 >= mesh->totvert | 
					
						
							|  |  |  | 					|| (int)index2 >= mesh->totvert ) { | 
					
						
							|  |  |  | 				MEM_freeN( oldpair ); | 
					
						
							|  |  |  | 				Py_DECREF( args ); | 
					
						
							|  |  |  | 				Py_DECREF( list ); | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_IndexError, | 
					
						
							|  |  |  | 						"index out of range" ); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			MEM_freeN( oldpair ); | 
					
						
							|  |  |  | 			Py_DECREF( args ); | 
					
						
							|  |  |  | 			Py_DECREF( list ); | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"expected tuple to contain MVerts" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* sort verts into order */ | 
					
						
							|  |  |  | 		if( index1 < index2 ) { | 
					
						
							|  |  |  | 			target.v[0] = index1; | 
					
						
							|  |  |  | 			target.v[1] = index2; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			target.v[0] = index2; | 
					
						
							|  |  |  | 			target.v[1] = index1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* search edge list for a match; result is index or None */ | 
					
						
							|  |  |  | 		result = bsearch( &target, oldpair, mesh->totedge, | 
					
						
							|  |  |  | 				sizeof(SrchEdges), medge_comp ); | 
					
						
							|  |  |  | 		if( result ) | 
					
						
							|  |  |  | 			tmp = PyInt_FromLong( result->index ); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			tmp = EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | 		if( !tmp ) { | 
					
						
							|  |  |  | 			MEM_freeN( oldpair ); | 
					
						
							|  |  |  | 			Py_DECREF( args ); | 
					
						
							|  |  |  | 			Py_DECREF( list ); | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		PyList_SET_ITEM( list, i, tmp ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MEM_freeN( oldpair ); | 
					
						
							|  |  |  | 	Py_DECREF ( args ); | 
					
						
							|  |  |  | 	return list; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * replace mesh data with mesh data from another object | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | static PyObject *Mesh_getFromObject( BPy_Mesh * self, PyObject * args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *ob; | 
					
						
							|  |  |  | 	char *name; | 
					
						
							|  |  |  | 	ID tmpid; | 
					
						
							|  |  |  | 	Mesh *tmpmesh; | 
					
						
							| 
									
										
										
										
											2006-01-03 16:27:34 +00:00
										 |  |  | 	Curve *tmpcu = NULL; | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	DispListMesh *dlm; | 
					
						
							|  |  |  | 	DerivedMesh *dm; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	Object *tmpobj = NULL; | 
					
						
							| 
									
										
										
										
											2006-09-17 05:15:56 +00:00
										 |  |  | 	int cage = 0, render = 0, i; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-17 05:15:56 +00:00
										 |  |  | 	if( !PyArg_ParseTuple( args, "s|i", &name, &cage, &render ) ) | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 				"expected string and optional integer arguments" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( cage != 0 && cage != 1 ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"cage value must be 0 or 1" ); | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* find the specified object */ | 
					
						
							|  |  |  | 	ob = ( Object * ) GetIdFromList( &( G.main->object ), name ); | 
					
						
							|  |  |  | 	if( !ob ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, name ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* perform the mesh extraction based on type */ | 
					
						
							|  |  |  |  	switch (ob->type) { | 
					
						
							|  |  |  |  	case OB_FONT: | 
					
						
							|  |  |  |  	case OB_CURVE: | 
					
						
							|  |  |  |  	case OB_SURF: | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		/* copies object and modifiers (but not the data) */ | 
					
						
							|  |  |  | 		tmpobj= copy_object( ob ); | 
					
						
							|  |  |  | 		tmpcu = (Curve *)tmpobj->data; | 
					
						
							|  |  |  | 		tmpcu->id.us--; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 		/* if getting the original caged mesh, delete object modifiers */ | 
					
						
							|  |  |  | 		if( cage ) | 
					
						
							|  |  |  | 			object_free_modifiers(tmpobj); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		/* copies the data */ | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		tmpobj->data = copy_curve( (Curve *) ob->data ); | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 		/* copy_curve() sets disp.first null, so currently not need */ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			Curve *cu; | 
					
						
							|  |  |  | 			cu = (Curve *)tmpobj->data; | 
					
						
							|  |  |  | 			if( cu->disp.first ) | 
					
						
							|  |  |  | 				MEM_freeN( cu->disp.first ); | 
					
						
							|  |  |  | 			cu->disp.first = NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* get updated display list, and convert to a mesh */ | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		makeDispListCurveTypes( tmpobj, 0 ); | 
					
						
							|  |  |  | 		nurbs_to_mesh( tmpobj ); | 
					
						
							|  |  |  | 		tmpmesh = tmpobj->data; | 
					
						
							|  |  |  | 		free_libblock_us( &G.main->object, tmpobj ); | 
					
						
							|  |  |  |  		break; | 
					
						
							|  |  |  |  	case OB_MBALL: | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		/* metaballs don't have modifiers, so just convert to mesh */ | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		ob = find_basis_mball( ob ); | 
					
						
							|  |  |  | 		tmpmesh = add_mesh(); | 
					
						
							|  |  |  | 		mball_to_mesh( &ob->disp, tmpmesh ); | 
					
						
							| 
									
										
										
										
											2006-07-05 18:28:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * mball_to_mesh doesn't create edges, which confuses Blender in | 
					
						
							|  |  |  | 		 * object mode.  So this hack is necessary to quickly calculate the | 
					
						
							|  |  |  | 		 * edges from the face list. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		dlm = MEM_callocN( sizeof(DispListMesh), "tmp displist"); | 
					
						
							|  |  |  | 		dlm->totface = tmpmesh->totface; | 
					
						
							|  |  |  | 		dlm->mface = tmpmesh->mface; | 
					
						
							|  |  |  | 		displistmesh_add_edges( dlm ); | 
					
						
							|  |  |  | 		tmpmesh->totedge = dlm->totedge; | 
					
						
							|  |  |  | 		tmpmesh->medge = dlm->medge; | 
					
						
							|  |  |  | 		MEM_freeN( dlm ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  |  		break; | 
					
						
							|  |  |  |  	case OB_MESH: | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		/* copies object and modifiers (but not the data) */ | 
					
						
							| 
									
										
										
										
											2006-09-11 07:05:29 +00:00
										 |  |  | 		if (cage) { | 
					
						
							|  |  |  | 			/* copies the data */ | 
					
						
							| 
									
										
										
										
											2006-09-17 05:15:56 +00:00
										 |  |  | 			tmpmesh = copy_mesh( ob->data ); | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 		/* if not getting the original caged mesh, get final derived mesh */ | 
					
						
							| 
									
										
										
										
											2006-09-11 07:05:29 +00:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			/* Make a dummy mesh, saves copying */ | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			/* Write the display mesh into the dummy mesh */ | 
					
						
							| 
									
										
										
										
											2006-09-17 05:15:56 +00:00
										 |  |  | 			if (render) | 
					
						
							|  |  |  | 				dm = mesh_create_derived_render( ob ); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				dm = mesh_create_derived_view( ob ); | 
					
						
							|  |  |  | 			 | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 			dlm = dm->convertToDispListMesh( dm, 0 ); | 
					
						
							| 
									
										
										
										
											2006-09-17 05:15:56 +00:00
										 |  |  | 			tmpmesh = add_mesh(  ); | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 			displistmesh_to_mesh( dlm, tmpmesh ); | 
					
						
							|  |  |  | 			dm->release( dm ); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-12-30 09:56:02 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		break; | 
					
						
							|  |  |  |  	default: | 
					
						
							|  |  |  |  		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 				"Object does not have geometry data" ); | 
					
						
							|  |  |  |   	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* free mesh data in the original */ | 
					
						
							|  |  |  | 	free_mesh( self->mesh ); | 
					
						
							|  |  |  | 	/* save a copy of our ID, dup the temporary mesh, restore the ID */ | 
					
						
							|  |  |  | 	tmpid = self->mesh->id; | 
					
						
							|  |  |  | 	memcpy( self->mesh, tmpmesh, sizeof( Mesh ) ); | 
					
						
							| 
									
										
										
										
											2005-12-13 18:39:50 +00:00
										 |  |  | 	self->mesh->id = tmpid; | 
					
						
							| 
									
										
										
										
											2005-12-30 09:56:02 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-12-13 18:39:50 +00:00
										 |  |  | 	/* if mesh has keys, make sure they point back to this mesh */ | 
					
						
							|  |  |  | 	if( self->mesh->key ) | 
					
						
							|  |  |  | 		self->mesh->key->from = (ID *)self->mesh; | 
					
						
							| 
									
										
										
										
											2005-12-30 09:56:02 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* Copy materials to new object */ | 
					
						
							|  |  |  | 	switch (ob->type) { | 
					
						
							|  |  |  | 	case OB_SURF: | 
					
						
							|  |  |  | 		self->mesh->totcol = tmpcu->totcol;		 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/* free old material list (if it exists) and adjust user counts */ | 
					
						
							|  |  |  | 		if( tmpcu->mat ) { | 
					
						
							|  |  |  | 			for( i = tmpcu->totcol; i-- > 0; ) { | 
					
						
							| 
									
										
										
										
											2006-05-10 01:38:02 +00:00
										 |  |  | 				 | 
					
						
							|  |  |  | 				/* are we an object material or data based? */ | 
					
						
							|  |  |  | 				if (ob->colbits & 1<<i) { | 
					
						
							|  |  |  | 					self->mesh->mat[i] = ob->mat[i]; | 
					
						
							|  |  |  | 					ob->mat[i]->id.us++; | 
					
						
							|  |  |  | 					tmpmesh->mat[i]->id.us--; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					self->mesh->mat[i] = tmpcu->mat[i]; | 
					
						
							|  |  |  | 					if (self->mesh->mat[i]) { | 
					
						
							|  |  |  | 						tmpmesh->mat[i]->id.us++; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2005-12-30 09:56:02 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2005-12-13 18:39:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-30 09:56:02 +00:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  | 	/* Crashes when assigning the new material, not sure why */ | 
					
						
							|  |  |  | 	case OB_MBALL: | 
					
						
							|  |  |  | 		tmpmb = (MetaBall *)ob->data; | 
					
						
							|  |  |  | 		self->mesh->totcol = tmpmb->totcol; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/* free old material list (if it exists) and adjust user counts */ | 
					
						
							|  |  |  | 		if( tmpmb->mat ) { | 
					
						
							|  |  |  | 			for( i = tmpmb->totcol; i-- > 0; ) { | 
					
						
							|  |  |  | 				self->mesh->mat[i] = tmpmb->mat[i]; /* CRASH HERE ??? */ | 
					
						
							|  |  |  | 				if (self->mesh->mat[i]) { | 
					
						
							|  |  |  | 					tmpmb->mat[i]->id.us++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case OB_MESH: | 
					
						
							| 
									
										
										
										
											2006-09-11 07:05:29 +00:00
										 |  |  | 		if (!cage) { | 
					
						
							|  |  |  | 			Mesh *origmesh= ob->data; | 
					
						
							|  |  |  | 			self->mesh->mat = MEM_dupallocN(origmesh->mat); | 
					
						
							|  |  |  | 			self->mesh->totcol = origmesh->totcol;		 | 
					
						
							|  |  |  | 			if( origmesh->mat ) { | 
					
						
							|  |  |  | 				for( i = origmesh->totcol; i-- > 0; ) { | 
					
						
							|  |  |  | 					/* are we an object material or data based? */ | 
					
						
							|  |  |  | 					if (ob->colbits & 1<<i) { | 
					
						
							|  |  |  | 						self->mesh->mat[i] = ob->mat[i]; | 
					
						
							| 
									
										
										
										
											2006-09-15 14:52:59 +00:00
										 |  |  | 						 | 
					
						
							|  |  |  | 						if (ob->mat[i]) | 
					
						
							|  |  |  | 							ob->mat[i]->id.us++; | 
					
						
							|  |  |  | 						if (origmesh->mat[i]) | 
					
						
							|  |  |  | 							origmesh->mat[i]->id.us--; | 
					
						
							| 
									
										
										
										
											2006-09-11 07:05:29 +00:00
										 |  |  | 					} else { | 
					
						
							|  |  |  | 						self->mesh->mat[i] = origmesh->mat[i]; | 
					
						
							| 
									
										
										
										
											2006-09-15 14:52:59 +00:00
										 |  |  | 						 | 
					
						
							|  |  |  | 						if (origmesh->mat[i]) | 
					
						
							|  |  |  | 							origmesh->mat[i]->id.us++; | 
					
						
							| 
									
										
										
										
											2006-09-11 07:05:29 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2005-12-30 09:56:02 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} /* end copy materials */ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	/* remove the temporary mesh */ | 
					
						
							|  |  |  | 	BLI_remlink( &G.main->mesh, tmpmesh ); | 
					
						
							|  |  |  | 	MEM_freeN( tmpmesh ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 	/* make sure materials get updated in objects */ | 
					
						
							| 
									
										
										
										
											2005-12-13 18:39:50 +00:00
										 |  |  | 	test_object_materials( ( ID * ) self->mesh ); | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	mesh_update( self->mesh ); | 
					
						
							|  |  |  | 	return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * apply a transform to the mesh's vertices | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * WARNING: unlike NMesh, this method ALWAYS changes the original mesh | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_transform( BPy_Mesh *self, PyObject *args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 	MVert *mv; | 
					
						
							|  |  |  | 	PyObject *ob1 = NULL; | 
					
						
							|  |  |  | 	MatrixObject *mat; | 
					
						
							|  |  |  | 	int i, recalc_normals = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple( args, "O!|i", &matrix_Type, &ob1, &recalc_normals ) ) | 
					
						
							|  |  |  | 		return ( EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					"expected matrix and optionally an int as arguments" ) ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mat = ( MatrixObject * ) ob1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( mat->colSize != 4 || mat->rowSize != 4 ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 				"matrix must be a 4x4 transformation matrix\n" | 
					
						
							|  |  |  | 				"for example as returned by object.getMatrix()" ); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* loop through all the verts and transform by the supplied matrix */ | 
					
						
							|  |  |  | 	mv = mesh->mvert; | 
					
						
							|  |  |  | 	for( i = 0; i < mesh->totvert; i++, mv++ ) | 
					
						
							|  |  |  | 		Mat4MulVecfl( (float(*)[4])*mat->matrix, mv->co ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( recalc_normals ) { | 
					
						
							|  |  |  | 		/* loop through all the verts and transform normals by the inverse
 | 
					
						
							|  |  |  | 		 * of the transpose of the supplied matrix */ | 
					
						
							|  |  |  | 		float invmat[4][4]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * we only need to invert a 3x3 submatrix, because the 4th component of | 
					
						
							|  |  |  | 		 * affine vectors is 0, but Mat4Invert reports non invertible matrices | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!Mat4Invert((float(*)[4])*invmat, (float(*)[4])*mat->matrix)) | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError (PyExc_AttributeError, | 
					
						
							|  |  |  | 				"given matrix is not invertible"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		 * since normal is stored as shorts, convert to float  | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		mv = mesh->mvert; | 
					
						
							|  |  |  | 		for( i = 0; i < mesh->totvert; i++, mv++ ) { | 
					
						
							|  |  |  | 			float vec[3]; | 
					
						
							| 
									
										
										
										
											2005-11-07 19:34:44 +00:00
										 |  |  | 			vec[0] = (float)(mv->no[0] / 32767.0); | 
					
						
							|  |  |  | 			vec[1] = (float)(mv->no[1] / 32767.0); | 
					
						
							|  |  |  | 			vec[2] = (float)(mv->no[2] / 32767.0); | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 			Mat4MulVecfl( (float(*)[4])*invmat, vec ); | 
					
						
							|  |  |  | 			Normalise( vec ); | 
					
						
							|  |  |  | 			mv->no[0] = (short)(vec[0] * 32767.0); | 
					
						
							|  |  |  | 			mv->no[1] = (short)(vec[1] * 32767.0); | 
					
						
							|  |  |  | 			mv->no[2] = (short)(vec[2] * 32767.0); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | static PyObject *Mesh_addVertGroup( PyObject * self, PyObject * args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *groupStr; | 
					
						
							|  |  |  | 	struct Object *object; | 
					
						
							|  |  |  | 	PyObject *tempStr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple( args, "s", &groupStr ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					      "expected string argument" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( ( ( BPy_Mesh * ) self )->object == NULL ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "mesh not linked to an object" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	object = ( ( BPy_Mesh * ) self )->object; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-10 01:38:02 +00:00
										 |  |  | 	/*get clamped name*/ | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	tempStr = PyString_FromStringAndSize( groupStr, 32 ); | 
					
						
							|  |  |  | 	groupStr = PyString_AsString( tempStr ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	add_defgroup_name( object, groupStr ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	EXPP_allqueue( REDRAWBUTSALL, 1 ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_removeVertGroup( PyObject * self, PyObject * args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *groupStr; | 
					
						
							|  |  |  | 	struct Object *object; | 
					
						
							|  |  |  | 	int nIndex; | 
					
						
							|  |  |  | 	bDeformGroup *pGroup; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple( args, "s", &groupStr ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					      "expected string argument" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( ( ( BPy_Mesh * ) self )->object == NULL ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "mesh must be linked to an object first..." ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	object = ( ( BPy_Mesh * ) self )->object; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pGroup = get_named_vertexgroup( object, groupStr ); | 
					
						
							|  |  |  | 	if( pGroup == NULL ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "group does not exist!" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nIndex = get_defgroup_num( object, pGroup ); | 
					
						
							|  |  |  | 	if( nIndex == -1 ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "no deform groups assigned to mesh" ); | 
					
						
							|  |  |  | 	nIndex++; | 
					
						
							|  |  |  | 	object->actdef = (unsigned short)nIndex; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	del_defgroup( object ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	EXPP_allqueue( REDRAWBUTSALL, 1 ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern void add_vert_defnr( Object * ob, int def_nr, int vertnum, float weight, | 
					
						
							|  |  |  | 		             int assignmode ); | 
					
						
							|  |  |  | extern void remove_vert_def_nr (Object *ob, int def_nr, int vertnum); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_assignVertsToGroup( BPy_Mesh * self, PyObject * args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *groupStr; | 
					
						
							|  |  |  | 	int nIndex; | 
					
						
							|  |  |  | 	bDeformGroup *pGroup; | 
					
						
							|  |  |  | 	PyObject *listObject; | 
					
						
							|  |  |  | 	int tempInt; | 
					
						
							|  |  |  | 	int x; | 
					
						
							|  |  |  | 	int assignmode = WEIGHT_REPLACE; | 
					
						
							|  |  |  | 	float weight = 1.0; | 
					
						
							|  |  |  | 	Object *object = self->object; | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !object ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "mesh must be linked to an object first" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( ((Mesh *)object->data) != mesh ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "object no longer linked to this mesh" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple ( args, "sO!fi", &groupStr, &PyList_Type, | 
					
						
							|  |  |  | 			&listObject, &weight, &assignmode) ) { | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					      "expected string, list,	float, string arguments" ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pGroup = get_named_vertexgroup( object, groupStr ); | 
					
						
							|  |  |  | 	if( pGroup == NULL ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "group does not exist!" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nIndex = get_defgroup_num( object, pGroup ); | 
					
						
							|  |  |  | 	if( nIndex == -1 ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "no deform groups assigned to mesh" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( assignmode != WEIGHT_REPLACE && assignmode != WEIGHT_ADD && | 
					
						
							|  |  |  | 			assignmode != WEIGHT_SUBTRACT ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 					      "bad assignment mode" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* makes a set of dVerts corresponding to the mVerts */ | 
					
						
							|  |  |  | 	if( !mesh->dvert )  | 
					
						
							| 
									
										
										
										
											2006-09-03 12:16:14 +00:00
										 |  |  | 		create_dverts( &mesh->id ); | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* loop list adding verts to group */ | 
					
						
							|  |  |  | 	for( x = 0; x < PyList_Size( listObject ); x++ ) { | 
					
						
							|  |  |  | 		if( !PyArg_Parse ( PyList_GetItem( listObject, x ), "i", &tempInt ) ) | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 						      "python list integer not parseable" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if( tempInt < 0 || tempInt >= mesh->totvert ) | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 						      "bad vertex index in list" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		add_vert_defnr( object, nIndex, tempInt, weight, assignmode ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_removeVertsFromGroup( BPy_Mesh * self, PyObject * args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* not passing a list will remove all verts from group */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	char *groupStr; | 
					
						
							|  |  |  | 	int nIndex; | 
					
						
							|  |  |  | 	Object *object; | 
					
						
							|  |  |  | 	Mesh *mesh; | 
					
						
							|  |  |  | 	bDeformGroup *pGroup; | 
					
						
							|  |  |  | 	PyObject *listObject = NULL; | 
					
						
							|  |  |  | 	int tempInt; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	object = self->object; | 
					
						
							|  |  |  | 	mesh = self->mesh; | 
					
						
							|  |  |  | 	if( !object ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "mesh must be linked to an object first" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( ((Mesh *)object->data) != mesh ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "object no longer linked to this mesh" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple | 
					
						
							|  |  |  | 	    ( args, "s|O!", &groupStr, &PyList_Type, &listObject ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					      "expected string and optional list argument" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !mesh->dvert ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					      "this mesh contains no deform vertices" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pGroup = get_named_vertexgroup( object, groupStr ); | 
					
						
							|  |  |  | 	if( pGroup == NULL ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					      "group does not exist!" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nIndex = get_defgroup_num( object, pGroup ); | 
					
						
							|  |  |  | 	if( nIndex == -1 ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					      "no deform groups assigned to mesh" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* get out of edit mode */ | 
					
						
							| 
									
										
										
										
											2006-05-09 14:17:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( G.obedit ) { | 
					
						
							|  |  |  | 		load_editMesh(); | 
					
						
							|  |  |  | 		free_editMesh(G.editMesh); | 
					
						
							|  |  |  | 		G.obedit = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( !listObject ) /* no list given */ | 
					
						
							|  |  |  | 		for( i = 0; i < mesh->totvert; i++ ) | 
					
						
							|  |  |  | 			remove_vert_def_nr( object, nIndex, i ); | 
					
						
							|  |  |  | 	else		 /* loop list removing verts to group */ | 
					
						
							|  |  |  | 		for( i = 0; i < PyList_Size( listObject ); i++ ) { | 
					
						
							|  |  |  | 			if( !PyArg_Parse( PyList_GetItem( listObject, i ), "i", &tempInt ) ) | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 							      "python list integer not parseable" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if( tempInt < 0 || tempInt >= mesh->totvert ) | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 							      "bad vertex index in list" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			remove_vert_def_nr( object, nIndex, tempInt ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_getVertsFromGroup( BPy_Mesh* self, PyObject * args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * not passing a list will return all verts from group | 
					
						
							|  |  |  | 	 * passing indecies not part of the group will not return data in pyList | 
					
						
							|  |  |  | 	 * can be used as a index/group check for a vertex | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	char *groupStr; | 
					
						
							|  |  |  | 	int nIndex; | 
					
						
							|  |  |  | 	bDeformGroup *pGroup; | 
					
						
							|  |  |  | 	MDeformVert *dvert; | 
					
						
							|  |  |  | 	int i, k, count; | 
					
						
							|  |  |  | 	PyObject *vertexList; | 
					
						
							|  |  |  | 	Object *object; | 
					
						
							|  |  |  | 	Mesh *mesh; | 
					
						
							|  |  |  | 	PyObject *tempVertexList; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int num = 0; | 
					
						
							|  |  |  | 	int weightRet = 0; | 
					
						
							|  |  |  | 	PyObject *listObject = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	object = self->object; | 
					
						
							|  |  |  | 	mesh = self->mesh; | 
					
						
							|  |  |  | 	if( !object ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "mesh must be linked to an object first" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( ((Mesh *)object->data) != mesh ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "object no longer linked to this mesh" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple( args, "s|iO!", &groupStr, &weightRet, | 
					
						
							|  |  |  | 			       &PyList_Type, &listObject ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					      "expected string and optional int and list arguments" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( weightRet < 0 || weightRet > 1 ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 					      "return weights flag must be 0 or 1" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !mesh->dvert ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "this mesh contains no deform vertices" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	pGroup = get_named_vertexgroup( object, groupStr ); | 
					
						
							|  |  |  | 	if( !pGroup ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "group does not exist!" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nIndex = get_defgroup_num( object, pGroup ); | 
					
						
							|  |  |  | 	if( nIndex == -1 ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "no deform groups assigned to mesh" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* temporary list */ | 
					
						
							|  |  |  | 	tempVertexList = PyList_New( mesh->totvert ); | 
					
						
							|  |  |  | 	if( !tempVertexList ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					      "getVertsFromGroup: can't create pylist!" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	count = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !listObject ) {	/* do entire group */ | 
					
						
							|  |  |  | 		dvert = mesh->dvert; | 
					
						
							|  |  |  | 		for( num = 0; num < mesh->totvert; num++, ++dvert ) { | 
					
						
							|  |  |  | 			for( i = 0; i < dvert->totweight; i++ ) { | 
					
						
							|  |  |  | 				if( dvert->dw[i].def_nr == nIndex ) { | 
					
						
							|  |  |  | 					PyObject *attr; | 
					
						
							|  |  |  | 					if( weightRet ) | 
					
						
							|  |  |  | 						attr = Py_BuildValue( "(i,f)", num, | 
					
						
							|  |  |  | 								dvert->dw[i].weight ); | 
					
						
							|  |  |  | 					else | 
					
						
							|  |  |  | 						attr = PyInt_FromLong ( num ); | 
					
						
							|  |  |  | 					PyList_SetItem( tempVertexList, count, attr ); | 
					
						
							|  |  |  | 					count++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else {			/* do individual vertices */ | 
					
						
							|  |  |  | 		for( i = 0; i < PyList_Size( listObject ); i++ ) { | 
					
						
							|  |  |  | 			PyObject *attr = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if( !PyArg_Parse( PyList_GetItem( listObject, i ), "i", &num ) ) | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 							      "python list integer not parseable" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if( num < 0 || num >= mesh->totvert ) | 
					
						
							|  |  |  | 				return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 							      "bad vertex index in list" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			dvert = mesh->dvert + num; | 
					
						
							|  |  |  | 			for( k = 0; k < dvert->totweight; k++ ) { | 
					
						
							|  |  |  | 				if( dvert->dw[k].def_nr == nIndex ) { | 
					
						
							|  |  |  | 					if( weightRet ) | 
					
						
							|  |  |  | 						attr = Py_BuildValue( "(i,f)", num, | 
					
						
							|  |  |  | 								dvert->dw[k].weight ); | 
					
						
							|  |  |  | 					else | 
					
						
							|  |  |  | 						attr = PyInt_FromLong ( num ); | 
					
						
							|  |  |  | 					PyList_SetItem( tempVertexList, count, attr ); | 
					
						
							|  |  |  | 					count++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* only return what we need */ | 
					
						
							|  |  |  | 	vertexList = PyList_GetSlice( tempVertexList, 0, count ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Py_DECREF( tempVertexList ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return vertexList; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_renameVertGroup( BPy_Mesh * self, PyObject * args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *oldGr = NULL; | 
					
						
							|  |  |  | 	char *newGr = NULL; | 
					
						
							|  |  |  | 	bDeformGroup *defGroup; | 
					
						
							|  |  |  | 	Object *object; | 
					
						
							|  |  |  | 	Mesh *mesh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	object = self->object; | 
					
						
							|  |  |  | 	mesh = self->mesh; | 
					
						
							|  |  |  | 	if( !object ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "mesh must be linked to an object first" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( ((Mesh *)object->data) != mesh ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "object no longer linked to this mesh" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple( args, "ss", &oldGr, &newGr ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					      "expected two string arguments" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	defGroup = get_named_vertexgroup( object, oldGr ); | 
					
						
							|  |  |  | 	if( !defGroup ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					      "couldn't find the vertex group" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyOS_snprintf( defGroup->name, 32, newGr ); | 
					
						
							|  |  |  | 	unique_vertexgroup_name( defGroup, object ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_getVertGroupNames( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	bDeformGroup *defGroup; | 
					
						
							|  |  |  | 	PyObject *list; | 
					
						
							|  |  |  | 	Object *obj = self->object; | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 	int count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !obj ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "mesh must be linked to an object first" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( ((Mesh *)obj->data) != mesh ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "object no longer linked to this mesh" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !obj ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					      "This mesh must be linked to an object" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	count = 0; | 
					
						
							|  |  |  | 	for( defGroup = obj->defbase.first; defGroup; defGroup = defGroup->next ) | 
					
						
							|  |  |  | 		++count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list = PyList_New( count ); | 
					
						
							|  |  |  | 	count = 0; | 
					
						
							|  |  |  | 	for( defGroup = obj->defbase.first; defGroup; defGroup = defGroup->next ) | 
					
						
							|  |  |  | 		PyList_SET_ITEM( list, count++, | 
					
						
							|  |  |  | 				PyString_FromString( defGroup->name ) ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return list; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-19 15:48:56 +00:00
										 |  |  | static PyObject *Mesh_getVertexInfluences( BPy_Mesh * self, PyObject * args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int index; | 
					
						
							|  |  |  | 	PyObject *influence_list = NULL; | 
					
						
							|  |  |  | 	Object *object = self->object; | 
					
						
							|  |  |  | 	Mesh *me = self->mesh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Get a reference to the mesh object wrapped in here. */ | 
					
						
							|  |  |  | 	if( !object ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"This mesh must be linked to an object" );  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Parse the parameters: only on integer (vertex index) */ | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple( args, "i", &index ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected int argument (index of the vertex)" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* check for valid index */ | 
					
						
							|  |  |  | 	if( index < 0 || index >= me->totvert ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_IndexError, | 
					
						
							|  |  |  | 				"vertex index out of range" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	influence_list = PyList_New( 0 ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Proceed only if we have vertex deformation information */ | 
					
						
							|  |  |  | 	if( me->dvert ) { | 
					
						
							|  |  |  | 		int i; | 
					
						
							|  |  |  | 		MDeformWeight *sweight = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Number of bones influencing the vertex */ | 
					
						
							|  |  |  | 		int totinfluences = me->dvert[index].totweight; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Get the reference of the first weight structure */ | 
					
						
							|  |  |  | 		sweight = me->dvert[index].dw; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Build the list only with weights and names of the influent bones */ | 
					
						
							|  |  |  | 		for( i = 0; i < totinfluences; i++, sweight++ ) { | 
					
						
							|  |  |  | 			bDeformGroup *defgroup = BLI_findlink( &object->defbase, | 
					
						
							|  |  |  | 					sweight->def_nr ); | 
					
						
							|  |  |  | 			if( defgroup ) | 
					
						
							|  |  |  | 				PyList_Append( influence_list, Py_BuildValue( "[sf]", | 
					
						
							|  |  |  | 						defgroup->name, sweight->weight ) );  | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return influence_list; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-27 16:33:02 +00:00
										 |  |  | static PyObject *Mesh_removeAllKeys( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if( !mesh || !mesh->key ) | 
					
						
							|  |  |  | 		Py_RETURN_FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mesh->key->id.us--; | 
					
						
							|  |  |  | 	mesh->key = NULL; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	Py_RETURN_TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_insertKey( BPy_Mesh * self, PyObject * args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 	int fra = -1, oldfra = -1; | 
					
						
							|  |  |  | 	char *type = NULL; | 
					
						
							|  |  |  | 	short typenum; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple( args, "|is", &fra, &type ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					      "expected nothing or an int and optionally a string as arguments" ); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if( !type || !strcmp( type, "relative" ) ) | 
					
						
							|  |  |  | 		typenum = 1; | 
					
						
							|  |  |  | 	else if( !strcmp( type, "absolute" ) ) | 
					
						
							|  |  |  | 		typenum = 2; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_AttributeError, | 
					
						
							|  |  |  | 					      "if given, type should be 'relative' or 'absolute'" ); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if( fra > 0 ) { | 
					
						
							|  |  |  | 		fra = EXPP_ClampInt( fra, 1, MAXFRAME ); | 
					
						
							|  |  |  | 		oldfra = G.scene->r.cfra; | 
					
						
							|  |  |  | 		G.scene->r.cfra = fra; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	insert_meshkey( mesh, typenum ); | 
					
						
							|  |  |  | 	allspace(REMAKEIPO, 0); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if( fra > 0 ) | 
					
						
							|  |  |  | 		G.scene->r.cfra = oldfra; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | static PyObject *Mesh_Tools( BPy_Mesh * self, int type, void **args ) | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-05-08 05:37:00 +00:00
										 |  |  | 	Base *base; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	int result; | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | 	Object *object = NULL;  | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	PyObject *attr = NULL; | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* if already in edit mode, exit */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( G.obedit ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError(PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"can't use mesh tools while in edit mode" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for( base = FIRSTBASE; base; base = base->next ) { | 
					
						
							|  |  |  | 		if( base->object->type == OB_MESH &&  | 
					
						
							|  |  |  | 				base->object->data == self->mesh ) { | 
					
						
							|  |  |  | 			object = base->object; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if( !object ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError(PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"can't find an object for the mesh" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( object->type != OB_MESH ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 						"Object specified is not a mesh." ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-08 05:37:00 +00:00
										 |  |  | 	/* make mesh's object active, enter mesh edit mode */ | 
					
						
							|  |  |  | 	G.obedit = object; | 
					
						
							|  |  |  | 	make_editMesh(); | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-08 05:37:00 +00:00
										 |  |  | 	/* apply operation, then exit edit mode */ | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | 	switch( type ) { | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	case MESH_TOOL_TOSPHERE: | 
					
						
							|  |  |  | 		vertices_to_sphere(); | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	case MESH_TOOL_VERTEXSMOOTH: | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | 		vertexsmooth(); | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	case MESH_TOOL_FLIPNORM: | 
					
						
							|  |  |  | 		/* would be simple to rewrite this to not use edit mesh */ | 
					
						
							|  |  |  | 		/* see flipface() */ | 
					
						
							|  |  |  | 		flip_editnormals(); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case MESH_TOOL_SUBDIV: | 
					
						
							|  |  |  | 		esubdivideflag( 1, 0.0, *((int *)args[0]), 1, 0 ); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case MESH_TOOL_REMDOUB: | 
					
						
							|  |  |  | 		result = removedoublesflag( 1, *((float *)args[0]) ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-03 00:58:41 +00:00
										 |  |  | 		attr = PyInt_FromLong( result ); | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		if( !attr ) | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					"PyInt_FromLong() failed" ); | 
					
						
							| 
									
										
										
										
											2005-11-03 00:58:41 +00:00
										 |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	case MESH_TOOL_FILL: | 
					
						
							|  |  |  | 		fill_mesh(); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case MESH_TOOL_RECALCNORM: | 
					
						
							|  |  |  | 		righthandfaces( *((int *)args[0]) ); | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 	case MESH_TOOL_TRI2QUAD: | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		join_triangles(); | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 	case MESH_TOOL_QUAD2TRI: | 
					
						
							|  |  |  | 		convert_to_triface( *((int *)args[0]) ); | 
					
						
							|  |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-05-08 05:37:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* exit edit mode, free edit mesh */ | 
					
						
							|  |  |  | 	load_editMesh(); | 
					
						
							|  |  |  | 	free_editMesh(G.editMesh); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(G.f & G_FACESELECT) | 
					
						
							|  |  |  | 		EXPP_allqueue( REDRAWIMAGE, 0 ); | 
					
						
							|  |  |  | 	if(G.f & G_WEIGHTPAINT) | 
					
						
							|  |  |  | 		mesh_octree_table(G.obedit, NULL, 'e'); | 
					
						
							|  |  |  | 	G.obedit = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	if( attr ) | 
					
						
							|  |  |  | 		return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | 	return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * "Subdivide" function | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | static PyObject *Mesh_subdivide( BPy_Mesh * self, PyObject * args ) | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	int beauty = 0; | 
					
						
							|  |  |  | 	void *params = &beauty; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple( args, "|i", &beauty ) ) | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					"expected nothing or an int argument" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return Mesh_Tools( self, MESH_TOOL_SUBDIV, ¶ms ); | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * "Smooth" function | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | static PyObject *Mesh_smooth( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return Mesh_Tools( self, MESH_TOOL_VERTEXSMOOTH, NULL ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * "Remove doubles" function | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_removeDoubles( BPy_Mesh * self, PyObject *args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float limit; | 
					
						
							|  |  |  | 	void *params = &limit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple( args, "f", &limit ) ) | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					"expected float argument" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	limit = EXPP_ClampFloat( limit, 0.0f, 1.0f ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return Mesh_Tools( self, MESH_TOOL_REMDOUB, ¶ms ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * "recalc normals" function | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_recalcNormals( BPy_Mesh * self, PyObject *args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int direction = 0; | 
					
						
							|  |  |  | 	void *params = &direction; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple( args, "|i", &direction ) ) | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					"expected nothing or an int in range [0,1]" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( direction < 0 || direction > 1 ) | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 					"expected int in range [0,1]" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* righthandfaces(1) = outward, righthandfaces(2) = inward */ | 
					
						
							|  |  |  | 	++direction; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return Mesh_Tools( self, MESH_TOOL_RECALCNORM, ¶ms ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  |  * "Quads to Triangles"  function | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | static PyObject *Mesh_quad2tri( BPy_Mesh * self, PyObject *args ) | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 	int kind = 0; | 
					
						
							|  |  |  | 	void *params = &kind; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple( args, "|i", &kind ) ) | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					"expected nothing or an int in range [0,1]" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( kind < 0 || kind > 1 ) | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 					"expected int in range [0,1]" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return Mesh_Tools( self, MESH_TOOL_QUAD2TRI, ¶ms ); | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  |  * "Triangles to Quads"  function | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | static PyObject *Mesh_tri2quad( BPy_Mesh * self ) | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 	return Mesh_Tools( self, MESH_TOOL_TRI2QUAD, NULL ); | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  |  * "Flip normals" function | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | static PyObject *Mesh_flipNormals( BPy_Mesh * self ) | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 	return Mesh_Tools( self, MESH_TOOL_FLIPNORM, NULL ); | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  |  * "To sphere" function | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | static PyObject *Mesh_toSphere( BPy_Mesh * self ) | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 	return Mesh_Tools( self, MESH_TOOL_TOSPHERE, NULL ); | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  |  * "Fill" (scan fill) function | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | static PyObject *Mesh_fill( BPy_Mesh * self ) | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 	return Mesh_Tools( self, MESH_TOOL_FILL, NULL ); | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-13 01:51:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * "__copy__" return a copy of the mesh | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_copy( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BPy_Mesh *obj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	obj = (BPy_Mesh *)PyObject_NEW( BPy_Mesh, &Mesh_Type ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !obj ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				       "PyObject_New() failed" ); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	obj->mesh = copy_mesh( self->mesh ); | 
					
						
							|  |  |  | 	obj->mesh->id.us= 0; | 
					
						
							|  |  |  | 	obj->object = NULL; | 
					
						
							|  |  |  | 	obj->new = 1; | 
					
						
							|  |  |  | 	return (PyObject *)obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | static struct PyMethodDef BPy_Mesh_methods[] = { | 
					
						
							|  |  |  | 	{"calcNormals", (PyCFunction)Mesh_calcNormals, METH_NOARGS, | 
					
						
							|  |  |  | 		"all recalculate vertex normals"}, | 
					
						
							|  |  |  | 	{"vertexShade", (PyCFunction)Mesh_vertexShade, METH_VARARGS, | 
					
						
							|  |  |  | 		"color vertices based on the current lighting setup"}, | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	{"findEdges", (PyCFunction)Mesh_findEdges, METH_VARARGS, | 
					
						
							|  |  |  | 		"find indices of an multiple edges in the mesh"}, | 
					
						
							|  |  |  | 	{"getFromObject", (PyCFunction)Mesh_getFromObject, METH_VARARGS, | 
					
						
							|  |  |  | 		"Get a mesh by name"}, | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	{"update", (PyCFunction)Mesh_Update, METH_NOARGS, | 
					
						
							|  |  |  | 		"Update display lists after changes to mesh"}, | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	{"transform", (PyCFunction)Mesh_transform, METH_VARARGS, | 
					
						
							|  |  |  | 		"Applies a transformation matrix to mesh's vertices"}, | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	{"addVertGroup", (PyCFunction)Mesh_addVertGroup, METH_VARARGS, | 
					
						
							|  |  |  | 		"Assign vertex group name to the object linked to the mesh"}, | 
					
						
							|  |  |  | 	{"removeVertGroup", (PyCFunction)Mesh_removeVertGroup, METH_VARARGS, | 
					
						
							|  |  |  | 		"Delete vertex group name from the object linked to the mesh"}, | 
					
						
							|  |  |  | 	{"assignVertsToGroup", (PyCFunction)Mesh_assignVertsToGroup, METH_VARARGS, | 
					
						
							|  |  |  | 		"Assigns vertices to a vertex group"}, | 
					
						
							|  |  |  | 	{"removeVertsFromGroup", (PyCFunction)Mesh_removeVertsFromGroup, METH_VARARGS, | 
					
						
							|  |  |  | 		"Removes vertices from a vertex group"}, | 
					
						
							|  |  |  | 	{"getVertsFromGroup", (PyCFunction)Mesh_getVertsFromGroup, METH_VARARGS, | 
					
						
							|  |  |  | 		"Get index and optional weight for vertices in vertex group"}, | 
					
						
							|  |  |  | 	{"renameVertGroup", (PyCFunction)Mesh_renameVertGroup, METH_VARARGS, | 
					
						
							|  |  |  | 		"Rename an existing vertex group"}, | 
					
						
							|  |  |  | 	{"getVertGroupNames", (PyCFunction)Mesh_getVertGroupNames, METH_NOARGS, | 
					
						
							|  |  |  | 		"Get names of vertex groups"}, | 
					
						
							| 
									
										
										
										
											2006-01-19 15:48:56 +00:00
										 |  |  | 	{"getVertexInfluences", (PyCFunction)Mesh_getVertexInfluences, METH_VARARGS, | 
					
						
							|  |  |  | 		"Get list of the influences of bones for a given mesh vertex"}, | 
					
						
							| 
									
										
										
										
											2006-09-27 16:33:02 +00:00
										 |  |  | 	/* Shape Keys */ | 
					
						
							|  |  |  | 	{"removeAllKeys", (PyCFunction)Mesh_removeAllKeys, METH_NOARGS, | 
					
						
							|  |  |  | 		"Remove all the shape keys from a mesh"}, | 
					
						
							|  |  |  | 	{"insertKey", (PyCFunction)Mesh_insertKey, METH_VARARGS, | 
					
						
							|  |  |  | 		"(frame = None, type = 'relative') - inserts a Mesh key at the given frame"}, | 
					
						
							| 
									
										
										
										
											2006-01-19 15:48:56 +00:00
										 |  |  | 	/* Mesh tools */ | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	{"smooth", (PyCFunction)Mesh_smooth, METH_NOARGS, | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  | 		"Flattens angle of selected faces (experimental)"}, | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	{"flipNormals", (PyCFunction)Mesh_flipNormals, METH_NOARGS, | 
					
						
							|  |  |  | 		"Toggles the direction of selected face's normals (experimental)"}, | 
					
						
							|  |  |  | 	{"toSphere", (PyCFunction)Mesh_toSphere, METH_NOARGS, | 
					
						
							|  |  |  | 		"Moves selected vertices outward in a spherical shape (experimental)"}, | 
					
						
							|  |  |  | 	{"fill", (PyCFunction)Mesh_fill, METH_NOARGS, | 
					
						
							|  |  |  | 		"Scan fill a closed edge loop (experimental)"}, | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 	{"triangleToQuad", (PyCFunction)Mesh_tri2quad, METH_VARARGS, | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		"Convert selected triangles to quads (experimental)"}, | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 	{"quadToTriangle", (PyCFunction)Mesh_quad2tri, METH_VARARGS, | 
					
						
							|  |  |  | 		"Convert selected quads to triangles (experimental)"}, | 
					
						
							| 
									
										
										
										
											2005-11-27 23:15:39 +00:00
										 |  |  | 	{"subdivide", (PyCFunction)Mesh_subdivide, METH_VARARGS, | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		"Subdivide selected edges in a mesh (experimental)"}, | 
					
						
							|  |  |  | 	{"remDoubles", (PyCFunction)Mesh_removeDoubles, METH_VARARGS, | 
					
						
							|  |  |  | 		"Removes duplicates from selected vertices (experimental)"}, | 
					
						
							|  |  |  | 	{"recalcNormals", (PyCFunction)Mesh_recalcNormals, METH_VARARGS, | 
					
						
							|  |  |  | 		"Recalculates inside or outside normals (experimental)"}, | 
					
						
							| 
									
										
										
										
											2006-08-13 01:51:47 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* python standard class functions */ | 
					
						
							|  |  |  | 	{"__copy__", (PyCFunction)Mesh_copy, METH_NOARGS, | 
					
						
							|  |  |  | 		"Return a copy of the mesh"}, | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	{NULL, NULL, 0, NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  |  * Python BPy_Mesh attributes | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | static PyObject *MVertSeq_CreatePyObject( Mesh * mesh ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	BPy_MVertSeq *obj = PyObject_NEW( BPy_MVertSeq, &MVertSeq_Type); | 
					
						
							|  |  |  | 	obj->mesh = mesh; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	an iter of -1 means this seq has not been used as an iterator yet | 
					
						
							|  |  |  | 	once it is, then any other calls on getIter will return a new copy of BPy_MVertSeq | 
					
						
							|  |  |  | 	This means you can loop do nested loops with the same iterator without worrying about | 
					
						
							|  |  |  | 	the iter variable being used twice and messing up the loops. | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	obj->iter = -1; | 
					
						
							|  |  |  | 	return (PyObject *)obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | static PyObject *Mesh_getVerts( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	return MVertSeq_CreatePyObject(self->mesh); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | static int Mesh_setVerts( BPy_Mesh * self, PyObject * args ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	MVert *dst; | 
					
						
							|  |  |  | 	MVert *src; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 	/* special case if None: delete the mesh */ | 
					
						
							|  |  |  | 	if( args == Py_None ) { | 
					
						
							|  |  |  | 		Mesh *me = self->mesh; | 
					
						
							|  |  |  | 		free_mesh( me ); | 
					
						
							| 
									
										
										
										
											2005-11-11 16:17:29 +00:00
										 |  |  |         me->mvert = NULL; me->medge = NULL; me->mface = NULL; | 
					
						
							|  |  |  | 		me->tface = NULL; me->dvert = NULL; me->mcol = NULL; | 
					
						
							|  |  |  | 		me->msticky = NULL; me->mat = NULL; me->bb = NULL; | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  | 		me->totvert = me->totedge = me->totface = me->totcol = 0; | 
					
						
							|  |  |  | 		mesh_update( me ); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( PyList_Check( args ) ) { | 
					
						
							|  |  |  | 		if( EXPP_check_sequence_consistency( args, &MVert_Type ) != 1 && | 
					
						
							|  |  |  | 			  EXPP_check_sequence_consistency( args, &PVert_Type ) != 1 ) | 
					
						
							|  |  |  | 			return EXPP_ReturnIntError( PyExc_TypeError,  | 
					
						
							|  |  |  | 					"expected a list of MVerts" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if( PyList_Size( args ) != self->mesh->totvert ) | 
					
						
							|  |  |  | 			return EXPP_ReturnIntError( PyExc_TypeError,  | 
					
						
							|  |  |  | 					"list must have the same number of vertices as the mesh" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		dst = self->mesh->mvert; | 
					
						
							|  |  |  | 		for( i = 0; i < PyList_Size( args ); ++i ) { | 
					
						
							|  |  |  | 			BPy_MVert *v = (BPy_MVert *)PyList_GET_ITEM( args, i ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if( BPy_MVert_Check( v ) ) | 
					
						
							|  |  |  | 				src = &((Mesh *)v->data)->mvert[v->index]; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				src = (MVert *)v->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			memcpy( dst, src, sizeof(MVert) ); | 
					
						
							|  |  |  | 			++dst; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else if( args->ob_type == &MVertSeq_Type ) { | 
					
						
							|  |  |  | 		Mesh *mesh = ( (BPy_MVertSeq *) args)->mesh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if( mesh->totvert != self->mesh->totvert ) | 
					
						
							|  |  |  | 			return EXPP_ReturnIntError( PyExc_TypeError,  | 
					
						
							|  |  |  | 					"vertex sequences must have the same number of vertices" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		memcpy( self->mesh->mvert, mesh->mvert, mesh->totvert*sizeof(MVert) ); | 
					
						
							|  |  |  | 	} else | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError,  | 
					
						
							|  |  |  | 				"expected a list or sequence of MVerts" ); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | static PyObject *MEdgeSeq_CreatePyObject( Mesh *mesh ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BPy_MEdgeSeq *obj = PyObject_NEW( BPy_MEdgeSeq, &MEdgeSeq_Type); | 
					
						
							|  |  |  | 	obj->mesh = mesh; | 
					
						
							|  |  |  | 	obj->iter = -1; /* iterator not yet used */ | 
					
						
							|  |  |  | 	return (PyObject *)obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | static PyObject *Mesh_getEdges( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	return MEdgeSeq_CreatePyObject(self->mesh); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *MFaceSeq_CreatePyObject( Mesh * mesh ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BPy_MFaceSeq *obj= PyObject_NEW( BPy_MFaceSeq, &MFaceSeq_Type); | 
					
						
							|  |  |  | 	obj->mesh = mesh; | 
					
						
							|  |  |  | 	obj->iter = -1; /* iterator not yet used */ | 
					
						
							|  |  |  | 	return (PyObject *)obj; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_getFaces( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-09-22 10:08:41 +00:00
										 |  |  | 	return MFaceSeq_CreatePyObject( self->mesh ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_getMaterials( BPy_Mesh *self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return EXPP_PyList_fromMaterialList( self->mesh->mat, | 
					
						
							|  |  |  | 			self->mesh->totcol, 1 ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int Mesh_setMaterials( BPy_Mesh *self, PyObject * value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Material **matlist; | 
					
						
							|  |  |  | 	int len; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-13 20:47:15 +00:00
										 |  |  |     if( !PySequence_Check( value ) || | 
					
						
							|  |  |  | 			!EXPP_check_sequence_consistency( value, &Material_Type ) ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  |         return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  |                   "list should only contain materials or None)" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     len = PyList_Size( value ); | 
					
						
							|  |  |  |     if( len > 16 ) | 
					
						
							|  |  |  |         return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  |                           "list can't have more than 16 materials" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* free old material list (if it exists) and adjust user counts */ | 
					
						
							|  |  |  | 	if( self->mesh->mat ) { | 
					
						
							|  |  |  | 		Mesh *me = self->mesh; | 
					
						
							|  |  |  | 		int i; | 
					
						
							|  |  |  | 		for( i = me->totcol; i-- > 0; ) | 
					
						
							|  |  |  | 			if( me->mat[i] ) | 
					
						
							|  |  |  |            		me->mat[i]->id.us--; | 
					
						
							|  |  |  | 		MEM_freeN( me->mat ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* build the new material list, increment user count, store it */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	matlist = EXPP_newMaterialList_fromPyList( value ); | 
					
						
							|  |  |  | 	EXPP_incr_mats_us( matlist, len ); | 
					
						
							|  |  |  | 	self->mesh->mat = matlist; | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  |     	self->mesh->totcol = (short)len; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /**@ This is another ugly fix due to the weird material handling of blender.
 | 
					
						
							|  |  |  |     * it makes sure that object material lists get updated (by their length) | 
					
						
							|  |  |  |     * according to their data material lists, otherwise blender crashes. | 
					
						
							|  |  |  |     * It just stupidly runs through all objects...BAD BAD BAD. | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-08 21:50:30 +00:00
										 |  |  |     	test_object_materials( ( ID * ) self->mesh ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_getMaxSmoothAngle( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *attr = PyInt_FromLong( self->mesh->smoothresh ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if( attr ) | 
					
						
							|  |  |  |         return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 			"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int Mesh_setMaxSmoothAngle( BPy_Mesh *self, PyObject *value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return EXPP_setIValueClamped( value, &self->mesh->smoothresh, | 
					
						
							|  |  |  |                             MESH_SMOOTHRESH_MIN, | 
					
						
							|  |  |  |                             MESH_SMOOTHRESH_MAX, 'h' ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_getSubDivLevels( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *attr = Py_BuildValue( "(h,h)", | 
					
						
							|  |  |  | 			self->mesh->subdiv, self->mesh->subdivr ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( attr ) | 
					
						
							|  |  |  | 		return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 			"Py_BuildValue() failed" ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int Mesh_setSubDivLevels( BPy_Mesh *self, PyObject *value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int subdiv[2]; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	PyObject *tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyTuple_Check( value ) || PyTuple_Size( value ) != 2 ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 						"expected (int, int) as argument" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for( i = 0; i < 2; i++ ) { | 
					
						
							|  |  |  | 		tmp = PyTuple_GET_ITEM( value, i ); | 
					
						
							|  |  |  | 		if( !PyInt_Check( tmp ) ) | 
					
						
							|  |  |  | 			return EXPP_ReturnIntError ( PyExc_TypeError, | 
					
						
							|  |  |  | 				  "expected a list [int, int] as argument" ); | 
					
						
							|  |  |  | 		subdiv[i] = EXPP_ClampInt( PyInt_AsLong( tmp ), | 
					
						
							|  |  |  | 						 MESH_SUBDIV_MIN, | 
					
						
							|  |  |  | 						 MESH_SUBDIV_MAX ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 20:48:43 +00:00
										 |  |  | 	self->mesh->subdiv = (short)subdiv[0]; | 
					
						
							|  |  |  | 	self->mesh->subdivr = (short)subdiv[1]; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_getName( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *attr = PyString_FromString( self->mesh->id.name + 2 ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( attr ) | 
					
						
							|  |  |  | 		return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					"couldn't get Mesh.name attribute" ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int Mesh_setName( BPy_Mesh * self, PyObject * value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *name; | 
					
						
							|  |  |  | 	char buf[21]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	name = PyString_AsString ( value ); | 
					
						
							|  |  |  | 	if( !name ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 					      "expected string argument" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyOS_snprintf( buf, sizeof( buf ), "%s", name ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rename_id( &self->mesh->id, buf ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_getUsers( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *attr = PyInt_FromLong( self->mesh->id.us ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( attr ) | 
					
						
							|  |  |  | 		return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					"couldn't get Mesh.users attribute" ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-22 09:13:44 +00:00
										 |  |  | static PyObject *Mesh_getFakeUser( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (self->mesh->id.flag & LIB_FAKEUSER) | 
					
						
							| 
									
										
										
										
											2006-08-22 18:08:57 +00:00
										 |  |  | 		Py_RETURN_TRUE; | 
					
						
							| 
									
										
										
										
											2006-08-22 09:13:44 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2006-08-22 18:08:57 +00:00
										 |  |  | 		Py_RETURN_FALSE; | 
					
						
							| 
									
										
										
										
											2006-08-22 09:13:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int Mesh_setFakeUser( BPy_Mesh * self, PyObject * value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int param; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	param = PyObject_IsTrue( value ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( param == -1 ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected int argument in range [0,1]" ); | 
					
						
							|  |  |  | 	if (param) { | 
					
						
							|  |  |  | 		self->mesh->id.flag |= LIB_FAKEUSER; | 
					
						
							|  |  |  | 		self->mesh->id.us++; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		self->mesh->id.flag &= ~LIB_FAKEUSER; | 
					
						
							|  |  |  | 		self->mesh->id.us--; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | static PyObject *Mesh_getFlag( BPy_Mesh * self, void *type ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *attr; | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 	switch( (long)type ) { | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	case MESH_HASFACEUV: | 
					
						
							|  |  |  | 		attr = self->mesh->tface ? EXPP_incr_ret_True() : | 
					
						
							|  |  |  | 			EXPP_incr_ret_False(); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case MESH_HASMCOL: | 
					
						
							|  |  |  | 		attr = self->mesh->mcol ? EXPP_incr_ret_True() : | 
					
						
							|  |  |  | 			EXPP_incr_ret_False(); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case MESH_HASVERTUV: | 
					
						
							|  |  |  | 		attr = self->mesh->msticky ? EXPP_incr_ret_True() : | 
					
						
							|  |  |  | 			EXPP_incr_ret_False(); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		attr = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( attr ) | 
					
						
							|  |  |  | 		return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					"couldn't get attribute" ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | static int Mesh_setFlag( BPy_Mesh * self, PyObject *value, void *type ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int param, i; | 
					
						
							|  |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 	param = PyObject_IsTrue( value ); | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-11 16:00:07 +00:00
										 |  |  | 	if( param == -1 ) | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected int argument in range [0,1]" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* sticky is independent of faceUV and vertUV */ | 
					
						
							|  |  |  | 	/* faceUV (tface) has priority over vertUV (mcol) */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-20 01:07:54 +00:00
										 |  |  | 	switch( (long)type ) { | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	case MESH_HASFACEUV: | 
					
						
							|  |  |  | 		if( !param ) { | 
					
						
							|  |  |  | 			if( mesh->tface ) { | 
					
						
							|  |  |  | 				MEM_freeN( mesh->tface ); | 
					
						
							|  |  |  | 				mesh->tface = NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-01-18 06:15:17 +00:00
										 |  |  | 		} else if( !mesh->tface ) { | 
					
						
							|  |  |  | 			if( !mesh->totface ) | 
					
						
							|  |  |  | 				return EXPP_ReturnIntError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					"mesh has no faces" ); | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 			make_tfaces( mesh ); | 
					
						
							| 
									
										
										
										
											2006-01-18 06:15:17 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	case MESH_HASMCOL: | 
					
						
							|  |  |  | 		if( !param ) { | 
					
						
							|  |  |  | 			if( mesh->mcol ) { | 
					
						
							|  |  |  | 				MEM_freeN( mesh->mcol ); | 
					
						
							|  |  |  | 				mesh->mcol = NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else if( !mesh->mcol ) { | 
					
						
							|  |  |  | 				/* TODO: mesh_create_shadedColors */ | 
					
						
							|  |  |  | 			mesh->mcol = MEM_callocN( sizeof(unsigned int)*mesh->totface*4, | 
					
						
							|  |  |  | 						"mcol" ); | 
					
						
							|  |  |  | 			for( i = 0; i < mesh->totface*4; i++ ) | 
					
						
							|  |  |  | 				mesh->mcol[i].a = 255; | 
					
						
							|  |  |  | 			if( mesh->tface ) | 
					
						
							|  |  |  | 				mcol_to_tface( mesh, 1 ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	case MESH_HASVERTUV: | 
					
						
							|  |  |  | 		if( !param ) { | 
					
						
							|  |  |  | 			if( mesh->msticky ) { | 
					
						
							|  |  |  | 				MEM_freeN( mesh->msticky ); | 
					
						
							|  |  |  | 				mesh->msticky = NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			if( !mesh->msticky ) { | 
					
						
							| 
									
										
										
										
											2006-02-05 07:19:37 +00:00
										 |  |  | 				mesh->msticky= MEM_mallocN( mesh->totvert*sizeof( MSticky ), | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 						"sticky" ); | 
					
						
							| 
									
										
										
										
											2006-02-05 07:19:37 +00:00
										 |  |  | 				memset( mesh->msticky, 255, mesh->totvert*sizeof( MSticky ) ); | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 				/* TODO: rework RE_make_sticky() so we can calculate */ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					"couldn't get attribute" ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | static PyObject *Mesh_getMode( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *attr = PyInt_FromLong( self->mesh->flag ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( attr ) | 
					
						
							|  |  |  | 		return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				      "couldn't get Mesh.mode attribute" ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int Mesh_setMode( BPy_Mesh *self, PyObject *value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	short param; | 
					
						
							| 
									
										
										
										
											2006-02-05 07:19:37 +00:00
										 |  |  | 	static short bitmask = ME_ISDONE | ME_NOPUNOFLIP | ME_TWOSIDED | | 
					
						
							|  |  |  | 		ME_UVEFFECT | ME_VCOLEFFECT | ME_AUTOSMOOTH | ME_SMESH | | 
					
						
							|  |  |  | 		ME_SUBSURF | ME_OPT_EDGES; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyInt_CheckExact ( value ) ) { | 
					
						
							|  |  |  | 		char errstr[128]; | 
					
						
							|  |  |  | 		sprintf ( errstr , "expected int bitmask of 0x%04x", bitmask ); | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, errstr ); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-03 20:48:43 +00:00
										 |  |  | 	param = (short)PyInt_AS_LONG ( value ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( ( param & bitmask ) != param ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 						"invalid bit(s) set in mask" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	self->mesh->flag = param;  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-27 16:33:02 +00:00
										 |  |  | static PyObject *Mesh_getKey( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if( self->mesh->key ) | 
					
						
							|  |  |  | 		return Key_CreatePyObject(self->mesh->key); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | static PyObject *Mesh_getActiveFace( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	TFace *face; | 
					
						
							|  |  |  | 	int i, totface; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !self->mesh->tface ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no texture values" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	face = self->mesh->tface; | 
					
						
							|  |  |  | 	totface = self->mesh->totface; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for( i = 0; i < totface; ++face, ++i ) | 
					
						
							|  |  |  | 		if( face->flag & TF_ACTIVE ) { | 
					
						
							|  |  |  | 			PyObject *attr = PyInt_FromLong( i ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if( attr ) | 
					
						
							|  |  |  | 				return attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 					"PyInt_FromLong() failed" ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int Mesh_setActiveFace( BPy_Mesh * self, PyObject * value ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	TFace *face; | 
					
						
							|  |  |  | 	int param; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if no texture faces, error */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !self->mesh->tface ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"face has no texture values" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if param isn't an int, error */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyInt_CheckExact( value ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected an int argument" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* check for a valid index */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	param = PyInt_AsLong( value ); | 
					
						
							|  |  |  | 	if( param < 0 || param > self->mesh->totface ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"face index out of range" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	face = self->mesh->tface; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if requested face isn't already active, then inactivate all
 | 
					
						
							|  |  |  | 	 * faces and activate the requested one */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !( face[param].flag & TF_ACTIVE ) ) { | 
					
						
							|  |  |  | 		int i; | 
					
						
							|  |  |  | 		for( i = self->mesh->totface; i > 0; ++face, --i ) | 
					
						
							|  |  |  | 			face->flag &= ~TF_ACTIVE; | 
					
						
							|  |  |  | 		self->mesh->tface[param].flag |= TF_ACTIVE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-02 17:44:44 +00:00
										 |  |  | static PyObject *Mesh_getActiveGroup( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	bDeformGroup *defGroup; | 
					
						
							|  |  |  | 	Object *object = self->object; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !object ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"This mesh must be linked to an object" );  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( object->actdef ) { | 
					
						
							|  |  |  | 		defGroup = BLI_findlink( &object->defbase, object->actdef-1 ); | 
					
						
							|  |  |  | 		return PyString_FromString( defGroup->name ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int Mesh_setActiveGroup( BPy_Mesh * self, PyObject * arg ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *name; | 
					
						
							|  |  |  | 	int tmp; | 
					
						
							|  |  |  | 	Object *object = self->object; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !object ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				"This mesh must be linked to an object" );  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyString_Check( arg ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_AttributeError, | 
					
						
							|  |  |  | 				"expected a string argument" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	name = PyString_AsString( arg ); | 
					
						
							|  |  |  | 	tmp = object->actdef; | 
					
						
							|  |  |  | 	vertexgroup_select_by_name( object, name ); | 
					
						
							|  |  |  | 	if( !object->actdef ) { | 
					
						
							|  |  |  | 		object->actdef = tmp; | 
					
						
							|  |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"vertex group not found" ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-07-31 12:57:46 +00:00
										 |  |  | static PyObject *Mesh_getTexMesh( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Mesh *texme= self->mesh->texcomesh; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (texme) | 
					
						
							|  |  |  | 		return Mesh_CreatePyObject( texme, NULL ); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int Mesh_setTexMesh( BPy_Mesh * self, PyObject * arg ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*None or Mesh*/ | 
					
						
							| 
									
										
										
										
											2006-07-31 13:28:00 +00:00
										 |  |  | 	if ( arg != Py_None && !Mesh_CheckPyObject(arg) ) | 
					
						
							| 
									
										
										
										
											2006-07-31 12:57:46 +00:00
										 |  |  | 		return EXPP_ReturnIntError( PyExc_ValueError, | 
					
						
							|  |  |  | 			"texmesh must be a Mesh or None type" ); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*remove existing texmesh*/ | 
					
						
							|  |  |  | 	if (self->mesh->texcomesh) { | 
					
						
							|  |  |  | 		self->mesh->texcomesh->id.us--; | 
					
						
							|  |  |  | 		self->mesh->texcomesh= NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (arg != Py_None) { /* its a mesh */ | 
					
						
							|  |  |  | 		BPy_Mesh *blen_obj = ( BPy_Mesh * ) arg; | 
					
						
							|  |  |  | 		/*This is a mesh so it needs to be added */ | 
					
						
							|  |  |  | 		self->mesh->texcomesh= blen_obj->mesh; | 
					
						
							|  |  |  | 		self->mesh->texcomesh->id.us++; | 
					
						
							| 
									
										
										
										
											2006-08-13 01:51:47 +00:00
										 |  |  | 		blen_obj->new= 0; | 
					
						
							| 
									
										
										
										
											2006-07-31 12:57:46 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-28 00:39:13 +00:00
										 |  |  | static int Mesh_setSel( BPy_Mesh * self, PyObject * arg ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	Mesh *me = self->mesh; | 
					
						
							|  |  |  | 	MVert *mvert = me->mvert; | 
					
						
							|  |  |  | 	MEdge *medge = me->medge; | 
					
						
							|  |  |  | 	MFace *mface = me->mface; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( PyObject_IsTrue( arg ) ) { | 
					
						
							|  |  |  | 		for( i = 0; i < me->totvert; ++mvert, ++i ) | 
					
						
							|  |  |  | 			mvert->flag |= SELECT; | 
					
						
							|  |  |  | 		for( i = 0; i < me->totedge; ++medge, ++i ) | 
					
						
							|  |  |  | 			medge->flag |= SELECT; | 
					
						
							|  |  |  | 		for( i = 0; i < me->totface; ++mface, ++i ) | 
					
						
							|  |  |  | 			mface->flag |= ME_FACE_SEL; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		for( i = 0; i < me->totvert; ++mvert, ++i ) | 
					
						
							|  |  |  | 			mvert->flag &= ~SELECT; | 
					
						
							|  |  |  | 		for( i = 0; i < me->totedge; ++medge, ++i ) | 
					
						
							|  |  |  | 			medge->flag &= ~SELECT; | 
					
						
							|  |  |  | 		for( i = 0; i < me->totface; ++mface, ++i ) | 
					
						
							|  |  |  | 			mface->flag &= ~ME_FACE_SEL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int Mesh_setHide( BPy_Mesh * self, PyObject * arg ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	Mesh *me = self->mesh; | 
					
						
							|  |  |  | 	MVert *mvert = me->mvert; | 
					
						
							|  |  |  | 	MEdge *medge = me->medge; | 
					
						
							|  |  |  | 	MFace *mface = me->mface; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( PyObject_IsTrue( arg ) ) { | 
					
						
							|  |  |  | 		for( i = 0; i < me->totvert; ++mvert, ++i ) | 
					
						
							|  |  |  | 			mvert->flag |= ME_HIDE; | 
					
						
							|  |  |  | 		for( i = 0; i < me->totedge; ++medge, ++i ) | 
					
						
							|  |  |  | 			medge->flag |= ME_HIDE; | 
					
						
							|  |  |  | 		for( i = 0; i < me->totface; ++mface, ++i ) | 
					
						
							|  |  |  | 			mface->flag |= ME_HIDE; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		for( i = 0; i < me->totvert; ++mvert, ++i ) | 
					
						
							|  |  |  | 			mvert->flag &= ~ME_HIDE; | 
					
						
							|  |  |  | 		for( i = 0; i < me->totedge; ++medge, ++i ) | 
					
						
							|  |  |  | 			medge->flag &= ~ME_HIDE; | 
					
						
							|  |  |  | 		for( i = 0; i < me->totface; ++mface, ++i ) | 
					
						
							|  |  |  | 			mface->flag &= ~ME_HIDE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | /************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Python Mesh_Type standard operations | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  ************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | static void Mesh_dealloc( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-05-20 16:52:11 +00:00
										 |  |  | 	Mesh *mesh = self->mesh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if the mesh is new and has no users, delete it */ | 
					
						
							|  |  |  | 	if( self->new && !mesh->id.us ) | 
					
						
							|  |  |  | 	    free_libblock( &G.main->mesh, mesh ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	PyObject_DEL( self ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *Mesh_repr( BPy_Mesh * self ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return PyString_FromFormat( "[Mesh \"%s\"]", | 
					
						
							|  |  |  | 				    self->mesh->id.name + 2 ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*****************************************************************************/ | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | /* Python Mesh_Type attributes get/set structure:                           */ | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | /*****************************************************************************/ | 
					
						
							|  |  |  | static PyGetSetDef BPy_Mesh_getseters[] = { | 
					
						
							|  |  |  | 	{"verts", | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 	 (getter)Mesh_getVerts, (setter)Mesh_setVerts, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	 "The mesh's vertices (MVert)", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"edges", | 
					
						
							|  |  |  | 	 (getter)Mesh_getEdges, (setter)NULL, | 
					
						
							|  |  |  | 	 "The mesh's edge data (MEdge)", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"faces", | 
					
						
							|  |  |  | 	 (getter)Mesh_getFaces, (setter)NULL, | 
					
						
							|  |  |  | 	 "The mesh's face data (MFace)", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"materials", | 
					
						
							|  |  |  | 	 (getter)Mesh_getMaterials, (setter)Mesh_setMaterials, | 
					
						
							|  |  |  | 	 "List of the mesh's materials", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"degr", | 
					
						
							| 
									
										
										
										
											2006-05-10 03:59:16 +00:00
										 |  |  | 	 (getter)Mesh_getMaxSmoothAngle, (setter)Mesh_setMaxSmoothAngle, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	 "The max angle for auto smoothing", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"maxSmoothAngle", | 
					
						
							|  |  |  | 	 (getter)Mesh_getMaxSmoothAngle, (setter)Mesh_setMaxSmoothAngle, | 
					
						
							|  |  |  | 	 "deprecated: see 'degr'", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"subDivLevels", | 
					
						
							|  |  |  | 	 (getter)Mesh_getSubDivLevels, (setter)Mesh_setSubDivLevels, | 
					
						
							|  |  |  | 	 "The display and rendering subdivision levels", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"name", | 
					
						
							|  |  |  | 	 (getter)Mesh_getName, (setter)Mesh_setName, | 
					
						
							|  |  |  | 	 "The mesh's data name", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"mode", | 
					
						
							|  |  |  | 	 (getter)Mesh_getMode, (setter)Mesh_setMode, | 
					
						
							|  |  |  | 	 "The mesh's mode bitfield", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							| 
									
										
										
										
											2006-09-27 16:33:02 +00:00
										 |  |  | 	{"key", | 
					
						
							|  |  |  | 	 (getter)Mesh_getKey, (setter)NULL, | 
					
						
							|  |  |  | 	 "The mesh's key", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	{"faceUV", | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	 (getter)Mesh_getFlag, (setter)Mesh_setFlag, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	 "UV-mapped textured faces enabled", | 
					
						
							|  |  |  |  	 (void *)MESH_HASFACEUV}, | 
					
						
							|  |  |  | 	{"vertexColors", | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	 (getter)Mesh_getFlag, (setter)Mesh_setFlag, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	 "Vertex colors for the mesh enabled", | 
					
						
							|  |  |  | 	 (void *)MESH_HASMCOL}, | 
					
						
							|  |  |  | 	{"vertexUV", | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	 (getter)Mesh_getFlag, (setter)Mesh_setFlag, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	 "'Sticky' flag for per vertex UV coordinates enabled", | 
					
						
							|  |  |  | 	 (void *)MESH_HASVERTUV}, | 
					
						
							|  |  |  | 	{"activeFace", | 
					
						
							|  |  |  | 	 (getter)Mesh_getActiveFace, (setter)Mesh_setActiveFace, | 
					
						
							|  |  |  | 	 "Index of the mesh's active texture face (in UV editor)", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"users", | 
					
						
							|  |  |  | 	 (getter)Mesh_getUsers, (setter)NULL, | 
					
						
							|  |  |  | 	 "Number of users of the mesh", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							| 
									
										
										
										
											2006-08-22 09:13:44 +00:00
										 |  |  | 	{"fakeUser", | 
					
						
							|  |  |  | 	 (getter)Mesh_getFakeUser, (setter)Mesh_setFakeUser, | 
					
						
							|  |  |  | 	 "The fake user status of this mesh", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							| 
									
										
										
										
											2006-05-02 17:44:44 +00:00
										 |  |  | 	{"activeGroup", | 
					
						
							|  |  |  | 	 (getter)Mesh_getActiveGroup, (setter)Mesh_setActiveGroup, | 
					
						
							|  |  |  | 	 "Active group for the mesh", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							| 
									
										
										
										
											2006-07-31 12:57:46 +00:00
										 |  |  | 	{"texMesh", | 
					
						
							|  |  |  | 	 (getter)Mesh_getTexMesh, (setter)Mesh_setTexMesh, | 
					
						
							|  |  |  | 	 "The meshes tex mesh proxy texture coord mesh", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							| 
									
										
										
										
											2006-05-28 00:39:13 +00:00
										 |  |  | 	{"sel", | 
					
						
							|  |  |  | 	 (getter)NULL, (setter)Mesh_setSel, | 
					
						
							|  |  |  | 	 "Select/deselect all verts, edges, faces in the mesh", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							|  |  |  | 	{"hide", | 
					
						
							|  |  |  | 	 (getter)NULL, (setter)Mesh_setHide, | 
					
						
							|  |  |  | 	 "Hide/unhide all verts, edges, faces in the mesh", | 
					
						
							|  |  |  | 	 NULL}, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	{NULL,NULL,NULL,NULL,NULL}  /* Sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*****************************************************************************/ | 
					
						
							|  |  |  | /* Python Mesh_Type structure definition:                                   */ | 
					
						
							|  |  |  | /*****************************************************************************/ | 
					
						
							|  |  |  | PyTypeObject Mesh_Type = { | 
					
						
							|  |  |  | 	PyObject_HEAD_INIT( NULL )  /* required py macro */ | 
					
						
							|  |  |  | 	0,                          /* ob_size */ | 
					
						
							|  |  |  | 	/*  For printing, in format "<module>.<name>" */ | 
					
						
							|  |  |  | 	"Blender Mesh",             /* char *tp_name; */ | 
					
						
							|  |  |  | 	sizeof( BPy_Mesh ),         /* int tp_basicsize; */ | 
					
						
							|  |  |  | 	0,                          /* tp_itemsize;  For allocation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Methods to implement standard operations */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	( destructor ) Mesh_dealloc,/* destructor tp_dealloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* printfunc tp_print; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrfunc tp_getattr; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrfunc tp_setattr; */ | 
					
						
							|  |  |  | 	NULL,                       /* cmpfunc tp_compare; */ | 
					
						
							|  |  |  | 	( reprfunc ) Mesh_repr,     /* reprfunc tp_repr; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Method suites for standard classes */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /* PyNumberMethods *tp_as_number; */ | 
					
						
							|  |  |  | 	NULL,                       /* PySequenceMethods *tp_as_sequence; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyMappingMethods *tp_as_mapping; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* More standard operations (here for binary compatibility) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /* hashfunc tp_hash; */ | 
					
						
							|  |  |  | 	NULL,                       /* ternaryfunc tp_call; */ | 
					
						
							|  |  |  | 	NULL,                       /* reprfunc tp_str; */ | 
					
						
							|  |  |  | 	NULL,                       /* getattrofunc tp_getattro; */ | 
					
						
							|  |  |  | 	NULL,                       /* setattrofunc tp_setattro; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Functions to access object as input/output buffer */ | 
					
						
							|  |  |  | 	NULL,                       /* PyBufferProcs *tp_as_buffer; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Flags to define presence of optional/expanded features ***/ | 
					
						
							|  |  |  | 	Py_TPFLAGS_DEFAULT,         /* long tp_flags; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	NULL,                       /*  char *tp_doc;  Documentation string */ | 
					
						
							|  |  |  |   /*** Assigned meaning in release 2.0 ***/ | 
					
						
							|  |  |  | 	/* call function for all accessible objects */ | 
					
						
							|  |  |  | 	NULL,                       /* traverseproc tp_traverse; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* delete references to contained objects */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_clear; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  Assigned meaning in release 2.1 ***/ | 
					
						
							|  |  |  |   /*** rich comparisons ***/ | 
					
						
							|  |  |  | 	NULL,                       /* richcmpfunc tp_richcompare; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /***  weak reference enabler ***/ | 
					
						
							|  |  |  | 	0,                          /* long tp_weaklistoffset; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Added in release 2.2 ***/ | 
					
						
							|  |  |  | 	/*   Iterators */ | 
					
						
							|  |  |  | 	NULL,                       /* getiterfunc tp_iter; */ | 
					
						
							|  |  |  | 	NULL,                       /* iternextfunc tp_iternext; */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /*** Attribute descriptor and subclassing stuff ***/ | 
					
						
							|  |  |  | 	BPy_Mesh_methods,          /* struct PyMethodDef *tp_methods; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct PyMemberDef *tp_members; */ | 
					
						
							|  |  |  | 	BPy_Mesh_getseters,        /* struct PyGetSetDef *tp_getset; */ | 
					
						
							|  |  |  | 	NULL,                       /* struct _typeobject *tp_base; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_dict; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrgetfunc tp_descr_get; */ | 
					
						
							|  |  |  | 	NULL,                       /* descrsetfunc tp_descr_set; */ | 
					
						
							|  |  |  | 	0,                          /* long tp_dictoffset; */ | 
					
						
							|  |  |  | 	NULL,                       /* initproc tp_init; */ | 
					
						
							|  |  |  | 	NULL,                       /* allocfunc tp_alloc; */ | 
					
						
							|  |  |  | 	NULL,                       /* newfunc tp_new; */ | 
					
						
							|  |  |  | 	/*  Low-level free-memory routine */ | 
					
						
							|  |  |  | 	NULL,                       /* freefunc tp_free;  */ | 
					
						
							|  |  |  | 	/* For PyObject_IS_GC */ | 
					
						
							|  |  |  | 	NULL,                       /* inquiry tp_is_gc;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_bases; */ | 
					
						
							|  |  |  | 	/* method resolution order */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_mro;  */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_cache; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_subclasses; */ | 
					
						
							|  |  |  | 	NULL,                       /* PyObject *tp_weaklist; */ | 
					
						
							|  |  |  | 	NULL | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-04 15:17:27 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * get one or all mesh data objects | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-08 05:37:00 +00:00
										 |  |  | static PyObject *M_Mesh_Get( PyObject * self_unused, PyObject * args ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	char *name = NULL; | 
					
						
							|  |  |  | 	Mesh *mesh = NULL; | 
					
						
							|  |  |  | 	BPy_Mesh* obj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple( args, "|s", &name ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 				"expected zero or one string arguments" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( name ) { | 
					
						
							|  |  |  | 		mesh = ( Mesh * ) GetIdFromList( &( G.main->mesh ), name ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if( !mesh ) | 
					
						
							|  |  |  | 			return EXPP_incr_ret( Py_None ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		return Mesh_CreatePyObject( mesh, NULL ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	} else {			/* () - return a list with all meshes in the scene */ | 
					
						
							|  |  |  | 		PyObject *meshlist; | 
					
						
							|  |  |  | 		Link *link; | 
					
						
							|  |  |  | 		int index = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		meshlist = PyList_New( BLI_countlist( &( G.main->mesh ) ) ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if( !meshlist ) | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_MemoryError, | 
					
						
							|  |  |  | 					"couldn't create PyList" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		link = G.main->mesh.first; | 
					
						
							|  |  |  | 		index = 0; | 
					
						
							|  |  |  | 		while( link ) { | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 			obj = ( BPy_Mesh * ) Mesh_CreatePyObject( ( Mesh * )link, NULL ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 			PyList_SetItem( meshlist, index, ( PyObject * ) obj ); | 
					
						
							|  |  |  | 			index++; | 
					
						
							|  |  |  | 			link = link->next; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return meshlist; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-04 15:17:27 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * create a new mesh data object | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-08 05:37:00 +00:00
										 |  |  | static PyObject *M_Mesh_New( PyObject * self_unused, PyObject * args ) | 
					
						
							| 
									
										
										
										
											2005-10-04 15:17:27 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	char *name = "Mesh"; | 
					
						
							|  |  |  | 	Mesh *mesh; | 
					
						
							|  |  |  | 	BPy_Mesh *obj; | 
					
						
							|  |  |  | 	char buf[21]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple( args, "|s", &name ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					      "expected nothing or a string as argument" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	obj = (BPy_Mesh *)PyObject_NEW( BPy_Mesh, &Mesh_Type ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !obj ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				       "PyObject_New() failed" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mesh = add_mesh(); /* doesn't return NULL now, but might someday */ | 
					
						
							| 
									
										
										
										
											2006-09-05 06:45:39 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-10-04 15:17:27 +00:00
										 |  |  | 	if( !mesh ) { | 
					
						
							|  |  |  | 		Py_DECREF ( obj ); | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_RuntimeError, | 
					
						
							|  |  |  | 				       "FATAL: could not create mesh object" ); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-09-05 06:45:39 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* Bound box set to null needed because a new mesh is initialized
 | 
					
						
							|  |  |  | 	with a bounding box of -1 -1 -1 -1 -1 -1 | 
					
						
							|  |  |  | 	if its not set to null the bounding box is not re-calculated | 
					
						
							|  |  |  | 	when ob.getBoundBox() is called.*/ | 
					
						
							|  |  |  | 	MEM_freeN(mesh->bb); | 
					
						
							|  |  |  | 	mesh->bb= NULL; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2005-10-04 15:17:27 +00:00
										 |  |  | 	mesh->id.us = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyOS_snprintf( buf, sizeof( buf ), "%s", name ); | 
					
						
							|  |  |  | 	rename_id( &mesh->id, buf ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	obj->mesh = mesh; | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	obj->object = NULL; | 
					
						
							| 
									
										
										
										
											2006-05-20 16:52:11 +00:00
										 |  |  | 	obj->new = 1; | 
					
						
							| 
									
										
										
										
											2005-10-04 15:17:27 +00:00
										 |  |  | 	return (PyObject *)obj; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * creates a new MVert for users to manipulate | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-08 05:37:00 +00:00
										 |  |  | static PyObject *M_Mesh_MVert( PyObject * self_unused, PyObject * args ) | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	MVert vert; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* initialize the new vert's data */ | 
					
						
							|  |  |  | 	memset( &vert, 0, sizeof( MVert ) ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * accept either a 3D vector or tuple of three floats | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( PyTuple_Size ( args ) == 1 ) { | 
					
						
							| 
									
										
										
										
											2005-10-19 21:24:18 +00:00
										 |  |  | 		PyObject *tmp = PyTuple_GET_ITEM( args, 0 ); | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 		if( !VectorObject_Check( tmp ) || ((VectorObject *)tmp)->size != 3 ) | 
					
						
							|  |  |  | 			return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 				"expected three floats or vector of size 3" ); | 
					
						
							|  |  |  | 		for( i = 0; i < 3; ++i ) | 
					
						
							|  |  |  | 			vert.co[i] = ((VectorObject *)tmp)->vec[i]; | 
					
						
							|  |  |  | 	} else if( !PyArg_ParseTuple ( args, "fff", | 
					
						
							|  |  |  | 				&vert.co[0], &vert.co[1], &vert.co[2] ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 			"expected three floats or vector of size 3" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* make a new MVert from the data */ | 
					
						
							|  |  |  | 	return PVert_CreatePyObject( &vert ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-08 05:37:00 +00:00
										 |  |  | static PyObject *M_Mesh_Modes( PyObject * self_unused, PyObject * args ) | 
					
						
							| 
									
										
										
										
											2006-01-17 06:18:43 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int modes = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !G.scene ) { | 
					
						
							|  |  |  | 		Py_RETURN_NONE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !PyArg_ParseTuple( args, "|i", &modes ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_TypeError, | 
					
						
							|  |  |  | 					      "expected optional int as argument" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( modes > ( SCE_SELECT_VERTEX | SCE_SELECT_EDGE | SCE_SELECT_FACE ) ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_ValueError, | 
					
						
							|  |  |  | 					      "value out of range" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( modes > 0 ) | 
					
						
							| 
									
										
										
										
											2006-04-24 15:09:07 +00:00
										 |  |  | 		G.scene->selectmode = (short)modes; | 
					
						
							| 
									
										
										
										
											2006-01-17 06:18:43 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	return PyInt_FromLong( G.scene->selectmode ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | static struct PyMethodDef M_Mesh_methods[] = { | 
					
						
							| 
									
										
										
										
											2005-10-04 15:17:27 +00:00
										 |  |  | 	{"New", (PyCFunction)M_Mesh_New, METH_VARARGS, | 
					
						
							|  |  |  | 		"Create a new mesh"}, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	{"Get", (PyCFunction)M_Mesh_Get, METH_VARARGS, | 
					
						
							|  |  |  | 		"Get a mesh by name"}, | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	{"MVert", (PyCFunction)M_Mesh_MVert, METH_VARARGS, | 
					
						
							|  |  |  | 		"Create a new MVert"}, | 
					
						
							| 
									
										
										
										
											2006-01-17 06:18:43 +00:00
										 |  |  | 	{"Mode", (PyCFunction)M_Mesh_Modes, METH_VARARGS, | 
					
						
							| 
									
										
										
										
											2006-01-17 09:20:37 +00:00
										 |  |  | 		"Get/set edit selection mode(s)"}, | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	{NULL, NULL, 0, NULL}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-17 06:18:43 +00:00
										 |  |  | static PyObject *M_Mesh_ModesDict( void ) | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyObject *Modes = PyConstant_New(  ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( Modes ) { | 
					
						
							|  |  |  | 		BPy_constant *d = ( BPy_constant * ) Modes; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "NOVNORMALSFLIP", | 
					
						
							|  |  |  | 				PyInt_FromLong( ME_NOPUNOFLIP ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "TWOSIDED", PyInt_FromLong( ME_TWOSIDED ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "AUTOSMOOTH",  | 
					
						
							|  |  |  | 				PyInt_FromLong( ME_AUTOSMOOTH ) ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return Modes; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Set constants for face drawing mode -- see drawmesh.c */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *M_Mesh_FaceModesDict( void ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *FM = PyConstant_New(  ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( FM ) { | 
					
						
							|  |  |  | 		BPy_constant *d = ( BPy_constant * ) FM; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "BILLBOARD", | 
					
						
							|  |  |  | 				 PyInt_FromLong( TF_BILLBOARD2 ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "ALL", PyInt_FromLong( 0xffff ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "HALO", PyInt_FromLong( TF_BILLBOARD ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "DYNAMIC", PyInt_FromLong( TF_DYNAMIC ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "INVISIBLE", PyInt_FromLong( TF_INVISIBLE ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "LIGHT", PyInt_FromLong( TF_LIGHT ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "OBCOL", PyInt_FromLong( TF_OBCOL ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "SHADOW", PyInt_FromLong( TF_SHADOW ) ); | 
					
						
							| 
									
										
										
										
											2006-08-16 19:20:37 +00:00
										 |  |  | 		PyConstant_Insert( d, "TEXT", PyInt_FromLong( TF_BMFONT ) ); | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 		PyConstant_Insert( d, "SHAREDVERT", PyInt_FromLong( TF_SHAREDVERT ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "SHAREDCOL", PyInt_FromLong( TF_SHAREDCOL ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "TEX", PyInt_FromLong( TF_TEX ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "TILES", PyInt_FromLong( TF_TILES ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "TWOSIDE", PyInt_FromLong( TF_TWOSIDE ) ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return FM; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *M_Mesh_FaceFlagsDict( void ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *FF = PyConstant_New(  ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( FF ) { | 
					
						
							|  |  |  | 		BPy_constant *d = ( BPy_constant * ) FF; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-19 15:44:43 +00:00
										 |  |  | 		PyConstant_Insert( d, "SELECT", PyInt_FromLong( TF_SELECT ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "HIDE", PyInt_FromLong( TF_HIDE ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "ACTIVE", PyInt_FromLong( TF_ACTIVE ) ); | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return FF; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *M_Mesh_FaceTranspModesDict( void ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *FTM = PyConstant_New(  ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( FTM ) { | 
					
						
							|  |  |  | 		BPy_constant *d = ( BPy_constant * ) FTM; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-19 15:44:43 +00:00
										 |  |  | 		PyConstant_Insert( d, "SOLID", PyInt_FromLong( TF_SOLID ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "ADD", PyInt_FromLong( TF_ADD ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "ALPHA", PyInt_FromLong( TF_ALPHA ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert( d, "SUB", PyInt_FromLong( TF_SUB ) ); | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return FTM; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *M_Mesh_EdgeFlagsDict( void ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *EF = PyConstant_New(  ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( EF ) { | 
					
						
							|  |  |  | 		BPy_constant *d = ( BPy_constant * ) EF; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		PyConstant_Insert(d, "SELECT", PyInt_FromLong( SELECT ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert(d, "EDGEDRAW", PyInt_FromLong( ME_EDGEDRAW ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert(d, "EDGERENDER", PyInt_FromLong( ME_EDGERENDER ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert(d, "SEAM", PyInt_FromLong( ME_SEAM ) ); | 
					
						
							|  |  |  | 		PyConstant_Insert(d, "FGON", PyInt_FromLong( ME_FGON ) ); | 
					
						
							| 
									
										
										
										
											2006-06-26 04:14:12 +00:00
										 |  |  | 		PyConstant_Insert(d, "LOOSE", PyInt_FromLong( ME_LOOSEEDGE ) ); | 
					
						
							| 
									
										
										
										
											2006-08-29 10:04:10 +00:00
										 |  |  | 		PyConstant_Insert(d, "SHARP", PyInt_FromLong( ME_SHARP ) ); | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return EF; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *M_Mesh_VertAssignDict( void ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *Vert = PyConstant_New(  ); | 
					
						
							|  |  |  | 	if( Vert ) { | 
					
						
							|  |  |  | 		BPy_constant *d = ( BPy_constant * ) Vert; | 
					
						
							|  |  |  | 		PyConstant_Insert(d, "ADD", PyInt_FromLong(WEIGHT_ADD)); | 
					
						
							|  |  |  | 		PyConstant_Insert(d, "REPLACE", PyInt_FromLong(WEIGHT_REPLACE)); | 
					
						
							|  |  |  | 		PyConstant_Insert(d, "SUBTRACT", PyInt_FromLong(WEIGHT_SUBTRACT)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return Vert; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-17 06:18:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject *M_Mesh_SelectModeDict( void ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *Mode = PyConstant_New(  ); | 
					
						
							|  |  |  | 	if( Mode ) { | 
					
						
							|  |  |  | 		BPy_constant *d = ( BPy_constant * ) Mode; | 
					
						
							|  |  |  | 		PyConstant_Insert(d, "VERTEX", PyInt_FromLong(SCE_SELECT_VERTEX)); | 
					
						
							|  |  |  | 		PyConstant_Insert(d, "EDGE", PyInt_FromLong(SCE_SELECT_EDGE)); | 
					
						
							|  |  |  | 		PyConstant_Insert(d, "FACE", PyInt_FromLong(SCE_SELECT_FACE)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return Mode; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | static char M_Mesh_doc[] = "The Blender.Mesh submodule"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *Mesh_Init( void ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *submodule; | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-01-17 06:18:43 +00:00
										 |  |  | 	PyObject *Modes = M_Mesh_ModesDict( ); | 
					
						
							|  |  |  | 	PyObject *FaceFlags = M_Mesh_FaceFlagsDict( ); | 
					
						
							|  |  |  | 	PyObject *FaceModes = M_Mesh_FaceModesDict( ); | 
					
						
							|  |  |  | 	PyObject *FaceTranspModes = M_Mesh_FaceTranspModesDict( ); | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	PyObject *EdgeFlags = M_Mesh_EdgeFlagsDict(  ); | 
					
						
							| 
									
										
										
										
											2006-01-17 06:18:43 +00:00
										 |  |  | 	PyObject *AssignModes = M_Mesh_VertAssignDict( ); | 
					
						
							|  |  |  | 	PyObject *SelectModes = M_Mesh_SelectModeDict( ); | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( PyType_Ready( &MCol_Type ) < 0 ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	if( PyType_Ready( &MVert_Type ) < 0 ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-10-11 04:09:08 +00:00
										 |  |  | 	if( PyType_Ready( &PVert_Type ) < 0 ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	if( PyType_Ready( &MVertSeq_Type ) < 0 ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	if( PyType_Ready( &MEdge_Type ) < 0 ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	if( PyType_Ready( &MEdgeSeq_Type ) < 0 ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	if( PyType_Ready( &MFace_Type ) < 0 ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	if( PyType_Ready( &MFaceSeq_Type ) < 0 ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	if( PyType_Ready( &Mesh_Type ) < 0 ) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	submodule = | 
					
						
							|  |  |  | 		Py_InitModule3( "Blender.Mesh", M_Mesh_methods, M_Mesh_doc ); | 
					
						
							| 
									
										
										
										
											2006-05-25 16:45:24 +00:00
										 |  |  | 	PyDict_SetItemString( PyModule_GetDict( submodule ), | 
					
						
							|  |  |  | 			"Primitives", MeshPrimitives_Init( ) ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	if( Modes ) | 
					
						
							|  |  |  | 		PyModule_AddObject( submodule, "Modes", Modes ); | 
					
						
							|  |  |  | 	if( FaceFlags ) | 
					
						
							|  |  |  | 		PyModule_AddObject( submodule, "FaceFlags", FaceFlags ); | 
					
						
							|  |  |  | 	if( FaceModes ) | 
					
						
							|  |  |  | 		PyModule_AddObject( submodule, "FaceModes", FaceModes ); | 
					
						
							|  |  |  | 	if( FaceTranspModes ) | 
					
						
							|  |  |  | 		PyModule_AddObject( submodule, "FaceTranspModes", | 
					
						
							|  |  |  | 				    FaceTranspModes ); | 
					
						
							|  |  |  | 	if( EdgeFlags ) | 
					
						
							|  |  |  | 		PyModule_AddObject( submodule, "EdgeFlags", EdgeFlags ); | 
					
						
							|  |  |  | 	if( AssignModes ) | 
					
						
							| 
									
										
										
										
											2005-10-28 13:51:08 +00:00
										 |  |  | 		PyModule_AddObject( submodule, "AssignModes", AssignModes ); | 
					
						
							| 
									
										
										
										
											2006-01-17 06:18:43 +00:00
										 |  |  | 	if( SelectModes ) | 
					
						
							|  |  |  | 		PyModule_AddObject( submodule, "SelectModes", SelectModes ); | 
					
						
							| 
									
										
										
										
											2005-10-28 13:51:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 	return submodule; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* These are needed by Object.c */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | PyObject *Mesh_CreatePyObject( Mesh * me, Object *obj ) | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BPy_Mesh *nmesh = PyObject_NEW( BPy_Mesh, &Mesh_Type ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !nmesh ) | 
					
						
							|  |  |  | 		return EXPP_ReturnPyObjError( PyExc_MemoryError, | 
					
						
							|  |  |  | 				"couldn't create BPy_Mesh object" ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nmesh->mesh = me; | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	nmesh->object = obj; | 
					
						
							| 
									
										
										
										
											2006-05-20 16:52:11 +00:00
										 |  |  | 	nmesh->new = 0; | 
					
						
							| 
									
										
										
										
											2006-08-13 01:51:47 +00:00
										 |  |  | 	G.totmesh++; | 
					
						
							| 
									
										
										
										
											2005-10-03 19:36:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return ( PyObject * ) nmesh; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int Mesh_CheckPyObject( PyObject * pyobj ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return ( pyobj->ob_type == &Mesh_Type ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | Mesh *Mesh_FromPyObject( PyObject * pyobj, Object *obj ) | 
					
						
							| 
									
										
										
										
											2005-10-04 15:17:27 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BPy_Mesh *blen_obj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	blen_obj = ( BPy_Mesh * ) pyobj; | 
					
						
							| 
									
										
										
										
											2005-10-27 19:37:37 +00:00
										 |  |  | 	blen_obj->object = obj; | 
					
						
							| 
									
										
										
										
											2005-10-04 15:17:27 +00:00
										 |  |  | 	return blen_obj->mesh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |