| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  |  /* $Id: 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * ***** BEGIN GPL 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. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 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) 2004 by Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is: all of this file. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): Johnny Matthews, Geoffrey Bantle. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise in mods.c | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <math.h>
 | 
					
						
							|  |  |  | #include <float.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | #include "PIL_time.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLO_sys_types.h" // for intptr_t support
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_mesh_types.h"
 | 
					
						
							|  |  |  | #include "DNA_material_types.h"
 | 
					
						
							|  |  |  | #include "DNA_meshdata_types.h"
 | 
					
						
							|  |  |  | #include "DNA_modifier_types.h"
 | 
					
						
							|  |  |  | #include "DNA_object_types.h"
 | 
					
						
							|  |  |  | #include "DNA_scene_types.h"
 | 
					
						
							|  |  |  | #include "DNA_screen_types.h"
 | 
					
						
							|  |  |  | #include "DNA_view3d_types.h"
 | 
					
						
							|  |  |  | #include "DNA_key_types.h"
 | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | #include "DNA_windowmanager_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "RNA_types.h"
 | 
					
						
							|  |  |  | #include "RNA_define.h"
 | 
					
						
							|  |  |  | #include "RNA_access.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_blenlib.h"
 | 
					
						
							|  |  |  | #include "BLI_arithb.h"
 | 
					
						
							|  |  |  | #include "BLI_editVert.h"
 | 
					
						
							|  |  |  | #include "BLI_rand.h"
 | 
					
						
							|  |  |  | #include "BLI_ghash.h"
 | 
					
						
							|  |  |  | #include "BLI_linklist.h"
 | 
					
						
							|  |  |  | #include "BLI_heap.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 16:03:29 +00:00
										 |  |  | #include "BKE_context.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | #include "BKE_customdata.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 16:03:29 +00:00
										 |  |  | #include "BKE_depsgraph.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | #include "BKE_global.h"
 | 
					
						
							|  |  |  | #include "BKE_library.h"
 | 
					
						
							|  |  |  | #include "BKE_mesh.h"
 | 
					
						
							|  |  |  | #include "BKE_object.h"
 | 
					
						
							|  |  |  | #include "BKE_utildefines.h"
 | 
					
						
							|  |  |  | #include "BKE_bmesh.h"
 | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | #include "BKE_report.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "BIF_gl.h"
 | 
					
						
							|  |  |  | #include "BIF_glutil.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | #include "WM_api.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | #include "WM_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "ED_mesh.h"
 | 
					
						
							|  |  |  | #include "ED_view3d.h"
 | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | #include "ED_util.h"
 | 
					
						
							|  |  |  | #include "ED_screen.h"
 | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | #include "BIF_transform.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-22 15:46:35 +00:00
										 |  |  | #include "UI_interface.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-01 13:15:35 +00:00
										 |  |  | #include "mesh_intern.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* XXX */ | 
					
						
							|  |  |  | static int extern_qread() {return 0;} | 
					
						
							|  |  |  | static void waitcursor() {} | 
					
						
							|  |  |  | static int pupmenu() {return 0;} | 
					
						
							|  |  |  | static int qtest() {return 0;} | 
					
						
							|  |  |  | #define add_numbut(a, b, c, d, e, f, g) {}
 | 
					
						
							|  |  |  | static int snap_sel_to_curs() {return 0;} | 
					
						
							|  |  |  | static int snap_to_center() {return 0;} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* XXX */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* local prototypes ---------------*/ | 
					
						
							|  |  |  | static void free_tagged_edges_faces(EditMesh *em, EditEdge *eed, EditFace *efa); | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | int EdgeLoopDelete(EditMesh *em, wmOperator *op); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /********* qsort routines *********/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct xvertsort { | 
					
						
							|  |  |  | 	float x; | 
					
						
							|  |  |  | 	EditVert *v1; | 
					
						
							|  |  |  | } xvertsort; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vergxco(const void *v1, const void *v2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const xvertsort *x1=v1, *x2=v2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( x1->x > x2->x ) return 1; | 
					
						
							|  |  |  | 	else if( x1->x < x2->x) return -1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct facesort { | 
					
						
							|  |  |  | 	uintptr_t x; | 
					
						
							|  |  |  | 	struct EditFace *efa; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vergface(const void *v1, const void *v2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const struct facesort *x1=v1, *x2=v2; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if( x1->x > x2->x ) return 1; | 
					
						
							|  |  |  | 	else if( x1->x < x2->x) return -1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* *********************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void convert_to_triface(EditMesh *em, int direction) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa, *efan, *next; | 
					
						
							|  |  |  | 	float fac; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	efa= em->faces.last; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		next= efa->prev; | 
					
						
							|  |  |  | 		if(efa->v4) { | 
					
						
							|  |  |  | 			if(efa->f & SELECT) { | 
					
						
							|  |  |  | 				/* choose shortest diagonal for split */ | 
					
						
							|  |  |  | 				fac= VecLenf(efa->v1->co, efa->v3->co) - VecLenf(efa->v2->co, efa->v4->co); | 
					
						
							|  |  |  | 				/* this makes sure exact squares get split different in both cases */ | 
					
						
							|  |  |  | 				if( (direction==0 && fac<FLT_EPSILON) || (direction && fac>0.0f) ) { | 
					
						
							|  |  |  | 					efan= EM_face_from_faces(em, efa, NULL, 0, 1, 2, -1); | 
					
						
							|  |  |  | 					if(efa->f & SELECT) EM_select_face(efan, 1); | 
					
						
							|  |  |  | 					efan= EM_face_from_faces(em, efa, NULL, 0, 2, 3, -1); | 
					
						
							|  |  |  | 					if(efa->f & SELECT) EM_select_face(efan, 1); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					efan= EM_face_from_faces(em, efa, NULL, 0, 1, 3, -1); | 
					
						
							|  |  |  | 					if(efa->f & SELECT) EM_select_face(efan, 1); | 
					
						
							|  |  |  | 					efan= EM_face_from_faces(em, efa, NULL, 1, 2, 3, -1); | 
					
						
							|  |  |  | 					if(efa->f & SELECT) EM_select_face(efan, 1); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				BLI_remlink(&em->faces, efa); | 
					
						
							|  |  |  | 				free_editface(em, efa); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		efa= next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	EM_fgon_flags(em);	// redo flags and indices for fgons
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int removedoublesflag(EditMesh *em, short flag, short automerge, float limit)		/* return amount */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 		flag -		Test with vert->flags | 
					
						
							|  |  |  | 		automerge -	Alternative operation, merge unselected into selected. | 
					
						
							|  |  |  | 					Used for "Auto Weld" mode. warning. | 
					
						
							|  |  |  | 		limit -		Quick manhattan distance between verts. | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* all verts with (flag & 'flag') are being evaluated */ | 
					
						
							|  |  |  | 	EditVert *eve, *v1, *nextve; | 
					
						
							|  |  |  | 	EditEdge *eed, *e1, *nexted; | 
					
						
							|  |  |  | 	EditFace *efa, *nextvl; | 
					
						
							|  |  |  | 	xvertsort *sortblock, *sb, *sb1; | 
					
						
							|  |  |  | 	struct facesort *vlsortblock, *vsb, *vsb1; | 
					
						
							|  |  |  | 	int a, b, test, amount; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* flag 128 is cleared, count */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Normal non weld operation */ | 
					
						
							|  |  |  | 	eve= em->verts.first; | 
					
						
							|  |  |  | 	amount= 0; | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							|  |  |  | 		eve->f &= ~128; | 
					
						
							|  |  |  | 		if(eve->h==0 && (automerge || (eve->f & flag))) amount++; | 
					
						
							|  |  |  | 		eve= eve->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(amount==0) return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* allocate memory and qsort */ | 
					
						
							|  |  |  | 	sb= sortblock= MEM_mallocN(sizeof(xvertsort)*amount,"sortremovedoub"); | 
					
						
							|  |  |  | 	eve= em->verts.first; | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							|  |  |  | 		if(eve->h==0 && (automerge || (eve->f & flag))) { | 
					
						
							|  |  |  | 			sb->x= eve->co[0]+eve->co[1]+eve->co[2]; | 
					
						
							|  |  |  | 			sb->v1= eve; | 
					
						
							|  |  |  | 			sb++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eve= eve->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	qsort(sortblock, amount, sizeof(xvertsort), vergxco); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* test for doubles */ | 
					
						
							|  |  |  | 	sb= sortblock;	 | 
					
						
							|  |  |  | 	if (automerge) { | 
					
						
							|  |  |  | 		for(a=0; a<amount; a++, sb++) { | 
					
						
							|  |  |  | 			eve= sb->v1; | 
					
						
							|  |  |  | 			if( (eve->f & 128)==0 ) { | 
					
						
							|  |  |  | 				sb1= sb+1; | 
					
						
							|  |  |  | 				for(b=a+1; b<amount && (eve->f & 128)==0; b++, sb1++) { | 
					
						
							|  |  |  | 					if(sb1->x - sb->x > limit) break; | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 					/* when automarge, only allow unselected->selected */ | 
					
						
							|  |  |  | 					v1= sb1->v1; | 
					
						
							|  |  |  | 					if( (v1->f & 128)==0 ) { | 
					
						
							|  |  |  | 						if ((eve->f & flag)==0 && (v1->f & flag)==1) { | 
					
						
							|  |  |  | 							if(	(float)fabs(v1->co[0]-eve->co[0])<=limit &&  | 
					
						
							|  |  |  | 								(float)fabs(v1->co[1]-eve->co[1])<=limit && | 
					
						
							|  |  |  | 								(float)fabs(v1->co[2]-eve->co[2])<=limit) | 
					
						
							|  |  |  | 							{	/* unique bit */ | 
					
						
							|  |  |  | 								eve->f|= 128; | 
					
						
							|  |  |  | 								eve->tmp.v = v1; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} else if(	(eve->f & flag)==1 && (v1->f & flag)==0 ) { | 
					
						
							|  |  |  | 							if(	(float)fabs(v1->co[0]-eve->co[0])<=limit &&  | 
					
						
							|  |  |  | 								(float)fabs(v1->co[1]-eve->co[1])<=limit && | 
					
						
							|  |  |  | 								(float)fabs(v1->co[2]-eve->co[2])<=limit) | 
					
						
							|  |  |  | 							{	/* unique bit */ | 
					
						
							|  |  |  | 								v1->f|= 128; | 
					
						
							|  |  |  | 								v1->tmp.v = eve; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		for(a=0; a<amount; a++, sb++) { | 
					
						
							|  |  |  | 			eve= sb->v1; | 
					
						
							|  |  |  | 			if( (eve->f & 128)==0 ) { | 
					
						
							|  |  |  | 				sb1= sb+1; | 
					
						
							|  |  |  | 				for(b=a+1; b<amount; b++, sb1++) { | 
					
						
							|  |  |  | 					/* first test: simpel dist */ | 
					
						
							|  |  |  | 					if(sb1->x - sb->x > limit) break; | 
					
						
							|  |  |  | 					v1= sb1->v1; | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 					/* second test: is vertex allowed */ | 
					
						
							|  |  |  | 					if( (v1->f & 128)==0 ) { | 
					
						
							|  |  |  | 						if(	(float)fabs(v1->co[0]-eve->co[0])<=limit &&  | 
					
						
							|  |  |  | 							(float)fabs(v1->co[1]-eve->co[1])<=limit && | 
					
						
							|  |  |  | 							(float)fabs(v1->co[2]-eve->co[2])<=limit) | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							v1->f|= 128; | 
					
						
							|  |  |  | 							v1->tmp.v = eve; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	MEM_freeN(sortblock); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (!automerge) | 
					
						
							|  |  |  | 		for(eve = em->verts.first; eve; eve=eve->next) | 
					
						
							|  |  |  | 			if((eve->f & flag) && (eve->f & 128)) | 
					
						
							|  |  |  | 				EM_data_interp_from_verts(em, eve, eve->tmp.v, eve->tmp.v, 0.5f); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* test edges and insert again */ | 
					
						
							|  |  |  | 	eed= em->edges.first; | 
					
						
							|  |  |  | 	while(eed) { | 
					
						
							|  |  |  | 		eed->f2= 0; | 
					
						
							|  |  |  | 		eed= eed->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	eed= em->edges.last; | 
					
						
							|  |  |  | 	while(eed) { | 
					
						
							|  |  |  | 		nexted= eed->prev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(eed->f2==0) { | 
					
						
							|  |  |  | 			if( (eed->v1->f & 128) || (eed->v2->f & 128) ) { | 
					
						
							|  |  |  | 				remedge(em, eed); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if(eed->v1->f & 128) eed->v1 = eed->v1->tmp.v; | 
					
						
							|  |  |  | 				if(eed->v2->f & 128) eed->v2 = eed->v2->tmp.v; | 
					
						
							|  |  |  | 				e1= addedgelist(em, eed->v1, eed->v2, eed); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if(e1) { | 
					
						
							|  |  |  | 					e1->f2= 1; | 
					
						
							|  |  |  | 					if(eed->f & SELECT) | 
					
						
							|  |  |  | 						e1->f |= SELECT; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if(e1!=eed) free_editedge(em, eed); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eed= nexted; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* first count amount of test faces */ | 
					
						
							|  |  |  | 	efa= (struct EditFace *)em->faces.first; | 
					
						
							|  |  |  | 	amount= 0; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		efa->f1= 0; | 
					
						
							|  |  |  | 		if(efa->v1->f & 128) efa->f1= 1; | 
					
						
							|  |  |  | 		else if(efa->v2->f & 128) efa->f1= 1; | 
					
						
							|  |  |  | 		else if(efa->v3->f & 128) efa->f1= 1; | 
					
						
							|  |  |  | 		else if(efa->v4 && (efa->v4->f & 128)) efa->f1= 1; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if(efa->f1==1) amount++; | 
					
						
							|  |  |  | 		efa= efa->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* test faces for double vertices, and if needed remove them */ | 
					
						
							|  |  |  | 	efa= (struct EditFace *)em->faces.first; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		nextvl= efa->next; | 
					
						
							|  |  |  | 		if(efa->f1==1) { | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if(efa->v1->f & 128) efa->v1= efa->v1->tmp.v; | 
					
						
							|  |  |  | 			if(efa->v2->f & 128) efa->v2= efa->v2->tmp.v; | 
					
						
							|  |  |  | 			if(efa->v3->f & 128) efa->v3= efa->v3->tmp.v; | 
					
						
							|  |  |  | 			if(efa->v4 && (efa->v4->f & 128)) efa->v4= efa->v4->tmp.v; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			test= 0; | 
					
						
							|  |  |  | 			if(efa->v1==efa->v2) test+=1; | 
					
						
							|  |  |  | 			if(efa->v2==efa->v3) test+=2; | 
					
						
							|  |  |  | 			if(efa->v3==efa->v1) test+=4; | 
					
						
							|  |  |  | 			if(efa->v4==efa->v1) test+=8; | 
					
						
							|  |  |  | 			if(efa->v3==efa->v4) test+=16; | 
					
						
							|  |  |  | 			if(efa->v2==efa->v4) test+=32; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if(test) { | 
					
						
							|  |  |  | 				if(efa->v4) { | 
					
						
							|  |  |  | 					if(test==1 || test==2) { | 
					
						
							|  |  |  | 						efa->v2= efa->v3; | 
					
						
							|  |  |  | 						efa->v3= efa->v4; | 
					
						
							|  |  |  | 						efa->v4= 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						EM_data_interp_from_faces(em, efa, NULL, efa, 0, 2, 3, 3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						test= 0; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					else if(test==8 || test==16) { | 
					
						
							|  |  |  | 						efa->v4= 0; | 
					
						
							|  |  |  | 						test= 0; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					else { | 
					
						
							|  |  |  | 						BLI_remlink(&em->faces, efa); | 
					
						
							|  |  |  | 						free_editface(em, efa); | 
					
						
							|  |  |  | 						amount--; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					BLI_remlink(&em->faces, efa); | 
					
						
							|  |  |  | 					free_editface(em, efa); | 
					
						
							|  |  |  | 					amount--; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if(test==0) { | 
					
						
							|  |  |  | 				/* set edge pointers */ | 
					
						
							|  |  |  | 				efa->e1= findedgelist(em, efa->v1, efa->v2); | 
					
						
							|  |  |  | 				efa->e2= findedgelist(em, efa->v2, efa->v3); | 
					
						
							|  |  |  | 				if(efa->v4==0) { | 
					
						
							|  |  |  | 					efa->e3= findedgelist(em, efa->v3, efa->v1); | 
					
						
							|  |  |  | 					efa->e4= 0; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					efa->e3= findedgelist(em, efa->v3, efa->v4); | 
					
						
							|  |  |  | 					efa->e4= findedgelist(em, efa->v4, efa->v1); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		efa= nextvl; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* double faces: sort block */ | 
					
						
							|  |  |  | 	/* count again, now all selected faces */ | 
					
						
							|  |  |  | 	amount= 0; | 
					
						
							|  |  |  | 	efa= em->faces.first; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		efa->f1= 0; | 
					
						
							|  |  |  | 		if(faceselectedOR(efa, 1)) { | 
					
						
							|  |  |  | 			efa->f1= 1; | 
					
						
							|  |  |  | 			amount++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		efa= efa->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(amount) { | 
					
						
							|  |  |  | 		/* double faces: sort block */ | 
					
						
							|  |  |  | 		vsb= vlsortblock= MEM_mallocN(sizeof(struct facesort)*amount, "sortremovedoub"); | 
					
						
							|  |  |  | 		efa= em->faces.first; | 
					
						
							|  |  |  | 		while(efa) { | 
					
						
							|  |  |  | 			if(efa->f1 & 1) { | 
					
						
							|  |  |  | 				if(efa->v4) vsb->x= (uintptr_t) MIN4( (uintptr_t)efa->v1, (uintptr_t)efa->v2, (uintptr_t)efa->v3, (uintptr_t)efa->v4); | 
					
						
							|  |  |  | 				else vsb->x= (uintptr_t) MIN3( (uintptr_t)efa->v1, (uintptr_t)efa->v2, (uintptr_t)efa->v3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				vsb->efa= efa; | 
					
						
							|  |  |  | 				vsb++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			efa= efa->next; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		qsort(vlsortblock, amount, sizeof(struct facesort), vergface); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		vsb= vlsortblock; | 
					
						
							|  |  |  | 		for(a=0; a<amount; a++) { | 
					
						
							|  |  |  | 			efa= vsb->efa; | 
					
						
							|  |  |  | 			if( (efa->f1 & 128)==0 ) { | 
					
						
							|  |  |  | 				vsb1= vsb+1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				for(b=a+1; b<amount; b++) { | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 					/* first test: same pointer? */ | 
					
						
							|  |  |  | 					if(vsb->x != vsb1->x) break; | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 					/* second test: is test permitted? */ | 
					
						
							|  |  |  | 					efa= vsb1->efa; | 
					
						
							|  |  |  | 					if( (efa->f1 & 128)==0 ) { | 
					
						
							|  |  |  | 						if( compareface(efa, vsb->efa)) efa->f1 |= 128; | 
					
						
							|  |  |  | 						 | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					vsb1++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			vsb++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		MEM_freeN(vlsortblock); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/* remove double faces */ | 
					
						
							|  |  |  | 		efa= (struct EditFace *)em->faces.first; | 
					
						
							|  |  |  | 		while(efa) { | 
					
						
							|  |  |  | 			nextvl= efa->next; | 
					
						
							|  |  |  | 			if(efa->f1 & 128) { | 
					
						
							|  |  |  | 				BLI_remlink(&em->faces, efa); | 
					
						
							|  |  |  | 				free_editface(em, efa); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			efa= nextvl; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* remove double vertices */ | 
					
						
							|  |  |  | 	a= 0; | 
					
						
							|  |  |  | 	eve= (struct EditVert *)em->verts.first; | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							|  |  |  | 		nextve= eve->next; | 
					
						
							|  |  |  | 		if(automerge || eve->f & flag) { | 
					
						
							|  |  |  | 			if(eve->f & 128) { | 
					
						
							|  |  |  | 				a++; | 
					
						
							|  |  |  | 				BLI_remlink(&em->verts, eve); | 
					
						
							|  |  |  | 				free_editvert(em, eve); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eve= nextve; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return a;	/* amount */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-23 03:07:07 +00:00
										 |  |  | static int removedoublesflag_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							|  |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 	char msg[100]; | 
					
						
							| 
									
										
										
										
											2009-01-23 03:07:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 	int cnt = removedoublesflag(em,1,0,scene->toolsettings->doublimit); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(cnt) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		sprintf(msg, "Removed %d vertices", cnt); | 
					
						
							|  |  |  | 		BKE_report(op->reports, RPT_INFO, msg); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-01-23 03:07:07 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-01-23 03:07:07 +00:00
										 |  |  | 	return OPERATOR_FINISHED;	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-15 15:40:31 +00:00
										 |  |  | void MESH_OT_remove_doubles(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2009-01-23 03:07:07 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Remove Doubles"; | 
					
						
							| 
									
										
										
										
											2009-04-15 15:40:31 +00:00
										 |  |  | 	ot->idname= "MESH_OT_remove_doubles"; | 
					
						
							| 
									
										
										
										
											2009-01-23 03:07:07 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= removedoublesflag_exec; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2009-01-23 03:07:07 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // XXX is this needed?
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | /* called from buttons */ | 
					
						
							|  |  |  | static void xsortvert_flag__doSetX(void *userData, EditVert *eve, int x, int y, int index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xvertsort *sortblock = userData; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sortblock[index].x = x; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 16:03:29 +00:00
										 |  |  | /* all verts with (flag & 'flag') are sorted */ | 
					
						
							|  |  |  | void xsortvert_flag(bContext *C, int flag) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-30 16:03:29 +00:00
										 |  |  | 	ViewContext vc; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	xvertsort *sortblock; | 
					
						
							|  |  |  | 	ListBase tbase; | 
					
						
							| 
									
										
										
										
											2008-12-30 16:03:29 +00:00
										 |  |  | 	int i, amount; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-30 16:03:29 +00:00
										 |  |  | 	em_setup_viewcontext(C, &vc); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	amount = BLI_countlist(&vc.em->verts); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	sortblock = MEM_callocN(sizeof(xvertsort)*amount,"xsort"); | 
					
						
							| 
									
										
										
										
											2008-12-30 16:03:29 +00:00
										 |  |  | 	for (i=0,eve= vc.em->verts.first; eve; i++,eve=eve->next) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		if(eve->f & flag) | 
					
						
							|  |  |  | 			sortblock[i].v1 = eve; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-30 16:03:29 +00:00
										 |  |  | 	mesh_foreachScreenVert(&vc, xsortvert_flag__doSetX, sortblock, 0); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	qsort(sortblock, amount, sizeof(xvertsort), vergxco); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		/* make temporal listbase */ | 
					
						
							|  |  |  | 	tbase.first= tbase.last= 0; | 
					
						
							|  |  |  | 	for (i=0; i<amount; i++) { | 
					
						
							|  |  |  | 		eve = sortblock[i].v1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (eve) { | 
					
						
							| 
									
										
										
										
											2008-12-30 16:03:29 +00:00
										 |  |  | 			BLI_remlink(&vc.em->verts, eve); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			BLI_addtail(&tbase, eve); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-30 16:03:29 +00:00
										 |  |  | 	addlisttolist(&vc.em->verts, &tbase); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	MEM_freeN(sortblock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* called from buttons */ | 
					
						
							|  |  |  | void hashvert_flag(EditMesh *em, int flag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* switch vertex order using hash table */ | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	struct xvertsort *sortblock, *sb, onth, *newsort; | 
					
						
							|  |  |  | 	ListBase tbase; | 
					
						
							|  |  |  | 	int amount, a, b; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* count */ | 
					
						
							|  |  |  | 	eve= em->verts.first; | 
					
						
							|  |  |  | 	amount= 0; | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							|  |  |  | 		if(eve->f & flag) amount++; | 
					
						
							|  |  |  | 		eve= eve->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(amount==0) return; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* allocate memory */ | 
					
						
							|  |  |  | 	sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*amount,"sortremovedoub"); | 
					
						
							|  |  |  | 	eve= em->verts.first; | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							|  |  |  | 		if(eve->f & flag) { | 
					
						
							|  |  |  | 			sb->v1= eve; | 
					
						
							|  |  |  | 			sb++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eve= eve->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_srand(1); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	sb= sortblock; | 
					
						
							|  |  |  | 	for(a=0; a<amount; a++, sb++) { | 
					
						
							|  |  |  | 		b= (int)(amount*BLI_drand()); | 
					
						
							|  |  |  | 		if(b>=0 && b<amount) { | 
					
						
							|  |  |  | 			newsort= sortblock+b; | 
					
						
							|  |  |  | 			onth= *sb; | 
					
						
							|  |  |  | 			*sb= *newsort; | 
					
						
							|  |  |  | 			*newsort= onth; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* make temporal listbase */ | 
					
						
							|  |  |  | 	tbase.first= tbase.last= 0; | 
					
						
							|  |  |  | 	sb= sortblock; | 
					
						
							|  |  |  | 	while(amount--) { | 
					
						
							|  |  |  | 		eve= sb->v1; | 
					
						
							|  |  |  | 		BLI_remlink(&em->verts, eve); | 
					
						
							|  |  |  | 		BLI_addtail(&tbase, eve); | 
					
						
							|  |  |  | 		sb++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	addlisttolist(&em->verts, &tbase); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	MEM_freeN(sortblock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* generic extern called extruder */ | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | void extrude_mesh(Object *obedit, EditMesh *em, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 	Scene *scene= NULL;		// XXX CTX!
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	float nor[3]= {0.0, 0.0, 0.0}; | 
					
						
							|  |  |  | 	short nr, transmode= 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(em->selectmode & SCE_SELECT_VERTEX) { | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 		if(em->totvertsel==0) nr= 0; | 
					
						
							|  |  |  | 		else if(em->totvertsel==1) nr= 4; | 
					
						
							|  |  |  | 		else if(em->totedgesel==0) nr= 4; | 
					
						
							|  |  |  | 		else if(em->totfacesel==0)  | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 			nr= 3; // pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4");
 | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 		else if(em->totfacesel==1) | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 			nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4");
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		else  | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 			nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4");
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if(em->selectmode & SCE_SELECT_EDGE) { | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 		if (em->totedgesel==0) nr = 0; | 
					
						
							|  |  |  | 		else if (em->totedgesel==1) nr = 3; | 
					
						
							|  |  |  | 		else if(em->totfacesel==0) nr = 3; | 
					
						
							|  |  |  | 		else if(em->totfacesel==1) | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 			nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3");
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 			nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3");
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 		if (em->totfacesel == 0) nr = 0; | 
					
						
							|  |  |  | 		else if (em->totfacesel == 1) nr = 1; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 			nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2");
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	if(nr<1) return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	if(nr==1)  transmode= extrudeflag(obedit, em, SELECT, nor); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	else if(nr==4) transmode= extrudeflag_verts_indiv(em, SELECT, nor); | 
					
						
							|  |  |  | 	else if(nr==3) transmode= extrudeflag_edges_indiv(em, SELECT, nor); | 
					
						
							|  |  |  | 	else transmode= extrudeflag_face_indiv(em, SELECT, nor); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(transmode==0) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "Not a valid selection for extrude"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		EM_fgon_flags(em); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			/* We need to force immediate calculation here because 
 | 
					
						
							|  |  |  | 			* transform may use derived objects (which are now stale). | 
					
						
							|  |  |  | 			* | 
					
						
							|  |  |  | 			* This shouldn't be necessary, derived queries should be | 
					
						
							|  |  |  | 			* automatically building this data if invalid. Or something. | 
					
						
							|  |  |  | 			*/ | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //		DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);	
 | 
					
						
							|  |  |  | 		object_handle_update(scene, obedit); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* individual faces? */ | 
					
						
							|  |  |  | //		BIF_TransformSetUndo("Extrude");
 | 
					
						
							|  |  |  | 		if(nr==2) { | 
					
						
							|  |  |  | //			initTransform(TFM_SHRINKFATTEN, CTX_NO_PET|CTX_NO_MIRROR);
 | 
					
						
							|  |  |  | //			Transform();
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | //			initTransform(TFM_TRANSLATION, CTX_NO_PET|CTX_NO_MIRROR);
 | 
					
						
							|  |  |  | 			if(transmode=='n') { | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 				Mat4MulVecfl(obedit->obmat, nor); | 
					
						
							|  |  |  | 				VecSubf(nor, nor, obedit->obmat[3]); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | //				BIF_setSingleAxisConstraint(nor, "along normal");
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | //			Transform();
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | // XXX should be a menu item
 | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | static int mesh_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event) | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 	extrude_mesh(obedit,em, op); | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	RNA_int_set(op->ptr, "mode", TFM_TRANSLATION); | 
					
						
							|  |  |  | 	WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 	return OPERATOR_FINISHED;	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* extrude without transform */ | 
					
						
							|  |  |  | static int mesh_extrude_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh(obedit->data); | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	extrude_mesh(obedit,em, op); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	return OPERATOR_FINISHED;	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-01 12:40:27 +00:00
										 |  |  | void MESH_OT_extrude(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Extrude Mesh"; | 
					
						
							| 
									
										
										
										
											2009-02-01 12:40:27 +00:00
										 |  |  | 	ot->idname= "MESH_OT_extrude"; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 	ot->invoke= mesh_extrude_invoke; | 
					
						
							| 
									
										
										
										
											2009-02-01 12:40:27 +00:00
										 |  |  | 	ot->exec= mesh_extrude_exec; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* to give to transform */ | 
					
						
							|  |  |  | 	RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | static int split_mesh(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	WM_cursor_wait(1); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* make duplicate first */ | 
					
						
							|  |  |  | 	adduplicateflag(em, SELECT); | 
					
						
							|  |  |  | 	/* old faces have flag 128 set, delete them */ | 
					
						
							|  |  |  | 	delfaceflag(em, 128); | 
					
						
							|  |  |  | 	recalc_editnormals(em); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	WM_cursor_wait(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-29 02:15:13 +00:00
										 |  |  | void MESH_OT_split(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Split Mesh"; | 
					
						
							| 
									
										
										
										
											2009-03-29 02:15:13 +00:00
										 |  |  | 	ot->idname= "MESH_OT_split"; | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= split_mesh; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int extrude_repeat_mesh(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-03-30 07:28:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	RegionView3D *rv3d = CTX_wm_region_view3d(C);		 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	int steps = RNA_int_get(op->ptr,"steps"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	float offs = RNA_float_get(op->ptr,"offset"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	float dvec[3], tmat[3][3], bmat[3][3], nor[3]= {0.0, 0.0, 0.0}; | 
					
						
							|  |  |  | 	short a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* dvec */ | 
					
						
							| 
									
										
											  
											
												2.5
View3D has been split now in a local part (RegionView3D) and a
per-area part (old View3D). Currently local is:
- view transform
- camera zoom/offset
- gpencil (todo)
- custom clipping planes
Rest is in Area still, like active camera, draw type, layers,
localview, custom centers, around-settings, transform widget,
gridlines, and so on (mostly stuff as available in header).
To see it work; also added new feature for region split, 
press SHIFT+ALT+CTRL+S for four-split. 
The idea is to make a preset 4-split, configured to stick
to top/right/front views for three views.
Another cool idea to explore is to then box-clip all drawing
based on these 3 views.
Note about the code:
- currently view3d still stores some depricated settings, to
  convert from older files. Not all settings are copied over
  though, like custom clip planes or the 'lock view to object'.
- since some view3d ops are now on area level, the operators
  for it should keep track of that.
Bugfix in transform: quat initialize in operator-invoke missed
one zero.
Als brought back GE to compile for missing Ipos and channels.
											
										 
											2009-01-19 16:54:41 +00:00
										 |  |  | 	dvec[0]= rv3d->persinv[2][0]; | 
					
						
							|  |  |  | 	dvec[1]= rv3d->persinv[2][1]; | 
					
						
							|  |  |  | 	dvec[2]= rv3d->persinv[2][2]; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	Normalize(dvec); | 
					
						
							|  |  |  | 	dvec[0]*= offs; | 
					
						
							|  |  |  | 	dvec[1]*= offs; | 
					
						
							|  |  |  | 	dvec[2]*= offs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* base correction */ | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	Mat3CpyMat4(bmat, obedit->obmat); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	Mat3Inv(tmat, bmat); | 
					
						
							|  |  |  | 	Mat3MulVecfl(tmat, dvec); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(a=0; a<steps; a++) { | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 		extrudeflag(obedit, em, SELECT, nor); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		translateflag(em, SELECT, dvec); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	recalc_editnormals(em); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	EM_fgon_flags(em); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | //	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | void MESH_OT_extrude_repeat(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Extrude Repeat Mesh"; | 
					
						
							|  |  |  | 	ot->idname= "MESH_OT_extrude_repeat"; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= extrude_repeat_mesh; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* props */ | 
					
						
							|  |  |  | 	RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 100.0f, "Offset", "", 0.0f, FLT_MAX); | 
					
						
							|  |  |  | 	RNA_def_int(ot->srna, "steps", 10, 0, 180, "Steps", "", 0, INT_MAX); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* ************************** spin operator ******************** */ | 
					
						
							| 
									
										
										
										
											2009-06-01 14:08:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int spin_mesh(bContext *C, wmOperator *op, float *dvec, int steps, float degr, int dupli ) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-16 20:04:01 +00:00
										 |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							|  |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditVert *eve,*nextve; | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	float nor[3]= {0.0f, 0.0f, 0.0f}; | 
					
						
							| 
									
										
										
										
											2009-06-01 14:08:19 +00:00
										 |  |  | 	float si, n[3], q[4], cmat[3][3], imat[3][3], tmat[3][3]; | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	float cent[3], bmat[3][3]; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	float phi; | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	short a, ok= 1; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 14:08:19 +00:00
										 |  |  | 	RNA_float_get_array(op->ptr, "center", cent); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	/* imat and center and size */ | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	Mat3CpyMat4(bmat, obedit->obmat); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	Mat3Inv(imat,bmat); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	cent[0]-= obedit->obmat[3][0]; | 
					
						
							|  |  |  | 	cent[1]-= obedit->obmat[3][1]; | 
					
						
							|  |  |  | 	cent[2]-= obedit->obmat[3][2]; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	Mat3MulVecfl(imat, cent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	phi= degr*M_PI/360.0; | 
					
						
							|  |  |  | 	phi/= steps; | 
					
						
							| 
									
										
										
										
											2009-01-29 18:54:22 +00:00
										 |  |  | 	if(scene->toolsettings->editbutflag & B_CLOCKWISE) phi= -phi; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 14:08:19 +00:00
										 |  |  | 	RNA_float_get_array(op->ptr, "axis", n); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	Normalize(n); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	q[0]= (float)cos(phi); | 
					
						
							|  |  |  | 	si= (float)sin(phi); | 
					
						
							|  |  |  | 	q[1]= n[0]*si; | 
					
						
							|  |  |  | 	q[2]= n[1]*si; | 
					
						
							|  |  |  | 	q[3]= n[2]*si; | 
					
						
							|  |  |  | 	QuatToMat3(q, cmat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Mat3MulMat3(tmat,cmat,bmat); | 
					
						
							|  |  |  | 	Mat3MulMat3(bmat,imat,tmat); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	if(dupli==0)  | 
					
						
							|  |  |  | 		if(scene->toolsettings->editbutflag & B_KEEPORIG)  | 
					
						
							|  |  |  | 			adduplicateflag(em, 1); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	for(a=0; a<steps; a++) { | 
					
						
							|  |  |  | 		if(dupli==0) ok= extrudeflag(obedit, em, SELECT, nor); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		else adduplicateflag(em, SELECT); | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		if(ok==0) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		rotateflag(em, SELECT, cent, bmat); | 
					
						
							|  |  |  | 		if(dvec) { | 
					
						
							|  |  |  | 			Mat3MulVecfl(bmat,dvec); | 
					
						
							|  |  |  | 			translateflag(em, SELECT, dvec); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(ok==0) { | 
					
						
							|  |  |  | 		/* no vertices or only loose ones selected, remove duplicates */ | 
					
						
							|  |  |  | 		eve= em->verts.first; | 
					
						
							|  |  |  | 		while(eve) { | 
					
						
							|  |  |  | 			nextve= eve->next; | 
					
						
							|  |  |  | 			if(eve->f & SELECT) { | 
					
						
							|  |  |  | 				BLI_remlink(&em->verts,eve); | 
					
						
							|  |  |  | 				free_editvert(em, eve); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			eve= nextve; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	else { | 
					
						
							|  |  |  | 		recalc_editnormals(em); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 		EM_fgon_flags(em); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 		DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	return ok; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-16 20:04:01 +00:00
										 |  |  | static int spin_mesh_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	int ok; | 
					
						
							| 
									
										
										
										
											2009-02-16 20:04:01 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-06-01 14:08:19 +00:00
										 |  |  | 	ok= spin_mesh(C, op, NULL, RNA_int_get(op->ptr,"steps"), RNA_float_get(op->ptr,"degrees"), RNA_boolean_get(op->ptr,"dupli")); | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	if(ok==0) { | 
					
						
							|  |  |  | 		BKE_report(op->reports, RPT_ERROR, "No valid vertices are selected"); | 
					
						
							|  |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-16 20:04:01 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 14:08:19 +00:00
										 |  |  | /* get center and axis, in global coords */ | 
					
						
							|  |  |  | static int spin_mesh_invoke(bContext *C, wmOperator *op, wmEvent *event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							|  |  |  | 	View3D *v3d = CTX_wm_view3d(C); | 
					
						
							|  |  |  | 	RegionView3D *rv3d= CTX_wm_region_view3d(C); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d)); | 
					
						
							|  |  |  | 	RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[2]); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return spin_mesh_exec(C, op); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-16 20:04:01 +00:00
										 |  |  | void MESH_OT_spin(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Spin"; | 
					
						
							|  |  |  | 	ot->idname= "MESH_OT_spin"; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							| 
									
										
										
										
											2009-06-01 14:08:19 +00:00
										 |  |  | 	ot->invoke= spin_mesh_invoke; | 
					
						
							| 
									
										
										
										
											2009-02-16 20:04:01 +00:00
										 |  |  | 	ot->exec= spin_mesh_exec; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-06-01 14:08:19 +00:00
										 |  |  | 	/* props */ | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, INT_MAX); | 
					
						
							|  |  |  | 	RNA_def_boolean(ot->srna, "dupli", 0, "Dupli", "Make Duplicates"); | 
					
						
							|  |  |  | 	RNA_def_float(ot->srna, "degrees", 90.0f, -FLT_MAX, FLT_MAX, "Degrees", "Degrees", -360.0f, 360.0f); | 
					
						
							| 
									
										
										
										
											2009-06-01 14:08:19 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX); | 
					
						
							|  |  |  | 	RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-16 20:04:01 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | static int screw_mesh_exec(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-16 20:04:01 +00:00
										 |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditVert *eve,*v1=0,*v2=0; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	float dvec[3], nor[3]; | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	int steps, turns; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	turns= RNA_int_get(op->ptr, "turns"); | 
					
						
							|  |  |  | 	steps= RNA_int_get(op->ptr, "steps"); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	/* clear flags */ | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	for(eve= em->verts.first; eve; eve= eve->next) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		eve->f1= 0; | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	/* edges set flags in verts */ | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		if(eed->v1->f & SELECT) { | 
					
						
							|  |  |  | 			if(eed->v2->f & SELECT) { | 
					
						
							|  |  |  | 				/* watch: f1 is a byte */ | 
					
						
							|  |  |  | 				if(eed->v1->f1<2) eed->v1->f1++; | 
					
						
							|  |  |  | 				if(eed->v2->f1<2) eed->v2->f1++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* find two vertices with eve->f1==1, more or less is wrong */ | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	for(eve= em->verts.first; eve; eve= eve->next) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		if(eve->f1==1) { | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 			if(v1==NULL) v1= eve; | 
					
						
							|  |  |  | 			else if(v2==NULL) v2= eve; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			else { | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 				v1= NULL; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	if(v1==NULL || v2==NULL) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "You have to select a string of connected vertices too"); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 		BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* calculate dvec */ | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	dvec[0]= ( v1->co[0]- v2->co[0] )/steps; | 
					
						
							|  |  |  | 	dvec[1]= ( v1->co[1]- v2->co[1] )/steps; | 
					
						
							|  |  |  | 	dvec[2]= ( v1->co[2]- v2->co[2] )/steps; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	VECCOPY(nor, obedit->obmat[2]); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if(nor[0]*dvec[0]+nor[1]*dvec[1]+nor[2]*dvec[2]>0.000) { | 
					
						
							|  |  |  | 		dvec[0]= -dvec[0]; | 
					
						
							|  |  |  | 		dvec[1]= -dvec[1]; | 
					
						
							|  |  |  | 		dvec[2]= -dvec[2]; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-18 03:01:45 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-06-01 14:08:19 +00:00
										 |  |  | 	if(spin_mesh(C, op, dvec, turns*steps, 360.0f*turns, 0)) { | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 		WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 		BKE_mesh_end_editmesh(obedit->data, em);		 | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 		return OPERATOR_FINISHED; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		BKE_report(op->reports, RPT_ERROR, "No valid vertices are selected"); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 		BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-03-30 07:28:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-01 14:08:19 +00:00
										 |  |  | /* get center and axis, in global coords */ | 
					
						
							|  |  |  | static int screw_mesh_invoke(bContext *C, wmOperator *op, wmEvent *event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							|  |  |  | 	View3D *v3d = CTX_wm_view3d(C); | 
					
						
							|  |  |  | 	RegionView3D *rv3d= CTX_wm_region_view3d(C); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d)); | 
					
						
							|  |  |  | 	RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[1]); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return screw_mesh_exec(C, op); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-18 03:01:45 +00:00
										 |  |  | void MESH_OT_screw(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Screw"; | 
					
						
							|  |  |  | 	ot->idname= "MESH_OT_screw"; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							| 
									
										
										
										
											2009-06-01 14:08:19 +00:00
										 |  |  | 	ot->invoke= screw_mesh_invoke; | 
					
						
							| 
									
										
										
										
											2009-02-18 03:01:45 +00:00
										 |  |  | 	ot->exec= screw_mesh_exec; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*props */ | 
					
						
							| 
									
										
										
										
											2009-02-19 16:22:07 +00:00
										 |  |  | 	RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, 256); | 
					
						
							|  |  |  | 	RNA_def_int(ot->srna, "turns", 1, 0, INT_MAX, "Turns", "Turns", 0, 256); | 
					
						
							| 
									
										
										
										
											2009-06-01 14:08:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX); | 
					
						
							|  |  |  | 	RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX); | 
					
						
							| 
									
										
										
										
											2009-02-18 03:01:45 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void erase_edges(EditMesh *em, ListBase *l) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *ed, *nexted; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	ed = (EditEdge *) l->first; | 
					
						
							|  |  |  | 	while(ed) { | 
					
						
							|  |  |  | 		nexted= ed->next; | 
					
						
							|  |  |  | 		if( (ed->v1->f & SELECT) || (ed->v2->f & SELECT) ) { | 
					
						
							|  |  |  | 			remedge(em, ed); | 
					
						
							|  |  |  | 			free_editedge(em, ed); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		ed= nexted; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void erase_faces(EditMesh *em, ListBase *l) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *f, *nextf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	f = (EditFace *) l->first; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while(f) { | 
					
						
							|  |  |  | 		nextf= f->next; | 
					
						
							|  |  |  | 		if( faceselectedOR(f, SELECT) ) { | 
					
						
							|  |  |  | 			BLI_remlink(l, f); | 
					
						
							|  |  |  | 			free_editface(em, f); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		f = nextf; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void erase_vertices(EditMesh *em, ListBase *l) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *v, *nextv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	v = (EditVert *) l->first; | 
					
						
							|  |  |  | 	while(v) { | 
					
						
							|  |  |  | 		nextv= v->next; | 
					
						
							|  |  |  | 		if(v->f & 1) { | 
					
						
							|  |  |  | 			BLI_remlink(l, v); | 
					
						
							|  |  |  | 			free_editvert(em, v); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		v = nextv; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | void delete_mesh(Object *obedit, EditMesh *em, wmOperator *op, int event) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa, *nextvl; | 
					
						
							|  |  |  | 	EditVert *eve,*nextve; | 
					
						
							|  |  |  | 	EditEdge *eed,*nexted; | 
					
						
							|  |  |  | 	int count; | 
					
						
							|  |  |  | 	char *str="Erase"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-31 02:31:58 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	if(event<1) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(event==10 ) { | 
					
						
							|  |  |  | 		str= "Erase Vertices"; | 
					
						
							|  |  |  | 		erase_edges(em, &em->edges); | 
					
						
							|  |  |  | 		erase_faces(em, &em->faces); | 
					
						
							|  |  |  | 		erase_vertices(em, &em->verts); | 
					
						
							|  |  |  | 	}  | 
					
						
							|  |  |  | 	else if(event==6) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		if(!EdgeLoopDelete(em, op)) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		str= "Erase Edge Loop"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if(event==4) { | 
					
						
							|  |  |  | 		str= "Erase Edges & Faces"; | 
					
						
							|  |  |  | 		efa= em->faces.first; | 
					
						
							|  |  |  | 		while(efa) { | 
					
						
							|  |  |  | 			nextvl= efa->next; | 
					
						
							|  |  |  | 			/* delete only faces with 1 or more edges selected */ | 
					
						
							|  |  |  | 			count= 0; | 
					
						
							|  |  |  | 			if(efa->e1->f & SELECT) count++; | 
					
						
							|  |  |  | 			if(efa->e2->f & SELECT) count++; | 
					
						
							|  |  |  | 			if(efa->e3->f & SELECT) count++; | 
					
						
							|  |  |  | 			if(efa->e4 && (efa->e4->f & SELECT)) count++; | 
					
						
							|  |  |  | 			if(count) { | 
					
						
							|  |  |  | 				BLI_remlink(&em->faces, efa); | 
					
						
							|  |  |  | 				free_editface(em, efa); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			efa= nextvl; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eed= em->edges.first; | 
					
						
							|  |  |  | 		while(eed) { | 
					
						
							|  |  |  | 			nexted= eed->next; | 
					
						
							|  |  |  | 			if(eed->f & SELECT) { | 
					
						
							|  |  |  | 				remedge(em, eed); | 
					
						
							|  |  |  | 				free_editedge(em, eed); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			eed= nexted; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		efa= em->faces.first; | 
					
						
							|  |  |  | 		while(efa) { | 
					
						
							|  |  |  | 			nextvl= efa->next; | 
					
						
							|  |  |  | 			event=0; | 
					
						
							|  |  |  | 			if( efa->v1->f & SELECT) event++; | 
					
						
							|  |  |  | 			if( efa->v2->f & SELECT) event++; | 
					
						
							|  |  |  | 			if( efa->v3->f & SELECT) event++; | 
					
						
							|  |  |  | 			if(efa->v4 && (efa->v4->f & SELECT)) event++; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if(event>1) { | 
					
						
							|  |  |  | 				BLI_remlink(&em->faces, efa); | 
					
						
							|  |  |  | 				free_editface(em, efa); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			efa= nextvl; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}  | 
					
						
							|  |  |  | 	else if(event==1) { | 
					
						
							|  |  |  | 		str= "Erase Edges"; | 
					
						
							|  |  |  | 		// faces first
 | 
					
						
							|  |  |  | 		efa= em->faces.first; | 
					
						
							|  |  |  | 		while(efa) { | 
					
						
							|  |  |  | 			nextvl= efa->next; | 
					
						
							|  |  |  | 			event=0; | 
					
						
							|  |  |  | 			if( efa->e1->f & SELECT) event++; | 
					
						
							|  |  |  | 			if( efa->e2->f & SELECT) event++; | 
					
						
							|  |  |  | 			if( efa->e3->f & SELECT) event++; | 
					
						
							|  |  |  | 			if(efa->e4 && (efa->e4->f & SELECT)) event++; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if(event) { | 
					
						
							|  |  |  | 				BLI_remlink(&em->faces, efa); | 
					
						
							|  |  |  | 				free_editface(em, efa); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			efa= nextvl; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eed= em->edges.first; | 
					
						
							|  |  |  | 		while(eed) { | 
					
						
							|  |  |  | 			nexted= eed->next; | 
					
						
							|  |  |  | 			if(eed->f & SELECT) { | 
					
						
							|  |  |  | 				remedge(em, eed); | 
					
						
							|  |  |  | 				free_editedge(em, eed); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			eed= nexted; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		/* to remove loose vertices: */ | 
					
						
							|  |  |  | 		eed= em->edges.first; | 
					
						
							|  |  |  | 		while(eed) { | 
					
						
							|  |  |  | 			if( eed->v1->f & SELECT) eed->v1->f-=SELECT; | 
					
						
							|  |  |  | 			if( eed->v2->f & SELECT) eed->v2->f-=SELECT; | 
					
						
							|  |  |  | 			eed= eed->next; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eve= em->verts.first; | 
					
						
							|  |  |  | 		while(eve) { | 
					
						
							|  |  |  | 			nextve= eve->next; | 
					
						
							|  |  |  | 			if(eve->f & SELECT) { | 
					
						
							|  |  |  | 				BLI_remlink(&em->verts,eve); | 
					
						
							|  |  |  | 				free_editvert(em, eve); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			eve= nextve; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if(event==2) { | 
					
						
							|  |  |  | 		str="Erase Faces"; | 
					
						
							|  |  |  | 		delfaceflag(em, SELECT); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if(event==3) { | 
					
						
							|  |  |  | 		str= "Erase All"; | 
					
						
							|  |  |  | 		if(em->verts.first) free_vertlist(em, &em->verts); | 
					
						
							|  |  |  | 		if(em->edges.first) free_edgelist(em, &em->edges); | 
					
						
							|  |  |  | 		if(em->faces.first) free_facelist(em, &em->faces); | 
					
						
							|  |  |  | 		if(em->selected.first) BLI_freelistN(&(em->selected)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if(event==5) { | 
					
						
							|  |  |  | 		str= "Erase Only Faces"; | 
					
						
							|  |  |  | 		efa= em->faces.first; | 
					
						
							|  |  |  | 		while(efa) { | 
					
						
							|  |  |  | 			nextvl= efa->next; | 
					
						
							|  |  |  | 			if(efa->f & SELECT) { | 
					
						
							|  |  |  | 				BLI_remlink(&em->faces, efa); | 
					
						
							|  |  |  | 				free_editface(em, efa); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			efa= nextvl; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	EM_fgon_flags(em);	// redo flags and indices for fgons
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-01 02:37:12 +00:00
										 |  |  | /* Note, these values must match delete_mesh() event values */ | 
					
						
							|  |  |  | static EnumPropertyItem prop_mesh_delete_types[] = { | 
					
						
							| 
									
										
										
										
											2009-06-16 00:52:21 +00:00
										 |  |  | 	{10,"VERT",		0, "Vertices", ""}, | 
					
						
							|  |  |  | 	{1, "EDGE",		0, "Edges", ""}, | 
					
						
							|  |  |  | 	{2, "FACE",		0, "Faces", ""}, | 
					
						
							|  |  |  | 	{3, "ALL",		0, "All", ""}, | 
					
						
							|  |  |  | 	{4, "EDGE_FACE",0, "Edges & Faces", ""}, | 
					
						
							|  |  |  | 	{5, "ONLY_FACE",0, "Only Faces", ""}, | 
					
						
							|  |  |  | 	{6, "EDGE_LOOP",0, "Edge Loop", ""}, | 
					
						
							|  |  |  | 	{0, NULL, 0, NULL, NULL} | 
					
						
							| 
									
										
										
										
											2009-02-01 02:37:12 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-31 02:31:58 +00:00
										 |  |  | static int delete_mesh_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-01-31 02:31:58 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 	delete_mesh(obedit,em, op,RNA_enum_get(op->ptr, "type")); | 
					
						
							| 
									
										
										
										
											2009-01-31 02:31:58 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-01-31 02:31:58 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-01 12:40:27 +00:00
										 |  |  | void MESH_OT_delete(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2009-01-31 02:31:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							| 
									
										
										
										
											2009-02-11 23:02:21 +00:00
										 |  |  | 	ot->name= "Delete"; | 
					
						
							| 
									
										
										
										
											2009-02-01 12:40:27 +00:00
										 |  |  | 	ot->idname= "MESH_OT_delete"; | 
					
						
							| 
									
										
										
										
											2009-01-31 02:31:58 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							| 
									
										
										
										
											2009-02-01 02:37:12 +00:00
										 |  |  | 	ot->invoke= WM_menu_invoke; | 
					
						
							| 
									
										
										
										
											2009-01-31 02:31:58 +00:00
										 |  |  | 	ot->exec= delete_mesh_exec; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-31 02:31:58 +00:00
										 |  |  | 	/*props */ | 
					
						
							| 
									
										
										
										
											2009-02-01 02:37:12 +00:00
										 |  |  | 	RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, 10, "Type", "Method used for deleting mesh data"); | 
					
						
							| 
									
										
										
										
											2009-01-31 02:31:58 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | /*GB*/ | 
					
						
							|  |  |  | /*-------------------------------------------------------------------------------*/ | 
					
						
							|  |  |  | /*--------------------------- Edge Based Subdivide ------------------------------*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define EDGENEW	2
 | 
					
						
							|  |  |  | #define FACENEW	2
 | 
					
						
							|  |  |  | #define EDGEINNER  4
 | 
					
						
							|  |  |  | #define EDGEOLD  8
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*used by faceloop cut to select only edges valid for edge slide*/ | 
					
						
							|  |  |  | #define DOUBLEOPFILL 16
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* calculates offset for co, based on fractal, sphere or smooth settings  */ | 
					
						
							|  |  |  | static void alter_co(float *co, EditEdge *edge, float rad, int beauty, float perc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float vec1[3], fac; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(beauty & B_SMOOTH) { | 
					
						
							|  |  |  | 		/* we calculate an offset vector vec1[], to be added to *co */ | 
					
						
							|  |  |  | 		float len, fac, nor[3], nor1[3], nor2[3]; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		VecSubf(nor, edge->v1->co, edge->v2->co); | 
					
						
							|  |  |  | 		len= 0.5f*Normalize(nor); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		VECCOPY(nor1, edge->v1->no); | 
					
						
							|  |  |  | 		VECCOPY(nor2, edge->v2->no); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		/* cosine angle */ | 
					
						
							|  |  |  | 		fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		vec1[0]= fac*nor1[0]; | 
					
						
							|  |  |  | 		vec1[1]= fac*nor1[1]; | 
					
						
							|  |  |  | 		vec1[2]= fac*nor1[2]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		/* cosine angle */ | 
					
						
							|  |  |  | 		fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		vec1[0]+= fac*nor2[0]; | 
					
						
							|  |  |  | 		vec1[1]+= fac*nor2[1]; | 
					
						
							|  |  |  | 		vec1[2]+= fac*nor2[2]; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		vec1[0]*= rad*len; | 
					
						
							|  |  |  | 		vec1[1]*= rad*len; | 
					
						
							|  |  |  | 		vec1[2]*= rad*len; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		co[0] += vec1[0]; | 
					
						
							|  |  |  | 		co[1] += vec1[1]; | 
					
						
							|  |  |  | 		co[2] += vec1[2]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		if(rad > 0.0) {   /* subdivide sphere */ | 
					
						
							|  |  |  | 			Normalize(co); | 
					
						
							|  |  |  | 			co[0]*= rad; | 
					
						
							|  |  |  | 			co[1]*= rad; | 
					
						
							|  |  |  | 			co[2]*= rad; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if(rad< 0.0) {  /* fractal subdivide */ | 
					
						
							|  |  |  | 			fac= rad* VecLenf(edge->v1->co, edge->v2->co); | 
					
						
							|  |  |  | 			vec1[0]= fac*(float)(0.5-BLI_drand()); | 
					
						
							|  |  |  | 			vec1[1]= fac*(float)(0.5-BLI_drand()); | 
					
						
							|  |  |  | 			vec1[2]= fac*(float)(0.5-BLI_drand()); | 
					
						
							|  |  |  | 			VecAddf(co, co, vec1); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* assumes in the edge is the correct interpolated vertices already */ | 
					
						
							|  |  |  | /* percent defines the interpolation, rad and beauty are for special options */ | 
					
						
							|  |  |  | /* results in new vertex with correct coordinate, vertex normal and weight group info */ | 
					
						
							|  |  |  | static EditVert *subdivide_edge_addvert(EditMesh *em, EditEdge *edge, float rad, int beauty, float percent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *ev; | 
					
						
							|  |  |  | 	float co[3]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	co[0] = (edge->v2->co[0]-edge->v1->co[0])*percent + edge->v1->co[0]; | 
					
						
							|  |  |  | 	co[1] = (edge->v2->co[1]-edge->v1->co[1])*percent + edge->v1->co[1]; | 
					
						
							|  |  |  | 	co[2] = (edge->v2->co[2]-edge->v1->co[2])*percent + edge->v1->co[2];					 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* offset for smooth or sphere or fractal */ | 
					
						
							|  |  |  | 	alter_co(co, edge, rad, beauty, percent); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* clip if needed by mirror modifier */ | 
					
						
							|  |  |  | 	if (edge->v1->f2) { | 
					
						
							|  |  |  | 		if ( edge->v1->f2 & edge->v2->f2 & 1) { | 
					
						
							|  |  |  | 			co[0]= 0.0f; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if ( edge->v1->f2 & edge->v2->f2 & 2) { | 
					
						
							|  |  |  | 			co[1]= 0.0f; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if ( edge->v1->f2 & edge->v2->f2 & 4) { | 
					
						
							|  |  |  | 			co[2]= 0.0f; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	ev = addvertlist(em, co, NULL); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* vert data (vgroups, ..) */ | 
					
						
							|  |  |  | 	EM_data_interp_from_verts(em, edge->v1, edge->v2, ev, percent); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* normal */ | 
					
						
							|  |  |  | 	ev->no[0] = (edge->v2->no[0]-edge->v1->no[0])*percent + edge->v1->no[0]; | 
					
						
							|  |  |  | 	ev->no[1] = (edge->v2->no[1]-edge->v1->no[1])*percent + edge->v1->no[1]; | 
					
						
							|  |  |  | 	ev->no[2] = (edge->v2->no[2]-edge->v1->no[2])*percent + edge->v1->no[2]; | 
					
						
							|  |  |  | 	Normalize(ev->no); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return ev; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void flipvertarray(EditVert** arr, short size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *hold; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(i=0; i<size/2; i++) { | 
					
						
							|  |  |  | 		hold = arr[i]; | 
					
						
							|  |  |  | 		arr[i] = arr[size-i-1]; | 
					
						
							|  |  |  | 		arr[size-i-1] = hold;    | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void facecopy(EditMesh *em, EditFace *source, EditFace *target) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float *v1 = source->v1->co, *v2 = source->v2->co, *v3 = source->v3->co; | 
					
						
							|  |  |  | 	float *v4 = source->v4? source->v4->co: NULL; | 
					
						
							|  |  |  | 	float w[4][4]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	CustomData_em_copy_data(&em->fdata, &em->fdata, source->data, &target->data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	target->mat_nr = source->mat_nr; | 
					
						
							|  |  |  | 	target->flag   = source->flag;	 | 
					
						
							|  |  |  | 	target->h	   = source->h; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v1->co, w[0]); | 
					
						
							|  |  |  | 	InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v2->co, w[1]); | 
					
						
							|  |  |  | 	InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v3->co, w[2]); | 
					
						
							|  |  |  | 	if (target->v4) | 
					
						
							|  |  |  | 		InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v4->co, w[3]); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	CustomData_em_interp(&em->fdata, &source->data, NULL, (float*)w, 1, target->data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void fill_quad_single(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, int seltype) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *cedge=NULL; | 
					
						
							|  |  |  | 	EditVert *v[4], **verts; | 
					
						
							|  |  |  | 	EditFace *hold; | 
					
						
							|  |  |  | 	short start=0, end, left, right, vertsize,i;    | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 	v[0] = efa->v1; | 
					
						
							|  |  |  | 	v[1] = efa->v2; | 
					
						
							|  |  |  | 	v[2] = efa->v3; | 
					
						
							|  |  |  | 	v[3] = efa->v4;	  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(efa->e1->f & SELECT)	  { cedge = efa->e1; start = 0;} | 
					
						
							|  |  |  | 	else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}	    | 
					
						
							|  |  |  | 	else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}	    | 
					
						
							|  |  |  | 	else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}		  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Point verts to the array of new verts for cedge
 | 
					
						
							|  |  |  | 	verts = BLI_ghash_lookup(gh, cedge); | 
					
						
							|  |  |  | 	//This is the index size of the verts array
 | 
					
						
							|  |  |  | 	vertsize = numcuts+2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Is the original v1 the same as the first vert on the selected edge?
 | 
					
						
							|  |  |  | 	// if not, the edge is running the opposite direction in this face so flip
 | 
					
						
							|  |  |  | 	// the array to the correct direction
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);} | 
					
						
							|  |  |  | 	end	= (start+1)%4; | 
					
						
							|  |  |  | 	left   = (start+2)%4; | 
					
						
							|  |  |  | 	right  = (start+3)%4;  | 
					
						
							|  |  |  | 		    | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	We should have something like this now | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			  end		 start				  | 
					
						
							|  |  |  | 			   3   2   1   0    | 
					
						
							|  |  |  | 			   |---*---*---| | 
					
						
							|  |  |  | 			   |		   | | 
					
						
							|  |  |  | 			   |		   |	    | 
					
						
							|  |  |  | 			   |		   | | 
					
						
							|  |  |  | 			   -------------	    | 
					
						
							|  |  |  | 			  left	   right | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	where start,end,left, right are indexes of EditFace->v1, etc (stored in v) | 
					
						
							|  |  |  | 	and 0,1,2... are the indexes of the new verts stored in verts | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	We will fill this case like this or this depending on even or odd cuts | 
					
						
							|  |  |  | 	  | 
					
						
							|  |  |  | 			   |---*---*---|		  |---*---| | 
					
						
							|  |  |  | 			   |  /	 \  |		  |  / \  | | 
					
						
							|  |  |  | 			   | /	   \ |		  | /   \ |	  | 
					
						
							|  |  |  | 			   |/		 \|		  |/	 \| | 
					
						
							|  |  |  | 			   -------------		  ---------   | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Make center face
 | 
					
						
							|  |  |  | 	if(vertsize % 2 == 0) { | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[(vertsize-1)/2],verts[((vertsize-1)/2)+1],v[left],v[right], NULL,NULL); | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		hold->e4->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 	}else{ | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[(vertsize-1)/2],v[left],v[right],NULL, NULL,NULL);   | 
					
						
							|  |  |  | 		hold->e1->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	facecopy(em, efa,hold); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Make side faces
 | 
					
						
							|  |  |  | 	for(i=0;i<(vertsize-1)/2;i++) { | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[i],verts[i+1],v[right],NULL,NULL,NULL);   | 
					
						
							|  |  |  | 		facecopy(em, efa,hold); | 
					
						
							|  |  |  | 		if(i+1 != (vertsize-1)/2) { | 
					
						
							|  |  |  |             if(seltype == SUBDIV_SELECT_INNER) { | 
					
						
							|  |  |  | 	 		   hold->e2->f2 |= EDGEINNER; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[vertsize-2-i],verts[vertsize-1-i],v[left],NULL,NULL,NULL);  | 
					
						
							|  |  |  | 		facecopy(em, efa,hold); | 
					
						
							|  |  |  | 		if(i+1 != (vertsize-1)/2) { | 
					
						
							|  |  |  |             if(seltype == SUBDIV_SELECT_INNER) { | 
					
						
							|  |  |  | 		 		hold->e3->f2 |= EDGEINNER; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}	  | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void fill_tri_single(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, int seltype) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *cedge=NULL; | 
					
						
							|  |  |  | 	EditVert *v[3], **verts; | 
					
						
							|  |  |  | 	EditFace *hold; | 
					
						
							|  |  |  | 	short start=0, end, op, vertsize,i;    | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 	v[0] = efa->v1; | 
					
						
							|  |  |  | 	v[1] = efa->v2; | 
					
						
							|  |  |  | 	v[2] = efa->v3;	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(efa->e1->f & SELECT)	  { cedge = efa->e1; start = 0;} | 
					
						
							|  |  |  | 	else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}	    | 
					
						
							|  |  |  | 	else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}		  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Point verts to the array of new verts for cedge
 | 
					
						
							|  |  |  | 	verts = BLI_ghash_lookup(gh, cedge); | 
					
						
							|  |  |  | 	//This is the index size of the verts array
 | 
					
						
							|  |  |  | 	vertsize = numcuts+2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Is the original v1 the same as the first vert on the selected edge?
 | 
					
						
							|  |  |  | 	// if not, the edge is running the opposite direction in this face so flip
 | 
					
						
							|  |  |  | 	// the array to the correct direction
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);} | 
					
						
							|  |  |  | 	   end	= (start+1)%3; | 
					
						
							|  |  |  | 	   op	 = (start+2)%3; | 
					
						
							|  |  |  | 		    | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	We should have something like this now | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			  end		 start				  | 
					
						
							|  |  |  | 			   3   2   1   0    | 
					
						
							|  |  |  | 			   |---*---*---| | 
					
						
							|  |  |  | 			   \		   | | 
					
						
							|  |  |  | 				 \		 |	    | 
					
						
							|  |  |  | 				   \	   | | 
					
						
							|  |  |  | 					 \	 | | 
					
						
							|  |  |  | 					   \   | | 
					
						
							|  |  |  | 						 \ | | 
					
						
							|  |  |  | 						   |op | 
					
						
							|  |  |  | 						    | 
					
						
							|  |  |  | 	where start,end,op are indexes of EditFace->v1, etc (stored in v) | 
					
						
							|  |  |  | 	and 0,1,2... are the indexes of the new verts stored in verts | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	We will fill this case like this or this depending on even or odd cuts | 
					
						
							|  |  |  | 	  | 
					
						
							|  |  |  | 			   3   2   1   0    | 
					
						
							|  |  |  | 			   |---*---*---| | 
					
						
							|  |  |  | 			   \	\  \   | | 
					
						
							|  |  |  | 				 \	\ \  |	    | 
					
						
							|  |  |  | 				   \   \ \ | | 
					
						
							|  |  |  | 					 \  \ \| | 
					
						
							|  |  |  | 					   \ \\| | 
					
						
							|  |  |  | 						 \ | | 
					
						
							|  |  |  | 						   |op | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Make side faces
 | 
					
						
							|  |  |  | 	for(i=0;i<(vertsize-1);i++) { | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[i],verts[i+1],v[op],NULL,NULL,NULL);   | 
					
						
							|  |  |  | 		if(i+1 != vertsize-1) { | 
					
						
							|  |  |  |             if(seltype == SUBDIV_SELECT_INNER) { | 
					
						
							|  |  |  | 		 		hold->e2->f2 |= EDGEINNER; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		facecopy(em, efa,hold); | 
					
						
							|  |  |  | 	}	   | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void fill_quad_double_op(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *cedge[2]={NULL, NULL}; | 
					
						
							|  |  |  | 	EditVert *v[4], **verts[2]; | 
					
						
							|  |  |  | 	EditFace *hold; | 
					
						
							|  |  |  | 	short start=0, end, left, right, vertsize,i; | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 	v[0] = efa->v1; | 
					
						
							|  |  |  | 	v[1] = efa->v2; | 
					
						
							|  |  |  | 	v[2] = efa->v3; | 
					
						
							|  |  |  | 	v[3] = efa->v4;	  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(efa->e1->f & SELECT)	  { cedge[0] = efa->e1;  cedge[1] = efa->e3; start = 0;} | 
					
						
							|  |  |  | 	else if(efa->e2->f & SELECT)	  { cedge[0] = efa->e2;  cedge[1] = efa->e4; start = 1;} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
 | 
					
						
							|  |  |  | 	verts[0] = BLI_ghash_lookup(gh, cedge[0]); | 
					
						
							|  |  |  | 	verts[1] = BLI_ghash_lookup(gh, cedge[1]); | 
					
						
							|  |  |  | 	//This is the index size of the verts array
 | 
					
						
							|  |  |  | 	vertsize = numcuts+2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Is the original v1 the same as the first vert on the selected edge?
 | 
					
						
							|  |  |  | 	// if not, the edge is running the opposite direction in this face so flip
 | 
					
						
							|  |  |  | 	// the array to the correct direction
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);} | 
					
						
							|  |  |  | 	end	= (start+1)%4; | 
					
						
							|  |  |  | 	left   = (start+2)%4; | 
					
						
							|  |  |  | 	right  = (start+3)%4;  | 
					
						
							|  |  |  | 	if(verts[1][0] != v[left]) {flipvertarray(verts[1],numcuts+2);}	 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	We should have something like this now | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			  end		 start				  | 
					
						
							|  |  |  | 			   3   2   1   0    | 
					
						
							|  |  |  | 			   |---*---*---| | 
					
						
							|  |  |  | 			   |		   | | 
					
						
							|  |  |  | 			   |		   |	    | 
					
						
							|  |  |  | 			   |		   | | 
					
						
							|  |  |  | 			   |---*---*---|	   | 
					
						
							|  |  |  | 			   0   1   2   3 | 
					
						
							|  |  |  | 			  left	   right | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	We will fill this case like this or this depending on even or odd cuts | 
					
						
							|  |  |  | 	  | 
					
						
							|  |  |  | 			   |---*---*---| | 
					
						
							|  |  |  | 			   |   |   |   | | 
					
						
							|  |  |  | 			   |   |   |   |	    | 
					
						
							|  |  |  | 			   |   |   |   | | 
					
						
							|  |  |  | 			   |---*---*---|  | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	    | 
					
						
							|  |  |  | 	// Make side faces
 | 
					
						
							|  |  |  | 	for(i=0;i<vertsize-1;i++) { | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-2-i],verts[1][vertsize-1-i],NULL,NULL);   | 
					
						
							|  |  |  | 		if(i < vertsize-2) { | 
					
						
							|  |  |  | 			hold->e2->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 			hold->e2->f2 |= DOUBLEOPFILL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		facecopy(em, efa,hold); | 
					
						
							|  |  |  | 	}	   | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void fill_quad_double_adj_path(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *cedge[2]={NULL, NULL}; | 
					
						
							|  |  |  | 	EditVert *v[4], **verts[2]; | 
					
						
							|  |  |  | 	EditFace *hold; | 
					
						
							|  |  |  | 	short start=0, start2=0, vertsize,i; | 
					
						
							|  |  |  | 	int ctrl= 0; // XXX
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	v[0] = efa->v1; | 
					
						
							|  |  |  | 	v[1] = efa->v2; | 
					
						
							|  |  |  | 	v[2] = efa->v3; | 
					
						
							|  |  |  | 	v[3] = efa->v4;	  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1;  cedge[1] = efa->e2; start = 0; start2 = 1;} | 
					
						
							|  |  |  | 	if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2;  cedge[1] = efa->e3; start = 1; start2 = 2;} | 
					
						
							|  |  |  | 	if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3;  cedge[1] = efa->e4; start = 2; start2 = 3;} | 
					
						
							|  |  |  | 	if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4;  cedge[1] = efa->e1; start = 3; start2 = 0;} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
 | 
					
						
							|  |  |  | 	verts[0] = BLI_ghash_lookup(gh, cedge[0]); | 
					
						
							|  |  |  | 	verts[1] = BLI_ghash_lookup(gh, cedge[1]); | 
					
						
							|  |  |  | 	//This is the index size of the verts array
 | 
					
						
							|  |  |  | 	vertsize = numcuts+2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Is the original v1 the same as the first vert on the selected edge?
 | 
					
						
							|  |  |  | 	// if not, the edge is running the opposite direction in this face so flip
 | 
					
						
							|  |  |  | 	// the array to the correct direction
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);} | 
					
						
							|  |  |  | 	if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}	 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	We should have something like this now | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			   end		 start				  | 
					
						
							|  |  |  | 				3   2   1   0    | 
					
						
							|  |  |  | 		start2 0|---*---*---| | 
					
						
							|  |  |  | 				|		   | | 
					
						
							|  |  |  | 			   1*		   | | 
					
						
							|  |  |  | 				|		   | | 
					
						
							|  |  |  | 			   2*		   |	    | 
					
						
							|  |  |  | 				|		   | | 
					
						
							|  |  |  | 		 end2  3|-----------|    | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	We will fill this case like this or this depending on even or odd cuts | 
					
						
							|  |  |  | 			   |---*---*---| | 
					
						
							|  |  |  | 			   | /   /   / | | 
					
						
							|  |  |  | 			   *   /   /   | | 
					
						
							|  |  |  | 			   | /   /	 | | 
					
						
							|  |  |  | 			   *   /	   |	    | 
					
						
							|  |  |  | 			   | /		 | | 
					
						
							|  |  |  | 			   |-----------|   | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Make outside tris
 | 
					
						
							|  |  |  | 	hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);   | 
					
						
							|  |  |  | 	/* when ctrl is depressed, only want verts on the cutline selected */ | 
					
						
							|  |  |  | 	if (ctrl) | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 	facecopy(em, efa,hold);	    | 
					
						
							|  |  |  | 	hold = addfacelist(em, verts[0][0],verts[1][vertsize-1],v[(start2+2)%4],NULL,NULL,NULL); | 
					
						
							|  |  |  | 	/* when ctrl is depressed, only want verts on the cutline selected */ | 
					
						
							|  |  |  | 	if (ctrl) | 
					
						
							|  |  |  | 		hold->e1->f2 |= EDGEINNER;   | 
					
						
							|  |  |  | 	facecopy(em, efa,hold);			    | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 	//if(scene->toolsettings->editbutflag & B_AUTOFGON) {
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	//	hold->e1->h |= EM_FGON;
 | 
					
						
							|  |  |  | 	//}	
 | 
					
						
							|  |  |  | 	// Make side faces
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(i=0;i<numcuts;i++) { | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);   | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa,hold); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	//EM_fgon_flags(em);
 | 
					
						
							|  |  |  | 		   | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void fill_quad_double_adj_fan(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *cedge[2]={NULL, NULL}; | 
					
						
							|  |  |  | 	EditVert *v[4], *op=NULL, **verts[2]; | 
					
						
							|  |  |  | 	EditFace *hold; | 
					
						
							|  |  |  | 	short start=0, start2=0, vertsize,i; | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 	v[0] = efa->v1; | 
					
						
							|  |  |  | 	v[1] = efa->v2; | 
					
						
							|  |  |  | 	v[2] = efa->v3; | 
					
						
							|  |  |  | 	v[3] = efa->v4;	  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1;  cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;} | 
					
						
							|  |  |  | 	if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2;  cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;} | 
					
						
							|  |  |  | 	if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3;  cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;} | 
					
						
							|  |  |  | 	if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4;  cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
 | 
					
						
							|  |  |  | 	verts[0] = BLI_ghash_lookup(gh, cedge[0]); | 
					
						
							|  |  |  | 	verts[1] = BLI_ghash_lookup(gh, cedge[1]); | 
					
						
							|  |  |  | 	//This is the index size of the verts array
 | 
					
						
							|  |  |  | 	vertsize = numcuts+2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Is the original v1 the same as the first vert on the selected edge?
 | 
					
						
							|  |  |  | 	// if not, the edge is running the opposite direction in this face so flip
 | 
					
						
							|  |  |  | 	// the array to the correct direction
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);} | 
					
						
							|  |  |  | 	if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}	 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	We should have something like this now | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			   end		 start				  | 
					
						
							|  |  |  | 				3   2   1   0    | 
					
						
							|  |  |  | 		start2 0|---*---*---| | 
					
						
							|  |  |  | 				|		   | | 
					
						
							|  |  |  | 			   1*		   | | 
					
						
							|  |  |  | 				|		   | | 
					
						
							|  |  |  | 			   2*		   |	    | 
					
						
							|  |  |  | 				|		   | | 
					
						
							|  |  |  | 		 end2  3|-----------|op    | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	We will fill this case like this or this (warning horrible ascii art follows) | 
					
						
							|  |  |  | 			   |---*---*---| | 
					
						
							|  |  |  | 			   | \  \   \  | | 
					
						
							|  |  |  | 			   *---\  \  \ | | 
					
						
							|  |  |  | 			   |   \ \ \  \| | 
					
						
							|  |  |  | 			   *---- \ \  \ |	    | 
					
						
							|  |  |  | 			   |    ---  \\\| | 
					
						
							|  |  |  | 			   |-----------|   | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(i=0;i<=numcuts;i++) { | 
					
						
							|  |  |  | 		hold = addfacelist(em, op,verts[1][numcuts-i],verts[1][numcuts-i+1],NULL,NULL,NULL);   | 
					
						
							|  |  |  | 		hold->e1->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa,hold); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		hold = addfacelist(em, op,verts[0][i],verts[0][i+1],NULL,NULL,NULL);   | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa,hold); | 
					
						
							|  |  |  | 	}	   | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void fill_quad_double_adj_inner(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *cedge[2]={NULL, NULL}; | 
					
						
							|  |  |  | 	EditVert *v[4], *op=NULL, **verts[2],**inner; | 
					
						
							|  |  |  | 	EditFace *hold; | 
					
						
							|  |  |  | 	short start=0, start2=0, vertsize,i; | 
					
						
							|  |  |  | 	float co[3]; | 
					
						
							|  |  |  | 						 | 
					
						
							|  |  |  | 	v[0] = efa->v1; | 
					
						
							|  |  |  | 	v[1] = efa->v2; | 
					
						
							|  |  |  | 	v[2] = efa->v3; | 
					
						
							|  |  |  | 	v[3] = efa->v4;	  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1;  cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;} | 
					
						
							|  |  |  | 	if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2;  cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;} | 
					
						
							|  |  |  | 	if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3;  cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;} | 
					
						
							|  |  |  | 	if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4;  cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
 | 
					
						
							|  |  |  | 	verts[0] = BLI_ghash_lookup(gh, cedge[0]); | 
					
						
							|  |  |  | 	verts[1] = BLI_ghash_lookup(gh, cedge[1]); | 
					
						
							|  |  |  | 	//This is the index size of the verts array
 | 
					
						
							|  |  |  | 	vertsize = numcuts+2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Is the original v1 the same as the first vert on the selected edge?
 | 
					
						
							|  |  |  | 	// if not, the edge is running the opposite direction in this face so flip
 | 
					
						
							|  |  |  | 	// the array to the correct direction
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);} | 
					
						
							|  |  |  | 	if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}	 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	We should have something like this now | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			   end		 start				  | 
					
						
							|  |  |  | 				3   2   1   0    | 
					
						
							|  |  |  | 		start2 0|---*---*---| | 
					
						
							|  |  |  | 				|		   | | 
					
						
							|  |  |  | 			   1*		   | | 
					
						
							|  |  |  | 				|		   | | 
					
						
							|  |  |  | 			   2*		   |	    | 
					
						
							|  |  |  | 				|		   | | 
					
						
							|  |  |  | 		 end2  3|-----------|op    | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	We will fill this case like this or this (warning horrible ascii art follows) | 
					
						
							|  |  |  | 			   |---*-----*---| | 
					
						
							|  |  |  | 			   | *     /     | | 
					
						
							|  |  |  | 			   *   \ /       | | 
					
						
							|  |  |  | 			   |    *        | | 
					
						
							|  |  |  | 			   | /	  \	     | | 
					
						
							|  |  |  | 			   *        \    |	    | 
					
						
							|  |  |  | 			   |           \ | | 
					
						
							|  |  |  | 			   |-------------|   | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Add Inner Vert(s)
 | 
					
						
							|  |  |  | 	inner = MEM_mallocN(sizeof(EditVert*)*numcuts,"New inner verts"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(i=0;i<numcuts;i++) { | 
					
						
							|  |  |  | 		co[0] = (verts[0][numcuts-i]->co[0] + verts[1][i+1]->co[0] ) / 2 ; | 
					
						
							|  |  |  | 		co[1] = (verts[0][numcuts-i]->co[1] + verts[1][i+1]->co[1] ) / 2 ; | 
					
						
							|  |  |  | 		co[2] = (verts[0][numcuts-i]->co[2] + verts[1][i+1]->co[2] ) / 2 ; | 
					
						
							|  |  |  | 		inner[i] = addvertlist(em, co, NULL); | 
					
						
							|  |  |  | 		inner[i]->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		EM_data_interp_from_verts(em, verts[0][numcuts-i], verts[1][i+1], inner[i], 0.5f); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// Add Corner Quad
 | 
					
						
							|  |  |  | 	hold = addfacelist(em, verts[0][numcuts+1],verts[1][1],inner[0],verts[0][numcuts],NULL,NULL);   | 
					
						
							|  |  |  | 	hold->e2->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 	hold->e3->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 	facecopy(em, efa,hold);	 | 
					
						
							|  |  |  | 	// Add Bottom Quads
 | 
					
						
							|  |  |  | 	hold = addfacelist(em, verts[0][0],verts[0][1],inner[numcuts-1],op,NULL,NULL);   | 
					
						
							|  |  |  | 	hold->e2->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 	facecopy(em, efa,hold);	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hold = addfacelist(em, op,inner[numcuts-1],verts[1][numcuts],verts[1][numcuts+1],NULL,NULL);   | 
					
						
							|  |  |  | 	hold->e2->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 	facecopy(em, efa,hold);		 | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 	//if(scene->toolsettings->editbutflag & B_AUTOFGON) {
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	//	hold->e1->h |= EM_FGON;
 | 
					
						
							|  |  |  | 	//}	
 | 
					
						
							|  |  |  | 	// Add Fill Quads (if # cuts > 1)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(i=0;i<numcuts-1;i++) { | 
					
						
							|  |  |  | 		hold = addfacelist(em, inner[i],verts[1][i+1],verts[1][i+2],inner[i+1],NULL,NULL);   | 
					
						
							|  |  |  | 		hold->e1->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa,hold); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		hold = addfacelist(em, inner[i],inner[i+1],verts[0][numcuts-1-i],verts[0][numcuts-i],NULL,NULL);   | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		hold->e4->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa,hold);	 | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 		//if(scene->toolsettings->editbutflag & B_AUTOFGON) {
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		//	hold->e1->h |= EM_FGON;
 | 
					
						
							|  |  |  | 		//}	
 | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	//EM_fgon_flags(em);
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	MEM_freeN(inner);   | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void fill_tri_double(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *cedge[2]={NULL, NULL}; | 
					
						
							|  |  |  | 	EditVert *v[3], **verts[2]; | 
					
						
							|  |  |  | 	EditFace *hold; | 
					
						
							|  |  |  | 	short start=0, start2=0, vertsize,i; | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 	v[0] = efa->v1; | 
					
						
							|  |  |  | 	v[1] = efa->v2; | 
					
						
							|  |  |  | 	v[2] = efa->v3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1;  cedge[1] = efa->e2; start = 0; start2 = 1;} | 
					
						
							|  |  |  | 	if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2;  cedge[1] = efa->e3; start = 1; start2 = 2;} | 
					
						
							|  |  |  | 	if(efa->e3->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e3;  cedge[1] = efa->e1; start = 2; start2 = 0;} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
 | 
					
						
							|  |  |  | 	verts[0] = BLI_ghash_lookup(gh, cedge[0]); | 
					
						
							|  |  |  | 	verts[1] = BLI_ghash_lookup(gh, cedge[1]); | 
					
						
							|  |  |  | 	//This is the index size of the verts array
 | 
					
						
							|  |  |  | 	vertsize = numcuts+2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Is the original v1 the same as the first vert on the selected edge?
 | 
					
						
							|  |  |  | 	// if not, the edge is running the opposite direction in this face so flip
 | 
					
						
							|  |  |  | 	// the array to the correct direction
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);} | 
					
						
							|  |  |  | 	if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}	 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	We should have something like this now | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			   end		 start				  | 
					
						
							|  |  |  | 				3   2   1   0    | 
					
						
							|  |  |  | 		start2 0|---*---*---| | 
					
						
							|  |  |  | 				|		 /	  | 
					
						
							|  |  |  | 			   1*	   /		 | 
					
						
							|  |  |  | 				|	 /		  | 
					
						
							|  |  |  | 			   2*   /				  | 
					
						
							|  |  |  | 				| /		    | 
					
						
							|  |  |  | 		 end2  3|   | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	We will fill this case like this or this depending on even or odd cuts | 
					
						
							|  |  |  | 			   |---*---*---| | 
					
						
							|  |  |  | 			   | /   /   /  | 
					
						
							|  |  |  | 			   *   /   /    | 
					
						
							|  |  |  | 			   | /   /	  | 
					
						
							|  |  |  | 			   *   /			   | 
					
						
							|  |  |  | 			   | /		  | 
					
						
							|  |  |  | 			   | | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Make outside tri
 | 
					
						
							|  |  |  | 	hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);   | 
					
						
							|  |  |  | 	hold->e3->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 	facecopy(em, efa,hold);			   | 
					
						
							|  |  |  | 	// Make side faces
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(i=0;i<numcuts;i++) { | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);   | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa,hold); | 
					
						
							|  |  |  | 	}	   | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void fill_quad_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *cedge[3]={0}; | 
					
						
							|  |  |  | 	EditVert *v[4], **verts[3]; | 
					
						
							|  |  |  | 	EditFace *hold; | 
					
						
							|  |  |  | 	short start=0, start2=0, start3=0, vertsize, i, repeats; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	v[0] = efa->v1; | 
					
						
							|  |  |  | 	v[1] = efa->v2; | 
					
						
							|  |  |  | 	v[2] = efa->v3; | 
					
						
							|  |  |  | 	v[3] = efa->v4;	  | 
					
						
							|  |  |  | 	    | 
					
						
							|  |  |  | 	if(!(efa->e1->f & SELECT)) { | 
					
						
							|  |  |  | 		cedge[0] = efa->e2;   | 
					
						
							|  |  |  | 		cedge[1] = efa->e3;  | 
					
						
							|  |  |  | 		cedge[2] = efa->e4; | 
					
						
							|  |  |  | 		start = 1;start2 = 2;start3 = 3;    | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(!(efa->e2->f & SELECT)) { | 
					
						
							|  |  |  | 		cedge[0] = efa->e3;   | 
					
						
							|  |  |  | 		cedge[1] = efa->e4;  | 
					
						
							|  |  |  | 		cedge[2] = efa->e1; | 
					
						
							|  |  |  | 		start = 2;start2 = 3;start3 = 0;    | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(!(efa->e3->f & SELECT)) { | 
					
						
							|  |  |  | 		cedge[0] = efa->e4;   | 
					
						
							|  |  |  | 		cedge[1] = efa->e1;  | 
					
						
							|  |  |  | 		cedge[2] = efa->e2; | 
					
						
							|  |  |  | 		start = 3;start2 = 0;start3 = 1;    | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(!(efa->e4->f & SELECT)) { | 
					
						
							|  |  |  | 		cedge[0] = efa->e1;   | 
					
						
							|  |  |  | 		cedge[1] = efa->e2;  | 
					
						
							|  |  |  | 		cedge[2] = efa->e3; | 
					
						
							|  |  |  | 		start = 0;start2 = 1;start3 = 2;    | 
					
						
							|  |  |  | 	}	    | 
					
						
							|  |  |  | 	// Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
 | 
					
						
							|  |  |  | 	verts[0] = BLI_ghash_lookup(gh, cedge[0]); | 
					
						
							|  |  |  | 	verts[1] = BLI_ghash_lookup(gh, cedge[1]); | 
					
						
							|  |  |  | 	verts[2] = BLI_ghash_lookup(gh, cedge[2]); | 
					
						
							|  |  |  | 	//This is the index size of the verts array
 | 
					
						
							|  |  |  | 	vertsize = numcuts+2; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// Is the original v1 the same as the first vert on the selected edge?
 | 
					
						
							|  |  |  | 	// if not, the edge is running the opposite direction in this face so flip
 | 
					
						
							|  |  |  | 	// the array to the correct direction
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);} | 
					
						
							|  |  |  | 	if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);}   | 
					
						
							|  |  |  | 	if(verts[2][0] != v[start3]) {flipvertarray(verts[2],numcuts+2);}    | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 We should have something like this now | 
					
						
							|  |  |  | 	  | 
					
						
							|  |  |  | 	 start2				  | 
					
						
							|  |  |  | 	 3   2   1   0    | 
					
						
							|  |  |  | 	 start3 0|---*---*---|3  | 
					
						
							|  |  |  | 	 |		   | | 
					
						
							|  |  |  | 	 1*		   *2 | 
					
						
							|  |  |  | 	 |		   | | 
					
						
							|  |  |  | 	 2*		   *1	    | 
					
						
							|  |  |  | 	 |		   | | 
					
						
							|  |  |  | 	 3|-----------|0 start    | 
					
						
							|  |  |  | 	  | 
					
						
							|  |  |  | 	 We will fill this case like this or this depending on even or odd cuts   | 
					
						
							|  |  |  | 	 there are a couple of differences. For odd cuts, there is a tri in the | 
					
						
							|  |  |  | 	 middle as well as 1 quad at the bottom (not including the extra quads | 
					
						
							|  |  |  | 	 for odd cuts > 1		   | 
					
						
							|  |  |  | 	  | 
					
						
							|  |  |  | 	 For even cuts, there is a quad in the middle and 2 quads on the bottom | 
					
						
							|  |  |  | 	  | 
					
						
							|  |  |  | 	 they are numbered here for clarity | 
					
						
							|  |  |  | 	  | 
					
						
							|  |  |  | 	 1 outer tris and bottom quads | 
					
						
							|  |  |  | 	 2 inner tri or quad | 
					
						
							|  |  |  | 	 3 repeating quads | 
					
						
							|  |  |  | 	  | 
					
						
							|  |  |  | 	 |---*---*---*---| | 
					
						
							|  |  |  | 	 |1/   /  \   \ 1| | 
					
						
							|  |  |  | 	 |/ 3 /	\  3 \| | 
					
						
							|  |  |  | 	 *  /	2   \   * | 
					
						
							|  |  |  | 	 | /		  \  | | 
					
						
							|  |  |  | 	 |/			\ |  | 
					
						
							|  |  |  | 	 *---------------* | 
					
						
							|  |  |  | 	 |	  3		| | 
					
						
							|  |  |  | 	 |			   |   | 
					
						
							|  |  |  | 	 *---------------* | 
					
						
							|  |  |  | 	 |			   | | 
					
						
							|  |  |  | 	 |	  1		|				   | 
					
						
							|  |  |  | 	 |			   | | 
					
						
							|  |  |  | 	 |---------------| | 
					
						
							|  |  |  | 	  | 
					
						
							|  |  |  | 	 |---*---*---*---*---| | 
					
						
							|  |  |  | 	 | 1/   /	 \   \ 1|    | 
					
						
							|  |  |  | 	 | /   /	   \   \ |   | 
					
						
							|  |  |  | 	 |/ 3 /		 \ 3 \| | 
					
						
							|  |  |  | 	 *   /		   \   * | 
					
						
							|  |  |  | 	 |  /			 \  |	 | 
					
						
							|  |  |  | 	 | /	   2	   \ |    | 
					
						
							|  |  |  | 	 |/				 \| | 
					
						
							|  |  |  | 	 *-------------------* | 
					
						
							|  |  |  | 	 |				   | | 
					
						
							|  |  |  | 	 |		 3		 | | 
					
						
							|  |  |  | 	 |				   |  | 
					
						
							|  |  |  | 	 *-------------------* | 
					
						
							|  |  |  | 	 |				   | | 
					
						
							|  |  |  | 	 |		 1		 | | 
					
						
							|  |  |  | 	 |				   |  | 
					
						
							|  |  |  | 	 *-------------------* | 
					
						
							|  |  |  | 	 |				   | | 
					
						
							|  |  |  | 	 |		1		  | | 
					
						
							|  |  |  | 	 |				   |  | 
					
						
							|  |  |  | 	 |-------------------| | 
					
						
							|  |  |  | 	  | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Make outside tris
 | 
					
						
							|  |  |  | 	hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);   | 
					
						
							|  |  |  | 	hold->e3->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 	facecopy(em, efa,hold);	   | 
					
						
							|  |  |  | 	hold = addfacelist(em, verts[1][vertsize-2],verts[1][vertsize-1],verts[2][1],NULL,NULL,NULL);   | 
					
						
							|  |  |  | 	hold->e3->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 	facecopy(em, efa,hold);			   | 
					
						
							|  |  |  | 	// Make bottom quad
 | 
					
						
							|  |  |  | 	hold = addfacelist(em, verts[0][0],verts[0][1],verts[2][vertsize-2],verts[2][vertsize-1],NULL,NULL);   | 
					
						
							|  |  |  | 	hold->e2->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 	facecopy(em, efa,hold);		  | 
					
						
							|  |  |  | 	//If it is even cuts, add the 2nd lower quad
 | 
					
						
							|  |  |  | 	if(numcuts % 2 == 0) { | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[0][1],verts[0][2],verts[2][vertsize-3],verts[2][vertsize-2],NULL,NULL);   | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa,hold);		  | 
					
						
							|  |  |  | 		// Also Make inner quad
 | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[1][numcuts/2],verts[1][(numcuts/2)+1],verts[2][numcuts/2],verts[0][(numcuts/2)+1],NULL,NULL);		    | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGEINNER; | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 		//if(scene->toolsettings->editbutflag & B_AUTOFGON) {
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		//	hold->e3->h |= EM_FGON;
 | 
					
						
							|  |  |  | 		//}
 | 
					
						
							|  |  |  | 		facecopy(em, efa,hold); | 
					
						
							|  |  |  | 		repeats = (numcuts / 2) -1; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		// Make inner tri	 
 | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[1][(numcuts/2)+1],verts[2][(numcuts/2)+1],verts[0][(numcuts/2)+1],NULL,NULL,NULL);		    | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGEINNER; | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 		//if(scene->toolsettings->editbutflag & B_AUTOFGON) {
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		//	hold->e2->h |= EM_FGON;
 | 
					
						
							|  |  |  | 		//}
 | 
					
						
							|  |  |  | 		facecopy(em, efa,hold);    | 
					
						
							|  |  |  | 		repeats = ((numcuts+1) / 2)-1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// cuts for 1 and 2 do not have the repeating quads
 | 
					
						
							|  |  |  | 	if(numcuts < 3) {repeats = 0;} | 
					
						
							|  |  |  | 	for(i=0;i<repeats;i++) { | 
					
						
							|  |  |  | 		//Make side repeating Quads
 | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[1][i+1],verts[1][i+2],verts[0][vertsize-i-3],verts[0][vertsize-i-2],NULL,NULL);   | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGEINNER;		  | 
					
						
							|  |  |  | 		facecopy(em, efa,hold);			    | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[1][vertsize-i-3],verts[1][vertsize-i-2],verts[2][i+1],verts[2][i+2],NULL,NULL);		    | 
					
						
							|  |  |  | 		hold->e4->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa,hold);  | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Do repeating bottom quads 
 | 
					
						
							|  |  |  | 	for(i=0;i<repeats;i++) { | 
					
						
							|  |  |  | 		if(numcuts % 2 == 1) {	  | 
					
						
							|  |  |  | 			hold = addfacelist(em, verts[0][1+i],verts[0][2+i],verts[2][vertsize-3-i],verts[2][vertsize-2-i],NULL,NULL);   | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			hold = addfacelist(em, verts[0][2+i],verts[0][3+i],verts[2][vertsize-4-i],verts[2][vertsize-3-i],NULL,NULL);				   | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa,hold);				 | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 	//EM_fgon_flags(em);
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void fill_quad_quadruple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, float rad, int beauty) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert **verts[4], ***innerverts; | 
					
						
							|  |  |  | 	EditFace *hold;	 | 
					
						
							|  |  |  | 	EditEdge temp; | 
					
						
							|  |  |  | 	short vertsize, i, j; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
 | 
					
						
							|  |  |  | 	verts[0] = BLI_ghash_lookup(gh, efa->e1); | 
					
						
							|  |  |  | 	verts[1] = BLI_ghash_lookup(gh, efa->e2); | 
					
						
							|  |  |  | 	verts[2] = BLI_ghash_lookup(gh, efa->e3); | 
					
						
							|  |  |  | 	verts[3] = BLI_ghash_lookup(gh, efa->e4); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//This is the index size of the verts array
 | 
					
						
							|  |  |  | 	vertsize = numcuts+2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Is the original v1 the same as the first vert on the selected edge?
 | 
					
						
							|  |  |  | 	// if not, the edge is running the opposite direction in this face so flip
 | 
					
						
							|  |  |  | 	// the array to the correct direction
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);} | 
					
						
							|  |  |  | 	if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}   | 
					
						
							|  |  |  | 	if(verts[2][0] == efa->v3) {flipvertarray(verts[2],numcuts+2);} | 
					
						
							|  |  |  | 	if(verts[3][0] == efa->v4) {flipvertarray(verts[3],numcuts+2);}	  | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	We should have something like this now | 
					
						
							|  |  |  | 					  1 | 
					
						
							|  |  |  | 										   | 
					
						
							|  |  |  | 				3   2   1   0    | 
					
						
							|  |  |  | 			   0|---*---*---|0  | 
					
						
							|  |  |  | 				|           | | 
					
						
							|  |  |  | 			   1*           *1 | 
					
						
							|  |  |  | 		     2  |           |   4 | 
					
						
							|  |  |  | 			   2*           *2	    | 
					
						
							|  |  |  | 				|           | | 
					
						
							|  |  |  | 			   3|---*---*---|3	 | 
					
						
							|  |  |  | 				3   2   1   0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					  3 | 
					
						
							|  |  |  | 	// we will fill a 2 dim array of editvert*s to make filling easier
 | 
					
						
							|  |  |  | 	//  the innervert order is shown
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				0   0---1---2---3  | 
					
						
							|  |  |  | 					|   |   |   | | 
					
						
							|  |  |  | 				1   0---1---2---3  | 
					
						
							|  |  |  | 					|   |   |   | | 
					
						
							|  |  |  | 				2   0---1---2---3		 | 
					
						
							|  |  |  | 					|   |   |   | | 
					
						
							|  |  |  | 				3   0---1---2---3   | 
					
						
							|  |  |  | 		   | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts outer array");  | 
					
						
							|  |  |  | 	for(i=0;i<numcuts+2;i++) { | 
					
						
							|  |  |  | 		innerverts[i] = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts inner array"); | 
					
						
							|  |  |  | 	}   | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// first row is e1 last row is e3
 | 
					
						
							|  |  |  | 	for(i=0;i<numcuts+2;i++) { | 
					
						
							|  |  |  | 		innerverts[0][i]		  = verts[0][(numcuts+1)-i]; | 
					
						
							|  |  |  | 		innerverts[numcuts+1][i]  = verts[2][(numcuts+1)-i]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(i=1;i<=numcuts;i++) { | 
					
						
							|  |  |  | 		/* we create a fake edge for the next loop */ | 
					
						
							|  |  |  | 		temp.v2 = innerverts[i][0]			= verts[1][i]; | 
					
						
							|  |  |  | 		temp.v1 = innerverts[i][numcuts+1]  = verts[3][i]; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for(j=1;j<=numcuts;j++) {  | 
					
						
							|  |  |  | 			float percent= (float)j/(float)(numcuts+1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			innerverts[i][(numcuts+1)-j]= subdivide_edge_addvert(em, &temp, rad, beauty, percent); | 
					
						
							|  |  |  | 		}	 | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 	// Fill with faces
 | 
					
						
							|  |  |  | 	for(i=0;i<numcuts+1;i++) { | 
					
						
							|  |  |  | 		for(j=0;j<numcuts+1;j++) { | 
					
						
							|  |  |  | 			hold = addfacelist(em, innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],innerverts[i+1][j+1],NULL,NULL);	  | 
					
						
							|  |  |  | 			hold->e1->f2 = EDGENEW;	   | 
					
						
							|  |  |  | 			hold->e2->f2 = EDGENEW;   | 
					
						
							|  |  |  | 			hold->e3->f2 = EDGENEW;			 | 
					
						
							|  |  |  | 			hold->e4->f2 = EDGENEW;    | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if(i != 0) { hold->e1->f2 |= EDGEINNER; } | 
					
						
							|  |  |  | 			if(j != 0) { hold->e2->f2 |= EDGEINNER; } | 
					
						
							|  |  |  | 			if(i != numcuts) { hold->e3->f2 |= EDGEINNER; } | 
					
						
							|  |  |  | 			if(j != numcuts) { hold->e4->f2 |= EDGEINNER; } | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			facecopy(em, efa,hold);		 | 
					
						
							|  |  |  | 		}		 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Clean up our dynamic multi-dim array
 | 
					
						
							|  |  |  | 	for(i=0;i<numcuts+2;i++) { | 
					
						
							|  |  |  | 	   MEM_freeN(innerverts[i]);    | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 	MEM_freeN(innerverts); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void fill_tri_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, float rad, int beauty) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert **verts[3], ***innerverts; | 
					
						
							|  |  |  | 	short vertsize, i, j; | 
					
						
							|  |  |  | 	EditFace *hold;   | 
					
						
							|  |  |  | 	EditEdge temp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
 | 
					
						
							|  |  |  | 	verts[0] = BLI_ghash_lookup(gh, efa->e1); | 
					
						
							|  |  |  | 	verts[1] = BLI_ghash_lookup(gh, efa->e2); | 
					
						
							|  |  |  | 	verts[2] = BLI_ghash_lookup(gh, efa->e3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//This is the index size of the verts array
 | 
					
						
							|  |  |  | 	vertsize = numcuts+2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Is the original v1 the same as the first vert on the selected edge?
 | 
					
						
							|  |  |  | 	// if not, the edge is running the opposite direction in this face so flip
 | 
					
						
							|  |  |  | 	// the array to the correct direction
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);} | 
					
						
							|  |  |  | 	if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}   | 
					
						
							|  |  |  | 	if(verts[2][0] != efa->v3) {flipvertarray(verts[2],numcuts+2);}    | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	We should have something like this now | 
					
						
							|  |  |  | 					   3 | 
					
						
							|  |  |  | 										   | 
					
						
							|  |  |  | 				3   2   1   0    | 
					
						
							|  |  |  | 			   0|---*---*---|3  | 
					
						
							|  |  |  | 				|		  /	 | 
					
						
							|  |  |  | 		  1	1*		*2    | 
					
						
							|  |  |  | 				|	  /	   | 
					
						
							|  |  |  | 			   2*	*1	   2		  | 
					
						
							|  |  |  | 				|  /		    | 
					
						
							|  |  |  | 			   3|/  | 
					
						
							|  |  |  | 				 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	we will fill a 2 dim array of editvert*s to make filling easier | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						3 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			 0  0---1---2---3---4 | 
					
						
							|  |  |  | 				| / | /  |/  | /	 | 
					
						
							|  |  |  | 			 1  0---1----2---3  | 
					
						
							|  |  |  | 	   1		| /  | / | /	 | 
					
						
							|  |  |  | 			 2  0----1---2	 2 | 
					
						
							|  |  |  | 				|  / |  /	    | 
					
						
							|  |  |  | 				|/   |/    | 
					
						
							|  |  |  | 			 3  0---1  | 
					
						
							|  |  |  | 				|  / | 
					
						
							|  |  |  | 				|/ | 
					
						
							|  |  |  | 			 4  0   | 
					
						
							|  |  |  | 	   | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"tri-tri subdiv inner verts outer array");  | 
					
						
							|  |  |  | 	for(i=0;i<numcuts+2;i++) { | 
					
						
							|  |  |  | 		  innerverts[i] = MEM_mallocN(sizeof(EditVert*)*((numcuts+2)-i),"tri-tri subdiv inner verts inner array"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	//top row is e3 backwards
 | 
					
						
							|  |  |  | 	for(i=0;i<numcuts+2;i++) { | 
					
						
							|  |  |  | 		  innerverts[0][i]		  = verts[2][(numcuts+1)-i]; | 
					
						
							|  |  |  | 	}    | 
					
						
							|  |  |  | 		    | 
					
						
							|  |  |  | 	for(i=1;i<=numcuts+1;i++) { | 
					
						
							|  |  |  | 		//fake edge, first vert is from e1, last is from e2
 | 
					
						
							|  |  |  | 		temp.v1= innerverts[i][0]			  = verts[0][i]; | 
					
						
							|  |  |  | 		temp.v2= innerverts[i][(numcuts+1)-i]  = verts[1][(numcuts+1)-i]; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for(j=1;j<(numcuts+1)-i;j++) { | 
					
						
							|  |  |  | 			float percent= (float)j/(float)((numcuts+1)-i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			innerverts[i][((numcuts+1)-i)-j]= subdivide_edge_addvert(em, &temp, rad, beauty, 1-percent); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Now fill the verts with happy little tris :)
 | 
					
						
							|  |  |  | 	for(i=0;i<=numcuts+1;i++) { | 
					
						
							|  |  |  | 		for(j=0;j<(numcuts+1)-i;j++) {    | 
					
						
							|  |  |  | 			//We always do the first tri
 | 
					
						
							|  |  |  | 			hold = addfacelist(em, innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],NULL,NULL,NULL);	 | 
					
						
							|  |  |  | 			hold->e1->f2 |= EDGENEW;	   | 
					
						
							|  |  |  | 			hold->e2->f2 |= EDGENEW;   | 
					
						
							|  |  |  | 			hold->e3->f2 |= EDGENEW;   | 
					
						
							|  |  |  | 			if(i != 0) { hold->e1->f2 |= EDGEINNER; } | 
					
						
							|  |  |  | 			if(j != 0) { hold->e2->f2 |= EDGEINNER; } | 
					
						
							|  |  |  | 			if(j+1 != (numcuts+1)-i) {hold->e3->f2 |= EDGEINNER;} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			facecopy(em, efa,hold);		 | 
					
						
							|  |  |  | 			//if there are more to come, we do the 2nd	 
 | 
					
						
							|  |  |  | 			if(j+1 <= numcuts-i) { | 
					
						
							|  |  |  | 				hold = addfacelist(em, innerverts[i+1][j],innerverts[i+1][j+1],innerverts[i][j+1],NULL,NULL,NULL);		    | 
					
						
							|  |  |  | 				facecopy(em, efa,hold);  | 
					
						
							|  |  |  | 				hold->e1->f2 |= EDGENEW;	   | 
					
						
							|  |  |  | 				hold->e2->f2 |= EDGENEW;   | 
					
						
							|  |  |  | 				hold->e3->f2 |= EDGENEW;  	 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}  | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Clean up our dynamic multi-dim array
 | 
					
						
							|  |  |  | 	for(i=0;i<numcuts+2;i++) { | 
					
						
							|  |  |  | 		MEM_freeN(innerverts[i]);    | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 	MEM_freeN(innerverts); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //Next two fill types are for knife exact only and are provided to allow for knifing through vertices
 | 
					
						
							|  |  |  | //This means there is no multicut!
 | 
					
						
							|  |  |  | static void fill_quad_doublevert(EditMesh *em, EditFace *efa, int v1, int v2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *hold; | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 		Depending on which two vertices have been knifed through (v1 and v2), we | 
					
						
							|  |  |  | 		triangulate like the patterns below. | 
					
						
							|  |  |  | 				X-------|	|-------X | 
					
						
							|  |  |  | 				| \  	|	|     / | | 
					
						
							|  |  |  | 				|   \	|	|   /	| | 
					
						
							|  |  |  | 				|	  \	|	| /	    | | 
					
						
							|  |  |  | 				--------X	X-------- | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(v1 == 1 && v2 == 3){ | 
					
						
							|  |  |  | 		hold= addfacelist(em, efa->v1, efa->v2, efa->v3, 0, efa, NULL); | 
					
						
							|  |  |  | 		hold->e1->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa, hold); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		hold= addfacelist(em, efa->v1, efa->v3, efa->v4, 0, efa, NULL); | 
					
						
							|  |  |  | 		hold->e1->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e1->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa, hold); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else{ | 
					
						
							|  |  |  | 		hold= addfacelist(em, efa->v1, efa->v2, efa->v4, 0, efa, NULL); | 
					
						
							|  |  |  | 		hold->e1->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa, hold); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		hold= addfacelist(em, efa->v2, efa->v3, efa->v4, 0, efa, NULL); | 
					
						
							|  |  |  | 		hold->e1->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa, hold); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void fill_quad_singlevert(EditMesh *em, EditFace *efa, struct GHash *gh) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *cedge=NULL; | 
					
						
							|  |  |  | 	EditVert *v[4], **verts; | 
					
						
							|  |  |  | 	EditFace *hold; | 
					
						
							|  |  |  | 	short start=0, end, left, right, vertsize;    | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 	v[0] = efa->v1; | 
					
						
							|  |  |  | 	v[1] = efa->v2; | 
					
						
							|  |  |  | 	v[2] = efa->v3; | 
					
						
							|  |  |  | 	v[3] = efa->v4;	  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(efa->e1->f & SELECT)	  { cedge = efa->e1; start = 0;} | 
					
						
							|  |  |  | 	else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}	    | 
					
						
							|  |  |  | 	else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}	    | 
					
						
							|  |  |  | 	else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}		  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Point verts to the array of new verts for cedge
 | 
					
						
							|  |  |  | 	verts = BLI_ghash_lookup(gh, cedge); | 
					
						
							|  |  |  | 	//This is the index size of the verts array
 | 
					
						
							|  |  |  | 	vertsize = 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Is the original v1 the same as the first vert on the selected edge?
 | 
					
						
							|  |  |  | 	// if not, the edge is running the opposite direction in this face so flip
 | 
					
						
							|  |  |  | 	// the array to the correct direction
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(verts[0] != v[start]) {flipvertarray(verts,3);} | 
					
						
							|  |  |  | 	end	= (start+1)%4; | 
					
						
							|  |  |  | 	left   = (start+2)%4; | 
					
						
							|  |  |  | 	right  = (start+3)%4;  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | 	We should have something like this now | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			  end		 start				  | 
					
						
							|  |  |  | 			   2     1     0    | 
					
						
							|  |  |  | 			   |-----*-----| | 
					
						
							|  |  |  | 			   |		   | | 
					
						
							|  |  |  | 			   |		   |	    | 
					
						
							|  |  |  | 			   |		   | | 
					
						
							|  |  |  | 			   -------------	    | 
					
						
							|  |  |  | 			  left	   right | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	where start,end,left, right are indexes of EditFace->v1, etc (stored in v) | 
					
						
							|  |  |  | 	and 0,1,2 are the indexes of the new verts stored in verts. We fill like | 
					
						
							|  |  |  | 	this, depending on whether its vertex 'left' or vertex 'right' thats | 
					
						
							|  |  |  | 	been knifed through... | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				|---*---|	|---*---| | 
					
						
							|  |  |  | 				|  /	|	|    \  | | 
					
						
							|  |  |  | 				| /		|	|	  \ | | 
					
						
							|  |  |  | 				|/		|	|	   \| | 
					
						
							|  |  |  | 				X--------	--------X | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(v[left]->f1){ | 
					
						
							|  |  |  | 		//triangle is composed of cutvert, end and left
 | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[1],v[end],v[left],NULL, NULL,NULL); | 
					
						
							|  |  |  | 		hold->e1->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa, hold); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		//quad is composed of cutvert, left, right and start
 | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[1],v[left],v[right],v[start], NULL, NULL); | 
					
						
							|  |  |  | 		hold->e1->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e4->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e1->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa, hold); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if(v[right]->f1){ | 
					
						
							|  |  |  | 		//triangle is composed of cutvert, right and start
 | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[1],v[right],v[start], NULL, NULL, NULL); | 
					
						
							|  |  |  | 		hold->e1->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e1->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa, hold); | 
					
						
							|  |  |  | 		//quad is composed of cutvert, end, left, right
 | 
					
						
							|  |  |  | 		hold = addfacelist(em, verts[1],v[end], v[left], v[right], NULL, NULL); | 
					
						
							|  |  |  | 		hold->e1->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e2->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e3->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e4->f2 |= EDGENEW; | 
					
						
							|  |  |  | 		hold->e4->f2 |= EDGEINNER; | 
					
						
							|  |  |  | 		facecopy(em, efa, hold); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | }	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This function takes an example edge, the current point to create and 
 | 
					
						
							|  |  |  | // the total # of points to create, then creates the point and return the
 | 
					
						
							|  |  |  | // editvert pointer to it.
 | 
					
						
							|  |  |  | static EditVert *subdivideedgenum(EditMesh *em, EditEdge *edge, int curpoint, int totpoint, float rad, int beauty) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *ev; | 
					
						
							|  |  |  | 	float percent; | 
					
						
							|  |  |  | 	  | 
					
						
							|  |  |  | 	if (beauty & (B_PERCENTSUBD) && totpoint == 1) | 
					
						
							|  |  |  | 		//percent=(float)(edge->tmp.l)/32768.0f;
 | 
					
						
							|  |  |  | 		percent= edge->tmp.fp; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		percent= (float)curpoint/(float)(totpoint+1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ev= subdivide_edge_addvert(em, edge, rad, beauty, percent); | 
					
						
							|  |  |  | 	ev->f = edge->v1->f; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return ev; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | void esubdivideflag(Object *obedit, EditMesh *em, int flag, float rad, int beauty, int numcuts, int seltype) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditFace *ef; | 
					
						
							|  |  |  | 	EditEdge *eed, *cedge, *sort[4]; | 
					
						
							|  |  |  | 	EditVert *eve, **templist; | 
					
						
							|  |  |  | 	struct GHash *gh; | 
					
						
							|  |  |  | 	float length[4], v1mat[3], v2mat[3], v3mat[3], v4mat[3]; | 
					
						
							|  |  |  | 	int i, j, edgecount, touchcount, facetype,hold; | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	ModifierData *md= obedit->modifiers.first; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	int ctrl= 0; // XXX
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	//Set faces f1 to 0 cause we need it later
 | 
					
						
							|  |  |  | 	for(ef=em->faces.first;ef;ef = ef->next) ef->f1 = 0; | 
					
						
							|  |  |  | 	for(eve=em->verts.first; eve; eve=eve->next) { | 
					
						
							|  |  |  | 		if(!(beauty & B_KNIFE)) /* knife sets this flag for vertex cuts */ | 
					
						
							|  |  |  | 			eve->f1 = 0; | 
					
						
							|  |  |  | 		eve->f2 = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (; md; md=md->next) { | 
					
						
							|  |  |  | 		if (md->type==eModifierType_Mirror) { | 
					
						
							|  |  |  | 			MirrorModifierData *mmd = (MirrorModifierData*) md;	 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			if(mmd->flag & MOD_MIR_CLIPPING) { | 
					
						
							|  |  |  | 				for (eve= em->verts.first; eve; eve= eve->next) { | 
					
						
							|  |  |  | 					eve->f2= 0; | 
					
						
							|  |  |  | 					switch(mmd->axis){ | 
					
						
							|  |  |  | 						case 0: | 
					
						
							|  |  |  | 							if (fabs(eve->co[0]) < mmd->tolerance) | 
					
						
							|  |  |  | 								eve->f2 |= 1; | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						case 1: | 
					
						
							|  |  |  | 							if (fabs(eve->co[1]) < mmd->tolerance) | 
					
						
							|  |  |  | 								eve->f2 |= 2; | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						case 2: | 
					
						
							|  |  |  | 							if (fabs(eve->co[2]) < mmd->tolerance) | 
					
						
							|  |  |  | 								eve->f2 |= 4; | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	//Flush vertex flags upward to the edges
 | 
					
						
							|  |  |  | 	for(eed = em->edges.first;eed;eed = eed->next) { | 
					
						
							|  |  |  | 		//if(eed->f & flag && eed->v1->f == eed->v2->f) {
 | 
					
						
							|  |  |  | 		//	eed->f |= eed->v1->f;   
 | 
					
						
							|  |  |  | 		// }
 | 
					
						
							|  |  |  | 		eed->f2 = 0;    | 
					
						
							|  |  |  | 		if(eed->f & flag) { | 
					
						
							|  |  |  | 			eed->f2	|= EDGEOLD; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// We store an array of verts for each edge that is subdivided,
 | 
					
						
							|  |  |  | 	// we put this array as a value in a ghash which is keyed by the EditEdge*
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Now for beauty subdivide deselect edges based on length
 | 
					
						
							|  |  |  | 	if(beauty & B_BEAUTY) {  | 
					
						
							|  |  |  | 		for(ef = em->faces.first;ef;ef = ef->next) { | 
					
						
							|  |  |  | 			if(!ef->v4) { | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(ef->f & SELECT) { | 
					
						
							|  |  |  | 				VECCOPY(v1mat, ef->v1->co); | 
					
						
							|  |  |  | 				VECCOPY(v2mat, ef->v2->co); | 
					
						
							|  |  |  | 				VECCOPY(v3mat, ef->v3->co); | 
					
						
							|  |  |  | 				VECCOPY(v4mat, ef->v4->co);						 | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 				Mat4Mul3Vecfl(obedit->obmat, v1mat); | 
					
						
							|  |  |  | 				Mat4Mul3Vecfl(obedit->obmat, v2mat);											 | 
					
						
							|  |  |  | 				Mat4Mul3Vecfl(obedit->obmat, v3mat); | 
					
						
							|  |  |  | 				Mat4Mul3Vecfl(obedit->obmat, v4mat); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				 | 
					
						
							|  |  |  | 				length[0] = VecLenf(v1mat, v2mat); | 
					
						
							|  |  |  | 				length[1] = VecLenf(v2mat, v3mat); | 
					
						
							|  |  |  | 				length[2] = VecLenf(v3mat, v4mat); | 
					
						
							|  |  |  | 				length[3] = VecLenf(v4mat, v1mat); | 
					
						
							|  |  |  | 				sort[0] = ef->e1; | 
					
						
							|  |  |  | 				sort[1] = ef->e2; | 
					
						
							|  |  |  | 				sort[2] = ef->e3; | 
					
						
							|  |  |  | 				sort[3] = ef->e4; | 
					
						
							|  |  |  | 												   | 
					
						
							|  |  |  | 												 | 
					
						
							|  |  |  | 				// Beauty Short Edges
 | 
					
						
							|  |  |  | 				if(beauty & B_BEAUTY_SHORT) { | 
					
						
							|  |  |  | 					for(j=0;j<2;j++) { | 
					
						
							|  |  |  | 						hold = -1; | 
					
						
							|  |  |  | 						for(i=0;i<4;i++) { | 
					
						
							|  |  |  | 							if(length[i] < 0) { | 
					
						
							|  |  |  | 								continue;							 | 
					
						
							|  |  |  | 							} else if(hold == -1) {   | 
					
						
							|  |  |  | 								hold = i;  | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								if(length[hold] < length[i]) { | 
					
						
							|  |  |  | 									hold = i;    | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						if (hold > -1) { | 
					
						
							|  |  |  | 							sort[hold]->f &= ~SELECT; | 
					
						
							|  |  |  | 							sort[hold]->f2 |= EDGENEW; | 
					
						
							|  |  |  | 							length[hold] = -1; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				 | 
					
						
							|  |  |  | 				// Beauty Long Edges
 | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					 for(j=0;j<2;j++) { | 
					
						
							|  |  |  | 						hold = -1; | 
					
						
							|  |  |  | 						for(i=0;i<4;i++) { | 
					
						
							|  |  |  | 							if(length[i] < 0) { | 
					
						
							|  |  |  | 								continue;							 | 
					
						
							|  |  |  | 							} else if(hold == -1) {   | 
					
						
							|  |  |  | 								hold = i;  | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								if(length[hold] > length[i]) { | 
					
						
							|  |  |  | 									hold = i;    | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						if (hold > -1) { | 
					
						
							|  |  |  | 							sort[hold]->f &= ~SELECT; | 
					
						
							|  |  |  | 							sort[hold]->f2 |= EDGENEW; | 
					
						
							|  |  |  | 							length[hold] = -1; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// If we are knifing, We only need the selected edges that were cut, so deselect if it was not cut
 | 
					
						
							|  |  |  | 	if(beauty & B_KNIFE) {	 | 
					
						
							|  |  |  | 		for(eed= em->edges.first;eed;eed=eed->next) {	 | 
					
						
							|  |  |  | 			if( eed->tmp.fp == 0 ) { | 
					
						
							|  |  |  | 				EM_select_edge(eed,0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}   | 
					
						
							|  |  |  | 	// So for each edge, if it is selected, we allocate an array of size cuts+2
 | 
					
						
							|  |  |  | 	// so we can have a place for the v1, the new verts and v2  
 | 
					
						
							|  |  |  | 	for(eed=em->edges.first;eed;eed = eed->next) { | 
					
						
							|  |  |  | 		if(eed->f & flag) { | 
					
						
							|  |  |  | 			templist = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"vertlist"); | 
					
						
							|  |  |  | 			templist[0] = eed->v1; | 
					
						
							|  |  |  | 			for(i=0;i<numcuts;i++) { | 
					
						
							|  |  |  | 				// This function creates the new vert and returns it back
 | 
					
						
							|  |  |  | 				// to the array
 | 
					
						
							|  |  |  | 				templist[i+1] = subdivideedgenum(em, eed, i+1, numcuts, rad, beauty); | 
					
						
							|  |  |  | 				//while we are here, we can copy edge info from the original edge
 | 
					
						
							|  |  |  | 				cedge = addedgelist(em, templist[i],templist[i+1],eed); | 
					
						
							|  |  |  | 				// Also set the edge f2 to EDGENEW so that we can use this info later
 | 
					
						
							|  |  |  | 				cedge->f2 = EDGENEW; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			templist[i+1] = eed->v2; | 
					
						
							|  |  |  | 			//Do the last edge too
 | 
					
						
							|  |  |  | 			cedge = addedgelist(em, templist[i],templist[i+1],eed); | 
					
						
							|  |  |  | 			cedge->f2 = EDGENEW; | 
					
						
							|  |  |  | 			// Now that the edge is subdivided, we can put its verts in the ghash 
 | 
					
						
							|  |  |  | 			BLI_ghash_insert(gh, eed, templist);			    | 
					
						
							|  |  |  | 		}								   | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	// Now for each face in the mesh we need to figure out How many edges were cut
 | 
					
						
							|  |  |  | 	// and which filling method to use for that face
 | 
					
						
							|  |  |  | 	for(ef = em->faces.first;ef;ef = ef->next) { | 
					
						
							|  |  |  | 		edgecount = 0; | 
					
						
							|  |  |  | 		facetype = 3; | 
					
						
							|  |  |  | 		if(ef->e1->f & flag) {edgecount++;} | 
					
						
							|  |  |  | 		if(ef->e2->f & flag) {edgecount++;} | 
					
						
							|  |  |  | 		if(ef->e3->f & flag) {edgecount++;} | 
					
						
							|  |  |  | 		if(ef->v4) { | 
					
						
							|  |  |  | 			facetype = 4; | 
					
						
							|  |  |  | 			if(ef->e4->f & flag) {edgecount++;} | 
					
						
							|  |  |  | 		}   | 
					
						
							|  |  |  | 		if(facetype == 4) { | 
					
						
							|  |  |  | 			switch(edgecount) { | 
					
						
							|  |  |  | 				case 0: | 
					
						
							|  |  |  | 					if(beauty & B_KNIFE && numcuts == 1){ | 
					
						
							|  |  |  | 						/*Test for when knifing through two opposite verts but no edges*/ | 
					
						
							|  |  |  | 						touchcount = 0; | 
					
						
							|  |  |  | 						if(ef->v1->f1) touchcount++; | 
					
						
							|  |  |  | 						if(ef->v2->f1) touchcount++; | 
					
						
							|  |  |  | 						if(ef->v3->f1) touchcount++; | 
					
						
							|  |  |  | 						if(ef->v4->f1) touchcount++; | 
					
						
							|  |  |  | 						if(touchcount == 2){ | 
					
						
							|  |  |  | 							if(ef->v1->f1 && ef->v3->f1){  | 
					
						
							|  |  |  | 								ef->f1 = SELECT; | 
					
						
							|  |  |  | 								fill_quad_doublevert(em, ef, 1, 3);  | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							else if(ef->v2->f1 && ef->v4->f1){ | 
					
						
							|  |  |  | 								ef->f1 = SELECT; | 
					
						
							|  |  |  | 								fill_quad_doublevert(em, ef, 2, 4); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					break;  | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				case 1:  | 
					
						
							|  |  |  | 					if(beauty & B_KNIFE && numcuts == 1){ | 
					
						
							|  |  |  | 						/*Test for when knifing through an edge and one vert*/ | 
					
						
							|  |  |  | 						touchcount = 0; | 
					
						
							|  |  |  | 						if(ef->v1->f1) touchcount++; | 
					
						
							|  |  |  | 						if(ef->v2->f1) touchcount++; | 
					
						
							|  |  |  | 						if(ef->v3->f1) touchcount++; | 
					
						
							|  |  |  | 						if(ef->v4->f1) touchcount++; | 
					
						
							|  |  |  | 						 | 
					
						
							|  |  |  | 						if(touchcount == 1){ | 
					
						
							|  |  |  | 							if( (ef->e1->f & flag && ( !ef->e1->v1->f1 && !ef->e1->v2->f1 )) || | 
					
						
							|  |  |  | 								(ef->e2->f & flag && ( !ef->e2->v1->f1 && !ef->e2->v2->f1 )) || | 
					
						
							|  |  |  | 								(ef->e3->f & flag && ( !ef->e3->v1->f1 && !ef->e3->v2->f1 )) || | 
					
						
							|  |  |  | 								(ef->e4->f & flag && ( !ef->e4->v1->f1 && !ef->e4->v2->f1 )) ){ | 
					
						
							|  |  |  | 								 | 
					
						
							|  |  |  | 								ef->f1 = SELECT;  | 
					
						
							|  |  |  | 								fill_quad_singlevert(em, ef, gh); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							else{ | 
					
						
							|  |  |  | 								ef->f1 = SELECT; | 
					
						
							|  |  |  | 								fill_quad_single(em, ef, gh, numcuts, seltype); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						else{  | 
					
						
							|  |  |  | 							ef->f1 = SELECT;  | 
					
						
							|  |  |  | 							fill_quad_single(em, ef, gh, numcuts, seltype); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					else{  | 
					
						
							|  |  |  | 						ef->f1 = SELECT; | 
					
						
							|  |  |  | 						fill_quad_single(em, ef, gh, numcuts, seltype); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					break;    | 
					
						
							|  |  |  | 				case 2: ef->f1 = SELECT; | 
					
						
							|  |  |  | 					// if there are 2, we check if edge 1 and 3 are either both on or off that way
 | 
					
						
							|  |  |  | 					// we can tell if the selected pair is Adjacent or Opposite of each other
 | 
					
						
							|  |  |  | 					if((ef->e1->f & flag && ef->e3->f & flag) ||  | 
					
						
							|  |  |  | 					   (ef->e2->f & flag && ef->e4->f & flag)) { | 
					
						
							|  |  |  | 						fill_quad_double_op(em, ef, gh, numcuts);							   | 
					
						
							|  |  |  | 					}else{ | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 						switch(0) { // XXX scene->toolsettings->cornertype) {
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 							case 0:	fill_quad_double_adj_path(em, ef, gh, numcuts); break; | 
					
						
							|  |  |  | 							case 1:	fill_quad_double_adj_inner(em, ef, gh, numcuts); break; | 
					
						
							|  |  |  | 							case 2:	fill_quad_double_adj_fan(em, ef, gh, numcuts); break; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 												   | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 						break;	 | 
					
						
							|  |  |  | 				case 3: ef->f1 = SELECT; | 
					
						
							|  |  |  | 					fill_quad_triple(em, ef, gh, numcuts);  | 
					
						
							|  |  |  | 					break;	 | 
					
						
							|  |  |  | 				case 4: ef->f1 = SELECT; | 
					
						
							|  |  |  | 					fill_quad_quadruple(em, ef, gh, numcuts, rad, beauty);  | 
					
						
							|  |  |  | 					break;	 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			switch(edgecount) { | 
					
						
							|  |  |  | 				case 0: break; | 
					
						
							|  |  |  | 				case 1: ef->f1 = SELECT; | 
					
						
							|  |  |  | 					fill_tri_single(em, ef, gh, numcuts, seltype); | 
					
						
							|  |  |  | 					break;    | 
					
						
							|  |  |  | 				case 2: ef->f1 = SELECT; | 
					
						
							|  |  |  | 					fill_tri_double(em, ef, gh, numcuts); | 
					
						
							|  |  |  | 					break;	 | 
					
						
							|  |  |  | 				case 3: ef->f1 = SELECT; | 
					
						
							|  |  |  | 					fill_tri_triple(em, ef, gh, numcuts, rad, beauty); | 
					
						
							|  |  |  | 					break;   | 
					
						
							|  |  |  | 			}	 | 
					
						
							|  |  |  | 		}	 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// Delete Old Edges and Faces
 | 
					
						
							|  |  |  | 	for(eed = em->edges.first;eed;eed = eed->next) { | 
					
						
							|  |  |  | 		if(BLI_ghash_haskey(gh,eed)) { | 
					
						
							|  |  |  | 			eed->f1 = SELECT;  | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			eed->f1 = 0;    | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}  | 
					
						
							|  |  |  | 	free_tagged_edges_faces(em, em->edges.first, em->faces.first);  | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(seltype == SUBDIV_SELECT_ORIG  && !ctrl) { | 
					
						
							|  |  |  | 		/* bugfix: vertex could get flagged as "not-selected"
 | 
					
						
							|  |  |  | 		// solution: clear flags before, not at the same time as setting SELECT flag -dg
 | 
					
						
							|  |  |  | 		*/ | 
					
						
							|  |  |  | 		for(eed = em->edges.first;eed;eed = eed->next) { | 
					
						
							|  |  |  | 			if(!(eed->f2 & EDGENEW || eed->f2 & EDGEOLD)) { | 
					
						
							|  |  |  | 				eed->f &= !flag; | 
					
						
							|  |  |  | 				EM_select_edge(eed,0);  | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for(eed = em->edges.first;eed;eed = eed->next) { | 
					
						
							|  |  |  | 			if(eed->f2 & EDGENEW || eed->f2 & EDGEOLD) { | 
					
						
							|  |  |  | 				eed->f |= flag; | 
					
						
							|  |  |  | 				EM_select_edge(eed,1); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else if ((seltype == SUBDIV_SELECT_INNER || seltype == SUBDIV_SELECT_INNER_SEL)|| ctrl) { | 
					
						
							|  |  |  | 		for(eed = em->edges.first;eed;eed = eed->next) { | 
					
						
							|  |  |  | 			if(eed->f2 & EDGEINNER) { | 
					
						
							|  |  |  | 				eed->f |= flag; | 
					
						
							|  |  |  | 				EM_select_edge(eed,1);    | 
					
						
							|  |  |  | 				if(eed->v1->f & EDGEINNER) eed->v1->f |= SELECT; | 
					
						
							|  |  |  | 				if(eed->v2->f & EDGEINNER) eed->v2->f |= SELECT; | 
					
						
							|  |  |  | 			}else{ | 
					
						
							|  |  |  | 				eed->f &= !flag; | 
					
						
							|  |  |  | 				EM_select_edge(eed,0);  | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}		   | 
					
						
							|  |  |  | 	} else if(seltype == SUBDIV_SELECT_LOOPCUT){ | 
					
						
							|  |  |  | 		for(eed = em->edges.first;eed;eed = eed->next) { | 
					
						
							|  |  |  | 			if(eed->f2 & DOUBLEOPFILL){ | 
					
						
							|  |  |  | 				eed->f |= flag; | 
					
						
							|  |  |  | 				EM_select_edge(eed,1); | 
					
						
							|  |  |  | 			}else{ | 
					
						
							|  |  |  | 				eed->f &= !flag; | 
					
						
							|  |  |  | 				EM_select_edge(eed,0); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}  | 
					
						
							|  |  |  | 	 if(em->selectmode & SCE_SELECT_VERTEX) { | 
					
						
							|  |  |  | 		 for(eed = em->edges.first;eed;eed = eed->next) { | 
					
						
							|  |  |  | 			if(eed->f & SELECT) { | 
					
						
							|  |  |  | 				eed->v1->f |= SELECT; | 
					
						
							|  |  |  | 				eed->v2->f |= SELECT; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}	 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	//fix hide flags for edges. First pass, hide edges of hidden faces
 | 
					
						
							|  |  |  | 	for(ef=em->faces.first; ef; ef=ef->next){ | 
					
						
							|  |  |  | 		if(ef->h){ | 
					
						
							|  |  |  | 			ef->e1->h |= 1; | 
					
						
							|  |  |  | 			ef->e2->h |= 1; | 
					
						
							|  |  |  | 			ef->e3->h |= 1; | 
					
						
							|  |  |  | 			if(ef->e4) ef->e4->h |= 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	//second pass: unhide edges of visible faces adjacent to hidden faces
 | 
					
						
							|  |  |  | 	for(ef=em->faces.first; ef; ef=ef->next){ | 
					
						
							|  |  |  | 		if(ef->h == 0){ | 
					
						
							|  |  |  | 			ef->e1->h &= ~1; | 
					
						
							|  |  |  | 			ef->e2->h &= ~1; | 
					
						
							|  |  |  | 			ef->e3->h &= ~1; | 
					
						
							|  |  |  | 			if(ef->e4) ef->e4->h &= ~1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// Free the ghash and call MEM_freeN on all the value entries to return 
 | 
					
						
							|  |  |  | 	// that memory
 | 
					
						
							|  |  |  | 	BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);    | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	EM_selectmode_flush(em); | 
					
						
							|  |  |  | 	for(ef=em->faces.first;ef;ef = ef->next) { | 
					
						
							|  |  |  | 		if(ef->e4) { | 
					
						
							|  |  |  | 			if(  (ef->e1->f & SELECT && ef->e2->f & SELECT) && | 
					
						
							|  |  |  | 			 (ef->e3->f & SELECT && ef->e4->f & SELECT) ) { | 
					
						
							|  |  |  | 				ef->f |= SELECT;			  | 
					
						
							|  |  |  | 			}				    | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			if(  (ef->e1->f & SELECT && ef->e2->f & SELECT) && ef->e3->f & SELECT) { | 
					
						
							|  |  |  | 				ef->f |= SELECT;			  | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	recalc_editnormals(em); | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int count_selected_edges(EditEdge *ed) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int totedge = 0; | 
					
						
							|  |  |  | 	while(ed) { | 
					
						
							|  |  |  | 		ed->tmp.p = 0; | 
					
						
							|  |  |  | 		if( ed->f & SELECT ) totedge++; | 
					
						
							|  |  |  | 		ed= ed->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return totedge; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* hurms, as if this makes code readable! It's pointerpointer hiding... (ton) */ | 
					
						
							|  |  |  | typedef EditFace *EVPtr; | 
					
						
							|  |  |  | typedef EVPtr EVPTuple[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** builds EVPTuple array efaa of face tuples (in fact pointers to EditFaces)
 | 
					
						
							|  |  |  | 	sharing one edge. | 
					
						
							|  |  |  | 	arguments: selected edge list, face list. | 
					
						
							|  |  |  | 	Edges will also be tagged accordingly (see eed->f2)		  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int collect_quadedges(EVPTuple *efaa, EditEdge *eed, EditFace *efa) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *e1, *e2, *e3; | 
					
						
							|  |  |  | 	EVPtr *evp; | 
					
						
							|  |  |  | 	int i = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* run through edges, if selected, set pointer edge-> facearray */ | 
					
						
							|  |  |  | 	while(eed) { | 
					
						
							|  |  |  | 		eed->f2= 0; | 
					
						
							|  |  |  | 		eed->f1= 0; | 
					
						
							|  |  |  | 		if( eed->f & SELECT ) { | 
					
						
							|  |  |  | 			eed->tmp.p = (EditVert *) (&efaa[i]); | 
					
						
							|  |  |  | 			i++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else eed->tmp.p = NULL; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		eed= eed->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* find edges pointing to 2 faces by procedure:
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	- run through faces and their edges, increase | 
					
						
							|  |  |  | 	  face counter e->f1 for each face  | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		efa->f1= 0; | 
					
						
							|  |  |  | 		if(efa->v4==0 && (efa->f & SELECT)) {  /* if selected triangle */ | 
					
						
							|  |  |  | 			e1= efa->e1; | 
					
						
							|  |  |  | 			e2= efa->e2; | 
					
						
							|  |  |  | 			e3= efa->e3; | 
					
						
							|  |  |  | 			if(e1->f2<3 && e1->tmp.p) { | 
					
						
							|  |  |  | 				if(e1->f2<2) { | 
					
						
							|  |  |  | 					evp= (EVPtr *) e1->tmp.p; | 
					
						
							|  |  |  | 					evp[(int)e1->f2] = efa; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				e1->f2+= 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(e2->f2<3 && e2->tmp.p) { | 
					
						
							|  |  |  | 				if(e2->f2<2) { | 
					
						
							|  |  |  | 					evp= (EVPtr *) e2->tmp.p; | 
					
						
							|  |  |  | 					evp[(int)e2->f2]= efa; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				e2->f2+= 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(e3->f2<3 && e3->tmp.p) { | 
					
						
							|  |  |  | 				if(e3->f2<2) { | 
					
						
							|  |  |  | 					evp= (EVPtr *) e3->tmp.p; | 
					
						
							|  |  |  | 					evp[(int)e3->f2]= efa; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				e3->f2+= 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			/* set to 3 to make sure these are not flipped or joined */ | 
					
						
							|  |  |  | 			efa->e1->f2= 3; | 
					
						
							|  |  |  | 			efa->e2->f2= 3; | 
					
						
							|  |  |  | 			efa->e3->f2= 3; | 
					
						
							|  |  |  | 			if (efa->e4) efa->e4->f2= 3; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		efa= efa->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return i; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* returns vertices of two adjacent triangles forming a quad 
 | 
					
						
							|  |  |  |    - can be righthand or lefthand | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			4-----3 | 
					
						
							|  |  |  | 			|\	| | 
					
						
							|  |  |  | 			| \ 2 | <- efa1 | 
					
						
							|  |  |  | 			|  \  |  | 
					
						
							|  |  |  | 	  efa-> | 1 \ |  | 
					
						
							|  |  |  | 			|	\|  | 
					
						
							|  |  |  | 			1-----2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | #define VTEST(face, num, other) \
 | 
					
						
							|  |  |  | 	(face->v##num != other->v1 && face->v##num != other->v2 && face->v##num != other->v3)  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void givequadverts(EditFace *efa, EditFace *efa1, EditVert **v1, EditVert **v2, EditVert **v3, EditVert **v4, int *vindex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if VTEST(efa, 1, efa1) { | 
					
						
							|  |  |  | 		*v1= efa->v1; | 
					
						
							|  |  |  | 		*v2= efa->v2; | 
					
						
							|  |  |  | 		vindex[0]= 0; | 
					
						
							|  |  |  | 		vindex[1]= 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if VTEST(efa, 2, efa1) { | 
					
						
							|  |  |  | 		*v1= efa->v2; | 
					
						
							|  |  |  | 		*v2= efa->v3; | 
					
						
							|  |  |  | 		vindex[0]= 1; | 
					
						
							|  |  |  | 		vindex[1]= 2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if VTEST(efa, 3, efa1) { | 
					
						
							|  |  |  | 		*v1= efa->v3; | 
					
						
							|  |  |  | 		*v2= efa->v1; | 
					
						
							|  |  |  | 		vindex[0]= 2; | 
					
						
							|  |  |  | 		vindex[1]= 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if VTEST(efa1, 1, efa) { | 
					
						
							|  |  |  | 		*v3= efa1->v1; | 
					
						
							|  |  |  | 		*v4= efa1->v2; | 
					
						
							|  |  |  | 		vindex[2]= 0; | 
					
						
							|  |  |  | 		vindex[3]= 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if VTEST(efa1, 2, efa) { | 
					
						
							|  |  |  | 		*v3= efa1->v2; | 
					
						
							|  |  |  | 		*v4= efa1->v3; | 
					
						
							|  |  |  | 		vindex[2]= 1; | 
					
						
							|  |  |  | 		vindex[3]= 2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if VTEST(efa1, 3, efa) { | 
					
						
							|  |  |  | 		*v3= efa1->v3; | 
					
						
							|  |  |  | 		*v4= efa1->v1; | 
					
						
							|  |  |  | 		vindex[2]= 2; | 
					
						
							|  |  |  | 		vindex[3]= 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		*v3= *v4= NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Helper functions for edge/quad edit features*/ | 
					
						
							|  |  |  | static void untag_edges(EditFace *f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	f->e1->f1 = 0; | 
					
						
							|  |  |  | 	f->e2->f1 = 0; | 
					
						
							|  |  |  | 	f->e3->f1 = 0; | 
					
						
							|  |  |  | 	if (f->e4) f->e4->f1 = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** remove and free list of tagged edges and faces */ | 
					
						
							|  |  |  | static void free_tagged_edges_faces(EditMesh *em, EditEdge *eed, EditFace *efa) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *nexted; | 
					
						
							|  |  |  | 	EditFace *nextvl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		nextvl= efa->next; | 
					
						
							|  |  |  | 		if(efa->f1) { | 
					
						
							|  |  |  | 			BLI_remlink(&em->faces, efa); | 
					
						
							|  |  |  | 			free_editface(em, efa); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			/* avoid deleting edges that are still in use */ | 
					
						
							|  |  |  | 			untag_edges(efa); | 
					
						
							|  |  |  | 		efa= nextvl; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while(eed) { | 
					
						
							|  |  |  | 		nexted= eed->next; | 
					
						
							|  |  |  | 		if(eed->f1) { | 
					
						
							|  |  |  | 			remedge(em, eed); | 
					
						
							|  |  |  | 			free_editedge(em, eed); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eed= nexted; | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | }	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ******************** BEGIN TRIANGLE TO QUAD ************************************* */ | 
					
						
							|  |  |  | static float measure_facepair(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, float limit) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*gives a 'weight' to a pair of triangles that join an edge to decide how good a join they would make*/ | 
					
						
							|  |  |  | 	/*Note: this is more complicated than it needs to be and should be cleaned up...*/ | 
					
						
							|  |  |  | 	float	measure = 0.0, noA1[3], noA2[3], noB1[3], noB2[3], normalADiff, normalBDiff, | 
					
						
							|  |  |  | 			edgeVec1[3], edgeVec2[3], edgeVec3[3], edgeVec4[3], diff, | 
					
						
							|  |  |  | 			minarea, maxarea, areaA, areaB; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*First Test: Normal difference*/ | 
					
						
							|  |  |  | 	CalcNormFloat(v1->co, v2->co, v3->co, noA1); | 
					
						
							|  |  |  | 	CalcNormFloat(v1->co, v3->co, v4->co, noA2); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(noA1[0] == noA2[0] && noA1[1] == noA2[1] && noA1[2] == noA2[2]) normalADiff = 0.0; | 
					
						
							|  |  |  | 	else normalADiff = VecAngle2(noA1, noA2); | 
					
						
							|  |  |  | 		//if(!normalADiff) normalADiff = 179;
 | 
					
						
							|  |  |  | 	CalcNormFloat(v2->co, v3->co, v4->co, noB1); | 
					
						
							|  |  |  | 	CalcNormFloat(v4->co, v1->co, v2->co, noB2); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(noB1[0] == noB2[0] && noB1[1] == noB2[1] && noB1[2] == noB2[2]) normalBDiff = 0.0; | 
					
						
							|  |  |  | 	else normalBDiff = VecAngle2(noB1, noB2); | 
					
						
							|  |  |  | 		//if(!normalBDiff) normalBDiff = 179;
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	measure += (normalADiff/360) + (normalBDiff/360); | 
					
						
							|  |  |  | 	if(measure > limit) return measure; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*Second test: Colinearity*/ | 
					
						
							|  |  |  | 	VecSubf(edgeVec1, v1->co, v2->co); | 
					
						
							|  |  |  | 	VecSubf(edgeVec2, v2->co, v3->co); | 
					
						
							|  |  |  | 	VecSubf(edgeVec3, v3->co, v4->co); | 
					
						
							|  |  |  | 	VecSubf(edgeVec4, v4->co, v1->co); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	diff = 0.0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	diff = ( | 
					
						
							|  |  |  | 		fabs(VecAngle2(edgeVec1, edgeVec2) - 90) + | 
					
						
							|  |  |  | 		fabs(VecAngle2(edgeVec2, edgeVec3) - 90) +  | 
					
						
							|  |  |  | 		fabs(VecAngle2(edgeVec3, edgeVec4) - 90) +  | 
					
						
							|  |  |  | 		fabs(VecAngle2(edgeVec4, edgeVec1) - 90)) / 360; | 
					
						
							|  |  |  | 	if(!diff) return 0.0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	measure +=  diff; | 
					
						
							|  |  |  | 	if(measure > limit) return measure; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*Third test: Concavity*/ | 
					
						
							|  |  |  | 	areaA = AreaT3Dfl(v1->co, v2->co, v3->co) + AreaT3Dfl(v1->co, v3->co, v4->co); | 
					
						
							|  |  |  | 	areaB = AreaT3Dfl(v2->co, v3->co, v4->co) + AreaT3Dfl(v4->co, v1->co, v2->co); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(areaA <= areaB) minarea = areaA; | 
					
						
							|  |  |  | 	else minarea = areaB; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(areaA >= areaB) maxarea = areaA; | 
					
						
							|  |  |  | 	else maxarea = areaB; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(!maxarea) measure += 1; | 
					
						
							|  |  |  | 	else measure += (1 - (minarea / maxarea)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return measure; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define T2QUV_LIMIT 0.005
 | 
					
						
							|  |  |  | #define T2QCOL_LIMIT 3
 | 
					
						
							|  |  |  | static int compareFaceAttribs(EditMesh *em, EditFace *f1, EditFace *f2, EditEdge *eed)  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/*Test to see if the per-face attributes for the joining edge match within limit*/	 | 
					
						
							|  |  |  | 	MTFace *tf1, *tf2; | 
					
						
							|  |  |  | 	unsigned int *col1, *col2; | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 	short i,attrok=0, flag = 0, /* XXX scene->toolsettings->editbutflag,*/ fe1[2], fe2[2]; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	tf1 = CustomData_em_get(&em->fdata, f1->data, CD_MTFACE); | 
					
						
							|  |  |  | 	tf2 = CustomData_em_get(&em->fdata, f2->data, CD_MTFACE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	col1 = CustomData_em_get(&em->fdata, f1->data, CD_MCOL); | 
					
						
							|  |  |  | 	col2 = CustomData_em_get(&em->fdata, f2->data, CD_MCOL); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*store indices for faceedges*/ | 
					
						
							|  |  |  | 	f1->v1->f1 = 0; | 
					
						
							|  |  |  | 	f1->v2->f1 = 1; | 
					
						
							|  |  |  | 	f1->v3->f1 = 2; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	fe1[0] = eed->v1->f1; | 
					
						
							|  |  |  | 	fe1[1] = eed->v2->f1; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	f2->v1->f1 = 0; | 
					
						
							|  |  |  | 	f2->v2->f1 = 1; | 
					
						
							|  |  |  | 	f2->v3->f1 = 2; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	fe2[0] = eed->v1->f1; | 
					
						
							|  |  |  | 	fe2[1] = eed->v2->f1; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*compare faceedges for each face attribute. Additional per face attributes can be added later*/ | 
					
						
							|  |  |  | 	/*do UVs*/ | 
					
						
							|  |  |  | 	if(flag & B_JOINTRIA_UV){ | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if(tf1 == NULL || tf2 == NULL) attrok |= B_JOINTRIA_UV; | 
					
						
							|  |  |  | 		else if(tf1->tpage != tf2->tpage); /*do nothing*/ | 
					
						
							|  |  |  | 		else{ | 
					
						
							|  |  |  | 			for(i = 0; i < 2; i++){ | 
					
						
							|  |  |  | 				if(tf1->uv[fe1[i]][0] + T2QUV_LIMIT > tf2->uv[fe2[i]][0] && tf1->uv[fe1[i]][0] - T2QUV_LIMIT < tf2->uv[fe2[i]][0] && | 
					
						
							|  |  |  | 					tf1->uv[fe1[i]][1] + T2QUV_LIMIT > tf2->uv[fe2[i]][1] && tf1->uv[fe1[i]][1] - T2QUV_LIMIT < tf2->uv[fe2[i]][1]) attrok |= B_JOINTRIA_UV; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*do VCOLs*/ | 
					
						
							|  |  |  | 	if(flag & B_JOINTRIA_VCOL){ | 
					
						
							|  |  |  | 		if(!col1 || !col2) attrok |= B_JOINTRIA_VCOL; | 
					
						
							|  |  |  | 		else{ | 
					
						
							|  |  |  | 			char *f1vcol, *f2vcol; | 
					
						
							|  |  |  | 			for(i = 0; i < 2; i++){ | 
					
						
							|  |  |  | 				f1vcol = (char *)&(col1[fe1[i]]); | 
					
						
							|  |  |  | 				f2vcol = (char *)&(col2[fe2[i]]); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 				/*compare f1vcol with f2vcol*/ | 
					
						
							|  |  |  | 				if(	f1vcol[1] + T2QCOL_LIMIT > f2vcol[1] && f1vcol[1] - T2QCOL_LIMIT < f2vcol[1] && | 
					
						
							|  |  |  | 					f1vcol[2] + T2QCOL_LIMIT > f2vcol[2] && f1vcol[2] - T2QCOL_LIMIT < f2vcol[2] && | 
					
						
							|  |  |  | 					f1vcol[3] + T2QCOL_LIMIT > f2vcol[3] && f1vcol[3] - T2QCOL_LIMIT < f2vcol[3]) attrok |= B_JOINTRIA_VCOL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if( ((attrok & B_JOINTRIA_UV) == (flag & B_JOINTRIA_UV)) && ((attrok & B_JOINTRIA_VCOL) == (flag & B_JOINTRIA_VCOL)) ) return 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | }	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | static int fplcmp(const void *v1, const void *v2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const EditEdge *e1= *((EditEdge**)v1), *e2=*((EditEdge**)v2); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if( e1->crease > e2->crease) return 1; | 
					
						
							|  |  |  | 	else if( e1->crease < e2->crease) return -1; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*Bitflags for edges.*/ | 
					
						
							|  |  |  | #define T2QDELETE	1
 | 
					
						
							|  |  |  | #define T2QCOMPLEX	2
 | 
					
						
							|  |  |  | #define T2QJOIN		4
 | 
					
						
							|  |  |  | void join_triangles(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *v1, *v2, *v3, *v4, *eve; | 
					
						
							|  |  |  | 	EditEdge *eed, **edsortblock = NULL, **edb = NULL; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	EVPTuple *efaar = NULL; | 
					
						
							|  |  |  | 	EVPtr *efaa = NULL; | 
					
						
							|  |  |  | 	float *creases = NULL; | 
					
						
							|  |  |  | 	float measure; /*Used to set tolerance*/ | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 	float limit = 0.0f; // XXX scene->toolsettings->jointrilimit;
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	int i, ok, totedge=0, totseledge=0, complexedges, vindex[4]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*if we take a long time on very dense meshes we want waitcursor to display*/ | 
					
						
							|  |  |  | 	waitcursor(1); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	totseledge = count_selected_edges(em->edges.first); | 
					
						
							|  |  |  | 	if(totseledge==0) return; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*abusing crease value to store weights for edge pairs. Nasty*/ | 
					
						
							|  |  |  | 	for(eed=em->edges.first; eed; eed=eed->next) totedge++; | 
					
						
							|  |  |  | 	if(totedge) creases = MEM_callocN(sizeof(float) * totedge, "Join Triangles Crease Array");  | 
					
						
							|  |  |  | 	for(eed=em->edges.first, i = 0; eed; eed=eed->next, i++){ | 
					
						
							|  |  |  | 		creases[i] = eed->crease;  | 
					
						
							|  |  |  | 		eed->crease = 0.0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*clear temp flags*/ | 
					
						
							|  |  |  | 	for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = eve->f2 = 0; | 
					
						
							|  |  |  | 	for(eed=em->edges.first; eed; eed=eed->next) eed->f2 = eed->f1 = 0; | 
					
						
							|  |  |  | 	for(efa=em->faces.first; efa; efa=efa->next) efa->f1 = efa->tmp.l = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*For every selected 2 manifold edge, create pointers to its two faces.*/ | 
					
						
							|  |  |  | 	efaar= (EVPTuple *) MEM_callocN(totseledge * sizeof(EVPTuple), "Tri2Quad"); | 
					
						
							|  |  |  | 	ok = collect_quadedges(efaar, em->edges.first, em->faces.first); | 
					
						
							|  |  |  | 	complexedges = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(ok){ | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/*clear tmp.l flag and store number of faces that are selected and coincident to current face here.*/   | 
					
						
							|  |  |  | 		for(eed=em->edges.first; eed; eed=eed->next){ | 
					
						
							|  |  |  | 			/* eed->f2 is 2 only if this edge is part of exactly two
 | 
					
						
							|  |  |  | 			   triangles, and both are selected, and it has EVPTuple assigned */ | 
					
						
							|  |  |  | 			if(eed->f2 == 2){ | 
					
						
							|  |  |  | 				efaa= (EVPtr *) eed->tmp.p; | 
					
						
							|  |  |  | 				efaa[0]->tmp.l++; | 
					
						
							|  |  |  | 				efaa[1]->tmp.l++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for(eed=em->edges.first; eed; eed=eed->next){ | 
					
						
							|  |  |  | 			if(eed->f2 == 2){ | 
					
						
							|  |  |  | 				efaa= (EVPtr *) eed->tmp.p; | 
					
						
							|  |  |  | 				v1 = v2 = v3 = v4 = NULL; | 
					
						
							|  |  |  | 				givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex); | 
					
						
							|  |  |  | 				if(v1 && v2 && v3 && v4){ | 
					
						
							|  |  |  | 					/*test if simple island first. This mimics 2.42 behaviour and the tests are less restrictive.*/ | 
					
						
							|  |  |  | 					if(efaa[0]->tmp.l == 1 && efaa[1]->tmp.l == 1){ | 
					
						
							| 
									
										
										
										
											2009-04-20 15:06:46 +00:00
										 |  |  | 						eed->f1 |= T2QJOIN; | 
					
						
							|  |  |  | 						efaa[0]->f1 = 1; //mark for join
 | 
					
						
							|  |  |  | 						efaa[1]->f1 = 1; //mark for join
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					else{  | 
					
						
							|  |  |  | 						 | 
					
						
							|  |  |  | 						/*	The face pair is part of a 'complex' island, so the rules for dealing with it are more involved.
 | 
					
						
							|  |  |  | 							Depending on what options the user has chosen, this face pair can be 'thrown out' based upon the following criteria: | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 							1: the two faces do not share the same material | 
					
						
							|  |  |  | 							2: the edge joining the two faces is marked as sharp. | 
					
						
							|  |  |  | 							3: the two faces UV's do not make a good match | 
					
						
							|  |  |  | 							4: the two faces Vertex colors do not make a good match | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 							If the face pair passes all the applicable tests, it is then given a 'weight' with the measure_facepair() function. | 
					
						
							|  |  |  | 							This measures things like concavity, colinearity ect. If this weight is below the threshold set by the user | 
					
						
							|  |  |  | 							the edge joining them is marked as being 'complex' and will be compared against other possible pairs which contain one of the | 
					
						
							|  |  |  | 							same faces in the current pair later. | 
					
						
							|  |  |  | 						 | 
					
						
							|  |  |  | 							This technique is based upon an algorithm that Campbell Barton developed for his Tri2Quad script that was previously part of | 
					
						
							|  |  |  | 							the python scripts bundled with Blender releases. | 
					
						
							|  |  |  | 						*/ | 
					
						
							|  |  |  | 						 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | // XXX						if(scene->toolsettings->editbutflag & B_JOINTRIA_SHARP && eed->sharp); /*do nothing*/
 | 
					
						
							|  |  |  | //						else if(scene->toolsettings->editbutflag & B_JOINTRIA_MAT && efaa[0]->mat_nr != efaa[1]->mat_nr); /*do nothing*/
 | 
					
						
							|  |  |  | //						else if(((scene->toolsettings->editbutflag & B_JOINTRIA_UV) || (scene->toolsettings->editbutflag & B_JOINTRIA_VCOL)) &&
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 						compareFaceAttribs(em, efaa[0], efaa[1], eed); // XXX == 0); /*do nothing*/
 | 
					
						
							|  |  |  | //						else{	
 | 
					
						
							|  |  |  | 							measure = measure_facepair(v1, v2, v3, v4, limit); | 
					
						
							|  |  |  | 							if(measure < limit){ | 
					
						
							|  |  |  | 								complexedges++; | 
					
						
							|  |  |  | 								eed->f1 |= T2QCOMPLEX; | 
					
						
							|  |  |  | 								eed->crease = measure; /*we dont mark edges for join yet*/ | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | //						}
 | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/*Quicksort the complex edges according to their weighting*/ | 
					
						
							|  |  |  | 		if(complexedges){ | 
					
						
							|  |  |  | 			edsortblock = edb = MEM_callocN(sizeof(EditEdge*) * complexedges, "Face Pairs quicksort Array"); | 
					
						
							|  |  |  | 			for(eed = em->edges.first; eed; eed=eed->next){ | 
					
						
							|  |  |  | 				if(eed->f1 & T2QCOMPLEX){ | 
					
						
							|  |  |  | 					*edb = eed; | 
					
						
							|  |  |  | 					edb++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			qsort(edsortblock, complexedges, sizeof(EditEdge*), fplcmp); | 
					
						
							|  |  |  | 			/*now go through and mark the edges who get the highest weighting*/ | 
					
						
							|  |  |  | 			for(edb=edsortblock, i=0; i < complexedges; edb++, i++){  | 
					
						
							|  |  |  | 				efaa = (EVPtr *)((*edb)->tmp.p); /*suspect!*/ | 
					
						
							|  |  |  | 				if( !efaa[0]->f1 && !efaa[1]->f1){ | 
					
						
							|  |  |  | 					efaa[0]->f1 = 1; //mark for join
 | 
					
						
							|  |  |  | 					efaa[1]->f1 = 1; //mark for join
 | 
					
						
							|  |  |  | 					(*edb)->f1 |= T2QJOIN; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/*finally go through all edges marked for join (simple and complex) and create new faces*/  | 
					
						
							|  |  |  | 		for(eed=em->edges.first; eed; eed=eed->next){ | 
					
						
							|  |  |  | 			if(eed->f1 & T2QJOIN){ | 
					
						
							|  |  |  | 				efaa= (EVPtr *)eed->tmp.p; | 
					
						
							|  |  |  | 				v1 = v2 = v3 = v4 = NULL; | 
					
						
							|  |  |  | 				givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex); | 
					
						
							|  |  |  | 				if((v1 && v2 && v3 && v4) && (exist_face(em, v1, v2, v3, v4)==0)){ /*exist_face is very slow! Needs to be adressed.*/ | 
					
						
							|  |  |  | 					/*flag for delete*/ | 
					
						
							|  |  |  | 					eed->f1 |= T2QDELETE; | 
					
						
							|  |  |  | 					/*create new quad and select*/ | 
					
						
							|  |  |  | 					efa = EM_face_from_faces(em, efaa[0], efaa[1], vindex[0], vindex[1], 4+vindex[2], 4+vindex[3]); | 
					
						
							|  |  |  | 					EM_select_face(efa,1); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else{ | 
					
						
							|  |  |  | 						efaa[0]->f1 = 0; | 
					
						
							|  |  |  | 						efaa[1]->f1 = 0; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*free data and cleanup*/ | 
					
						
							|  |  |  | 	if(creases){ | 
					
						
							|  |  |  | 		for(eed=em->edges.first, i = 0; eed; eed=eed->next, i++) eed->crease = creases[i];  | 
					
						
							|  |  |  | 		MEM_freeN(creases); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for(eed=em->edges.first; eed; eed=eed->next){ | 
					
						
							|  |  |  | 		if(eed->f1 & T2QDELETE) eed->f1 = 1; | 
					
						
							|  |  |  | 		else eed->f1 = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	free_tagged_edges_faces(em, em->edges.first, em->faces.first); | 
					
						
							|  |  |  | 	if(efaar) MEM_freeN(efaar); | 
					
						
							|  |  |  | 	if(edsortblock) MEM_freeN(edsortblock); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	EM_selectmode_flush(em); | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /* ******************** END TRIANGLE TO QUAD ************************************* */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define FACE_MARKCLEAR(f) (f->f1 = 1)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* quick hack, basically a copy of beauty_fill */ | 
					
						
							|  |  |  | void edge_flip(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *v1, *v2, *v3, *v4; | 
					
						
							|  |  |  | 	EditEdge *eed, *nexted; | 
					
						
							|  |  |  | 	EditFace *efa, *w; | 
					
						
							|  |  |  | 	//void **efaar, **efaa;
 | 
					
						
							|  |  |  | 	EVPTuple *efaar; | 
					
						
							|  |  |  | 	EVPtr *efaa; | 
					
						
							|  |  |  | 	int totedge, ok, vindex[4]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* - all selected edges with two faces
 | 
					
						
							|  |  |  | 	 * - find the faces: store them in edges (using datablock) | 
					
						
							|  |  |  | 	 * - per edge: - test convex | 
					
						
							|  |  |  | 	 *			   - test edge: flip? | 
					
						
							|  |  |  | 						- if true: remedge,  addedge, all edges at the edge get new face pointers | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	EM_selectmode_flush(em);	// makes sure in selectmode 'face' the edges of selected faces are selected too 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	totedge = count_selected_edges(em->edges.first); | 
					
						
							|  |  |  | 	if(totedge==0) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* temporary array for : edge -> face[1], face[2] */ | 
					
						
							|  |  |  | 	efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "edgeflip"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ok = collect_quadedges(efaar, em->edges.first, em->faces.first); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	eed= em->edges.first; | 
					
						
							|  |  |  | 	while(eed) { | 
					
						
							|  |  |  | 		nexted= eed->next; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if(eed->f2==2) {  /* points to 2 faces */ | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			efaa= (EVPtr *) eed->tmp.p; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			/* don't do it if flagged */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			ok= 1; | 
					
						
							|  |  |  | 			efa= efaa[0]; | 
					
						
							|  |  |  | 			if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0; | 
					
						
							|  |  |  | 			efa= efaa[1]; | 
					
						
							|  |  |  | 			if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if(ok) { | 
					
						
							|  |  |  | 				/* test convex */ | 
					
						
							|  |  |  | 				givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  | 		4-----3		4-----3 | 
					
						
							|  |  |  | 		|\	|		|	/| | 
					
						
							|  |  |  | 		| \ 1 |		| 1 / | | 
					
						
							|  |  |  | 		|  \  |  ->	|  /  |	 | 
					
						
							|  |  |  | 		| 0 \ |		| / 0 |  | 
					
						
							|  |  |  | 		|	\|		|/	| | 
					
						
							|  |  |  | 		1-----2		1-----2 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 				/* make new faces */ | 
					
						
							|  |  |  | 				if (v1 && v2 && v3) { | 
					
						
							|  |  |  | 					if( convex(v1->co, v2->co, v3->co, v4->co) ) { | 
					
						
							|  |  |  | 						if(exist_face(em, v1, v2, v3, v4)==0) { | 
					
						
							|  |  |  | 							/* outch this may break seams */  | 
					
						
							|  |  |  | 							w= EM_face_from_faces(em, efaa[0], efaa[1], vindex[0], | 
					
						
							|  |  |  | 								vindex[1], 4+vindex[2], -1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							EM_select_face(w, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							/* outch this may break seams */ | 
					
						
							|  |  |  | 							w= EM_face_from_faces(em, efaa[0], efaa[1], vindex[0], | 
					
						
							|  |  |  | 								4+vindex[2], 4+vindex[3], -1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							EM_select_face(w, 1); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						/* tag as to-be-removed */ | 
					
						
							|  |  |  | 						FACE_MARKCLEAR(efaa[1]); | 
					
						
							|  |  |  | 						FACE_MARKCLEAR(efaa[0]); | 
					
						
							|  |  |  | 						eed->f1 = 1;  | 
					
						
							|  |  |  | 						 | 
					
						
							|  |  |  | 					} /* endif test convex */ | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eed= nexted; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* clear tagged edges and faces: */ | 
					
						
							|  |  |  | 	free_tagged_edges_faces(em, em->edges.first, em->faces.first); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	MEM_freeN(efaar); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | static void edge_rotate(EditMesh *em, wmOperator *op, EditEdge *eed,int dir) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditVert **verts[2]; | 
					
						
							|  |  |  | 	EditFace *face[2], *efa, *newFace[2]; | 
					
						
							|  |  |  | 	EditEdge **edges[2], **hiddenedges, *srchedge; | 
					
						
							|  |  |  | 	int facecount, p1, p2, p3, p4, fac1, fac2, i, j; | 
					
						
							|  |  |  | 	int numhidden, numshared, p[2][4]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* check to make sure that the edge is only part of 2 faces */ | 
					
						
							|  |  |  | 	facecount = 0; | 
					
						
							|  |  |  | 	for(efa = em->faces.first;efa;efa = efa->next) { | 
					
						
							|  |  |  | 		if((efa->e1 == eed || efa->e2 == eed) || (efa->e3 == eed || efa->e4 == eed)) { | 
					
						
							|  |  |  | 			if(facecount >= 2) { | 
					
						
							|  |  |  | 				/* more than two faces with this edge */ | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				face[facecount] = efa; | 
					
						
							|  |  |  | 				facecount++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |   | 
					
						
							|  |  |  | 	if(facecount < 2) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* how many edges does each face have */ | 
					
						
							|  |  |  |  	if(face[0]->e4) fac1= 4; | 
					
						
							|  |  |  | 	else fac1= 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(face[1]->e4) fac2= 4; | 
					
						
							|  |  |  | 	else fac2= 3; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* make a handy array for verts and edges */ | 
					
						
							|  |  |  | 	verts[0]= &face[0]->v1; | 
					
						
							|  |  |  | 	edges[0]= &face[0]->e1; | 
					
						
							|  |  |  | 	verts[1]= &face[1]->v1; | 
					
						
							|  |  |  | 	edges[1]= &face[1]->e1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* we don't want to rotate edges between faces that share more than one edge */ | 
					
						
							|  |  |  | 	numshared= 0; | 
					
						
							|  |  |  | 	for(i=0; i<fac1; i++) | 
					
						
							|  |  |  | 		for(j=0; j<fac2; j++) | 
					
						
							|  |  |  | 			if (edges[0][i] == edges[1][j]) | 
					
						
							|  |  |  | 				numshared++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(numshared > 1) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* we want to construct an array of vertex indicis in both faces, starting at
 | 
					
						
							|  |  |  | 	   the last vertex of the edge being rotated. | 
					
						
							|  |  |  | 	   - first we find the two vertices that lie on the rotating edge | 
					
						
							|  |  |  | 	   - then we make sure they are ordered according to the face vertex order | 
					
						
							|  |  |  | 	   - and then we construct the array */ | 
					
						
							|  |  |  | 	p1= p2= p3= p4= 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(i=0; i<4; i++) { | 
					
						
							|  |  |  | 		if(eed->v1 == verts[0][i]) p1 = i; | 
					
						
							|  |  |  | 		if(eed->v2 == verts[0][i]) p2 = i; | 
					
						
							|  |  |  | 		if(eed->v1 == verts[1][i]) p3 = i; | 
					
						
							|  |  |  | 		if(eed->v2 == verts[1][i]) p4 = i; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if((p1+1)%fac1 == p2) | 
					
						
							|  |  |  | 		SWAP(int, p1, p2); | 
					
						
							|  |  |  | 	if((p3+1)%fac2 == p4) | 
					
						
							|  |  |  | 		SWAP(int, p3, p4); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for (i = 0; i < 4; i++) { | 
					
						
							|  |  |  | 		p[0][i]= (p1 + i)%fac1; | 
					
						
							|  |  |  | 		p[1][i]= (p3 + i)%fac2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* create an Array of the Edges who have h set prior to rotate */ | 
					
						
							|  |  |  | 	numhidden = 0; | 
					
						
							|  |  |  | 	for(srchedge = em->edges.first;srchedge;srchedge = srchedge->next) | 
					
						
							|  |  |  | 		if(srchedge->h && ((srchedge->v1->f & SELECT) || (srchedge->v2->f & SELECT))) | 
					
						
							|  |  |  | 			numhidden++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hiddenedges = MEM_mallocN(sizeof(EditVert*)*numhidden+1, "RotateEdgeHiddenVerts"); | 
					
						
							|  |  |  | 	if(!hiddenedges) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  |         BKE_report(op->reports, RPT_ERROR, "Memory allocation failed"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  |         return;    | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     numhidden = 0; | 
					
						
							|  |  |  | 	for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next) | 
					
						
							|  |  |  | 		if(srchedge->h && (srchedge->v1->f & SELECT || srchedge->v2->f & SELECT)) | 
					
						
							|  |  |  | 			hiddenedges[numhidden++] = srchedge; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* create the 2 new faces */ | 
					
						
							|  |  |  | 	if(fac1 == 3 && fac2 == 3) { | 
					
						
							|  |  |  | 		/* no need of reverse setup */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1); | 
					
						
							|  |  |  | 		newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if(fac1 == 4 && fac2 == 3) { | 
					
						
							|  |  |  | 		if(dir == 1) { | 
					
						
							|  |  |  | 			newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]); | 
					
						
							|  |  |  | 			newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1); | 
					
						
							|  |  |  | 		} else if (dir == 2) { | 
					
						
							|  |  |  | 			newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][2], 4+p[1][1], p[0][0], p[0][1]); | 
					
						
							|  |  |  | 			newFace[1]= EM_face_from_faces(em, face[1], face[0], 4+p[0][2], p[1][0], p[1][1], -1); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			verts[0][p[0][2]]->f |= SELECT; | 
					
						
							|  |  |  | 			verts[1][p[1][1]]->f |= SELECT;		 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if(fac1 == 3 && fac2 == 4) { | 
					
						
							|  |  |  | 		if(dir == 1) { | 
					
						
							|  |  |  | 			newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1); | 
					
						
							|  |  |  | 			newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]); | 
					
						
							|  |  |  | 		} else if (dir == 2) { | 
					
						
							|  |  |  | 			newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][0], p[0][1], 4+p[1][2], -1); | 
					
						
							|  |  |  | 			newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], 4+p[0][1], 4+p[0][2]); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			verts[0][p[0][1]]->f |= SELECT; | 
					
						
							|  |  |  | 			verts[1][p[1][2]]->f |= SELECT;	 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if(fac1 == 4 && fac2 == 4) { | 
					
						
							|  |  |  | 		if(dir == 1) { | 
					
						
							|  |  |  | 			newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]); | 
					
						
							|  |  |  | 			newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]); | 
					
						
							|  |  |  | 		} else if (dir == 2) { | 
					
						
							|  |  |  | 			newFace[0]= EM_face_from_faces(em, face[0], face[1], p[0][2], p[0][3], 4+p[1][1], 4+p[1][2]); | 
					
						
							|  |  |  | 			newFace[1]= EM_face_from_faces(em, face[1], face[0], p[1][2], p[1][3], 4+p[0][1], 4+p[0][2]); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			verts[0][p[0][2]]->f |= SELECT; | 
					
						
							|  |  |  | 			verts[1][p[1][2]]->f |= SELECT;	 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}		 | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return; /* This should never happen */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(dir == 1 || (fac1 == 3 && fac2 == 3)) { | 
					
						
							|  |  |  | 		verts[0][p[0][1]]->f |= SELECT; | 
					
						
							|  |  |  | 		verts[1][p[1][1]]->f |= SELECT; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* copy old edge's flags to new center edge*/ | 
					
						
							|  |  |  | 	for(srchedge=em->edges.first;srchedge;srchedge=srchedge->next) { | 
					
						
							|  |  |  | 		if((srchedge->v1->f & SELECT) && (srchedge->v2->f & SELECT)) { | 
					
						
							|  |  |  | 			srchedge->f = eed->f; | 
					
						
							|  |  |  | 			srchedge->h = eed->h; | 
					
						
							|  |  |  | 			srchedge->dir = eed->dir; | 
					
						
							|  |  |  | 			srchedge->seam = eed->seam; | 
					
						
							|  |  |  | 			srchedge->crease = eed->crease; | 
					
						
							|  |  |  | 			srchedge->bweight = eed->bweight; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* resetting hidden flag */ | 
					
						
							|  |  |  | 	for(numhidden--; numhidden>=0; numhidden--) | 
					
						
							|  |  |  | 		hiddenedges[numhidden]->h= 1; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* check for orhphan edges */ | 
					
						
							|  |  |  | 	for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next) | 
					
						
							|  |  |  | 		srchedge->f1= -1;    | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* cleanup */ | 
					
						
							|  |  |  | 	MEM_freeN(hiddenedges); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* get rid of the old edge and faces*/ | 
					
						
							|  |  |  | 	remedge(em, eed); | 
					
						
							|  |  |  | 	free_editedge(em, eed);	 | 
					
						
							|  |  |  | 	BLI_remlink(&em->faces, face[0]); | 
					
						
							|  |  |  | 	free_editface(em, face[0]);	 | 
					
						
							|  |  |  | 	BLI_remlink(&em->faces, face[1]); | 
					
						
							|  |  |  | 	free_editface(em, face[1]);		 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | // XXX ton please check
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | /* only accepts 1 selected edge, or 2 selected faces */ | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | static int edge_rotate_selected(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 	int dir = RNA_int_get(op->ptr,"dir"); // dir == 2 when clockwise and ==1 for counter CW.
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	short edgeCount = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*clear new flag for new edges, count selected edges */ | 
					
						
							|  |  |  | 	for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 		eed->f1= 0; | 
					
						
							|  |  |  | 		eed->f2 &= ~2; | 
					
						
							|  |  |  | 		if(eed->f & SELECT) edgeCount++;	 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(edgeCount>1) { | 
					
						
							|  |  |  | 		/* more selected edges, check faces */ | 
					
						
							|  |  |  | 		for(efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 			if(efa->f & SELECT) { | 
					
						
							|  |  |  | 				efa->e1->f1++; | 
					
						
							|  |  |  | 				efa->e2->f1++; | 
					
						
							|  |  |  | 				efa->e3->f1++; | 
					
						
							|  |  |  | 				if(efa->e4) efa->e4->f1++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		edgeCount= 0; | 
					
						
							|  |  |  | 		for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 			if(eed->f1==2) edgeCount++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(edgeCount==1) { | 
					
						
							|  |  |  | 			for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 				if(eed->f1==2) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 					edge_rotate(em, op, eed,dir); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 		else  | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 			BKE_report(op->reports, RPT_ERROR, "Select one edge or two adjacent faces"); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 			BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 			return OPERATOR_CANCELLED; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if(edgeCount==1) { | 
					
						
							|  |  |  | 		for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 			if(eed->f & SELECT) { | 
					
						
							|  |  |  | 				EM_select_edge(eed, 0); | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 				edge_rotate(em, op, eed,dir); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	else  | 
					
						
							|  |  |  | 	{	 | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "Select one edge or two adjacent faces"); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 		BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* flush selected vertices (again) to edges/faces */ | 
					
						
							|  |  |  | 	EM_select_flush(em); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-29 02:15:13 +00:00
										 |  |  | void MESH_OT_edge_rotate(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Rotate Selected Edge"; | 
					
						
							| 
									
										
										
										
											2009-03-29 02:15:13 +00:00
										 |  |  | 	ot->idname= "MESH_OT_edge_rotate"; | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= edge_rotate_selected; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* props */ | 
					
						
							|  |  |  | 	RNA_def_int(ot->srna, "dir", 1, 1, 2, "Direction", "Clockwise and Counter Clockwise", 1, 2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | /******************* BEVEL CODE STARTS HERE ********************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* XXX old bevel not ported yet */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void bevel_menu(EditMesh *em)  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BME_Mesh *bm; | 
					
						
							|  |  |  | 	BME_TransData_Head *td; | 
					
						
							|  |  |  | //	TransInfo *t;
 | 
					
						
							|  |  |  | 	int options, res, gbm_free = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //	t = BIF_GetTransInfo();
 | 
					
						
							|  |  |  | 	if (!G.editBMesh) { | 
					
						
							|  |  |  | 		G.editBMesh = MEM_callocN(sizeof(*(G.editBMesh)),"bevel_menu() G.editBMesh"); | 
					
						
							|  |  |  | 		gbm_free = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	G.editBMesh->options = BME_BEVEL_RUNNING | BME_BEVEL_SELECT; | 
					
						
							|  |  |  | 	G.editBMesh->res = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while(G.editBMesh->options & BME_BEVEL_RUNNING) { | 
					
						
							|  |  |  | 		options = G.editBMesh->options; | 
					
						
							|  |  |  | 		res = G.editBMesh->res; | 
					
						
							|  |  |  | 		bm = BME_editmesh_to_bmesh(em); | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | //		BIF_undo_push("Pre-Bevel");
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		free_editMesh(em); | 
					
						
							|  |  |  | 		BME_bevel(bm,0.1f,res,options,0,0,&td); | 
					
						
							| 
									
										
										
										
											2008-12-31 17:11:42 +00:00
										 |  |  | 		BME_bmesh_to_editmesh(bm, td, em); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		EM_selectmode_flush(em); | 
					
						
							|  |  |  | 		G.editBMesh->bm = bm; | 
					
						
							|  |  |  | 		G.editBMesh->td = td; | 
					
						
							|  |  |  | //		initTransform(TFM_BEVEL,CTX_BMESH);
 | 
					
						
							|  |  |  | //		Transform();
 | 
					
						
							|  |  |  | 		BME_free_transdata(td); | 
					
						
							|  |  |  | 		BME_free_mesh(bm); | 
					
						
							|  |  |  | //		if (t->state != TRANS_CONFIRM) {
 | 
					
						
							|  |  |  | //			BIF_undo();
 | 
					
						
							|  |  |  | //		}
 | 
					
						
							|  |  |  | 		if (options == G.editBMesh->options) { | 
					
						
							|  |  |  | 			G.editBMesh->options &= ~BME_BEVEL_RUNNING; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (gbm_free) { | 
					
						
							|  |  |  | 		MEM_freeN(G.editBMesh); | 
					
						
							|  |  |  | 		G.editBMesh = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* *********** END BEVEL *********/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* this utility function checks to see if 2 edit edges share a face,
 | 
					
						
							|  |  |  | returns 1 if they do | 
					
						
							|  |  |  | returns 0 if they do not, or if the function is passed the same edge 2 times | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | short sharesFace(EditMesh *em, EditEdge* e1, EditEdge* e2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *search=NULL; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	search = em->faces.first; | 
					
						
							|  |  |  | 	if (e1 == e2){ | 
					
						
							|  |  |  | 		return 0 ; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	while(search){ | 
					
						
							|  |  |  | 		if( | 
					
						
							|  |  |  | 		   ((search->e1 == e1 || search->e2 == e1) || (search->e3 == e1 || search->e4 == e1)) && | 
					
						
							|  |  |  | 		   ((search->e1 == e2 || search->e2 == e2) || (search->e3 == e2 || search->e4 == e2)) | 
					
						
							|  |  |  | 		   ) { | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		search = search->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct SlideUv { | 
					
						
							|  |  |  | 	float origuv[2]; | 
					
						
							|  |  |  | 	float *uv_up, *uv_down; | 
					
						
							|  |  |  | 	//float *fuv[4];
 | 
					
						
							|  |  |  | 	LinkNode *fuv_list; | 
					
						
							|  |  |  | } SlideUv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct SlideVert { | 
					
						
							|  |  |  | 	EditEdge *up,*down; | 
					
						
							|  |  |  | 	EditVert origvert; | 
					
						
							|  |  |  | } SlideVert; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | int EdgeSlide(EditMesh *em, wmOperator *op, short immediate, float imperc) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-20 18:36:27 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | /* XXX REFACTOR - #if 0'd for now, otherwise can't make 64bit windows builds on 64bit machine */ | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | useless: | 
					
						
							|  |  |  | 	goto useless // because it doesn't do anything right now
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-31 13:30:56 +00:00
										 |  |  | //	NumInput num; XXX
 | 
					
						
							|  |  |  | 	Mesh *me= NULL; // XXX
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL; | 
					
						
							|  |  |  | 	EditVert *ev, *nearest; | 
					
						
							|  |  |  | 	LinkNode *edgelist = NULL, *vertlist=NULL, *look; | 
					
						
							|  |  |  | 	GHash *vertgh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	SlideVert *tempsv; | 
					
						
							| 
									
										
										
										
											2009-05-18 16:42:34 +00:00
										 |  |  | 	float perc = 0, percp = 0,vertdist; // XXX, projectMat[4][4];
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	float shiftlabda= 0.0f,len = 0.0f; | 
					
						
							|  |  |  | 	int i = 0,j, numsel, numadded=0, timesthrough = 0, vertsel=0, prop=1, cancel = 0,flip=0; | 
					
						
							|  |  |  | 	int wasshift = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* UV correction vars */ | 
					
						
							|  |  |  | 	GHash **uvarray= NULL; | 
					
						
							|  |  |  | 	int  uvlay_tot= CustomData_number_of_layers(&em->fdata, CD_MTFACE); | 
					
						
							|  |  |  | 	int uvlay_idx; | 
					
						
							|  |  |  | 	SlideUv *slideuvs=NULL, *suv=NULL, *suv_last=NULL;	 | 
					
						
							|  |  |  | 	float uv_tmp[2]; | 
					
						
							|  |  |  | 	LinkNode *fuv_link; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	short event, draw=1; | 
					
						
							|  |  |  | 	short mval[2], mvalo[2]; | 
					
						
							|  |  |  | 	char str[128];  | 
					
						
							|  |  |  | 	float labda = 0.0f; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | //	initNumInput(&num);
 | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2009-05-18 16:42:34 +00:00
										 |  |  | //	view3d_get_object_project_mat(curarea, obedit, projectMat);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	mvalo[0] = -1; mvalo[1] = -1;  | 
					
						
							|  |  |  | 	numsel =0;   | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// Get number of selected edges and clear some flags
 | 
					
						
							|  |  |  | 	for(eed=em->edges.first;eed;eed=eed->next) { | 
					
						
							|  |  |  | 		eed->f1 = 0; | 
					
						
							|  |  |  | 		eed->f2 = 0;    | 
					
						
							|  |  |  | 		if(eed->f & SELECT) numsel++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(ev=em->verts.first;ev;ev=ev->next) { | 
					
						
							|  |  |  | 		ev->f1 = 0;    | 
					
						
							|  |  |  | 	}  | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	//Make sure each edge only has 2 faces
 | 
					
						
							|  |  |  | 	// make sure loop doesn't cross face
 | 
					
						
							|  |  |  | 	for(efa=em->faces.first;efa;efa=efa->next) { | 
					
						
							|  |  |  | 		int ct = 0; | 
					
						
							|  |  |  | 		if(efa->e1->f & SELECT) { | 
					
						
							|  |  |  | 			ct++; | 
					
						
							|  |  |  | 			efa->e1->f1++; | 
					
						
							|  |  |  | 			if(efa->e1->f1 > 2) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 				BKE_report(op->reports, RPT_ERROR, "3+ face edge"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				return 0;				  | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(efa->e2->f & SELECT) { | 
					
						
							|  |  |  | 			ct++; | 
					
						
							|  |  |  | 			efa->e2->f1++; | 
					
						
							|  |  |  | 			if(efa->e2->f1 > 2) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 				BKE_report(op->reports, RPT_ERROR, "3+ face edge"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				return 0;				  | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(efa->e3->f & SELECT) { | 
					
						
							|  |  |  | 			ct++; | 
					
						
							|  |  |  | 			efa->e3->f1++; | 
					
						
							|  |  |  | 			if(efa->e3->f1 > 2) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 				BKE_report(op->reports, RPT_ERROR, "3+ face edge"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				return 0;				  | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(efa->e4 && efa->e4->f & SELECT) { | 
					
						
							|  |  |  | 			ct++; | 
					
						
							|  |  |  | 			efa->e4->f1++; | 
					
						
							|  |  |  | 			if(efa->e4->f1 > 2) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 				BKE_report(op->reports, RPT_ERROR, "3+ face edge"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				return 0;				  | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}	 | 
					
						
							|  |  |  | 		// Make sure loop is not 2 edges of same face	
 | 
					
						
							|  |  |  | 		if(ct > 1) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		   BKE_report(op->reports, RPT_ERROR, "Loop crosses itself"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		   return 0;    | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}	    | 
					
						
							|  |  |  | 	// Get # of selected verts
 | 
					
						
							|  |  |  | 	for(ev=em->verts.first;ev;ev=ev->next) {  | 
					
						
							|  |  |  | 		if(ev->f & SELECT) vertsel++; | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 	    | 
					
						
							|  |  |  | 	// Test for multiple segments
 | 
					
						
							|  |  |  | 	if(vertsel > numsel+1) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "Please choose a single edge loop"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		return 0;		    | 
					
						
							|  |  |  | 	}   | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// Get the edgeloop in order - mark f1 with SELECT once added
 | 
					
						
							|  |  |  | 	for(eed=em->edges.first;eed;eed=eed->next) { | 
					
						
							|  |  |  | 		if((eed->f & SELECT) && !(eed->f1 & SELECT)) { | 
					
						
							|  |  |  | 			// If this is the first edge added, just put it in
 | 
					
						
							|  |  |  | 			if(!edgelist) { | 
					
						
							|  |  |  | 				BLI_linklist_prepend(&edgelist,eed); | 
					
						
							|  |  |  | 				numadded++; | 
					
						
							|  |  |  | 				first = eed; | 
					
						
							|  |  |  | 				last  = eed;  | 
					
						
							|  |  |  | 				eed->f1 = SELECT; | 
					
						
							|  |  |  | 			} else {   | 
					
						
							|  |  |  | 				if(editedge_getSharedVert(eed, last)) { | 
					
						
							|  |  |  | 					BLI_linklist_append(&edgelist,eed); | 
					
						
							|  |  |  | 					eed->f1 = SELECT; | 
					
						
							|  |  |  | 					numadded++; | 
					
						
							|  |  |  | 					last = eed;					   | 
					
						
							|  |  |  | 				}  else if(editedge_getSharedVert(eed, first)) { | 
					
						
							|  |  |  | 					BLI_linklist_prepend(&edgelist,eed); | 
					
						
							|  |  |  | 					eed->f1 = SELECT; | 
					
						
							|  |  |  | 					numadded++; | 
					
						
							|  |  |  | 					first = eed;					   | 
					
						
							|  |  |  | 				}    | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}    | 
					
						
							|  |  |  | 		if(eed->next == NULL && numadded != numsel) { | 
					
						
							|  |  |  | 			eed=em->edges.first;	 | 
					
						
							|  |  |  | 			timesthrough++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		// It looks like there was an unexpected case - Hopefully should not happen
 | 
					
						
							|  |  |  | 		if(timesthrough >= numsel*2) { | 
					
						
							|  |  |  | 			BLI_linklist_free(edgelist,NULL);  | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 			BKE_report(op->reports, RPT_ERROR, "Could not order loop"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			return 0;    | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// Put the verts in order in a linklist
 | 
					
						
							|  |  |  | 	look = edgelist; | 
					
						
							|  |  |  | 	while(look) { | 
					
						
							|  |  |  | 		eed = look->link; | 
					
						
							|  |  |  | 		if(!vertlist) { | 
					
						
							|  |  |  | 			if(look->next) { | 
					
						
							|  |  |  | 				temp = look->next->link; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				//This is the first entry takes care of extra vert
 | 
					
						
							|  |  |  | 				if(eed->v1 != temp->v1 && eed->v1 != temp->v2) { | 
					
						
							|  |  |  | 					BLI_linklist_append(&vertlist,eed->v1);  | 
					
						
							|  |  |  | 					eed->v1->f1 = 1;  | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					BLI_linklist_append(&vertlist,eed->v2);   | 
					
						
							|  |  |  | 					eed->v2->f1 = 1;  | 
					
						
							|  |  |  | 				}			  | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				//This is the case that we only have 1 edge
 | 
					
						
							|  |  |  | 				BLI_linklist_append(&vertlist,eed->v1);  | 
					
						
							|  |  |  | 				eed->v1->f1 = 1;					 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}		 | 
					
						
							|  |  |  | 		// for all the entries
 | 
					
						
							|  |  |  | 		if(eed->v1->f1 != 1) { | 
					
						
							|  |  |  | 			BLI_linklist_append(&vertlist,eed->v1);  | 
					
						
							|  |  |  | 			eed->v1->f1 = 1;		    | 
					
						
							|  |  |  | 		} else  if(eed->v2->f1 != 1) { | 
					
						
							|  |  |  | 			BLI_linklist_append(&vertlist,eed->v2);  | 
					
						
							|  |  |  | 			eed->v2->f1 = 1;					 | 
					
						
							|  |  |  | 		}  | 
					
						
							|  |  |  | 		look = look->next;    | 
					
						
							|  |  |  | 	}		  | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// populate the SlideVerts
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	vertgh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);  | 
					
						
							|  |  |  | 	look = vertlist;	   | 
					
						
							|  |  |  | 	while(look) { | 
					
						
							|  |  |  | 		i=0; | 
					
						
							|  |  |  | 		j=0; | 
					
						
							|  |  |  | 		ev = look->link; | 
					
						
							|  |  |  | 		tempsv = (struct SlideVert*)MEM_mallocN(sizeof(struct SlideVert),"SlideVert"); | 
					
						
							|  |  |  | 		tempsv->up = NULL; | 
					
						
							|  |  |  | 		tempsv->down = NULL; | 
					
						
							|  |  |  | 		tempsv->origvert.co[0] = ev->co[0]; | 
					
						
							|  |  |  | 		tempsv->origvert.co[1] = ev->co[1]; | 
					
						
							|  |  |  | 		tempsv->origvert.co[2] = ev->co[2]; | 
					
						
							|  |  |  | 		tempsv->origvert.no[0] = ev->no[0]; | 
					
						
							|  |  |  | 		tempsv->origvert.no[1] = ev->no[1]; | 
					
						
							|  |  |  | 		tempsv->origvert.no[2] = ev->no[2]; | 
					
						
							|  |  |  | 		// i is total edges that vert is on
 | 
					
						
							|  |  |  | 		// j is total selected edges that vert is on
 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for(eed=em->edges.first;eed;eed=eed->next) { | 
					
						
							|  |  |  | 			if(eed->v1 == ev || eed->v2 == ev) { | 
					
						
							|  |  |  | 				i++;	 | 
					
						
							|  |  |  | 				if(eed->f & SELECT) { | 
					
						
							|  |  |  | 					 j++;    | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}		 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// If the vert is in the middle of an edge loop, it touches 2 selected edges and 2 unselected edges
 | 
					
						
							|  |  |  | 		if(i == 4 && j == 2) { | 
					
						
							|  |  |  | 			for(eed=em->edges.first;eed;eed=eed->next) { | 
					
						
							|  |  |  | 				if(editedge_containsVert(eed, ev)) { | 
					
						
							|  |  |  | 					if(!(eed->f & SELECT)) { | 
					
						
							|  |  |  | 						 if(!tempsv->up) { | 
					
						
							|  |  |  | 							 tempsv->up = eed; | 
					
						
							|  |  |  | 						 } else if (!(tempsv->down)) { | 
					
						
							|  |  |  | 							 tempsv->down = eed;   | 
					
						
							|  |  |  | 						 } | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				}		 | 
					
						
							|  |  |  | 			}			 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// If it is on the end of the loop, it touches 1 selected and as least 2 more unselected
 | 
					
						
							|  |  |  | 		if(i >= 3 && j == 1) { | 
					
						
							|  |  |  | 			for(eed=em->edges.first;eed;eed=eed->next) { | 
					
						
							|  |  |  | 				if(editedge_containsVert(eed, ev) && eed->f & SELECT) { | 
					
						
							|  |  |  | 					for(efa = em->faces.first;efa;efa=efa->next) { | 
					
						
							|  |  |  | 						if(editface_containsEdge(efa, eed)) { | 
					
						
							|  |  |  | 							if(editedge_containsVert(efa->e1, ev) && efa->e1 != eed) { | 
					
						
							|  |  |  | 								 if(!tempsv->up) { | 
					
						
							|  |  |  | 									 tempsv->up = efa->e1; | 
					
						
							|  |  |  | 								 } else if (!(tempsv->down)) { | 
					
						
							|  |  |  | 									 tempsv->down = efa->e1;   | 
					
						
							|  |  |  | 								 }								    | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							if(editedge_containsVert(efa->e2, ev) && efa->e2 != eed) { | 
					
						
							|  |  |  | 								 if(!tempsv->up) { | 
					
						
							|  |  |  | 									 tempsv->up = efa->e2; | 
					
						
							|  |  |  | 								 } else if (!(tempsv->down)) { | 
					
						
							|  |  |  | 									 tempsv->down = efa->e2;   | 
					
						
							|  |  |  | 								 }								    | 
					
						
							|  |  |  | 							}							 | 
					
						
							|  |  |  | 							if(editedge_containsVert(efa->e3, ev) && efa->e3 != eed) { | 
					
						
							|  |  |  | 								 if(!tempsv->up) { | 
					
						
							|  |  |  | 									 tempsv->up = efa->e3; | 
					
						
							|  |  |  | 								 } else if (!(tempsv->down)) { | 
					
						
							|  |  |  | 									 tempsv->down = efa->e3;   | 
					
						
							|  |  |  | 								 }								    | 
					
						
							|  |  |  | 							}   | 
					
						
							|  |  |  | 							if(efa->e4) { | 
					
						
							|  |  |  | 								if(editedge_containsVert(efa->e4, ev) && efa->e4 != eed) { | 
					
						
							|  |  |  | 									 if(!tempsv->up) { | 
					
						
							|  |  |  | 										 tempsv->up = efa->e4; | 
					
						
							|  |  |  | 									 } else if (!(tempsv->down)) { | 
					
						
							|  |  |  | 										 tempsv->down = efa->e4;   | 
					
						
							|  |  |  | 									 }								    | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							}														   | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				}		 | 
					
						
							|  |  |  | 			}			 | 
					
						
							|  |  |  | 		}		 | 
					
						
							|  |  |  | 		if(i > 4 && j == 2) { | 
					
						
							|  |  |  | 			BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN); | 
					
						
							|  |  |  | 			BLI_linklist_free(vertlist,NULL);  | 
					
						
							|  |  |  | 			BLI_linklist_free(edgelist,NULL);  | 
					
						
							|  |  |  | 			return 0;    | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		BLI_ghash_insert(vertgh,ev,tempsv); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		look = look->next;    | 
					
						
							|  |  |  | 	}		   | 
					
						
							|  |  |  |     | 
					
						
							|  |  |  | 	// make sure the UPs nad DOWNs are 'faceloops'
 | 
					
						
							|  |  |  | 	// Also find the nearest slidevert to the cursor
 | 
					
						
							|  |  |  | // XXX	getmouseco_areawin(mval);
 | 
					
						
							|  |  |  | 	look = vertlist;	 | 
					
						
							|  |  |  | 	nearest = NULL; | 
					
						
							|  |  |  | 	vertdist = -1;   | 
					
						
							|  |  |  | 	while(look) {	 | 
					
						
							|  |  |  | 		tempsv  = BLI_ghash_lookup(vertgh,(EditVert*)look->link); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if(!tempsv->up || !tempsv->down) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 			BKE_report(op->reports, RPT_ERROR, "Missing rails"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN); | 
					
						
							|  |  |  | 			BLI_linklist_free(vertlist,NULL);  | 
					
						
							|  |  |  | 			BLI_linklist_free(edgelist,NULL);  | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-31 13:30:56 +00:00
										 |  |  | 		if(me->drawflag & ME_DRAW_EDGELEN) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			if(!(tempsv->up->f & SELECT)) { | 
					
						
							|  |  |  | 				tempsv->up->f |= SELECT; | 
					
						
							|  |  |  | 				tempsv->up->f2 |= 16; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				tempsv->up->f2 |= ~16; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(!(tempsv->down->f & SELECT)) { | 
					
						
							|  |  |  | 				tempsv->down->f |= SELECT; | 
					
						
							|  |  |  | 				tempsv->down->f2 |= 16; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				tempsv->down->f2 |= ~16; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(look->next != NULL) { | 
					
						
							|  |  |  | 			SlideVert *sv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			sv = BLI_ghash_lookup(vertgh,(EditVert*)look->next->link); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(sv) { | 
					
						
							|  |  |  | 				float tempdist, co[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if(!sharesFace(em, tempsv->up,sv->up)) { | 
					
						
							|  |  |  | 					EditEdge *swap; | 
					
						
							|  |  |  | 					swap = sv->up; | 
					
						
							|  |  |  | 					sv->up = sv->down; | 
					
						
							|  |  |  | 					sv->down = swap;  | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //				view3d_project_float(curarea, tempsv->origvert.co, co, projectMat);
 | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				tempdist = sqrt(pow(co[0] - mval[0],2)+pow(co[1]  - mval[1],2)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if(vertdist < 0) { | 
					
						
							|  |  |  | 					vertdist = tempdist; | 
					
						
							|  |  |  | 					nearest  = (EditVert*)look->link;    | 
					
						
							|  |  |  | 				} else if ( tempdist < vertdist ) { | 
					
						
							|  |  |  | 					vertdist = tempdist; | 
					
						
							|  |  |  | 					nearest  = (EditVert*)look->link;	 | 
					
						
							|  |  |  | 				}		 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}   		 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		look = look->next;    | 
					
						
							|  |  |  | 	}	    | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 	if (uvlay_tot) { // XXX && (scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		int maxnum = 0; | 
					
						
							|  |  |  | 		uvarray = MEM_callocN( uvlay_tot * sizeof(GHash *), "SlideUVs Array"); | 
					
						
							|  |  |  | 		suv_last = slideuvs = MEM_callocN( uvlay_tot * (numadded+1) * sizeof(SlideUv), "SlideUVs"); /* uvLayers * verts */ | 
					
						
							|  |  |  | 		suv = NULL; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) { | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			uvarray[uvlay_idx] = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);  | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			for(ev=em->verts.first;ev;ev=ev->next) { | 
					
						
							|  |  |  | 				ev->tmp.l = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			look = vertlist; | 
					
						
							|  |  |  | 			while(look) { | 
					
						
							|  |  |  | 				float *uv_new; | 
					
						
							|  |  |  | 				tempsv  = BLI_ghash_lookup(vertgh,(EditVert*)look->link); | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				ev = look->link; | 
					
						
							|  |  |  | 				suv = NULL; | 
					
						
							|  |  |  | 				for(efa = em->faces.first;efa;efa=efa->next) { | 
					
						
							|  |  |  | 					if (ev->tmp.l != -1) { /* test for self, in this case its invalid */ | 
					
						
							|  |  |  | 						int k=-1; /* face corner */ | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 						/* Is this vert in the faces corner? */ | 
					
						
							|  |  |  | 						if		(efa->v1==ev)				k=0; | 
					
						
							|  |  |  | 						else if	(efa->v2==ev)				k=1; | 
					
						
							|  |  |  | 						else if	(efa->v3==ev)				k=2; | 
					
						
							|  |  |  | 						else if	(efa->v4 && efa->v4==ev)	k=3; | 
					
						
							|  |  |  | 						 | 
					
						
							|  |  |  | 						if (k != -1) { | 
					
						
							|  |  |  | 							MTFace *tf = CustomData_em_get_n(&em->fdata, efa->data, CD_MTFACE, uvlay_idx); | 
					
						
							|  |  |  | 							EditVert *ev_up, *ev_down; | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 							uv_new = tf->uv[k]; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 							if (ev->tmp.l) { | 
					
						
							|  |  |  | 								if (fabs(suv->origuv[0]-uv_new[0]) > 0.0001 || fabs(suv->origuv[1]-uv_new[1])) { | 
					
						
							|  |  |  | 									ev->tmp.l = -1; /* Tag as invalid */ | 
					
						
							|  |  |  | 									BLI_linklist_free(suv->fuv_list,NULL); | 
					
						
							|  |  |  | 									suv->fuv_list = NULL; | 
					
						
							|  |  |  | 									BLI_ghash_remove(uvarray[uvlay_idx],ev, NULL, NULL); | 
					
						
							|  |  |  | 									suv = NULL; | 
					
						
							|  |  |  | 									break; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								ev->tmp.l = 1; | 
					
						
							|  |  |  | 								suv = suv_last; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								suv->fuv_list = NULL; | 
					
						
							|  |  |  | 								suv->uv_up = suv->uv_down = NULL; | 
					
						
							|  |  |  | 								suv->origuv[0] = uv_new[0]; | 
					
						
							|  |  |  | 								suv->origuv[1] = uv_new[1]; | 
					
						
							|  |  |  | 								 | 
					
						
							|  |  |  | 								BLI_linklist_prepend(&suv->fuv_list, uv_new); | 
					
						
							|  |  |  | 								BLI_ghash_insert(uvarray[uvlay_idx],ev,suv); | 
					
						
							|  |  |  | 								 | 
					
						
							|  |  |  | 								suv_last++; /* advance to next slide UV */ | 
					
						
							|  |  |  | 								maxnum++; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 							/* Now get the uvs along the up or down edge if we can */ | 
					
						
							|  |  |  | 							if (suv) { | 
					
						
							|  |  |  | 								if (!suv->uv_up) { | 
					
						
							|  |  |  | 									ev_up = editedge_getOtherVert(tempsv->up,ev); | 
					
						
							|  |  |  | 									if		(efa->v1==ev_up)				suv->uv_up = tf->uv[0]; | 
					
						
							|  |  |  | 									else if	(efa->v2==ev_up)				suv->uv_up = tf->uv[1]; | 
					
						
							|  |  |  | 									else if	(efa->v3==ev_up)				suv->uv_up = tf->uv[2]; | 
					
						
							|  |  |  | 									else if	(efa->v4 && efa->v4==ev_up)		suv->uv_up = tf->uv[3]; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 								if (!suv->uv_down) { /* if the first face was apart of the up edge, it cant be apart of the down edge */ | 
					
						
							|  |  |  | 									ev_down = editedge_getOtherVert(tempsv->down,ev); | 
					
						
							|  |  |  | 									if		(efa->v1==ev_down)				suv->uv_down = tf->uv[0]; | 
					
						
							|  |  |  | 									else if	(efa->v2==ev_down)				suv->uv_down = tf->uv[1]; | 
					
						
							|  |  |  | 									else if	(efa->v3==ev_down)				suv->uv_down = tf->uv[2]; | 
					
						
							|  |  |  | 									else if	(efa->v4 && efa->v4==ev_down)	suv->uv_down = tf->uv[3]; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 								/* Copy the pointers to the face UV's */ | 
					
						
							|  |  |  | 								BLI_linklist_prepend(&suv->fuv_list, uv_new); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				look = look->next; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} /* end uv layer loop */ | 
					
						
							|  |  |  | 	} /* end uvlay_tot */ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// we should have enough info now to slide
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	len = 0.0f;  | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	percp = -1; | 
					
						
							|  |  |  | 	while(draw) { | 
					
						
							|  |  |  | 		 /* For the % calculation */    | 
					
						
							|  |  |  | 		short mval[2];    | 
					
						
							|  |  |  | 		float rc[2]; | 
					
						
							|  |  |  | 		float v2[2], v3[2]; | 
					
						
							|  |  |  | 		EditVert *centerVert, *upVert, *downVert; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | // XXX		getmouseco_areawin(mval);  
 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if (!immediate && (mval[0] == mvalo[0] && mval[1] ==  mvalo[1])) { | 
					
						
							|  |  |  | 			PIL_sleep_ms(10); | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:46:20 +00:00
										 |  |  | 			char *p = str; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			int ctrl= 0, shift= 0; // XXX
 | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			mvalo[0] = mval[0]; | 
					
						
							|  |  |  | 			mvalo[1] = mval[1]; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			tempsv = BLI_ghash_lookup(vertgh,nearest); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			centerVert = editedge_getSharedVert(tempsv->up, tempsv->down); | 
					
						
							|  |  |  | 			upVert = editedge_getOtherVert(tempsv->up, centerVert); | 
					
						
							|  |  |  | 			downVert = editedge_getOtherVert(tempsv->down, centerVert); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //			view3d_project_float(curarea, upVert->co, v2, projectMat);
 | 
					
						
							|  |  |  | //			view3d_project_float(curarea, downVert->co, v3, projectMat);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* Determine the % on which the loop should be cut */    | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rc[0]= v3[0]-v2[0];    | 
					
						
							|  |  |  | 			rc[1]= v3[1]-v2[1];    | 
					
						
							|  |  |  | 			len= rc[0]*rc[0]+ rc[1]*rc[1]; | 
					
						
							|  |  |  | 			if (len==0) {len = 0.0001;} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (shift) { | 
					
						
							|  |  |  | 				wasshift = 0; | 
					
						
							|  |  |  | 				labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len;    | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				if (wasshift==0) { | 
					
						
							|  |  |  | 					wasshift = 1; | 
					
						
							|  |  |  | 					shiftlabda = labda; | 
					
						
							|  |  |  | 				}							 | 
					
						
							|  |  |  | 				labda= ( rc[0]*((mval[0]-v2[0])) + rc[1]*((mval[1]-v2[1])) )/len / 10.0 + shiftlabda;   			 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(labda<=0.0) labda=0.0;    | 
					
						
							|  |  |  | 			else if(labda>=1.0)labda=1.0;    | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			perc=((1-labda)*2)-1;		   | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if(shift == 0 && ctrl==0) { | 
					
						
							|  |  |  | 				perc *= 100; | 
					
						
							|  |  |  | 				perc = floor(perc); | 
					
						
							|  |  |  | 				perc /= 100; | 
					
						
							|  |  |  | 			} else if (ctrl) { | 
					
						
							|  |  |  | 				perc *= 10; | 
					
						
							|  |  |  | 				perc = floor(perc); | 
					
						
							|  |  |  | 				perc /= 10;				    | 
					
						
							|  |  |  | 			}			 | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if(prop == 0) { | 
					
						
							|  |  |  | 				len = VecLenf(upVert->co,downVert->co)*((perc+1)/2); | 
					
						
							|  |  |  | 				if(flip == 1) { | 
					
						
							|  |  |  | 					len = VecLenf(upVert->co,downVert->co) - len; | 
					
						
							|  |  |  | 				}  | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if (0) // XXX hasNumInput(&num))
 | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | // XXX				applyNumInput(&num, &perc);
 | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				if (prop) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					perc = MIN2(perc, 1); | 
					
						
							|  |  |  | 					perc = MAX2(perc, -1); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					len = MIN2(perc, VecLenf(upVert->co,downVert->co)); | 
					
						
							|  |  |  | 					len = MAX2(len, 0); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			//Adjust Edgeloop
 | 
					
						
							|  |  |  | 			if(immediate) { | 
					
						
							|  |  |  | 				perc = imperc;    | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			percp = perc; | 
					
						
							|  |  |  | 			if(prop) { | 
					
						
							|  |  |  | 				look = vertlist;	   | 
					
						
							|  |  |  | 				while(look) {  | 
					
						
							|  |  |  | 					EditVert *tempev; | 
					
						
							|  |  |  | 					ev = look->link; | 
					
						
							|  |  |  | 					tempsv = BLI_ghash_lookup(vertgh,ev); | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 					tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev); | 
					
						
							|  |  |  | 					VecLerpf(ev->co, tempsv->origvert.co, tempev->co, fabs(perc)); | 
					
						
							|  |  |  | 					 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 					if (0) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 						for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) { | 
					
						
							|  |  |  | 							suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev ); | 
					
						
							|  |  |  | 							if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) { | 
					
						
							|  |  |  | 								Vec2Lerpf(uv_tmp, suv->origuv,  (perc>=0)?suv->uv_up:suv->uv_down, fabs(perc)); | 
					
						
							|  |  |  | 								fuv_link = suv->fuv_list; | 
					
						
							|  |  |  | 								while (fuv_link) { | 
					
						
							|  |  |  | 									VECCOPY2D(((float *)fuv_link->link), uv_tmp); | 
					
						
							|  |  |  | 									fuv_link = fuv_link->next; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 					look = look->next;	  | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				//Non prop code  
 | 
					
						
							|  |  |  | 				look = vertlist;	   | 
					
						
							|  |  |  | 				while(look) {  | 
					
						
							|  |  |  | 					float newlen; | 
					
						
							|  |  |  | 					ev = look->link; | 
					
						
							|  |  |  | 					tempsv = BLI_ghash_lookup(vertgh,ev); | 
					
						
							|  |  |  | 					newlen = (len / VecLenf(editedge_getOtherVert(tempsv->up,ev)->co,editedge_getOtherVert(tempsv->down,ev)->co)); | 
					
						
							|  |  |  | 					if(newlen > 1.0) {newlen = 1.0;} | 
					
						
							|  |  |  | 					if(newlen < 0.0) {newlen = 0.0;} | 
					
						
							|  |  |  | 					if(flip == 0) { | 
					
						
							|  |  |  | 						VecLerpf(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen));									 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 						if (0) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 							/* dont do anything if no UVs */ | 
					
						
							|  |  |  | 							for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) { | 
					
						
							|  |  |  | 								suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev ); | 
					
						
							|  |  |  | 								if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) { | 
					
						
							|  |  |  | 									Vec2Lerpf(uv_tmp, suv->uv_down, suv->uv_up, fabs(newlen)); | 
					
						
							|  |  |  | 									fuv_link = suv->fuv_list; | 
					
						
							|  |  |  | 									while (fuv_link) { | 
					
						
							|  |  |  | 										VECCOPY2D(((float *)fuv_link->link), uv_tmp); | 
					
						
							|  |  |  | 										fuv_link = fuv_link->next; | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} else{ | 
					
						
							|  |  |  | 						VecLerpf(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen));				 | 
					
						
							|  |  |  | 						 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 						if (0) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) {
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 							/* dont do anything if no UVs */ | 
					
						
							|  |  |  | 							for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) { | 
					
						
							|  |  |  | 								suv = BLI_ghash_lookup( uvarray[uvlay_idx], ev ); | 
					
						
							|  |  |  | 								if (suv && suv->fuv_list && suv->uv_up && suv->uv_down) { | 
					
						
							|  |  |  | 									Vec2Lerpf(uv_tmp, suv->uv_up, suv->uv_down, fabs(newlen)); | 
					
						
							|  |  |  | 									fuv_link = suv->fuv_list; | 
					
						
							|  |  |  | 									while (fuv_link) { | 
					
						
							|  |  |  | 										VECCOPY2D(((float *)fuv_link->link), uv_tmp); | 
					
						
							|  |  |  | 										fuv_link = fuv_link->next; | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					look = look->next;	  | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			 // Highlight the Control Edges
 | 
					
						
							|  |  |  | //			scrarea_do_windraw(curarea);   
 | 
					
						
							|  |  |  | //			persp(PERSP_VIEW);   
 | 
					
						
							|  |  |  | //			glPushMatrix();   
 | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | //			mymultmatrix(obedit->obmat);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			glColor3ub(0, 255, 0);    | 
					
						
							|  |  |  | 			glBegin(GL_LINES); | 
					
						
							|  |  |  | 			glVertex3fv(upVert->co); | 
					
						
							|  |  |  | 			glVertex3fv(downVert->co); | 
					
						
							|  |  |  | 			glEnd();  | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if(prop == 0) { | 
					
						
							|  |  |  | 				// draw start edge for non-prop
 | 
					
						
							|  |  |  | 				glPointSize(5); | 
					
						
							|  |  |  | 				glBegin(GL_POINTS); | 
					
						
							|  |  |  | 				glColor3ub(255,0,255); | 
					
						
							|  |  |  | 				if(flip) { | 
					
						
							|  |  |  | 					glVertex3fv(upVert->co); | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					glVertex3fv(downVert->co);					 | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				glEnd();	 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			glPopMatrix();		  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(prop) { | 
					
						
							|  |  |  | 				p += sprintf(str, "(P)ercentage: "); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				p += sprintf(str, "Non (P)rop Length: "); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if (0) // XXX hasNumInput(&num))
 | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				char num_str[20]; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				// XX outputNumInput(&num, num_str);
 | 
					
						
							|  |  |  | 				p += sprintf(p, "%s", num_str); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (prop) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					p += sprintf(p, "%f", perc); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					p += sprintf(p, "%f", len); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if (prop == 0) { | 
					
						
							|  |  |  | 				p += sprintf(p, ", Press (F) to flip control side"); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //			headerprint(str);
 | 
					
						
							|  |  |  | //			screen_swapbuffers();			
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(!immediate) { | 
					
						
							|  |  |  | 			while(qtest()) { | 
					
						
							|  |  |  | 				short val=0;		   	 | 
					
						
							|  |  |  | 				event= extern_qread(&val);	// extern_qread stores important events for the mainloop to handle 
 | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 				/* val==0 on key-release event */ | 
					
						
							|  |  |  | 				if (val) { | 
					
						
							|  |  |  | 					if(ELEM(event, ESCKEY, RIGHTMOUSE)) { | 
					
						
							|  |  |  | 							prop = 1; // Go back to prop mode
 | 
					
						
							|  |  |  | 							imperc = 0; // This is the % that gets set for immediate
 | 
					
						
							|  |  |  | 							immediate = 1; //Run through eval code 1 more time
 | 
					
						
							|  |  |  | 							cancel = 1;   // Return -1
 | 
					
						
							|  |  |  | 							mvalo[0] = -1; | 
					
						
							|  |  |  | 					} else if(ELEM3(event, PADENTER, LEFTMOUSE, RETKEY)) { | 
					
						
							|  |  |  | 							draw = 0; // End looping now
 | 
					
						
							|  |  |  | 					} else if(event==MIDDLEMOUSE) { | 
					
						
							|  |  |  | 							perc = 0;   | 
					
						
							|  |  |  | 							immediate = 1; | 
					
						
							|  |  |  | 					} else if(event==PKEY) { | 
					
						
							|  |  |  | // XXX							initNumInput(&num); /* reset num input */
 | 
					
						
							|  |  |  | 							if (prop) { | 
					
						
							|  |  |  | 								prop = 0; | 
					
						
							|  |  |  | // XXX								num.flag |= NUM_NO_NEGATIVE;
 | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							else { | 
					
						
							|  |  |  | 								prop = 1; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							mvalo[0] = -1;   | 
					
						
							|  |  |  | 					} else if(event==FKEY) { | 
					
						
							|  |  |  | 							(flip == 1) ? (flip = 0):(flip = 1);  | 
					
						
							|  |  |  | 							mvalo[0] = -1;  | 
					
						
							|  |  |  | 					} else if(ELEM(event, RIGHTARROWKEY, WHEELUPMOUSE)) { // Scroll through Control Edges
 | 
					
						
							|  |  |  | 						look = vertlist;	 | 
					
						
							|  |  |  | 				 		while(look) {	 | 
					
						
							|  |  |  | 							if(nearest == (EditVert*)look->link) { | 
					
						
							|  |  |  | 								if(look->next == NULL) { | 
					
						
							|  |  |  | 									nearest =  (EditVert*)vertlist->link;   | 
					
						
							|  |  |  | 								} else { | 
					
						
							|  |  |  | 									nearest = (EditVert*)look->next->link; | 
					
						
							|  |  |  | 								}	  | 
					
						
							|  |  |  | 								mvalo[0] = -1; | 
					
						
							|  |  |  | 								break;				 | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							look = look->next;    | 
					
						
							|  |  |  | 						}	   | 
					
						
							|  |  |  | 					} else if(ELEM(event, LEFTARROWKEY, WHEELDOWNMOUSE)) { // Scroll through Control Edges
 | 
					
						
							|  |  |  | 						look = vertlist;	 | 
					
						
							|  |  |  | 				 		while(look) {	 | 
					
						
							|  |  |  | 							if(look->next) { | 
					
						
							|  |  |  | 								if(look->next->link == nearest) { | 
					
						
							|  |  |  | 									nearest = (EditVert*)look->link; | 
					
						
							|  |  |  | 									mvalo[0] = -1; | 
					
						
							|  |  |  | 									break; | 
					
						
							|  |  |  | 								}	   | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								if((EditVert*)vertlist->link == nearest) { | 
					
						
							|  |  |  | 									nearest = look->link; | 
					
						
							|  |  |  | 									mvalo[0] = -1; | 
					
						
							|  |  |  | 									break;							  | 
					
						
							|  |  |  | 								}	    | 
					
						
							|  |  |  | 							}    | 
					
						
							|  |  |  | 							look = look->next;    | 
					
						
							|  |  |  | 						}	   | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | // XXX					if (handleNumInput(&num, event))
 | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						mvalo[0] = -1; /* NEED A BETTER WAY TO TRIGGER REDRAW */ | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 			}  | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			draw = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //		DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);	 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-31 13:30:56 +00:00
										 |  |  | 	if(me->drawflag & ME_DRAW_EDGELEN) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		look = vertlist; | 
					
						
							|  |  |  | 		while(look) {	 | 
					
						
							|  |  |  | 			tempsv  = BLI_ghash_lookup(vertgh,(EditVert*)look->link); | 
					
						
							|  |  |  | 			if(tempsv != NULL) { | 
					
						
							|  |  |  | 				tempsv->up->f &= !SELECT; | 
					
						
							|  |  |  | 				tempsv->down->f &= !SELECT; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			look = look->next; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | //	force_draw(0);
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(!immediate) | 
					
						
							|  |  |  | 		EM_automerge(0); | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | //	scrarea_queue_winredraw(curarea);		 
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	//BLI_ghash_free(edgesgh, freeGHash, NULL); 
 | 
					
						
							|  |  |  | 	BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN); | 
					
						
							|  |  |  | 	BLI_linklist_free(vertlist,NULL);  | 
					
						
							|  |  |  | 	BLI_linklist_free(edgelist,NULL);  | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 	if (uvlay_tot) { // XXX  && (scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) {
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		for (uvlay_idx=0; uvlay_idx<uvlay_tot; uvlay_idx++) { | 
					
						
							|  |  |  | 			BLI_ghash_free(uvarray[uvlay_idx], NULL, NULL); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		MEM_freeN(uvarray); | 
					
						
							|  |  |  | 		MEM_freeN(slideuvs); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		suv = suv_last-1; | 
					
						
							|  |  |  | 		while (suv >= slideuvs) { | 
					
						
							|  |  |  | 			if (suv->fuv_list) { | 
					
						
							|  |  |  | 				BLI_linklist_free(suv->fuv_list,NULL); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			suv--; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(cancel == 1) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 1; | 
					
						
							| 
									
										
										
										
											2009-02-20 18:36:27 +00:00
										 |  |  | #endif // END OF XXX
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | int EdgeLoopDelete(EditMesh *em, wmOperator *op)  | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* temporal flag setting so we keep UVs when deleting edge loops,
 | 
					
						
							|  |  |  | 	* this is a bit of a hack but it works how you would want in almost all cases */ | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 	//	short uvcalc_flag_orig = 0; // XXX scene->toolsettings->uvcalc_flag; 
 | 
					
						
							|  |  |  | 	//	scene->toolsettings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 	if(!EdgeSlide(em, op, 1, 1)) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* restore uvcalc flag */ | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 	//	scene->toolsettings->uvcalc_flag = uvcalc_flag_orig;
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	EM_select_more(em); | 
					
						
							|  |  |  | 	removedoublesflag(em, 1,0, 0.001); | 
					
						
							|  |  |  | 	EM_select_flush(em); | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 	//	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------- More tools ------------------ */ | 
					
						
							| 
									
										
										
										
											2009-02-16 14:28:33 +00:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | void mesh_set_face_flags(EditMesh *em, short mode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	MTFace *tface; | 
					
						
							|  |  |  | 	short	m_tex=0, m_tiles=0, m_shared=0, | 
					
						
							|  |  |  | 			m_light=0, m_invis=0, m_collision=0, | 
					
						
							|  |  |  | 			m_twoside=0, m_obcolor=0, m_halo=0, | 
					
						
							|  |  |  | 			m_billboard=0, m_shadow=0, m_text=0, | 
					
						
							|  |  |  | 			m_sort=0; | 
					
						
							|  |  |  | 	short flag = 0, change = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | // XXX	if (!EM_texFaceCheck()) {
 | 
					
						
							|  |  |  | //		error("not a mesh with uv/image layers");
 | 
					
						
							|  |  |  | //		return;
 | 
					
						
							|  |  |  | //	}
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	add_numbut(0, TOG|SHO, "Texture", 0, 0, &m_tex, NULL); | 
					
						
							|  |  |  | 	add_numbut(1, TOG|SHO, "Tiles", 0, 0, &m_tiles, NULL); | 
					
						
							|  |  |  | 	add_numbut(2, TOG|SHO, "Light", 0, 0, &m_light, NULL); | 
					
						
							|  |  |  | 	add_numbut(3, TOG|SHO, "Invisible", 0, 0, &m_invis, NULL); | 
					
						
							|  |  |  | 	add_numbut(4, TOG|SHO, "Collision", 0, 0, &m_collision, NULL); | 
					
						
							|  |  |  | 	add_numbut(5, TOG|SHO, "Shared", 0, 0, &m_shared, NULL); | 
					
						
							|  |  |  | 	add_numbut(6, TOG|SHO, "Twoside", 0, 0, &m_twoside, NULL); | 
					
						
							|  |  |  | 	add_numbut(7, TOG|SHO, "ObColor", 0, 0, &m_obcolor, NULL); | 
					
						
							|  |  |  | 	add_numbut(8, TOG|SHO, "Halo", 0, 0, &m_halo, NULL); | 
					
						
							|  |  |  | 	add_numbut(9, TOG|SHO, "Billboard", 0, 0, &m_billboard, NULL); | 
					
						
							|  |  |  | 	add_numbut(10, TOG|SHO, "Shadow", 0, 0, &m_shadow, NULL); | 
					
						
							|  |  |  | 	add_numbut(11, TOG|SHO, "Text", 0, 0, &m_text, NULL); | 
					
						
							|  |  |  | 	add_numbut(12, TOG|SHO, "Sort", 0, 0, &m_sort, NULL); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (!do_clever_numbuts((mode ? "Set Flags" : "Clear Flags"), 13, REDRAW)) | 
					
						
							|  |  |  |  		return; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* these 2 cant both be on */ | 
					
						
							|  |  |  | 	if (mode) /* are we seeting*/ | 
					
						
							|  |  |  | 		if (m_halo) | 
					
						
							|  |  |  | 			m_billboard = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (m_tex)			flag |= TF_TEX; | 
					
						
							|  |  |  | 	if (m_tiles)		flag |= TF_TILES; | 
					
						
							|  |  |  | 	if (m_shared)		flag |= TF_SHAREDCOL; | 
					
						
							|  |  |  | 	if (m_light)		flag |= TF_LIGHT; | 
					
						
							|  |  |  | 	if (m_invis)		flag |= TF_INVISIBLE; | 
					
						
							|  |  |  | 	if (m_collision)	flag |= TF_DYNAMIC; | 
					
						
							|  |  |  | 	if (m_twoside)		flag |= TF_TWOSIDE; | 
					
						
							|  |  |  | 	if (m_obcolor)		flag |= TF_OBCOL; | 
					
						
							|  |  |  | 	if (m_halo)			flag |= TF_BILLBOARD; | 
					
						
							|  |  |  | 	if (m_billboard)	flag |= TF_BILLBOARD2; | 
					
						
							|  |  |  | 	if (m_shadow)		flag |= TF_SHADOW; | 
					
						
							|  |  |  | 	if (m_text)			flag |= TF_BMFONT; | 
					
						
							|  |  |  | 	if (m_sort)			flag |= TF_ALPHASORT; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (flag==0) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	efa= em->faces.first; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		if(efa->f & SELECT) { | 
					
						
							|  |  |  | 			tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | 
					
						
							|  |  |  | 			if (mode)	tface->mode |= flag; | 
					
						
							|  |  |  | 			else		tface->mode &= ~flag; | 
					
						
							|  |  |  | 			change = 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		efa= efa->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-02-16 14:28:33 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | void mesh_set_smooth_faces(EditMesh *em, short event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	if(em==NULL) return; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	efa= em->faces.first; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		if(efa->f & SELECT) { | 
					
						
							|  |  |  | 			if(event==1) efa->flag |= ME_SMOOTH; | 
					
						
							|  |  |  | 			else if(event==0) efa->flag &= ~ME_SMOOTH; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		efa= efa->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | /* ********************** mesh rip ********************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | /* helper to find edge for edge_rip */ | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | static float mesh_rip_edgedist(ARegion *ar, float mat[][4], float *co1, float *co2, short *mval) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	float vec1[3], vec2[3], mvalf[2]; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 	view3d_project_float(ar, co1, vec1, mat); | 
					
						
							|  |  |  | 	view3d_project_float(ar, co2, vec2, mat); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	mvalf[0]= (float)mval[0]; | 
					
						
							|  |  |  | 	mvalf[1]= (float)mval[1]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return PdistVL2Dfl(mvalf, vec1, vec2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* helper for below */ | 
					
						
							|  |  |  | static void mesh_rip_setface(EditMesh *em, EditFace *sefa) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* put new vertices & edges in best face */ | 
					
						
							|  |  |  | 	if(sefa->v1->tmp.v) sefa->v1= sefa->v1->tmp.v; | 
					
						
							|  |  |  | 	if(sefa->v2->tmp.v) sefa->v2= sefa->v2->tmp.v; | 
					
						
							|  |  |  | 	if(sefa->v3->tmp.v) sefa->v3= sefa->v3->tmp.v; | 
					
						
							|  |  |  | 	if(sefa->v4 && sefa->v4->tmp.v) sefa->v4= sefa->v4->tmp.v; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	sefa->e1= addedgelist(em, sefa->v1, sefa->v2, sefa->e1); | 
					
						
							|  |  |  | 	sefa->e2= addedgelist(em, sefa->v2, sefa->v3, sefa->e2); | 
					
						
							|  |  |  | 	if(sefa->v4) { | 
					
						
							|  |  |  | 		sefa->e3= addedgelist(em, sefa->v3, sefa->v4, sefa->e3); | 
					
						
							|  |  |  | 		sefa->e4= addedgelist(em, sefa->v4, sefa->v1, sefa->e4); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else  | 
					
						
							|  |  |  | 		sefa->e3= addedgelist(em, sefa->v3, sefa->v1, sefa->e3); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* based on mouse cursor position, it defines how is being ripped */ | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 	ARegion *ar= CTX_wm_region(C); | 
					
						
							|  |  |  | 	RegionView3D *rv3d= ar->regiondata; | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditVert *eve, *nextve; | 
					
						
							|  |  |  | 	EditEdge *eed, *seed= NULL; | 
					
						
							|  |  |  | 	EditFace *efa, *sefa= NULL; | 
					
						
							| 
									
										
										
										
											2009-05-18 16:42:34 +00:00
										 |  |  | 	float projectMat[4][4], vec[3], dist, mindist; | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 	short doit= 1, *mval= event->mval; // XXX ,propmode,prop;
 | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | // XXX	propmode = scene->prop_mode;
 | 
					
						
							|  |  |  | //	scene->prop_mode = 0;
 | 
					
						
							|  |  |  | //	prop = scene->proportional;
 | 
					
						
							|  |  |  | //	scene->proportional = 0;
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* select flush... vertices are important */ | 
					
						
							|  |  |  | 	EM_selectmode_set(em); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-05-18 16:42:34 +00:00
										 |  |  | 	view3d_get_object_project_mat(rv3d, obedit, projectMat); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* find best face, exclude triangles and break on face select or faces with 2 edges select */ | 
					
						
							|  |  |  | 	mindist= 1000000.0f; | 
					
						
							|  |  |  | 	for(efa= em->faces.first; efa; efa=efa->next) { | 
					
						
							|  |  |  | 		if( efa->f & 1)  | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		if(efa->v4 && faceselectedOR(efa, SELECT) ) { | 
					
						
							|  |  |  | 			int totsel=0; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if(efa->e1->f & SELECT) totsel++; | 
					
						
							|  |  |  | 			if(efa->e2->f & SELECT) totsel++; | 
					
						
							|  |  |  | 			if(efa->e3->f & SELECT) totsel++; | 
					
						
							|  |  |  | 			if(efa->e4->f & SELECT) totsel++; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if(totsel>1) | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 			view3d_project_float(ar, efa->cent, vec, projectMat); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			dist= sqrt( (vec[0]-mval[0])*(vec[0]-mval[0]) + (vec[1]-mval[1])*(vec[1]-mval[1]) ); | 
					
						
							|  |  |  | 			if(dist<mindist) { | 
					
						
							|  |  |  | 				mindist= dist; | 
					
						
							|  |  |  | 				sefa= efa; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(efa) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "Can't perform ripping with faces selected this way"); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 		BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if(sefa==NULL) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "No proper selection or faces included"); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 		BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* duplicate vertices, new vertices get selected */ | 
					
						
							|  |  |  | 	for(eve = em->verts.last; eve; eve= eve->prev) { | 
					
						
							|  |  |  | 		eve->tmp.v = NULL; | 
					
						
							|  |  |  | 		if(eve->f & SELECT) { | 
					
						
							|  |  |  | 			eve->tmp.v = addvertlist(em, eve->co, eve); | 
					
						
							|  |  |  | 			eve->f &= ~SELECT; | 
					
						
							|  |  |  | 			eve->tmp.v->f |= SELECT; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* find the best candidate edge */ | 
					
						
							|  |  |  | 	/* or one of sefa edges is selected... */ | 
					
						
							|  |  |  | 	if(sefa->e1->f & SELECT) seed= sefa->e2; | 
					
						
							|  |  |  | 	if(sefa->e2->f & SELECT) seed= sefa->e1; | 
					
						
							|  |  |  | 	if(sefa->e3->f & SELECT) seed= sefa->e2; | 
					
						
							|  |  |  | 	if(sefa->e4 && sefa->e4->f & SELECT) seed= sefa->e3; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* or we do the distance trick */ | 
					
						
							|  |  |  | 	if(seed==NULL) { | 
					
						
							|  |  |  | 		mindist= 1000000.0f; | 
					
						
							|  |  |  | 		if(sefa->e1->v1->tmp.v || sefa->e1->v2->tmp.v) { | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 			dist = mesh_rip_edgedist(ar, projectMat,  | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 									 sefa->e1->v1->co,  | 
					
						
							|  |  |  | 									 sefa->e1->v2->co, mval); | 
					
						
							|  |  |  | 			if(dist<mindist) { | 
					
						
							|  |  |  | 				seed= sefa->e1; | 
					
						
							|  |  |  | 				mindist= dist; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(sefa->e2->v1->tmp.v || sefa->e2->v2->tmp.v) { | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 			dist = mesh_rip_edgedist(ar, projectMat, | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 									 sefa->e2->v1->co,  | 
					
						
							|  |  |  | 									 sefa->e2->v2->co, mval); | 
					
						
							|  |  |  | 			if(dist<mindist) { | 
					
						
							|  |  |  | 				seed= sefa->e2; | 
					
						
							|  |  |  | 				mindist= dist; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(sefa->e3->v1->tmp.v || sefa->e3->v2->tmp.v) { | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 			dist= mesh_rip_edgedist(ar, projectMat,  | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 									sefa->e3->v1->co,  | 
					
						
							|  |  |  | 									sefa->e3->v2->co, mval); | 
					
						
							|  |  |  | 			if(dist<mindist) { | 
					
						
							|  |  |  | 				seed= sefa->e3; | 
					
						
							|  |  |  | 				mindist= dist; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(sefa->e4 && (sefa->e4->v1->tmp.v || sefa->e4->v2->tmp.v)) { | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 			dist= mesh_rip_edgedist(ar, projectMat,  | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 									sefa->e4->v1->co,  | 
					
						
							|  |  |  | 									sefa->e4->v2->co, mval); | 
					
						
							|  |  |  | 			if(dist<mindist) { | 
					
						
							|  |  |  | 				seed= sefa->e4; | 
					
						
							|  |  |  | 				mindist= dist; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(seed==NULL) {	// never happens?
 | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "No proper edge found to start"); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 		BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 	faceloop_select(em, seed, 2);	// tmp abuse for finding all edges that need duplicated, returns OK faces with f1
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* duplicate edges in the loop, with at least 1 vertex selected, needed for selection flip */ | 
					
						
							|  |  |  | 	for(eed = em->edges.last; eed; eed= eed->prev) { | 
					
						
							|  |  |  | 		eed->tmp.v = NULL; | 
					
						
							|  |  |  | 		if((eed->v1->tmp.v) || (eed->v2->tmp.v)) { | 
					
						
							|  |  |  | 			EditEdge *newed; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			newed= addedgelist(em, eed->v1->tmp.v?eed->v1->tmp.v:eed->v1,  | 
					
						
							|  |  |  | 							   eed->v2->tmp.v?eed->v2->tmp.v:eed->v2, eed); | 
					
						
							|  |  |  | 			if(eed->f & SELECT) { | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 				EM_select_edge(eed, 0); | 
					
						
							|  |  |  | 				EM_remove_selection(em, eed, EDITEDGE); | 
					
						
							|  |  |  | 				EM_select_edge(newed, 1); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			eed->tmp.v = (EditVert *)newed; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* first clear edges to help finding neighbours */ | 
					
						
							|  |  |  | 	for(eed = em->edges.last; eed; eed= eed->prev) eed->f1= 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* put new vertices & edges && flag in best face */ | 
					
						
							|  |  |  | 	mesh_rip_setface(em, sefa); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* starting with neighbours of best face, we loop over the seam */ | 
					
						
							|  |  |  | 	sefa->f1= 2; | 
					
						
							|  |  |  | 	doit= 1; | 
					
						
							|  |  |  | 	while(doit) { | 
					
						
							|  |  |  | 		doit= 0; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for(efa= em->faces.first; efa; efa=efa->next) { | 
					
						
							|  |  |  | 			/* new vert in face */ | 
					
						
							|  |  |  | 			if (efa->v1->tmp.v || efa->v2->tmp.v ||  | 
					
						
							|  |  |  | 				efa->v3->tmp.v || (efa->v4 && efa->v4->tmp.v)) { | 
					
						
							|  |  |  | 				/* face is tagged with loop */ | 
					
						
							|  |  |  | 				if(efa->f1==1) { | 
					
						
							|  |  |  | 					mesh_rip_setface(em, efa); | 
					
						
							|  |  |  | 					efa->f1= 2; | 
					
						
							|  |  |  | 					doit= 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}		 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* remove loose edges, that were part of a ripped face */ | 
					
						
							|  |  |  | 	for(eve = em->verts.first; eve; eve= eve->next) eve->f1= 0; | 
					
						
							|  |  |  | 	for(eed = em->edges.last; eed; eed= eed->prev) eed->f1= 0; | 
					
						
							|  |  |  | 	for(efa= em->faces.first; efa; efa=efa->next) { | 
					
						
							|  |  |  | 		efa->e1->f1= 1; | 
					
						
							|  |  |  | 		efa->e2->f1= 1; | 
					
						
							|  |  |  | 		efa->e3->f1= 1; | 
					
						
							|  |  |  | 		if(efa->e4) efa->e4->f1= 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(eed = em->edges.last; eed; eed= seed) { | 
					
						
							|  |  |  | 		seed= eed->prev; | 
					
						
							|  |  |  | 		if(eed->f1==0) { | 
					
						
							|  |  |  | 			if(eed->v1->tmp.v || eed->v2->tmp.v ||  | 
					
						
							|  |  |  | 			   (eed->v1->f & SELECT) || (eed->v2->f & SELECT)) { | 
					
						
							|  |  |  | 				remedge(em, eed); | 
					
						
							|  |  |  | 				free_editedge(em, eed); | 
					
						
							|  |  |  | 				eed= NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(eed) { | 
					
						
							|  |  |  | 			eed->v1->f1= 1; | 
					
						
							|  |  |  | 			eed->v2->f1= 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* and remove loose selected vertices, that got duplicated accidentally */ | 
					
						
							|  |  |  | 	for(eve = em->verts.first; eve; eve= nextve) { | 
					
						
							|  |  |  | 		nextve= eve->next; | 
					
						
							|  |  |  | 		if(eve->f1==0 && (eve->tmp.v || (eve->f & SELECT))) { | 
					
						
							|  |  |  | 			BLI_remlink(&em->verts,eve); | 
					
						
							|  |  |  | 			free_editvert(em, eve); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 	RNA_int_set(op->ptr, "mode", TFM_TRANSLATION); | 
					
						
							|  |  |  | 	WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //	scene->prop_mode = propmode;
 | 
					
						
							|  |  |  | // XXX	scene->proportional = prop;
 | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | void MESH_OT_rip(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Rip"; | 
					
						
							|  |  |  | 	ot->idname= "MESH_OT_rip"; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->invoke= mesh_rip_invoke; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; // XXX + v3d!
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* to give to transform */ | 
					
						
							|  |  |  | 	RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | void shape_propagate(Scene *scene, Object *obedit, EditMesh *em, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditVert *ev = NULL; | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	Mesh* me = (Mesh*)obedit->data; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	Key*  ky = NULL; | 
					
						
							|  |  |  | 	KeyBlock* kb = NULL; | 
					
						
							|  |  |  | 	Base* base=NULL; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(me->key){ | 
					
						
							|  |  |  | 		ky = me->key; | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "Object Has No Key");	 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(ky->block.first){ | 
					
						
							|  |  |  | 		for(ev = em->verts.first; ev ; ev = ev->next){ | 
					
						
							|  |  |  | 			if(ev->f & SELECT){ | 
					
						
							|  |  |  | 				for(kb=ky->block.first;kb;kb = kb->next){ | 
					
						
							|  |  |  | 					float *data;		 | 
					
						
							|  |  |  | 					data = kb->data;			 | 
					
						
							|  |  |  | 					VECCOPY(data+(ev->keyindex*3),ev->co);				 | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}		 | 
					
						
							|  |  |  | 		}						 | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "Object Has No Blendshapes");	 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		return;			 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	//TAG Mesh Objects that share this data
 | 
					
						
							|  |  |  | 	for(base = scene->base.first; base; base = base->next){ | 
					
						
							|  |  |  | 		if(base->object && base->object->data == me){ | 
					
						
							|  |  |  | 			base->object->recalc = OB_RECALC_DATA; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}		 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	return;	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void shape_copy_from_lerp(EditMesh *em, KeyBlock* thisBlock, KeyBlock* fromBlock) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *ev = NULL; | 
					
						
							|  |  |  | 	short mval[2], curval[2], event = 0, finished = 0, canceled = 0, fullcopy=0 ; | 
					
						
							|  |  |  | 	float perc = 0; | 
					
						
							|  |  |  | 	char str[64]; | 
					
						
							|  |  |  | 	float *data, *odata; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 	data  = fromBlock->data; | 
					
						
							|  |  |  | 	odata = thisBlock->data; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | // XXX	getmouseco_areawin(mval);
 | 
					
						
							|  |  |  | 	curval[0] = mval[0] + 1; curval[1] = mval[1] + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (finished == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | // XXX		getmouseco_areawin(mval);
 | 
					
						
							|  |  |  | 		if (mval[0] != curval[0] || mval[1] != curval[1]) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if(mval[0] > curval[0]) | 
					
						
							|  |  |  | 				perc += 0.1; | 
					
						
							|  |  |  | 			else if(mval[0] < curval[0]) | 
					
						
							|  |  |  | 				perc -= 0.1; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 			if(perc < 0) perc = 0; | 
					
						
							|  |  |  | 			if(perc > 1) perc = 1; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			curval[0] = mval[0]; | 
					
						
							|  |  |  | 			curval[1] = mval[1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(fullcopy == 1){ | 
					
						
							|  |  |  | 				perc = 1;	 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for(ev = em->verts.first; ev ; ev = ev->next){ | 
					
						
							|  |  |  | 				if(ev->f & SELECT){ | 
					
						
							|  |  |  | 					VecLerpf(ev->co,odata+(ev->keyindex*3),data+(ev->keyindex*3),perc); | 
					
						
							|  |  |  | 				}		 | 
					
						
							|  |  |  | 			}	 | 
					
						
							|  |  |  | 			sprintf(str,"Blending at %d%c  MMB to Copy at 100%c",(int)(perc*100),'%','%'); | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //			DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | //			headerprint(str);
 | 
					
						
							|  |  |  | //			force_draw(0);			
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(fullcopy == 1){ | 
					
						
							|  |  |  | 				break;	 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			PIL_sleep_ms(10);	 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		while(qtest()) { | 
					
						
							|  |  |  | 			short val=0;			 | 
					
						
							|  |  |  | 			event= extern_qread(&val);	 | 
					
						
							|  |  |  | 			if(val){ | 
					
						
							|  |  |  | 				if(ELEM3(event, PADENTER, LEFTMOUSE, RETKEY)){ | 
					
						
							|  |  |  | 					finished = 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else if (event == MIDDLEMOUSE){ | 
					
						
							|  |  |  | 					fullcopy = 1;	 | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else if (ELEM3(event,ESCKEY,RIGHTMOUSE,RIGHTMOUSE)){ | 
					
						
							|  |  |  | 					canceled = 1; | 
					
						
							|  |  |  | 					finished = 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}  | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	if(!canceled); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	else | 
					
						
							|  |  |  | 		for(ev = em->verts.first; ev ; ev = ev->next){ | 
					
						
							|  |  |  | 			if(ev->f & SELECT){ | 
					
						
							|  |  |  | 				VECCOPY(ev->co, odata+(ev->keyindex*3)); | 
					
						
							|  |  |  | 			}		 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	return; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | void shape_copy_select_from(Object *obedit, EditMesh *em, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	Mesh* me = (Mesh*)obedit->data; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditVert *ev = NULL; | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	int totverts = 0,curshape = obedit->shapenr; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	Key*  ky = NULL; | 
					
						
							|  |  |  | 	KeyBlock *kb = NULL,*thisBlock = NULL; | 
					
						
							|  |  |  | 	int maxlen=32, nr=0, a=0; | 
					
						
							|  |  |  | 	char *menu; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(me->key){ | 
					
						
							|  |  |  | 		ky = me->key; | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "Object Has No Key");	 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(ky->block.first){ | 
					
						
							|  |  |  | 		for(kb=ky->block.first;kb;kb = kb->next){ | 
					
						
							|  |  |  | 			maxlen += 40; // Size of a block name
 | 
					
						
							|  |  |  | 			if(a == curshape-1){ | 
					
						
							|  |  |  | 					thisBlock = kb;		 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			a++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		a=0; | 
					
						
							|  |  |  | 		menu = MEM_callocN(maxlen, "Copy Shape Menu Text"); | 
					
						
							|  |  |  | 		strcpy(menu, "Copy Vert Positions from Shape %t|"); | 
					
						
							|  |  |  | 		for(kb=ky->block.first;kb;kb = kb->next){ | 
					
						
							|  |  |  | 			if(a != curshape-1){  | 
					
						
							|  |  |  | 				sprintf(menu,"%s %s %cx%d|",menu,kb->name,'%',a); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			a++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | // XXX		nr = pupmenu_col(menu, 20);
 | 
					
						
							|  |  |  | 		MEM_freeN(menu);		 | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "Object Has No Blendshapes");	 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		return;			 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	a = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(kb=ky->block.first;kb;kb = kb->next){ | 
					
						
							|  |  |  | 		if(a == nr){ | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			for(ev = em->verts.first;ev;ev = ev->next){ | 
					
						
							|  |  |  | 				totverts++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if(me->totvert != totverts){ | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 				BKE_report(op->reports, RPT_ERROR, "Shape Has had Verts Added/Removed, please cycle editmode before copying"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				return;	 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			shape_copy_from_lerp(em, thisBlock,kb);		 | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		a++; | 
					
						
							|  |  |  | 	}		 | 
					
						
							|  |  |  | 	return; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Collection Routines|Currently used by the improved merge code*/ | 
					
						
							|  |  |  | /* buildEdge_collection() creates a list of lists*/ | 
					
						
							|  |  |  | /* these lists are filled with edges that are topologically connected.*/ | 
					
						
							|  |  |  | /* This whole tool needs to be redone, its rather poorly implemented...*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct Collection{ | 
					
						
							|  |  |  | 	struct Collection *next, *prev; | 
					
						
							|  |  |  | 	int index; | 
					
						
							|  |  |  | 	ListBase collectionbase; | 
					
						
							|  |  |  | } Collection; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct CollectedEdge{ | 
					
						
							|  |  |  | 	struct CollectedEdge *next, *prev; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | } CollectedEdge; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MERGELIMIT 0.000001
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void build_edgecollection(EditMesh *em, ListBase *allcollections) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	Collection *edgecollection, *newcollection; | 
					
						
							|  |  |  | 	CollectedEdge *newedge; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	int currtag = 1; | 
					
						
							|  |  |  | 	short ebalanced = 0; | 
					
						
							|  |  |  | 	short collectionfound = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for (eed=em->edges.first; eed; eed = eed->next){	 | 
					
						
							|  |  |  | 		eed->tmp.l = 0; | 
					
						
							|  |  |  | 		eed->v1->tmp.l = 0; | 
					
						
							|  |  |  | 		eed->v2->tmp.l = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*1st pass*/ | 
					
						
							|  |  |  | 	for(eed=em->edges.first; eed; eed=eed->next){ | 
					
						
							|  |  |  | 			if(eed->f&SELECT){ | 
					
						
							|  |  |  | 				eed->v1->tmp.l = currtag; | 
					
						
							|  |  |  | 				eed->v2->tmp.l = currtag; | 
					
						
							|  |  |  | 				currtag +=1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 	/*2nd pass - Brute force. Loop through selected faces until there are no 'unbalanced' edges left (those with both vertices 'tmp.l' tag matching */ | 
					
						
							|  |  |  | 	while(ebalanced == 0){ | 
					
						
							|  |  |  | 		ebalanced = 1; | 
					
						
							|  |  |  | 		for(eed=em->edges.first; eed; eed = eed->next){ | 
					
						
							|  |  |  | 			if(eed->f&SELECT){ | 
					
						
							|  |  |  | 				if(eed->v1->tmp.l != eed->v2->tmp.l) /*unbalanced*/{ | 
					
						
							|  |  |  | 					if(eed->v1->tmp.l > eed->v2->tmp.l && eed->v2->tmp.l !=0) eed->v1->tmp.l = eed->v2->tmp.l;  | 
					
						
							|  |  |  | 					else if(eed->v1 != 0) eed->v2->tmp.l = eed->v1->tmp.l;  | 
					
						
							|  |  |  | 					ebalanced = 0; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*3rd pass, set all the edge flags (unnessecary?)*/ | 
					
						
							|  |  |  | 	for(eed=em->edges.first; eed; eed = eed->next){ | 
					
						
							|  |  |  | 		if(eed->f&SELECT) eed->tmp.l = eed->v1->tmp.l; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(eed=em->edges.first; eed; eed=eed->next){ | 
					
						
							|  |  |  | 		if(eed->f&SELECT){ | 
					
						
							|  |  |  | 			if(allcollections->first){ | 
					
						
							|  |  |  | 				for(edgecollection = allcollections->first; edgecollection; edgecollection=edgecollection->next){ | 
					
						
							|  |  |  | 					if(edgecollection->index == eed->tmp.l){ | 
					
						
							|  |  |  | 						newedge = MEM_mallocN(sizeof(CollectedEdge), "collected edge"); | 
					
						
							|  |  |  | 						newedge->eed = eed; | 
					
						
							|  |  |  | 						BLI_addtail(&(edgecollection->collectionbase), newedge); | 
					
						
							|  |  |  | 						collectionfound = 1; | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					else collectionfound = 0; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(allcollections->first == NULL || collectionfound == 0){ | 
					
						
							|  |  |  | 				newcollection = MEM_mallocN(sizeof(Collection), "element collection"); | 
					
						
							|  |  |  | 				newcollection->index = eed->tmp.l; | 
					
						
							|  |  |  | 				newcollection->collectionbase.first = 0; | 
					
						
							|  |  |  | 				newcollection->collectionbase.last = 0; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				newedge = MEM_mallocN(sizeof(CollectedEdge), "collected edge"); | 
					
						
							|  |  |  | 				newedge->eed = eed; | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 				BLI_addtail(&(newcollection->collectionbase), newedge); | 
					
						
							|  |  |  | 				BLI_addtail(allcollections, newcollection); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void freecollections(ListBase *allcollections) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct Collection *curcollection; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(curcollection = allcollections->first; curcollection; curcollection = curcollection->next) | 
					
						
							|  |  |  | 		BLI_freelistN(&(curcollection->collectionbase)); | 
					
						
							|  |  |  | 	BLI_freelistN(allcollections); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*Begin UV Edge Collapse Code 
 | 
					
						
							|  |  |  | 	Like Edge subdivide, Edge Collapse should handle UV's intelligently, but since UV's are a per-face attribute, normal edge collapse will fail | 
					
						
							|  |  |  | 	in areas such as the boundries of 'UV islands'. So for each edge collection we need to build a set of 'welded' UV vertices and edges for it. | 
					
						
							|  |  |  | 	The welded UV edges can then be sorted and collapsed. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | typedef struct wUV{ | 
					
						
							|  |  |  | 	struct wUV *next, *prev; | 
					
						
							|  |  |  | 	ListBase nodes; | 
					
						
							|  |  |  | 	float u, v; /*cached copy of UV coordinates pointed to by nodes*/ | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	int f; | 
					
						
							|  |  |  | } wUV; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct wUVNode{ | 
					
						
							|  |  |  | 	struct wUVNode *next, *prev; | 
					
						
							|  |  |  | 	float *u; /*pointer to original tface data*/ | 
					
						
							|  |  |  | 	float *v; /*pointer to original tface data*/ | 
					
						
							|  |  |  | } wUVNode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct wUVEdge{ | 
					
						
							|  |  |  | 	struct wUVEdge *next, *prev; | 
					
						
							|  |  |  | 	float v1uv[2], v2uv[2]; /*nasty.*/ | 
					
						
							|  |  |  | 	struct wUV *v1, *v2; /*oriented same as editedge*/ | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	int f; | 
					
						
							|  |  |  | } wUVEdge; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct wUVEdgeCollect{ /*used for grouping*/ | 
					
						
							|  |  |  | 	struct wUVEdgeCollect *next, *prev; | 
					
						
							|  |  |  | 	wUVEdge *uved; | 
					
						
							|  |  |  | 	int id;  | 
					
						
							|  |  |  | } wUVEdgeCollect; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void append_weldedUV(EditMesh *em, EditFace *efa, EditVert *eve, int tfindex, ListBase *uvverts) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	wUV *curwvert, *newwvert; | 
					
						
							|  |  |  | 	wUVNode *newnode; | 
					
						
							|  |  |  | 	int found; | 
					
						
							|  |  |  | 	MTFace *tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	found = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){ | 
					
						
							|  |  |  | 		if(curwvert->eve == eve && curwvert->u == tf->uv[tfindex][0] && curwvert->v == tf->uv[tfindex][1]){ | 
					
						
							|  |  |  | 			newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node"); | 
					
						
							|  |  |  | 			newnode->u = &(tf->uv[tfindex][0]); | 
					
						
							|  |  |  | 			newnode->v = &(tf->uv[tfindex][1]); | 
					
						
							|  |  |  | 			BLI_addtail(&(curwvert->nodes), newnode); | 
					
						
							|  |  |  | 			found = 1; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(!found){ | 
					
						
							|  |  |  | 		newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node"); | 
					
						
							|  |  |  | 		newnode->u = &(tf->uv[tfindex][0]); | 
					
						
							|  |  |  | 		newnode->v = &(tf->uv[tfindex][1]); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		newwvert = MEM_callocN(sizeof(wUV), "Welded UV Vert"); | 
					
						
							|  |  |  | 		newwvert->u = *(newnode->u); | 
					
						
							|  |  |  | 		newwvert->v = *(newnode->v); | 
					
						
							|  |  |  | 		newwvert->eve = eve; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		BLI_addtail(&(newwvert->nodes), newnode); | 
					
						
							|  |  |  | 		BLI_addtail(uvverts, newwvert); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void build_weldedUVs(EditMesh *em, ListBase *uvverts) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	for(efa=em->faces.first; efa; efa=efa->next){ | 
					
						
							|  |  |  | 		if(efa->v1->f1) append_weldedUV(em, efa, efa->v1, 0, uvverts); | 
					
						
							|  |  |  | 		if(efa->v2->f1) append_weldedUV(em, efa, efa->v2, 1, uvverts); | 
					
						
							|  |  |  | 		if(efa->v3->f1) append_weldedUV(em, efa, efa->v3, 2, uvverts); | 
					
						
							|  |  |  | 		if(efa->v4 && efa->v4->f1) append_weldedUV(em, efa, efa->v4, 3, uvverts); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void append_weldedUVEdge(EditMesh *em, EditFace *efa, EditEdge *eed, ListBase *uvedges) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	wUVEdge *curwedge, *newwedge; | 
					
						
							|  |  |  | 	int v1tfindex, v2tfindex, found; | 
					
						
							|  |  |  | 	MTFace *tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	found = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(eed->v1 == efa->v1) v1tfindex = 0; | 
					
						
							|  |  |  | 	else if(eed->v1 == efa->v2) v1tfindex = 1; | 
					
						
							|  |  |  | 	else if(eed->v1 == efa->v3) v1tfindex = 2; | 
					
						
							|  |  |  | 	else /* if(eed->v1 == efa->v4) */ v1tfindex = 3; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 	if(eed->v2 == efa->v1) v2tfindex = 0; | 
					
						
							|  |  |  | 	else if(eed->v2 == efa->v2) v2tfindex = 1; | 
					
						
							|  |  |  | 	else if(eed->v2 == efa->v3) v2tfindex = 2; | 
					
						
							|  |  |  | 	else /* if(eed->v2 == efa->v4) */ v2tfindex = 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(curwedge=uvedges->first; curwedge; curwedge=curwedge->next){ | 
					
						
							|  |  |  | 			if(curwedge->eed == eed && curwedge->v1uv[0] == tf->uv[v1tfindex][0] && curwedge->v1uv[1] == tf->uv[v1tfindex][1] && curwedge->v2uv[0] == tf->uv[v2tfindex][0] && curwedge->v2uv[1] == tf->uv[v2tfindex][1]){ | 
					
						
							|  |  |  | 				found = 1; | 
					
						
							|  |  |  | 				break; //do nothing, we don't need another welded uv edge
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(!found){ | 
					
						
							|  |  |  | 		newwedge = MEM_callocN(sizeof(wUVEdge), "Welded UV Edge"); | 
					
						
							|  |  |  | 		newwedge->v1uv[0] = tf->uv[v1tfindex][0]; | 
					
						
							|  |  |  | 		newwedge->v1uv[1] = tf->uv[v1tfindex][1]; | 
					
						
							|  |  |  | 		newwedge->v2uv[0] = tf->uv[v2tfindex][0]; | 
					
						
							|  |  |  | 		newwedge->v2uv[1] = tf->uv[v2tfindex][1]; | 
					
						
							|  |  |  | 		newwedge->eed = eed; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		BLI_addtail(uvedges, newwedge); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void build_weldedUVEdges(EditMesh *em, ListBase *uvedges, ListBase *uvverts) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	wUV *curwvert; | 
					
						
							|  |  |  | 	wUVEdge *curwedge; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(efa=em->faces.first; efa; efa=efa->next){ | 
					
						
							|  |  |  | 		if(efa->e1->f1) append_weldedUVEdge(em, efa, efa->e1, uvedges); | 
					
						
							|  |  |  | 		if(efa->e2->f1) append_weldedUVEdge(em, efa, efa->e2, uvedges); | 
					
						
							|  |  |  | 		if(efa->e3->f1) append_weldedUVEdge(em, efa, efa->e3, uvedges); | 
					
						
							|  |  |  | 		if(efa->e4 && efa->e4->f1) append_weldedUVEdge(em, efa, efa->e4, uvedges); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	//link vertices: for each uvedge, search uvverts to populate v1 and v2 pointers
 | 
					
						
							|  |  |  | 	for(curwedge=uvedges->first; curwedge; curwedge=curwedge->next){ | 
					
						
							|  |  |  | 		for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){ | 
					
						
							|  |  |  | 			if(curwedge->eed->v1 == curwvert->eve && curwedge->v1uv[0] == curwvert->u && curwedge->v1uv[1] == curwvert->v){ | 
					
						
							|  |  |  | 				curwedge->v1 = curwvert; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){ | 
					
						
							|  |  |  | 			if(curwedge->eed->v2 == curwvert->eve && curwedge->v2uv[0] == curwvert->u && curwedge->v2uv[1] == curwvert->v){ | 
					
						
							|  |  |  | 				curwedge->v2 = curwvert; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void free_weldedUVs(ListBase *uvverts) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	wUV *curwvert; | 
					
						
							|  |  |  | 	for(curwvert = uvverts->first; curwvert; curwvert=curwvert->next) BLI_freelistN(&(curwvert->nodes)); | 
					
						
							|  |  |  | 	BLI_freelistN(uvverts); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void collapse_edgeuvs(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ListBase uvedges, uvverts, allcollections; | 
					
						
							|  |  |  | 	wUVEdge *curwedge; | 
					
						
							|  |  |  | 	wUVNode *curwnode; | 
					
						
							|  |  |  | 	wUVEdgeCollect *collectedwuve, *newcollectedwuve; | 
					
						
							|  |  |  | 	Collection *wuvecollection, *newcollection; | 
					
						
							|  |  |  | 	int curtag, balanced, collectionfound= 0, vcount; | 
					
						
							|  |  |  | 	float avg[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!EM_texFaceCheck(em)) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	uvverts.first = uvverts.last = uvedges.first = uvedges.last = allcollections.first = allcollections.last = NULL; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	build_weldedUVs(em, &uvverts); | 
					
						
							|  |  |  | 	build_weldedUVEdges(em, &uvedges, &uvverts); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	curtag = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){ | 
					
						
							|  |  |  | 		curwedge->v1->f = curtag; | 
					
						
							|  |  |  | 		curwedge->v2->f = curtag; | 
					
						
							|  |  |  | 		curtag +=1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	balanced = 0; | 
					
						
							|  |  |  | 	while(!balanced){ | 
					
						
							|  |  |  | 		balanced = 1; | 
					
						
							|  |  |  | 		for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){ | 
					
						
							|  |  |  | 			if(curwedge->v1->f != curwedge->v2->f){ | 
					
						
							|  |  |  | 				if(curwedge->v1->f > curwedge->v2->f) curwedge->v1->f = curwedge->v2->f; | 
					
						
							|  |  |  | 				else curwedge->v2->f = curwedge->v1->f; | 
					
						
							|  |  |  | 				balanced = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next) curwedge->f = curwedge->v1->f; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){ | 
					
						
							|  |  |  | 		if(allcollections.first){ | 
					
						
							|  |  |  | 			for(wuvecollection = allcollections.first; wuvecollection; wuvecollection=wuvecollection->next){ | 
					
						
							|  |  |  | 				if(wuvecollection->index == curwedge->f){ | 
					
						
							|  |  |  | 					newcollectedwuve = MEM_callocN(sizeof(wUVEdgeCollect), "Collected Welded UV Edge"); | 
					
						
							|  |  |  | 					newcollectedwuve->uved = curwedge; | 
					
						
							|  |  |  | 					BLI_addtail(&(wuvecollection->collectionbase), newcollectedwuve); | 
					
						
							|  |  |  | 					collectionfound = 1; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				else collectionfound = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(allcollections.first == NULL || collectionfound == 0){ | 
					
						
							|  |  |  | 			newcollection = MEM_callocN(sizeof(Collection), "element collection"); | 
					
						
							|  |  |  | 			newcollection->index = curwedge->f; | 
					
						
							|  |  |  | 			newcollection->collectionbase.first = 0; | 
					
						
							|  |  |  | 			newcollection->collectionbase.last = 0; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 			newcollectedwuve = MEM_callocN(sizeof(wUVEdgeCollect), "Collected Welded UV Edge"); | 
					
						
							|  |  |  | 			newcollectedwuve->uved = curwedge; | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 			BLI_addtail(&(newcollection->collectionbase), newcollectedwuve); | 
					
						
							|  |  |  | 			BLI_addtail(&allcollections, newcollection); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	for(wuvecollection=allcollections.first; wuvecollection; wuvecollection=wuvecollection->next){ | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		vcount = avg[0] = avg[1] = 0; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for(collectedwuve= wuvecollection->collectionbase.first; collectedwuve; collectedwuve = collectedwuve->next){ | 
					
						
							|  |  |  | 			avg[0] += collectedwuve->uved->v1uv[0]; | 
					
						
							|  |  |  | 			avg[1] += collectedwuve->uved->v1uv[1]; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			avg[0] += collectedwuve->uved->v2uv[0]; | 
					
						
							|  |  |  | 			avg[1] += collectedwuve->uved->v2uv[1]; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			vcount +=2; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		avg[0] /= vcount; avg[1] /= vcount; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for(collectedwuve= wuvecollection->collectionbase.first; collectedwuve; collectedwuve = collectedwuve->next){ | 
					
						
							|  |  |  | 			for(curwnode=collectedwuve->uved->v1->nodes.first; curwnode; curwnode=curwnode->next){ | 
					
						
							|  |  |  | 				*(curwnode->u) = avg[0]; | 
					
						
							|  |  |  | 				*(curwnode->v) = avg[1]; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			for(curwnode=collectedwuve->uved->v2->nodes.first; curwnode; curwnode=curwnode->next){ | 
					
						
							|  |  |  | 				*(curwnode->u) = avg[0]; | 
					
						
							|  |  |  | 				*(curwnode->v) = avg[1]; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	free_weldedUVs(&uvverts); | 
					
						
							|  |  |  | 	BLI_freelistN(&uvedges); | 
					
						
							|  |  |  | 	freecollections(&allcollections); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*End UV Edge collapse code*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void collapseuvs(EditMesh *em, EditVert *mergevert) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	MTFace *tf; | 
					
						
							|  |  |  | 	int uvcount; | 
					
						
							|  |  |  | 	float uvav[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!EM_texFaceCheck(em)) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	uvcount = 0; | 
					
						
							|  |  |  | 	uvav[0] = 0; | 
					
						
							|  |  |  | 	uvav[1] = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(efa = em->faces.first; efa; efa=efa->next){ | 
					
						
							|  |  |  | 		tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(efa->v1->f1 && ELEM(mergevert, NULL, efa->v1)) { | 
					
						
							|  |  |  | 			uvav[0] += tf->uv[0][0]; | 
					
						
							|  |  |  | 			uvav[1] += tf->uv[0][1]; | 
					
						
							|  |  |  | 			uvcount += 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(efa->v2->f1 && ELEM(mergevert, NULL, efa->v2)){ | 
					
						
							|  |  |  | 			uvav[0] += tf->uv[1][0];		 | 
					
						
							|  |  |  | 			uvav[1] += tf->uv[1][1]; | 
					
						
							|  |  |  | 			uvcount += 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(efa->v3->f1 && ELEM(mergevert, NULL, efa->v3)){ | 
					
						
							|  |  |  | 			uvav[0] += tf->uv[2][0]; | 
					
						
							|  |  |  | 			uvav[1] += tf->uv[2][1]; | 
					
						
							|  |  |  | 			uvcount += 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(efa->v4 && efa->v4->f1 && ELEM(mergevert, NULL, efa->v4)){ | 
					
						
							|  |  |  | 			uvav[0] += tf->uv[3][0]; | 
					
						
							|  |  |  | 			uvav[1] += tf->uv[3][1]; | 
					
						
							|  |  |  | 			uvcount += 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(uvcount > 0) { | 
					
						
							|  |  |  | 		uvav[0] /= uvcount;  | 
					
						
							|  |  |  | 		uvav[1] /= uvcount; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		for(efa = em->faces.first; efa; efa=efa->next){ | 
					
						
							|  |  |  | 			tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(efa->v1->f1){ | 
					
						
							|  |  |  | 				tf->uv[0][0] = uvav[0]; | 
					
						
							|  |  |  | 				tf->uv[0][1] = uvav[1]; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(efa->v2->f1){ | 
					
						
							|  |  |  | 				tf->uv[1][0] = uvav[0];		 | 
					
						
							|  |  |  | 				tf->uv[1][1] = uvav[1]; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(efa->v3->f1){ | 
					
						
							|  |  |  | 				tf->uv[2][0] = uvav[0]; | 
					
						
							|  |  |  | 				tf->uv[2][1] = uvav[1]; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(efa->v4 && efa->v4->f1){ | 
					
						
							|  |  |  | 				tf->uv[3][0] = uvav[0]; | 
					
						
							|  |  |  | 				tf->uv[3][1] = uvav[1]; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int collapseEdges(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	ListBase allcollections; | 
					
						
							|  |  |  | 	CollectedEdge *curredge; | 
					
						
							|  |  |  | 	Collection *edgecollection; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	int totedges, groupcount, mergecount,vcount; | 
					
						
							|  |  |  | 	float avgcount[3]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	allcollections.first = 0; | 
					
						
							|  |  |  | 	allcollections.last = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	mergecount = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	build_edgecollection(em, &allcollections); | 
					
						
							|  |  |  | 	groupcount = BLI_countlist(&allcollections); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(edgecollection = allcollections.first; edgecollection; edgecollection = edgecollection->next){ | 
					
						
							|  |  |  | 		totedges = BLI_countlist(&(edgecollection->collectionbase)); | 
					
						
							|  |  |  | 		mergecount += totedges; | 
					
						
							|  |  |  | 		avgcount[0] = 0; avgcount[1] = 0; avgcount[2] = 0; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		vcount = 0; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){ | 
					
						
							|  |  |  | 			avgcount[0] += ((EditEdge*)curredge->eed)->v1->co[0]; | 
					
						
							|  |  |  | 			avgcount[1] += ((EditEdge*)curredge->eed)->v1->co[1]; | 
					
						
							|  |  |  | 			avgcount[2] += ((EditEdge*)curredge->eed)->v1->co[2]; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			avgcount[0] += ((EditEdge*)curredge->eed)->v2->co[0]; | 
					
						
							|  |  |  | 			avgcount[1] += ((EditEdge*)curredge->eed)->v2->co[1]; | 
					
						
							|  |  |  | 			avgcount[2] += ((EditEdge*)curredge->eed)->v2->co[2]; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			vcount +=2; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		avgcount[0] /= vcount; avgcount[1] /=vcount; avgcount[2] /= vcount; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){ | 
					
						
							|  |  |  | 			VECCOPY(((EditEdge*)curredge->eed)->v1->co,avgcount); | 
					
						
							|  |  |  | 			VECCOPY(((EditEdge*)curredge->eed)->v2->co,avgcount); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if (EM_texFaceCheck(em)) { | 
					
						
							|  |  |  | 			/*uv collapse*/ | 
					
						
							|  |  |  | 			for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0; | 
					
						
							|  |  |  | 			for(eed=em->edges.first; eed; eed=eed->next) eed->f1 = 0; | 
					
						
							|  |  |  | 			for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){ | 
					
						
							|  |  |  | 				curredge->eed->v1->f1 = 1; | 
					
						
							|  |  |  | 				curredge->eed->v2->f1 = 1; | 
					
						
							|  |  |  | 				curredge->eed->f1 = 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			collapse_edgeuvs(em); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	freecollections(&allcollections); | 
					
						
							|  |  |  | 	removedoublesflag(em, 1, 0, MERGELIMIT); | 
					
						
							|  |  |  | 	/*get rid of this!*/ | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | //	if (EM_texFaceCheck())
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return mergecount; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int merge_firstlast(EditMesh *em, int first, int uvmerge) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve,*mergevert; | 
					
						
							|  |  |  | 	EditSelection *ese; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* do sanity check in mergemenu in edit.c ?*/ | 
					
						
							|  |  |  | 	if(first == 0){  | 
					
						
							|  |  |  | 		ese = em->selected.last; | 
					
						
							|  |  |  | 		mergevert= (EditVert*)ese->data; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else{  | 
					
						
							|  |  |  | 		ese = em->selected.first; | 
					
						
							|  |  |  | 		mergevert = (EditVert*)ese->data; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(mergevert->f&SELECT){ | 
					
						
							|  |  |  | 		for (eve=em->verts.first; eve; eve=eve->next){ | 
					
						
							|  |  |  | 			if (eve->f&SELECT) | 
					
						
							|  |  |  | 			VECCOPY(eve->co,mergevert->co); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(uvmerge && CustomData_has_layer(&em->fdata, CD_MTFACE)){ | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0; | 
					
						
							|  |  |  | 		for(eve=em->verts.first; eve; eve=eve->next){ | 
					
						
							|  |  |  | 			if(eve->f&SELECT) eve->f1 = 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		collapseuvs(em, mergevert); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return removedoublesflag(em, 1, 0, MERGELIMIT); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int merge_target(EditMesh *em, int target, int uvmerge) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(target) snap_sel_to_curs(); | 
					
						
							|  |  |  | 	else snap_to_center(); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(uvmerge && CustomData_has_layer(&em->fdata, CD_MTFACE)){ | 
					
						
							|  |  |  | 		for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0; | 
					
						
							|  |  |  | 		for(eve=em->verts.first; eve; eve=eve->next){ | 
					
						
							|  |  |  | 				if(eve->f&SELECT) eve->f1 = 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		collapseuvs(em, NULL); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return removedoublesflag(em, 1, 0, MERGELIMIT); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #undef MERGELIMIT
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct PathNode{ | 
					
						
							|  |  |  | 	int u; | 
					
						
							|  |  |  | 	int visited; | 
					
						
							|  |  |  | 	ListBase edges; | 
					
						
							|  |  |  | } PathNode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct PathEdge{ | 
					
						
							|  |  |  | 	struct PathEdge *next, *prev; | 
					
						
							|  |  |  | 	int v; | 
					
						
							|  |  |  | 	float w; | 
					
						
							|  |  |  | } PathEdge; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | void pathselect(EditMesh *em, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve, *s, *t; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditSelection *ese; | 
					
						
							|  |  |  | 	PathEdge *newpe, *currpe; | 
					
						
							|  |  |  | 	PathNode *currpn; | 
					
						
							|  |  |  | 	PathNode *Q; | 
					
						
							|  |  |  | 	int v, *previous, pathvert, pnindex; /*pnindex redundant?*/ | 
					
						
							|  |  |  |  	int unbalanced, totnodes; | 
					
						
							|  |  |  | 	short physical; | 
					
						
							|  |  |  | 	float *cost; | 
					
						
							|  |  |  | 	Heap *heap; /*binary heap for sorting pointers to PathNodes based upon a 'cost'*/ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	s = t = NULL; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	ese = ((EditSelection*)em->selected.last); | 
					
						
							|  |  |  | 	if(ese && ese->type == EDITVERT && ese->prev && ese->prev->type == EDITVERT){ | 
					
						
							|  |  |  | 		physical= pupmenu("Distance Method? %t|Edge Length%x1|Topological%x0"); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		t = (EditVert*)ese->data; | 
					
						
							|  |  |  | 		s = (EditVert*)ese->prev->data; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/*need to find out if t is actually reachable by s....*/ | 
					
						
							|  |  |  | 		for(eve=em->verts.first; eve; eve=eve->next){  | 
					
						
							|  |  |  | 			eve->f1 = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		s->f1 = 1; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		unbalanced = 1; | 
					
						
							|  |  |  | 		totnodes = 1; | 
					
						
							|  |  |  | 		while(unbalanced){ | 
					
						
							|  |  |  | 			unbalanced = 0; | 
					
						
							|  |  |  | 			for(eed=em->edges.first; eed; eed=eed->next){ | 
					
						
							|  |  |  | 				if(!eed->h){ | 
					
						
							|  |  |  | 					if(eed->v1->f1 && !eed->v2->f1){  | 
					
						
							|  |  |  | 							eed->v2->f1 = 1; | 
					
						
							|  |  |  | 							totnodes++; | 
					
						
							|  |  |  | 							unbalanced = 1; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					else if(eed->v2->f1 && !eed->v1->f1){ | 
					
						
							|  |  |  | 							eed->v1->f1 = 1; | 
					
						
							|  |  |  | 							totnodes++; | 
					
						
							|  |  |  | 							unbalanced = 1; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if(s->f1 && t->f1){ /*t can be reached by s*/ | 
					
						
							|  |  |  | 			Q = MEM_callocN(sizeof(PathNode)*totnodes, "Path Select Nodes"); | 
					
						
							|  |  |  | 			totnodes = 0; | 
					
						
							|  |  |  | 			for(eve=em->verts.first; eve; eve=eve->next){ | 
					
						
							|  |  |  | 				if(eve->f1){ | 
					
						
							|  |  |  | 					Q[totnodes].u = totnodes; | 
					
						
							|  |  |  | 					Q[totnodes].edges.first = 0; | 
					
						
							|  |  |  | 					Q[totnodes].edges.last = 0; | 
					
						
							|  |  |  | 					Q[totnodes].visited = 0; | 
					
						
							|  |  |  | 					eve->tmp.p = &(Q[totnodes]); | 
					
						
							|  |  |  | 					totnodes++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else eve->tmp.p = NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			for(eed=em->edges.first; eed; eed=eed->next){ | 
					
						
							|  |  |  | 				if(!eed->h){ | 
					
						
							|  |  |  | 					if(eed->v1->f1){ | 
					
						
							|  |  |  | 						currpn = ((PathNode*)eed->v1->tmp.p); | 
					
						
							|  |  |  | 						 | 
					
						
							|  |  |  | 						newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge"); | 
					
						
							|  |  |  | 						newpe->v = ((PathNode*)eed->v2->tmp.p)->u; | 
					
						
							|  |  |  | 						if(physical){ | 
					
						
							|  |  |  | 								newpe->w = VecLenf(eed->v1->co, eed->v2->co); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						else newpe->w = 1; | 
					
						
							|  |  |  | 						newpe->next = 0; | 
					
						
							|  |  |  | 						newpe->prev = 0; | 
					
						
							|  |  |  | 						BLI_addtail(&(currpn->edges), newpe); | 
					
						
							|  |  |  | 					}  | 
					
						
							|  |  |  | 					if(eed->v2->f1){ | 
					
						
							|  |  |  | 						currpn = ((PathNode*)eed->v2->tmp.p);  | 
					
						
							|  |  |  | 						newpe = MEM_mallocN(sizeof(PathEdge), "Path Edge"); | 
					
						
							|  |  |  | 						newpe->v = ((PathNode*)eed->v1->tmp.p)->u; | 
					
						
							|  |  |  | 						if(physical){ | 
					
						
							|  |  |  | 								newpe->w = VecLenf(eed->v1->co, eed->v2->co); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						else newpe->w = 1; | 
					
						
							|  |  |  | 						newpe->next = 0; | 
					
						
							|  |  |  | 						newpe->prev = 0; | 
					
						
							|  |  |  | 						BLI_addtail(&(currpn->edges), newpe); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			heap = BLI_heap_new(); | 
					
						
							|  |  |  | 			cost = MEM_callocN(sizeof(float)*totnodes, "Path Select Costs"); | 
					
						
							|  |  |  | 			previous = MEM_callocN(sizeof(int)*totnodes, "PathNode indices"); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			for(v=0; v < totnodes; v++){ | 
					
						
							|  |  |  | 				cost[v] = 1000000; | 
					
						
							|  |  |  | 				previous[v] = -1; /*array of indices*/ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			pnindex = ((PathNode*)s->tmp.p)->u; | 
					
						
							|  |  |  | 			cost[pnindex] = 0; | 
					
						
							|  |  |  | 			BLI_heap_insert(heap,  0.0f, SET_INT_IN_POINTER(pnindex)); | 
					
						
							|  |  |  | 						 | 
					
						
							|  |  |  | 			while( !BLI_heap_empty(heap) ){ | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				pnindex = GET_INT_FROM_POINTER(BLI_heap_popmin(heap)); | 
					
						
							|  |  |  | 				currpn = &(Q[pnindex]); | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				if(currpn == (PathNode*)t->tmp.p) /*target has been reached....*/ | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				for(currpe=currpn->edges.first; currpe; currpe=currpe->next){ | 
					
						
							|  |  |  | 					if(!Q[currpe->v].visited){ | 
					
						
							|  |  |  | 						if( cost[currpe->v] > (cost[currpn->u ] + currpe->w) ){ | 
					
						
							|  |  |  | 							cost[currpe->v] = cost[currpn->u] + currpe->w; | 
					
						
							|  |  |  | 							previous[currpe->v] = currpn->u; | 
					
						
							|  |  |  | 							Q[currpe->v].visited = 1; | 
					
						
							|  |  |  | 							BLI_heap_insert(heap, cost[currpe->v], SET_INT_IN_POINTER(currpe->v)); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			pathvert = ((PathNode*)t->tmp.p)->u; | 
					
						
							|  |  |  | 			while(pathvert != -1){ | 
					
						
							|  |  |  | 				for(eve=em->verts.first; eve; eve=eve->next){ | 
					
						
							|  |  |  | 					if(eve->f1){ | 
					
						
							|  |  |  | 						if( ((PathNode*)eve->tmp.p)->u == pathvert) eve->f |= SELECT; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				pathvert = previous[pathvert]; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			for(v=0; v < totnodes; v++) BLI_freelistN(&(Q[v].edges)); | 
					
						
							|  |  |  | 			MEM_freeN(Q); | 
					
						
							|  |  |  | 			MEM_freeN(cost); | 
					
						
							|  |  |  | 			MEM_freeN(previous); | 
					
						
							|  |  |  | 			BLI_heap_free(heap, NULL); | 
					
						
							|  |  |  | 			EM_select_flush(em); | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 		//			DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | //			if (EM_texFaceCheck())
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else{ | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "Path Selection requires that exactly two vertices be selected"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | static int region_to_loop(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	if(em->totfacesel){ | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		for(eed=em->edges.first; eed; eed=eed->next) eed->f1 = 0; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for(efa=em->faces.first; efa; efa=efa->next){ | 
					
						
							|  |  |  | 			if(efa->f&SELECT){ | 
					
						
							|  |  |  | 				efa->e1->f1++; | 
					
						
							|  |  |  | 				efa->e2->f1++; | 
					
						
							|  |  |  | 				efa->e3->f1++; | 
					
						
							|  |  |  | 				if(efa->e4) | 
					
						
							|  |  |  | 					efa->e4->f1++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		EM_clear_flag_all(em, SELECT); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for(eed=em->edges.first; eed; eed=eed->next){ | 
					
						
							|  |  |  | 			if(eed->f1 == 1) EM_select_edge(eed, 1); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		em->selectmode = SCE_SELECT_EDGE; | 
					
						
							|  |  |  | 		EM_selectmode_set(em); | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | 	//		DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | //		if (EM_texFaceCheck())
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MESH_OT_region_to_loop(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Region to Loop"; | 
					
						
							|  |  |  | 	ot->idname= "MESH_OT_region_to_loop"; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= region_to_loop; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int validate_loop(EditMesh *em, Collection *edgecollection) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	CollectedEdge *curredge; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*1st test*/ | 
					
						
							|  |  |  | 	for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){ | 
					
						
							|  |  |  | 		curredge->eed->v1->f1 = 0; | 
					
						
							|  |  |  | 		curredge->eed->v2->f1 = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){ | 
					
						
							|  |  |  | 		curredge->eed->v1->f1++; | 
					
						
							|  |  |  | 		curredge->eed->v2->f1++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){ | 
					
						
							|  |  |  | 		if(curredge->eed->v1->f1 > 2) return(0); else | 
					
						
							|  |  |  | 		if(curredge->eed->v2->f1 > 2) return(0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*2nd test*/ | 
					
						
							|  |  |  | 	for(eed = em->edges.first; eed; eed=eed->next) eed->f1 = 0; | 
					
						
							|  |  |  | 	for(efa=em->faces.first; efa; efa=efa->next){ | 
					
						
							|  |  |  | 		efa->e1->f1++; | 
					
						
							|  |  |  | 		efa->e2->f1++; | 
					
						
							|  |  |  | 		efa->e3->f1++; | 
					
						
							|  |  |  | 		if(efa->e4) efa->e4->f1++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){ | 
					
						
							|  |  |  | 		if(curredge->eed->f1 > 2) return(0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return(1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int loop_bisect(EditMesh *em, Collection *edgecollection){ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	EditFace *efa, *sf1, *sf2; | 
					
						
							|  |  |  | 	EditEdge *eed, *sed; | 
					
						
							|  |  |  | 	CollectedEdge *curredge; | 
					
						
							|  |  |  | 	int totsf1, totsf2, unbalanced,balancededges; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(eed=em->edges.first; eed; eed=eed->next) eed->f1 = eed->f2 = 0; | 
					
						
							|  |  |  | 	for(efa=em->faces.first; efa; efa=efa->next) efa->f1 = 0;	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next) curredge->eed->f1 = 1; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	sf1 = sf2 = NULL; | 
					
						
							|  |  |  | 	sed = ((CollectedEdge*)edgecollection->collectionbase.first)->eed; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(efa=em->faces.first; efa; efa=efa->next){ | 
					
						
							|  |  |  | 		if(sf2) break; | 
					
						
							|  |  |  | 		else if(sf1){ | 
					
						
							|  |  |  | 			if(efa->e1 == sed || efa->e2 == sed || efa->e3 == sed || ( (efa->e4) ? efa->e4 == sed : 0) ) sf2 = efa; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else{ | 
					
						
							|  |  |  | 			if(efa->e1 == sed || efa->e2 == sed || efa->e3 == sed || ( (efa->e4) ? efa->e4 == sed : 0) ) sf1 = efa; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(sf1==NULL || sf2==NULL) | 
					
						
							|  |  |  | 		return(-1); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(!(sf1->e1->f1)) sf1->e1->f2 = 1; | 
					
						
							|  |  |  | 	if(!(sf1->e2->f1)) sf1->e2->f2 = 1; | 
					
						
							|  |  |  | 	if(!(sf1->e3->f1)) sf1->e3->f2 = 1; | 
					
						
							|  |  |  | 	if(sf1->e4 && !(sf1->e4->f1)) sf1->e4->f2 = 1; | 
					
						
							|  |  |  | 	sf1->f1 = 1; | 
					
						
							|  |  |  | 	totsf1 = 1; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(!(sf2->e1->f1)) sf2->e1->f2 = 2; | 
					
						
							|  |  |  | 	if(!(sf2->e2->f1)) sf2->e2->f2 = 2; | 
					
						
							|  |  |  | 	if(!(sf2->e3->f1)) sf2->e3->f2 = 2; | 
					
						
							|  |  |  | 	if(sf2->e4 && !(sf2->e4->f1)) sf2->e4->f2 = 2; | 
					
						
							|  |  |  | 	sf2->f1 = 2; | 
					
						
							|  |  |  | 	totsf2 = 1; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*do sf1*/ | 
					
						
							|  |  |  | 	unbalanced = 1; | 
					
						
							|  |  |  | 	while(unbalanced){ | 
					
						
							|  |  |  | 		unbalanced = 0; | 
					
						
							|  |  |  | 		for(efa=em->faces.first; efa; efa=efa->next){ | 
					
						
							|  |  |  | 			balancededges = 0; | 
					
						
							|  |  |  | 			if(efa->f1 == 0){ | 
					
						
							|  |  |  | 				if(efa->e1->f2 == 1 || efa->e2->f2 == 1 || efa->e3->f2 == 1 || ( (efa->e4) ? efa->e4->f2 == 1 : 0) ){ | 
					
						
							|  |  |  | 					balancededges += efa->e1->f2 = (efa->e1->f1) ? 0 : 1; | 
					
						
							|  |  |  | 					balancededges += efa->e2->f2 = (efa->e2->f1) ? 0 : 1; | 
					
						
							|  |  |  | 					balancededges += efa->e3->f2 = (efa->e3->f1) ? 0 : 1; | 
					
						
							|  |  |  | 					if(efa->e4) balancededges += efa->e4->f2 = (efa->e4->f1) ? 0 : 1; | 
					
						
							|  |  |  | 					if(balancededges){ | 
					
						
							|  |  |  | 						unbalanced = 1; | 
					
						
							|  |  |  | 						efa->f1 = 1; | 
					
						
							|  |  |  | 						totsf1++; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*do sf2*/ | 
					
						
							|  |  |  | 	unbalanced = 1; | 
					
						
							|  |  |  | 	while(unbalanced){ | 
					
						
							|  |  |  | 		unbalanced = 0; | 
					
						
							|  |  |  | 		for(efa=em->faces.first; efa; efa=efa->next){ | 
					
						
							|  |  |  | 			balancededges = 0; | 
					
						
							|  |  |  | 			if(efa->f1 == 0){ | 
					
						
							|  |  |  | 				if(efa->e1->f2 == 2 || efa->e2->f2 == 2 || efa->e3->f2 == 2 || ( (efa->e4) ? efa->e4->f2 == 2 : 0) ){ | 
					
						
							|  |  |  | 					balancededges += efa->e1->f2 = (efa->e1->f1) ? 0 : 2; | 
					
						
							|  |  |  | 					balancededges += efa->e2->f2 = (efa->e2->f1) ? 0 : 2; | 
					
						
							|  |  |  | 					balancededges += efa->e3->f2 = (efa->e3->f1) ? 0 : 2; | 
					
						
							|  |  |  | 					if(efa->e4) balancededges += efa->e4->f2 = (efa->e4->f1) ? 0 : 2; | 
					
						
							|  |  |  | 					if(balancededges){ | 
					
						
							|  |  |  | 						unbalanced = 1; | 
					
						
							|  |  |  | 						efa->f1 = 2; | 
					
						
							|  |  |  | 						totsf2++; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	if(totsf1 < totsf2) return(1); | 
					
						
							|  |  |  | 	else return(2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | static int loop_to_region(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	ListBase allcollections={NULL,NULL}; | 
					
						
							|  |  |  | 	Collection *edgecollection; | 
					
						
							|  |  |  | 	int testflag; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	build_edgecollection(em, &allcollections); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(edgecollection = (Collection *)allcollections.first; edgecollection; edgecollection=edgecollection->next){ | 
					
						
							|  |  |  | 		if(validate_loop(em, edgecollection)){ | 
					
						
							|  |  |  | 			testflag = loop_bisect(em, edgecollection); | 
					
						
							|  |  |  | 			for(efa=em->faces.first; efa; efa=efa->next){ | 
					
						
							|  |  |  | 				if(efa->f1 == testflag){ | 
					
						
							|  |  |  | 					if(efa->f&SELECT) EM_select_face(efa, 0); | 
					
						
							|  |  |  | 					else EM_select_face(efa,1); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(efa=em->faces.first; efa; efa=efa->next){ /*fix this*/ | 
					
						
							|  |  |  | 		if(efa->f&SELECT) EM_select_face(efa,1); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	freecollections(&allcollections); | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //	DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | //	if (EM_texFaceCheck())
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | void MESH_OT_loop_to_region(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Loop to Region"; | 
					
						
							|  |  |  | 	ot->idname= "MESH_OT_loop_to_region"; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= loop_to_region; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // XXX please check if these functions do what you want them to
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | /* texface and vertex color editmode tools for the face menu */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | static int mesh_rotate_uvs(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	short change = 0, ccw; | 
					
						
							|  |  |  | 	MTFace *tf; | 
					
						
							|  |  |  | 	float u1, v1; | 
					
						
							|  |  |  | 	int shift = 0; // XXX
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!EM_texFaceCheck(em)) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "mesh has no uv/image layers"); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 		BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	ccw = (shift); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(efa=em->faces.first; efa; efa=efa->next) { | 
					
						
							|  |  |  | 		if (efa->f & SELECT) { | 
					
						
							|  |  |  | 			tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | 
					
						
							|  |  |  | 			u1= tf->uv[0][0]; | 
					
						
							|  |  |  | 			v1= tf->uv[0][1]; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if (ccw) { | 
					
						
							|  |  |  | 				if(efa->v4) { | 
					
						
							|  |  |  | 					tf->uv[0][0]= tf->uv[3][0]; | 
					
						
							|  |  |  | 					tf->uv[0][1]= tf->uv[3][1]; | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 					tf->uv[3][0]= tf->uv[2][0]; | 
					
						
							|  |  |  | 					tf->uv[3][1]= tf->uv[2][1]; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					tf->uv[0][0]= tf->uv[2][0]; | 
					
						
							|  |  |  | 					tf->uv[0][1]= tf->uv[2][1]; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				tf->uv[2][0]= tf->uv[1][0]; | 
					
						
							|  |  |  | 				tf->uv[2][1]= tf->uv[1][1]; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				tf->uv[1][0]= u1; | 
					
						
							|  |  |  | 				tf->uv[1][1]= v1; | 
					
						
							|  |  |  | 			} else {	 | 
					
						
							|  |  |  | 				tf->uv[0][0]= tf->uv[1][0]; | 
					
						
							|  |  |  | 				tf->uv[0][1]= tf->uv[1][1]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 				tf->uv[1][0]= tf->uv[2][0]; | 
					
						
							|  |  |  | 				tf->uv[1][1]= tf->uv[2][1]; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				if(efa->v4) { | 
					
						
							|  |  |  | 					tf->uv[2][0]= tf->uv[3][0]; | 
					
						
							|  |  |  | 					tf->uv[2][1]= tf->uv[3][1]; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 					tf->uv[3][0]= u1; | 
					
						
							|  |  |  | 					tf->uv[3][1]= v1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					tf->uv[2][0]= u1; | 
					
						
							|  |  |  | 					tf->uv[2][1]= v1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			change = 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (change) { | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //		DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 		WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | static int mesh_mirror_uvs(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	short change = 0, altaxis; | 
					
						
							|  |  |  | 	MTFace *tf; | 
					
						
							|  |  |  | 	float u1, v1; | 
					
						
							|  |  |  | 	int shift= 0; // XXX
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (!EM_texFaceCheck(em)) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "mesh has no uv/image layers"); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 		BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	altaxis = (shift); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(efa=em->faces.first; efa; efa=efa->next) { | 
					
						
							|  |  |  | 		if (efa->f & SELECT) { | 
					
						
							|  |  |  | 			tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | 
					
						
							|  |  |  | 			if (altaxis) { | 
					
						
							|  |  |  | 				u1= tf->uv[1][0]; | 
					
						
							|  |  |  | 				v1= tf->uv[1][1]; | 
					
						
							|  |  |  | 				if(efa->v4) { | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 					tf->uv[1][0]= tf->uv[2][0]; | 
					
						
							|  |  |  | 					tf->uv[1][1]= tf->uv[2][1]; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 					tf->uv[2][0]= u1; | 
					
						
							|  |  |  | 					tf->uv[2][1]= v1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					u1= tf->uv[3][0]; | 
					
						
							|  |  |  | 					v1= tf->uv[3][1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					tf->uv[3][0]= tf->uv[0][0]; | 
					
						
							|  |  |  | 					tf->uv[3][1]= tf->uv[0][1]; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 					tf->uv[0][0]= u1; | 
					
						
							|  |  |  | 					tf->uv[0][1]= v1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					tf->uv[1][0]= tf->uv[2][0]; | 
					
						
							|  |  |  | 					tf->uv[1][1]= tf->uv[2][1]; | 
					
						
							|  |  |  | 					tf->uv[2][0]= u1; | 
					
						
							|  |  |  | 					tf->uv[2][1]= v1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				u1= tf->uv[0][0]; | 
					
						
							|  |  |  | 				v1= tf->uv[0][1]; | 
					
						
							|  |  |  | 				if(efa->v4) { | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 					tf->uv[0][0]= tf->uv[1][0]; | 
					
						
							|  |  |  | 					tf->uv[0][1]= tf->uv[1][1]; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 					tf->uv[1][0]= u1; | 
					
						
							|  |  |  | 					tf->uv[1][1]= v1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					u1= tf->uv[3][0]; | 
					
						
							|  |  |  | 					v1= tf->uv[3][1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					tf->uv[3][0]= tf->uv[2][0]; | 
					
						
							|  |  |  | 					tf->uv[3][1]= tf->uv[2][1]; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 					tf->uv[2][0]= u1; | 
					
						
							|  |  |  | 					tf->uv[2][1]= v1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					tf->uv[0][0]= tf->uv[1][0]; | 
					
						
							|  |  |  | 					tf->uv[0][1]= tf->uv[1][1]; | 
					
						
							|  |  |  | 					tf->uv[1][0]= u1; | 
					
						
							|  |  |  | 					tf->uv[1][1]= v1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			change = 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (change) { | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //		DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 		WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-03-30 07:28:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | static int mesh_rotate_colors(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	short change = 0, ccw; | 
					
						
							|  |  |  | 	MCol tmpcol, *mcol; | 
					
						
							|  |  |  | 	int shift= 0; // XXX
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (!EM_vertColorCheck(em)) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "mesh has no color layers"); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 		BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	ccw = (shift); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(efa=em->faces.first; efa; efa=efa->next) { | 
					
						
							|  |  |  | 		if (efa->f & SELECT) { | 
					
						
							|  |  |  | 			mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); | 
					
						
							|  |  |  | 			tmpcol= mcol[0]; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if (ccw) { | 
					
						
							|  |  |  | 				if(efa->v4) { | 
					
						
							|  |  |  | 					mcol[0]= mcol[3]; | 
					
						
							|  |  |  | 					mcol[3]= mcol[2]; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					mcol[0]= mcol[2]; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				mcol[2]= mcol[1]; | 
					
						
							|  |  |  | 				mcol[1]= tmpcol; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				mcol[0]= mcol[1]; | 
					
						
							|  |  |  | 				mcol[1]= mcol[2]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 				if(efa->v4) { | 
					
						
							|  |  |  | 					mcol[2]= mcol[3]; | 
					
						
							|  |  |  | 					mcol[3]= tmpcol; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					mcol[2]= tmpcol; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			change = 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (change) { | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //		DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 		WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	}	 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | static int mesh_mirror_colors(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	short change = 0, altaxis; | 
					
						
							|  |  |  | 	MCol tmpcol, *mcol; | 
					
						
							|  |  |  | 	int shift= 0; // XXX
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (!EM_vertColorCheck(em)) { | 
					
						
							| 
									
										
										
										
											2009-02-14 21:31:34 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_ERROR, "Mesh has no color layers"); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 		BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	altaxis = (shift); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(efa=em->faces.first; efa; efa=efa->next) { | 
					
						
							|  |  |  | 		if (efa->f & SELECT) { | 
					
						
							|  |  |  | 			mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); | 
					
						
							|  |  |  | 			if (altaxis) { | 
					
						
							|  |  |  | 				tmpcol= mcol[1]; | 
					
						
							|  |  |  | 				mcol[1]= mcol[2]; | 
					
						
							|  |  |  | 				mcol[2]= tmpcol; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				if(efa->v4) { | 
					
						
							|  |  |  | 					tmpcol= mcol[0]; | 
					
						
							|  |  |  | 					mcol[0]= mcol[3]; | 
					
						
							|  |  |  | 					mcol[3]= tmpcol; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				tmpcol= mcol[0]; | 
					
						
							|  |  |  | 				mcol[0]= mcol[1]; | 
					
						
							|  |  |  | 				mcol[1]= tmpcol; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				if(efa->v4) { | 
					
						
							|  |  |  | 					tmpcol= mcol[2]; | 
					
						
							|  |  |  | 					mcol[2]= mcol[3]; | 
					
						
							|  |  |  | 					mcol[3]= tmpcol; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			change = 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (change) { | 
					
						
							| 
									
										
										
										
											2009-01-04 14:14:06 +00:00
										 |  |  | //		DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 		WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-12 17:54:07 +00:00
										 |  |  | void MESH_OT_uvs_rotate(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Rotate UVs"; | 
					
						
							| 
									
										
										
										
											2009-04-12 17:54:07 +00:00
										 |  |  | 	ot->idname= "MESH_OT_uvs_rotate"; | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= mesh_rotate_uvs; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-12 17:54:07 +00:00
										 |  |  | void MESH_OT_uvs_mirror(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Mirror UVs"; | 
					
						
							| 
									
										
										
										
											2009-04-12 17:54:07 +00:00
										 |  |  | 	ot->idname= "MESH_OT_uvs_mirror"; | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= mesh_mirror_uvs; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-12 17:54:07 +00:00
										 |  |  | void MESH_OT_colors_rotate(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Rotate Colors"; | 
					
						
							| 
									
										
										
										
											2009-04-12 17:54:07 +00:00
										 |  |  | 	ot->idname= "MESH_OT_colors_rotate"; | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= mesh_rotate_colors; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-12 17:54:07 +00:00
										 |  |  | void MESH_OT_colors_mirror(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Mirror Colors"; | 
					
						
							| 
									
										
										
										
											2009-04-12 17:54:07 +00:00
										 |  |  | 	ot->idname= "MESH_OT_colors_mirror"; | 
					
						
							| 
									
										
										
										
											2009-02-07 23:20:36 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= mesh_mirror_colors; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int subdivide_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							|  |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	esubdivideflag(obedit, em, 1, 0.0, scene->toolsettings->editbutflag, 1, 0); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 	return OPERATOR_FINISHED;	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MESH_OT_subdivide(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Subdivide"; | 
					
						
							|  |  |  | 	ot->idname= "MESH_OT_subdivide"; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= subdivide_exec; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int subdivide_multi_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							|  |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-16 23:53:11 +00:00
										 |  |  | 	esubdivideflag(obedit, em, 1, 0.0, scene->toolsettings->editbutflag, RNA_int_get(op->ptr,"number_cuts"), 0); | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 	return OPERATOR_FINISHED;	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MESH_OT_subdivide_multi(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Subdivide Multi"; | 
					
						
							|  |  |  | 	ot->idname= "MESH_OT_subdivide_multi"; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= subdivide_multi_exec; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 	/* flags */ | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* props */ | 
					
						
							| 
									
										
										
										
											2009-02-09 22:59:26 +00:00
										 |  |  | 	RNA_def_int(ot->srna, "number_cuts", 4, 1, 100, "Number of Cuts", "", 1, INT_MAX); | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int subdivide_multi_fractal_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							|  |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-16 23:53:11 +00:00
										 |  |  | 	esubdivideflag(obedit, em, 1, -(RNA_float_get(op->ptr, "random_factor")/100), scene->toolsettings->editbutflag, RNA_int_get(op->ptr, "number_cuts"), 0); | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 	return OPERATOR_FINISHED;	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MESH_OT_subdivide_multi_fractal(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Subdivide Multi Fractal"; | 
					
						
							|  |  |  | 	ot->idname= "MESH_OT_subdivide_multi_fractal"; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= subdivide_multi_fractal_exec; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-16 23:53:11 +00:00
										 |  |  | 	/* properties */ | 
					
						
							| 
									
										
										
										
											2009-02-09 22:59:26 +00:00
										 |  |  | 	RNA_def_int(ot->srna, "number_cuts", 4, 1, 100, "Number of Cuts", "", 1, INT_MAX); | 
					
						
							| 
									
										
										
										
											2009-01-16 23:53:11 +00:00
										 |  |  | 	RNA_def_float(ot->srna, "random_factor", 5.0, 0.0f, FLT_MAX, "Random Factor", "", 0.0f, 1000.0f); | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int subdivide_smooth_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							|  |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-16 23:53:11 +00:00
										 |  |  | 	esubdivideflag(obedit, em, 1, 0.292f*RNA_float_get(op->ptr, "smoothness"), scene->toolsettings->editbutflag | B_SMOOTH, 1, 0); | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 	return OPERATOR_FINISHED;	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MESH_OT_subdivide_smooth(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Subdivide Smooth"; | 
					
						
							|  |  |  | 	ot->idname= "MESH_OT_subdivide_smooth"; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= subdivide_smooth_exec; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2009-01-16 04:48:33 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* props */ | 
					
						
							| 
									
										
										
										
											2009-02-11 23:02:21 +00:00
										 |  |  | 	RNA_def_float(ot->srna, "smoothness", 1.0f, 0.0f, 1000.0f, "Smoothness", "", 0.0f, FLT_MAX); | 
					
						
							| 
									
										
										
										
											2009-01-16 23:53:11 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-01-19 18:36:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int subdivs_invoke(bContext *C, wmOperator *op, wmEvent *event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-22 18:39:44 +00:00
										 |  |  | 	uiPopupMenu *pup; | 
					
						
							|  |  |  | 	uiLayout *layout; | 
					
						
							| 
									
										
										
										
											2009-02-04 11:52:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												UI: Layout Engine
* Buttons are now created first, and after that the layout is computed.
  This means the layout engine now works at button level, and makes it
  easier to write templates. Otherwise you had to store all info and
  create the buttons later.
* Added interface_templates.c as a separate file to put templates in.
  These can contain regular buttons, and can be put in a Free layout,
  which means you can specify manual coordinates, but still get nested
  correct inside other layouts.
* API was changed to allow better nesting. Previously items were added
  in the last added layout specifier, i.e. one level up in the layout
  hierarchy. This doesn't work well in always, so now when creating things
  like rows or columns it always returns a layout which you have to add
  the items in. All py scripts were updated to follow this.
* Computing the layout now goes in two passes, first estimating the
  required width/height of all nested layouts, and then in the second
  pass using the results of that to decide on the actual locations.
* Enum and array buttons now follow the direction of the layout, i.e.
  they are vertical or horizontal depending if they are in a column or row.
* Color properties now get a color picker, and only get the additional
  RGB sliders with Expand=True.
* File/directory string properties now get a button next to them for
  opening the file browse, though this is not implemented yet.
* Layout items can now be aligned, set align=True when creating a column,
  row, etc.
* Buttons now get a minimum width of one icon (avoids squashing icon
  buttons).
* Moved some more space variables into Style.
											
										 
											2009-05-15 11:19:59 +00:00
										 |  |  | 	pup= uiPupMenuBegin(C, "Subdivision Type", 0); | 
					
						
							| 
									
										
										
										
											2009-04-22 18:39:44 +00:00
										 |  |  | 	layout= uiPupMenuLayout(pup); | 
					
						
							|  |  |  | 	uiItemsEnumO(layout, "MESH_OT_subdivs", "type"); | 
					
						
							|  |  |  | 	uiPupMenuEnd(C, pup); | 
					
						
							| 
									
										
										
										
											2009-01-19 18:36:54 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-02-04 11:52:16 +00:00
										 |  |  | 	return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2009-01-19 18:36:54 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int subdivs_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | {	 | 
					
						
							| 
									
										
										
										
											2009-02-04 11:52:16 +00:00
										 |  |  | 	switch(RNA_int_get(op->ptr, "type")) | 
					
						
							| 
									
										
										
										
											2009-01-19 18:36:54 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-02-04 11:52:16 +00:00
										 |  |  | 		case 0: // simple
 | 
					
						
							| 
									
										
										
										
											2009-01-19 18:36:54 +00:00
										 |  |  | 			subdivide_exec(C,op); | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-02-04 11:52:16 +00:00
										 |  |  | 		case 1: // multi
 | 
					
						
							| 
									
										
										
										
											2009-01-19 18:36:54 +00:00
										 |  |  | 			subdivide_multi_exec(C,op); | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-02-04 11:52:16 +00:00
										 |  |  | 		case 2: // fractal;
 | 
					
						
							| 
									
										
										
										
											2009-01-19 18:36:54 +00:00
										 |  |  | 			subdivide_multi_fractal_exec(C,op); | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-02-04 11:52:16 +00:00
										 |  |  | 		case 3: //smooth
 | 
					
						
							| 
									
										
										
										
											2009-01-19 18:36:54 +00:00
										 |  |  | 			subdivide_smooth_exec(C,op); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 					  | 
					
						
							|  |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MESH_OT_subdivs(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-02-04 11:52:16 +00:00
										 |  |  | 	static EnumPropertyItem type_items[]= { | 
					
						
							| 
									
										
										
										
											2009-06-16 00:52:21 +00:00
										 |  |  | 		{0, "SIMPLE", 0, "Simple", ""}, | 
					
						
							|  |  |  | 		{1, "MULTI", 0, "Multi", ""}, | 
					
						
							|  |  |  | 		{2, "FRACTAL", 0, "Fractal", ""}, | 
					
						
							|  |  |  | 		{3, "SMOOTH", 0, "Smooth", ""}, | 
					
						
							|  |  |  | 		{0, NULL, 0, NULL, NULL}}; | 
					
						
							| 
									
										
										
										
											2009-02-04 11:52:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-19 18:36:54 +00:00
										 |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "subdivs"; | 
					
						
							|  |  |  | 	ot->idname= "MESH_OT_subdivs"; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->invoke= subdivs_invoke; | 
					
						
							|  |  |  | 	ot->exec= subdivs_exec; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-19 18:36:54 +00:00
										 |  |  | 	/*props */ | 
					
						
							| 
									
										
										
										
											2009-02-04 11:52:16 +00:00
										 |  |  | 	RNA_def_enum(ot->srna, "type", type_items, 0, "Type", ""); | 
					
						
							| 
									
										
										
										
											2009-01-19 18:36:54 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* this is temp, the ops are different, but they are called from subdivs, so all the possible props should be here as well*/ | 
					
						
							| 
									
										
										
										
											2009-02-09 22:59:26 +00:00
										 |  |  | 	RNA_def_int(ot->srna, "number_cuts", 4, 1, 10, "Number of Cuts", "", 1, INT_MAX); | 
					
						
							| 
									
										
										
										
											2009-01-19 18:36:54 +00:00
										 |  |  | 	RNA_def_float(ot->srna, "random_factor", 5.0, 0.0f, FLT_MAX, "Random Factor", "", 0.0f, 1000.0f); | 
					
						
							| 
									
										
										
										
											2009-02-11 23:02:21 +00:00
										 |  |  | 	RNA_def_float(ot->srna, "smoothness", 1.0f, 0.0f, 1000.0f, "Smoothness", "", 0.0f, FLT_MAX); | 
					
						
							| 
									
										
										
										
											2009-01-19 18:36:54 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | /* ************************************* */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* note; the EM_selectmode_set() calls here illustrate how badly constructed it all is... from before the
 | 
					
						
							|  |  |  | edge/face flags, with very mixed results.... */ | 
					
						
							|  |  |  | static void beauty_fill(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *v1, *v2, *v3, *v4; | 
					
						
							|  |  |  | 	EditEdge *eed, *nexted; | 
					
						
							|  |  |  | 	EditEdge dia1, dia2; | 
					
						
							|  |  |  | 	EditFace *efa, *w; | 
					
						
							|  |  |  | 	// void **efaar, **efaa;
 | 
					
						
							|  |  |  | 	EVPTuple *efaar; | 
					
						
							|  |  |  | 	EVPtr *efaa; | 
					
						
							|  |  |  | 	float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2; | 
					
						
							|  |  |  | 	int totedge, ok, notbeauty=8, onedone, vindex[4]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* - all selected edges with two faces
 | 
					
						
							|  |  |  | 		* - find the faces: store them in edges (using datablock) | 
					
						
							|  |  |  | 		* - per edge: - test convex | 
					
						
							|  |  |  | 		*			   - test edge: flip? | 
					
						
							|  |  |  | 		*			   - if true: remedge,  addedge, all edges at the edge get new face pointers | 
					
						
							|  |  |  | 		*/ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	EM_selectmode_set(em);	// makes sure in selectmode 'face' the edges of selected faces are selected too 
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	totedge = count_selected_edges(em->edges.first); | 
					
						
							|  |  |  | 	if(totedge==0) return; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* temp block with face pointers */ | 
					
						
							|  |  |  | 	efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "beautyfill"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	while (notbeauty) { | 
					
						
							|  |  |  | 		notbeauty--; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		ok = collect_quadedges(efaar, em->edges.first, em->faces.first); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/* there we go */ | 
					
						
							|  |  |  | 		onedone= 0; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		eed= em->edges.first; | 
					
						
							|  |  |  | 		while(eed) { | 
					
						
							|  |  |  | 			nexted= eed->next; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			/* f2 is set in collect_quadedges() */ | 
					
						
							|  |  |  | 			if(eed->f2==2 && eed->h==0) { | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				efaa = (EVPtr *) eed->tmp.p; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				/* none of the faces should be treated before, nor be part of fgon */ | 
					
						
							|  |  |  | 				ok= 1; | 
					
						
							|  |  |  | 				efa= efaa[0]; | 
					
						
							|  |  |  | 				if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0; | 
					
						
							|  |  |  | 				if(efa->fgonf) ok= 0; | 
					
						
							|  |  |  | 				efa= efaa[1]; | 
					
						
							|  |  |  | 				if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0; | 
					
						
							|  |  |  | 				if(efa->fgonf) ok= 0; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				if(ok) { | 
					
						
							|  |  |  | 					/* test convex */ | 
					
						
							|  |  |  | 					givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex); | 
					
						
							|  |  |  | 					if(v1 && v2 && v3 && v4) { | 
					
						
							|  |  |  | 						if( convex(v1->co, v2->co, v3->co, v4->co) ) { | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 							/* test edges */ | 
					
						
							|  |  |  | 							if( (v1) > (v3) ) { | 
					
						
							|  |  |  | 								dia1.v1= v3; | 
					
						
							|  |  |  | 								dia1.v2= v1; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							else { | 
					
						
							|  |  |  | 								dia1.v1= v1; | 
					
						
							|  |  |  | 								dia1.v2= v3; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 							if( (v2) > (v4) ) { | 
					
						
							|  |  |  | 								dia2.v1= v4; | 
					
						
							|  |  |  | 								dia2.v2= v2; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							else { | 
					
						
							|  |  |  | 								dia2.v1= v2; | 
					
						
							|  |  |  | 								dia2.v2= v4; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 							/* testing rule:
 | 
					
						
							|  |  |  | 							* the area divided by the total edge lengths | 
					
						
							|  |  |  | 							*/ | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 							len1= VecLenf(v1->co, v2->co); | 
					
						
							|  |  |  | 							len2= VecLenf(v2->co, v3->co); | 
					
						
							|  |  |  | 							len3= VecLenf(v3->co, v4->co); | 
					
						
							|  |  |  | 							len4= VecLenf(v4->co, v1->co); | 
					
						
							|  |  |  | 							len5= VecLenf(v1->co, v3->co); | 
					
						
							|  |  |  | 							len6= VecLenf(v2->co, v4->co); | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 							opp1= AreaT3Dfl(v1->co, v2->co, v3->co); | 
					
						
							|  |  |  | 							opp2= AreaT3Dfl(v1->co, v3->co, v4->co); | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 							fac1= opp1/(len1+len2+len5) + opp2/(len3+len4+len5); | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 							opp1= AreaT3Dfl(v2->co, v3->co, v4->co); | 
					
						
							|  |  |  | 							opp2= AreaT3Dfl(v2->co, v4->co, v1->co); | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 							fac2= opp1/(len2+len3+len6) + opp2/(len4+len1+len6); | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 							ok= 0; | 
					
						
							|  |  |  | 							if(fac1 > fac2) { | 
					
						
							|  |  |  | 								if(dia2.v1==eed->v1 && dia2.v2==eed->v2) { | 
					
						
							|  |  |  | 									eed->f1= 1; | 
					
						
							|  |  |  | 									efa= efaa[0]; | 
					
						
							|  |  |  | 									efa->f1= 1; | 
					
						
							|  |  |  | 									efa= efaa[1]; | 
					
						
							|  |  |  | 									efa->f1= 1; | 
					
						
							|  |  |  | 									 | 
					
						
							|  |  |  | 									w= EM_face_from_faces(em, efaa[0], efaa[1], | 
					
						
							|  |  |  | 														  vindex[0], vindex[1], 4+vindex[2], -1); | 
					
						
							|  |  |  | 									w->f |= SELECT; | 
					
						
							|  |  |  | 									 | 
					
						
							|  |  |  | 									 | 
					
						
							|  |  |  | 									w= EM_face_from_faces(em, efaa[0], efaa[1], | 
					
						
							|  |  |  | 														  vindex[0], 4+vindex[2], 4+vindex[3], -1); | 
					
						
							|  |  |  | 									w->f |= SELECT; | 
					
						
							|  |  |  | 									 | 
					
						
							|  |  |  | 									onedone= 1; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							else if(fac1 < fac2) { | 
					
						
							|  |  |  | 								if(dia1.v1==eed->v1 && dia1.v2==eed->v2) { | 
					
						
							|  |  |  | 									eed->f1= 1; | 
					
						
							|  |  |  | 									efa= efaa[0]; | 
					
						
							|  |  |  | 									efa->f1= 1; | 
					
						
							|  |  |  | 									efa= efaa[1]; | 
					
						
							|  |  |  | 									efa->f1= 1; | 
					
						
							|  |  |  | 									 | 
					
						
							|  |  |  | 									 | 
					
						
							|  |  |  | 									w= EM_face_from_faces(em, efaa[0], efaa[1], | 
					
						
							|  |  |  | 														  vindex[1], 4+vindex[2], 4+vindex[3], -1); | 
					
						
							|  |  |  | 									w->f |= SELECT; | 
					
						
							|  |  |  | 									 | 
					
						
							|  |  |  | 									 | 
					
						
							|  |  |  | 									w= EM_face_from_faces(em, efaa[0], efaa[1], | 
					
						
							|  |  |  | 														  vindex[0], 4+vindex[1], 4+vindex[3], -1); | 
					
						
							|  |  |  | 									w->f |= SELECT; | 
					
						
							|  |  |  | 									 | 
					
						
							|  |  |  | 									onedone= 1; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			eed= nexted; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		free_tagged_edges_faces(em, em->edges.first, em->faces.first); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if(onedone==0) break; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		EM_selectmode_set(em);	// new edges/faces were added
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	MEM_freeN(efaar); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	EM_select_flush(em); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Got this from scanfill.c. You will need to juggle around the
 | 
					
						
							|  |  |  | * callbacks for the scanfill.c code a bit for this to work. */ | 
					
						
							|  |  |  | static void fill_mesh(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve,*v1; | 
					
						
							|  |  |  | 	EditEdge *eed,*e1,*nexted; | 
					
						
							|  |  |  | 	EditFace *efa,*nextvl, *efan; | 
					
						
							|  |  |  | 	short ok; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(em==NULL) return; | 
					
						
							|  |  |  | 	waitcursor(1); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* copy all selected vertices */ | 
					
						
							|  |  |  | 	eve= em->verts.first; | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							|  |  |  | 		if(eve->f & SELECT) { | 
					
						
							|  |  |  | 			v1= BLI_addfillvert(eve->co); | 
					
						
							|  |  |  | 			eve->tmp.v= v1; | 
					
						
							|  |  |  | 			v1->tmp.v= eve; | 
					
						
							|  |  |  | 			v1->xs= 0;	// used for counting edges
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eve= eve->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* copy all selected edges */ | 
					
						
							|  |  |  | 	eed= em->edges.first; | 
					
						
							|  |  |  | 	while(eed) { | 
					
						
							|  |  |  | 		if( (eed->v1->f & SELECT) && (eed->v2->f & SELECT) ) { | 
					
						
							|  |  |  | 			e1= BLI_addfilledge(eed->v1->tmp.v, eed->v2->tmp.v); | 
					
						
							|  |  |  | 			e1->v1->xs++;  | 
					
						
							|  |  |  | 			e1->v2->xs++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eed= eed->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* from all selected faces: remove vertices and edges to prevent doubles */ | 
					
						
							|  |  |  | 	/* all edges add values, faces subtract,
 | 
					
						
							|  |  |  | 		then remove edges with vertices ->xs<2 */ | 
					
						
							|  |  |  | 	efa= em->faces.first; | 
					
						
							|  |  |  | 	ok= 0; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		nextvl= efa->next; | 
					
						
							|  |  |  | 		if( faceselectedAND(efa, 1) ) { | 
					
						
							|  |  |  | 			efa->v1->tmp.v->xs--; | 
					
						
							|  |  |  | 			efa->v2->tmp.v->xs--; | 
					
						
							|  |  |  | 			efa->v3->tmp.v->xs--; | 
					
						
							|  |  |  | 			if(efa->v4) efa->v4->tmp.v->xs--; | 
					
						
							|  |  |  | 			ok= 1; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		efa= nextvl; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(ok) {	/* there are faces selected */ | 
					
						
							|  |  |  | 		eed= filledgebase.first; | 
					
						
							|  |  |  | 		while(eed) { | 
					
						
							|  |  |  | 			nexted= eed->next; | 
					
						
							|  |  |  | 			if(eed->v1->xs<2 || eed->v2->xs<2) { | 
					
						
							|  |  |  | 				BLI_remlink(&filledgebase,eed); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			eed= nexted; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(BLI_edgefill(0, em->mat_nr)) { | 
					
						
							|  |  |  | 		efa= fillfacebase.first; | 
					
						
							|  |  |  | 		while(efa) { | 
					
						
							|  |  |  | 			/* normals default pointing up */ | 
					
						
							|  |  |  | 			efan= addfacelist(em, efa->v3->tmp.v, efa->v2->tmp.v,  | 
					
						
							|  |  |  | 							  efa->v1->tmp.v, 0, NULL, NULL); | 
					
						
							|  |  |  | 			if(efan) EM_select_face(efan, 1); | 
					
						
							|  |  |  | 			efa= efa->next; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_end_edgefill(); | 
					
						
							|  |  |  | 	beauty_fill(em); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	WM_cursor_wait(0); | 
					
						
							|  |  |  | 	EM_select_flush(em); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | static int fill_mesh_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	fill_mesh(em); | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 	DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-01 12:40:27 +00:00
										 |  |  | void MESH_OT_fill(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Fill Mesh"; | 
					
						
							| 
									
										
										
										
											2009-02-01 12:40:27 +00:00
										 |  |  | 	ot->idname= "MESH_OT_fill"; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= fill_mesh_exec; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int beauty_fill_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-02-19 19:03:53 +00:00
										 |  |  | 	beauty_fill(em); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MESH_OT_beauty_fill(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Beauty Fill"; | 
					
						
							|  |  |  | 	ot->idname= "MESH_OT_beauty_fill"; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= beauty_fill_exec; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-15 15:40:31 +00:00
										 |  |  | static int quads_convert_to_tris_exec(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	convert_to_triface(em,0); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-15 15:40:31 +00:00
										 |  |  | void MESH_OT_quads_convert_to_tris(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Quads to Tris"; | 
					
						
							| 
									
										
										
										
											2009-04-15 15:40:31 +00:00
										 |  |  | 	ot->idname= "MESH_OT_quads_convert_to_tris"; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							| 
									
										
										
										
											2009-04-15 15:40:31 +00:00
										 |  |  | 	ot->exec= quads_convert_to_tris_exec; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-15 15:40:31 +00:00
										 |  |  | static int tris_convert_to_quads_exec(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	join_triangles(em); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-15 15:40:31 +00:00
										 |  |  | void MESH_OT_tris_convert_to_quads(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Tris to Quads"; | 
					
						
							| 
									
										
										
										
											2009-04-15 15:40:31 +00:00
										 |  |  | 	ot->idname= "MESH_OT_tris_convert_to_quads"; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							| 
									
										
										
										
											2009-04-15 15:40:31 +00:00
										 |  |  | 	ot->exec= tris_convert_to_quads_exec; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int edge_flip_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	edge_flip(em); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MESH_OT_edge_flip(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name= "Edge Flip"; | 
					
						
							|  |  |  | 	ot->idname= "MESH_OT_edge_flip"; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec= edge_flip_exec; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-01 04:22:18 +00:00
										 |  |  | static int mesh_faces_shade_smooth_exec(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	mesh_set_smooth_faces(em,1); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-01 04:22:18 +00:00
										 |  |  | void MESH_OT_faces_shade_smooth(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							| 
									
										
										
										
											2009-03-15 03:11:05 +00:00
										 |  |  | 	ot->name= "Smooth Face Shading"; | 
					
						
							| 
									
										
										
										
											2009-02-01 04:22:18 +00:00
										 |  |  | 	ot->idname= "MESH_OT_faces_shade_smooth"; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							| 
									
										
										
										
											2009-02-01 04:22:18 +00:00
										 |  |  | 	ot->exec= mesh_faces_shade_smooth_exec; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-01 04:22:18 +00:00
										 |  |  | static int mesh_faces_shade_solid_exec(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	mesh_set_smooth_faces(em,0); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(obedit->data, em); | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-01 04:22:18 +00:00
										 |  |  | void MESH_OT_faces_shade_solid(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							| 
									
										
										
										
											2009-03-15 03:11:05 +00:00
										 |  |  | 	ot->name= "Flat Face Shading"; | 
					
						
							| 
									
										
										
										
											2009-02-01 04:22:18 +00:00
										 |  |  | 	ot->idname= "MESH_OT_faces_shade_solid"; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							| 
									
										
										
										
											2009-02-01 04:22:18 +00:00
										 |  |  | 	ot->exec= mesh_faces_shade_solid_exec; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2009-01-24 22:21:12 +00:00
										 |  |  | } |