| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2010-03-21 01:14:04 +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, | 
					
						
							| 
									
										
										
										
											2010-02-12 13:34:04 +00:00
										 |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2004 by Blender Foundation | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is: all of this file. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): none yet. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-27 20:29:51 +00:00
										 |  |  | /** \file blender/editors/mesh/editmesh_lib.c
 | 
					
						
							|  |  |  |  *  \ingroup edmesh | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <math.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_meshdata_types.h"
 | 
					
						
							|  |  |  | #include "DNA_modifier_types.h"
 | 
					
						
							|  |  |  | #include "DNA_object_types.h"
 | 
					
						
							|  |  |  | #include "DNA_scene_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_blenlib.h"
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | #include "BLI_math.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | #include "BLI_editVert.h"
 | 
					
						
							| 
									
										
										
										
											2009-12-14 23:35:13 +00:00
										 |  |  | #include "BLI_edgehash.h"
 | 
					
						
							| 
									
										
										
										
											2011-01-07 18:36:47 +00:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_customdata.h"
 | 
					
						
							| 
									
										
										
										
											2009-06-16 13:09:36 +00:00
										 |  |  | #include "BKE_context.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | #include "BKE_global.h"
 | 
					
						
							|  |  |  | #include "BKE_mesh.h"
 | 
					
						
							| 
									
										
										
										
											2011-01-07 19:18:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "ED_mesh.h"
 | 
					
						
							| 
									
										
										
										
											2009-06-16 13:09:36 +00:00
										 |  |  | #include "ED_screen.h"
 | 
					
						
							| 
									
										
										
										
											2009-01-05 15:19:31 +00:00
										 |  |  | #include "ED_view3d.h"
 | 
					
						
							| 
									
										
										
										
											2010-10-13 07:43:39 +00:00
										 |  |  | #include "ED_transform.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-01 13:15:35 +00:00
										 |  |  | #include "mesh_intern.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-28 17:47:49 +00:00
										 |  |  | /* Helpers for EM_set_flag_all_selectmode */ | 
					
						
							|  |  |  | #define SET_EVE_FLAG(eve, flag) \
 | 
					
						
							|  |  |  | 	if (eve->h==0) { \ | 
					
						
							|  |  |  | 		if (flag & SELECT && !(eve->f & SELECT)) { \ | 
					
						
							|  |  |  | 			++selvert; \ | 
					
						
							|  |  |  | 		} \ | 
					
						
							|  |  |  | 		eve->f |= flag; \ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SET_EED_FLAG(eed, flag) \
 | 
					
						
							|  |  |  | 	if (eed->h==0) { \ | 
					
						
							|  |  |  | 		if (flag & SELECT && !(eed->f & SELECT)) { \ | 
					
						
							|  |  |  | 			++seledge; \ | 
					
						
							|  |  |  | 		} \ | 
					
						
							|  |  |  | 		eed->f |= flag; \ | 
					
						
							|  |  |  | 		SET_EVE_FLAG(eed->v1, flag); \ | 
					
						
							|  |  |  | 		SET_EVE_FLAG(eed->v2, flag); \ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | /* ****************** stats *************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int EM_nfaces_selected(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	int count= 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for (efa= em->faces.first; efa; efa= efa->next) | 
					
						
							|  |  |  | 		if (efa->f & SELECT) | 
					
						
							|  |  |  | 			count++; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	em->totfacesel= count; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return count; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int EM_nedges_selected(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	int count= 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for (eed= em->edges.first; eed; eed= eed->next)  | 
					
						
							|  |  |  | 		if(eed->f & SELECT) | 
					
						
							|  |  |  | 			count++; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	em->totedgesel= count; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return count; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int EM_nvertices_selected(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	int count= 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for (eve= em->verts.first; eve; eve= eve->next) | 
					
						
							|  |  |  | 		if (eve->f & SELECT) | 
					
						
							|  |  |  | 			count++; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	em->totvertsel= count; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return count; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_stats_update(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	em->totvert= BLI_countlist(&em->verts); | 
					
						
							|  |  |  | 	em->totedge= BLI_countlist(&em->edges); | 
					
						
							|  |  |  | 	em->totface= BLI_countlist(&em->faces); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	EM_nvertices_selected(em); | 
					
						
							|  |  |  | 	EM_nedges_selected(em); | 
					
						
							|  |  |  | 	EM_nfaces_selected(em); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | /* this replaces the active flag used in uv/face mode */ | 
					
						
							|  |  |  | void EM_set_actFace(EditMesh *em, EditFace *efa) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	em->act_face = efa; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EditFace *EM_get_actFace(EditMesh *em, int sloppy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (em->act_face) { | 
					
						
							|  |  |  | 		return em->act_face; | 
					
						
							|  |  |  | 	} else if (sloppy) { | 
					
						
							|  |  |  | 		EditFace *efa= NULL; | 
					
						
							|  |  |  | 		EditSelection *ese; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		ese = em->selected.last; | 
					
						
							|  |  |  | 		for (; ese; ese=ese->prev){ | 
					
						
							|  |  |  | 			if(ese->type == EDITFACE) { | 
					
						
							|  |  |  | 				efa = (EditFace *)ese->data; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				if (efa->h)	efa= NULL; | 
					
						
							|  |  |  | 				else		break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (efa==NULL) { | 
					
						
							|  |  |  | 			for (efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 				if (efa->f & SELECT) | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return efa; /* can still be null */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int EM_get_actSelection(EditMesh *em, EditSelection *ese) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditSelection *ese_last = em->selected.last; | 
					
						
							|  |  |  | 	EditFace *efa = EM_get_actFace(em, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ese->next = ese->prev = NULL; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (ese_last) { | 
					
						
							|  |  |  | 		if (ese_last->type == EDITFACE) { /* if there is an active face, use it over the last selected face */ | 
					
						
							|  |  |  | 			if (efa) { | 
					
						
							|  |  |  | 				ese->data = (void *)efa; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				ese->data = ese_last->data; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			ese->type = EDITFACE; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ese->data = ese_last->data; | 
					
						
							|  |  |  | 			ese->type = ese_last->type; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else if (efa) { /* no */ | 
					
						
							|  |  |  | 		ese->data = (void *)efa; | 
					
						
							|  |  |  | 		ese->type = EDITFACE; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ese->data = NULL; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ********* Selection History ************ */ | 
					
						
							|  |  |  | static int EM_check_selection(EditMesh *em, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditSelection *ese; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(ese = em->selected.first; ese; ese = ese->next){ | 
					
						
							|  |  |  | 		if(ese->data == data) return 1; | 
					
						
							| 
									
										
										
										
											2009-01-31 13:30:56 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-16 14:32:17 +00:00
										 |  |  | void EM_remove_selection(EditMesh *em, void *data, int UNUSED(type)) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditSelection *ese; | 
					
						
							|  |  |  | 	for(ese=em->selected.first; ese; ese = ese->next){ | 
					
						
							|  |  |  | 		if(ese->data == data){ | 
					
						
							|  |  |  | 			BLI_freelinkN(&(em->selected),ese); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_store_selection(EditMesh *em, void *data, int type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditSelection *ese; | 
					
						
							|  |  |  | 	if(!EM_check_selection(em, data)){ | 
					
						
							|  |  |  | 		ese = (EditSelection*) MEM_callocN( sizeof(EditSelection), "Edit Selection"); | 
					
						
							|  |  |  | 		ese->type = type; | 
					
						
							|  |  |  | 		ese->data = data; | 
					
						
							|  |  |  | 		BLI_addtail(&(em->selected),ese); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_validate_selections(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditSelection *ese, *nextese; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ese = em->selected.first; | 
					
						
							| 
									
										
										
										
											2009-02-09 20:58:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	while(ese){ | 
					
						
							|  |  |  | 		nextese = ese->next; | 
					
						
							|  |  |  | 		if(ese->type == EDITVERT && !(((EditVert*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese); | 
					
						
							|  |  |  | 		else if(ese->type == EDITEDGE && !(((EditEdge*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese); | 
					
						
							|  |  |  | 		else if(ese->type == EDITFACE && !(((EditFace*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese); | 
					
						
							|  |  |  | 		ese = nextese; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void EM_strip_selections(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditSelection *ese, *nextese; | 
					
						
							|  |  |  | 	if(!(em->selectmode & SCE_SELECT_VERTEX)){ | 
					
						
							|  |  |  | 		ese = em->selected.first; | 
					
						
							|  |  |  | 		while(ese){ | 
					
						
							|  |  |  | 			nextese = ese->next;  | 
					
						
							|  |  |  | 			if(ese->type == EDITVERT) BLI_freelinkN(&(em->selected),ese); | 
					
						
							|  |  |  | 			ese = nextese; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(!(em->selectmode & SCE_SELECT_EDGE)){ | 
					
						
							|  |  |  | 		ese=em->selected.first; | 
					
						
							|  |  |  | 		while(ese){ | 
					
						
							|  |  |  | 			nextese = ese->next; | 
					
						
							|  |  |  | 			if(ese->type == EDITEDGE) BLI_freelinkN(&(em->selected), ese); | 
					
						
							|  |  |  | 			ese = nextese; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(!(em->selectmode & SCE_SELECT_FACE)){ | 
					
						
							|  |  |  | 		ese=em->selected.first; | 
					
						
							|  |  |  | 		while(ese){ | 
					
						
							|  |  |  | 			nextese = ese->next; | 
					
						
							|  |  |  | 			if(ese->type == EDITFACE) BLI_freelinkN(&(em->selected), ese); | 
					
						
							|  |  |  | 			ese = nextese; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* generic way to get data from an EditSelection type 
 | 
					
						
							|  |  |  | These functions were written to be used by the Modifier widget when in Rotate about active mode, | 
					
						
							|  |  |  | but can be used anywhere. | 
					
						
							|  |  |  | EM_editselection_center | 
					
						
							|  |  |  | EM_editselection_normal | 
					
						
							|  |  |  | EM_editselection_plane | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | void EM_editselection_center(float *center, EditSelection *ese) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (ese->type==EDITVERT) { | 
					
						
							|  |  |  | 		EditVert *eve= ese->data; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		copy_v3_v3(center, eve->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} else if (ese->type==EDITEDGE) { | 
					
						
							|  |  |  | 		EditEdge *eed= ese->data; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		add_v3_v3v3(center, eed->v1->co, eed->v2->co); | 
					
						
							|  |  |  | 		mul_v3_fl(center, 0.5); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} else if (ese->type==EDITFACE) { | 
					
						
							|  |  |  | 		EditFace *efa= ese->data; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		copy_v3_v3(center, efa->cent); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_editselection_normal(float *normal, EditSelection *ese) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (ese->type==EDITVERT) { | 
					
						
							|  |  |  | 		EditVert *eve= ese->data; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		copy_v3_v3(normal, eve->no); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} else if (ese->type==EDITEDGE) { | 
					
						
							|  |  |  | 		EditEdge *eed= ese->data; | 
					
						
							|  |  |  | 		float plane[3]; /* need a plane to correct the normal */ | 
					
						
							|  |  |  | 		float vec[3]; /* temp vec storage */ | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		add_v3_v3v3(normal, eed->v1->no, eed->v2->no); | 
					
						
							|  |  |  | 		sub_v3_v3v3(plane, eed->v2->co, eed->v1->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		/* the 2 vertex normals will be close but not at rightangles to the edge
 | 
					
						
							|  |  |  | 		for rotate about edge we want them to be at right angles, so we need to | 
					
						
							|  |  |  | 		do some extra colculation to correct the vert normals, | 
					
						
							|  |  |  | 		we need the plane for this */ | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		cross_v3_v3v3(vec, normal, plane); | 
					
						
							|  |  |  | 		cross_v3_v3v3(normal, plane, vec);  | 
					
						
							|  |  |  | 		normalize_v3(normal); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 	} else if (ese->type==EDITFACE) { | 
					
						
							|  |  |  | 		EditFace *efa= ese->data; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		copy_v3_v3(normal, efa->n); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Calculate a plane that is rightangles to the edge/vert/faces normal
 | 
					
						
							|  |  |  | also make the plane run allong an axis that is related to the geometry, | 
					
						
							|  |  |  | because this is used for the manipulators Y axis.*/ | 
					
						
							|  |  |  | void EM_editselection_plane(float *plane, EditSelection *ese) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (ese->type==EDITVERT) { | 
					
						
							|  |  |  | 		EditVert *eve= ese->data; | 
					
						
							|  |  |  | 		float vec[3]={0,0,0}; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if (ese->prev) { /*use previously selected data to make a usefull vertex plane */ | 
					
						
							|  |  |  | 			EM_editselection_center(vec, ese->prev); | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			sub_v3_v3v3(plane, vec, eve->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			/* make a fake  plane thats at rightangles to the normal
 | 
					
						
							|  |  |  | 			we cant make a crossvec from a vec thats the same as the vec | 
					
						
							|  |  |  | 			unlikely but possible, so make sure if the normal is (0,0,1) | 
					
						
							|  |  |  | 			that vec isnt the same or in the same direction even.*/ | 
					
						
							|  |  |  | 			if (eve->no[0]<0.5)			vec[0]=1; | 
					
						
							|  |  |  | 			else if (eve->no[1]<0.5)	vec[1]=1; | 
					
						
							|  |  |  | 			else						vec[2]=1; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			cross_v3_v3v3(plane, eve->no, vec); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} else if (ese->type==EDITEDGE) { | 
					
						
							|  |  |  | 		EditEdge *eed= ese->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/*the plane is simple, it runs allong the edge
 | 
					
						
							|  |  |  | 		however selecting different edges can swap the direction of the y axis. | 
					
						
							|  |  |  | 		this makes it less likely for the y axis of the manipulator | 
					
						
							|  |  |  | 		(running along the edge).. to flip less often. | 
					
						
							| 
									
										
										
										
											2011-01-23 12:42:07 +00:00
										 |  |  | 		at least its more predictable */ | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		if (eed->v2->co[1] > eed->v1->co[1]) /*check which to do first */ | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			sub_v3_v3v3(plane, eed->v2->co, eed->v1->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			sub_v3_v3v3(plane, eed->v1->co, eed->v2->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 	} else if (ese->type==EDITFACE) { | 
					
						
							|  |  |  | 		EditFace *efa= ese->data; | 
					
						
							|  |  |  | 		float vec[3]; | 
					
						
							|  |  |  | 		if (efa->v4) { /*if its a quad- set the plane along the 2 longest edges.*/ | 
					
						
							|  |  |  | 			float vecA[3], vecB[3]; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			sub_v3_v3v3(vecA, efa->v4->co, efa->v3->co); | 
					
						
							|  |  |  | 			sub_v3_v3v3(vecB, efa->v1->co, efa->v2->co); | 
					
						
							|  |  |  | 			add_v3_v3v3(plane, vecA, vecB); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			sub_v3_v3v3(vecA, efa->v1->co, efa->v4->co); | 
					
						
							|  |  |  | 			sub_v3_v3v3(vecB, efa->v2->co, efa->v3->co); | 
					
						
							|  |  |  | 			add_v3_v3v3(vec, vecA, vecB);						 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			/*use the biggest edge length*/ | 
					
						
							|  |  |  | 			if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]) | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 				copy_v3_v3(plane, vec); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			/*start with v1-2 */ | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			sub_v3_v3v3(plane, efa->v1->co, efa->v2->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			 | 
					
						
							|  |  |  | 			/*test the edge between v2-3, use if longer */ | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			sub_v3_v3v3(vec, efa->v2->co, efa->v3->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]) | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 				copy_v3_v3(plane, vec); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			 | 
					
						
							|  |  |  | 			/*test the edge between v1-3, use if longer */ | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			sub_v3_v3v3(vec, efa->v3->co, efa->v1->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]) | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 				copy_v3_v3(plane, vec); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 	normalize_v3(plane); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_select_face(EditFace *efa, int sel) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(sel) { | 
					
						
							|  |  |  | 		efa->f |= SELECT; | 
					
						
							|  |  |  | 		efa->e1->f |= SELECT; | 
					
						
							|  |  |  | 		efa->e2->f |= SELECT; | 
					
						
							|  |  |  | 		efa->e3->f |= SELECT; | 
					
						
							|  |  |  | 		if(efa->e4) efa->e4->f |= SELECT; | 
					
						
							|  |  |  | 		efa->v1->f |= SELECT; | 
					
						
							|  |  |  | 		efa->v2->f |= SELECT; | 
					
						
							|  |  |  | 		efa->v3->f |= SELECT; | 
					
						
							|  |  |  | 		if(efa->v4) efa->v4->f |= SELECT; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		efa->f &= ~SELECT; | 
					
						
							|  |  |  | 		efa->e1->f &= ~SELECT; | 
					
						
							|  |  |  | 		efa->e2->f &= ~SELECT; | 
					
						
							|  |  |  | 		efa->e3->f &= ~SELECT; | 
					
						
							|  |  |  | 		if(efa->e4) efa->e4->f &= ~SELECT; | 
					
						
							|  |  |  | 		efa->v1->f &= ~SELECT; | 
					
						
							|  |  |  | 		efa->v2->f &= ~SELECT; | 
					
						
							|  |  |  | 		efa->v3->f &= ~SELECT; | 
					
						
							|  |  |  | 		if(efa->v4) efa->v4->f &= ~SELECT; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_select_edge(EditEdge *eed, int sel) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(sel) { | 
					
						
							|  |  |  | 		eed->f |= SELECT; | 
					
						
							|  |  |  | 		eed->v1->f |= SELECT; | 
					
						
							|  |  |  | 		eed->v2->f |= SELECT; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		eed->f &= ~SELECT; | 
					
						
							|  |  |  | 		eed->v1->f &= ~SELECT; | 
					
						
							|  |  |  | 		eed->v2->f &= ~SELECT; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_select_face_fgon(EditMesh *em, EditFace *efa, int val) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	short index=0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(efa->fgonf==0) EM_select_face(efa, val); | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		if(efa->e1->fgoni) index= efa->e1->fgoni; | 
					
						
							|  |  |  | 		if(efa->e2->fgoni) index= efa->e2->fgoni; | 
					
						
							|  |  |  | 		if(efa->e3->fgoni) index= efa->e3->fgoni; | 
					
						
							|  |  |  | 		if(efa->v4 && efa->e4->fgoni) index= efa->e4->fgoni; | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2010-01-22 06:48:29 +00:00
										 |  |  | 		if((index==0) && (G.f & G_DEBUG))printf("wrong fgon select\n"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		// select all ngon faces with index
 | 
					
						
							|  |  |  | 		for(efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 			if(efa->fgonf) { | 
					
						
							|  |  |  | 				if(efa->e1->fgoni==index || efa->e2->fgoni==index ||  | 
					
						
							|  |  |  | 				   efa->e3->fgoni==index || (efa->e4 && efa->e4->fgoni==index) ) { | 
					
						
							|  |  |  | 					EM_select_face(efa, val); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* only vertices */ | 
					
						
							|  |  |  | int faceselectedOR(EditFace *efa, int flag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if ((efa->v1->f | efa->v2->f | efa->v3->f | (efa->v4?efa->v4->f:0))&flag) { | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // replace with (efa->f & SELECT)
 | 
					
						
							|  |  |  | int faceselectedAND(EditFace *efa, int flag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if ((efa->v1->f & efa->v2->f & efa->v3->f & (efa->v4?efa->v4->f:flag))&flag) { | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_clear_flag_all(EditMesh *em, int flag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for (eve= em->verts.first; eve; eve= eve->next) eve->f &= ~flag; | 
					
						
							|  |  |  | 	for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~flag; | 
					
						
							|  |  |  | 	for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~flag; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	if(flag & SELECT) { | 
					
						
							|  |  |  | 		BLI_freelistN(&(em->selected)); | 
					
						
							|  |  |  | 		em->totvertsel= em->totedgesel= em->totfacesel= 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_set_flag_all(EditMesh *em, int flag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for (eve= em->verts.first; eve; eve= eve->next) if(eve->h==0) eve->f |= flag; | 
					
						
							|  |  |  | 	for (eed= em->edges.first; eed; eed= eed->next) if(eed->h==0) eed->f |= flag; | 
					
						
							|  |  |  | 	for (efa= em->faces.first; efa; efa= efa->next) if(efa->h==0) efa->f |= flag; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	if(flag & SELECT) { | 
					
						
							|  |  |  | 		em->totvertsel= em->totvert; | 
					
						
							|  |  |  | 		em->totedgesel= em->totedge; | 
					
						
							|  |  |  | 		em->totfacesel= em->totface; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-28 17:47:49 +00:00
										 |  |  | void EM_set_flag_all_selectmode(EditMesh *em, int flag) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-22 09:30:00 +00:00
										 |  |  | 	 EditVert *eve; | 
					
						
							|  |  |  | 	 EditEdge *eed; | 
					
						
							|  |  |  | 	 EditFace *efa; | 
					
						
							| 
									
										
										
										
											2010-02-28 17:47:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	int selvert= 0, seledge= 0, selface= 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (em->selectmode & SCE_SELECT_VERTEX) { | 
					
						
							|  |  |  | 		/* If vertex select mode enabled all the data could be affected */ | 
					
						
							|  |  |  | 		for (eve= em->verts.first; eve; eve= eve->next) if(eve->h==0) eve->f |= flag; | 
					
						
							|  |  |  | 		for (eed= em->edges.first; eed; eed= eed->next) if(eed->h==0) eed->f |= flag; | 
					
						
							|  |  |  | 		for (efa= em->faces.first; efa; efa= efa->next) if(efa->h==0) efa->f |= flag; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (flag & SELECT) { | 
					
						
							|  |  |  | 			selvert= em->totvert; | 
					
						
							|  |  |  | 			seledge= em->totedge; | 
					
						
							|  |  |  | 			selface= em->totface; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else if (em->selectmode & SCE_SELECT_EDGE) { | 
					
						
							|  |  |  | 		/* If edge select mode is enabled we should affect on all edges, faces and */ | 
					
						
							|  |  |  | 		/* vertices, connected to them */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 			SET_EED_FLAG(eed, flag) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 			if(efa->h==0) { | 
					
						
							|  |  |  | 				efa->f |= flag; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (flag & SELECT) { | 
					
						
							|  |  |  | 					++selface; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else if (em->selectmode & SCE_SELECT_FACE) { | 
					
						
							|  |  |  | 		/* No vertex and edge select mode, only face selection */ | 
					
						
							|  |  |  | 		/* In face select mode only edges and vertices belongs to faces should be affected */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 			if(efa->h==0) { | 
					
						
							|  |  |  | 				efa->f |= flag; | 
					
						
							|  |  |  | 				SET_EED_FLAG(efa->e1, flag); | 
					
						
							|  |  |  | 				SET_EED_FLAG(efa->e2, flag); | 
					
						
							|  |  |  | 				SET_EED_FLAG(efa->e3, flag); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (efa->e4) { | 
					
						
							|  |  |  | 					SET_EED_FLAG(efa->e4, flag); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (flag & SELECT) { | 
					
						
							|  |  |  | 					++selface; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(flag & SELECT) { | 
					
						
							|  |  |  | 		em->totvertsel= selvert; | 
					
						
							|  |  |  | 		em->totedgesel= seledge; | 
					
						
							|  |  |  | 		em->totfacesel= selface; | 
					
						
							| 
									
										
										
										
											2010-03-22 09:30:00 +00:00
										 |  |  | 	 } | 
					
						
							| 
									
										
										
										
											2010-02-28 17:47:49 +00:00
										 |  |  |  } | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | /* flush for changes in vertices only */ | 
					
						
							|  |  |  | void EM_deselect_flush(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 		if(eed->v1->f & eed->v2->f & SELECT); | 
					
						
							|  |  |  | 		else eed->f &= ~SELECT; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for(efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 		if(efa->v4) { | 
					
						
							|  |  |  | 			if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT ); | 
					
						
							|  |  |  | 			else efa->f &= ~SELECT; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT ); | 
					
						
							|  |  |  | 			else efa->f &= ~SELECT; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	EM_nedges_selected(em); | 
					
						
							|  |  |  | 	EM_nfaces_selected(em); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* flush selection to edges & faces */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*  this only based on coherent selected vertices, for example when adding new
 | 
					
						
							| 
									
										
										
										
											2009-12-15 23:35:26 +00:00
										 |  |  | 	objects. call clear_flag_all() before you select vertices to be sure it ends OK! | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_select_flush(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 		if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for(efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 		if(efa->v4) { | 
					
						
							|  |  |  | 			if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT ) efa->f |= SELECT; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT ) efa->f |= SELECT; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	EM_nedges_selected(em); | 
					
						
							|  |  |  | 	EM_nfaces_selected(em); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-15 15:40:31 +00:00
										 |  |  | /* when vertices or edges can be selected, also make fgon consistent */ | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | static void check_fgons_selection(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa, *efan; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	ListBase *lbar; | 
					
						
							|  |  |  | 	int sel, desel, index, totfgon= 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* count amount of fgons */ | 
					
						
							|  |  |  | 	for(eed= em->edges.first; eed; eed= eed->next)  | 
					
						
							|  |  |  | 		if(eed->fgoni>totfgon) totfgon= eed->fgoni; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(totfgon==0) return; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	lbar= MEM_callocN((totfgon+1)*sizeof(ListBase), "listbase array"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* put all fgons in lbar */ | 
					
						
							|  |  |  | 	for(efa= em->faces.first; efa; efa= efan) { | 
					
						
							|  |  |  | 		efan= efa->next; | 
					
						
							|  |  |  | 		index= efa->e1->fgoni; | 
					
						
							|  |  |  | 		if(index==0) index= efa->e2->fgoni; | 
					
						
							|  |  |  | 		if(index==0) index= efa->e3->fgoni; | 
					
						
							|  |  |  | 		if(index==0 && efa->e4) index= efa->e4->fgoni; | 
					
						
							|  |  |  | 		if(index) { | 
					
						
							|  |  |  | 			BLI_remlink(&em->faces, efa); | 
					
						
							|  |  |  | 			BLI_addtail(&lbar[index], efa); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* now check the fgons */ | 
					
						
							|  |  |  | 	for(index=1; index<=totfgon; index++) { | 
					
						
							|  |  |  | 		/* we count on vertices/faces/edges being set OK, so we only have to set ngon itself */ | 
					
						
							|  |  |  | 		sel= desel= 0; | 
					
						
							|  |  |  | 		for(efa= lbar[index].first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 			if(efa->e1->fgoni==0) { | 
					
						
							|  |  |  | 				if(efa->e1->f & SELECT) sel++; | 
					
						
							|  |  |  | 				else desel++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(efa->e2->fgoni==0) { | 
					
						
							|  |  |  | 				if(efa->e2->f & SELECT) sel++; | 
					
						
							|  |  |  | 				else desel++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(efa->e3->fgoni==0) { | 
					
						
							|  |  |  | 				if(efa->e3->f & SELECT) sel++; | 
					
						
							|  |  |  | 				else desel++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(efa->e4 && efa->e4->fgoni==0) { | 
					
						
							|  |  |  | 				if(efa->e4->f & SELECT) sel++; | 
					
						
							|  |  |  | 				else desel++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if(sel && desel) break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(sel && desel) sel= 0; | 
					
						
							|  |  |  | 		else if(sel) sel= 1; | 
					
						
							|  |  |  | 		else sel= 0; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/* select/deselect and put back */ | 
					
						
							|  |  |  | 		for(efa= lbar[index].first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 			if(sel) efa->f |= SELECT; | 
					
						
							|  |  |  | 			else efa->f &= ~SELECT; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-12-21 14:49:34 +00:00
										 |  |  | 		BLI_movelisttolist(&em->faces, &lbar[index]); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	MEM_freeN(lbar); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* flush to edges & faces */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* based on select mode it selects edges/faces 
 | 
					
						
							|  |  |  |    assumed is that verts/edges/faces were properly selected themselves | 
					
						
							|  |  |  |    with the calls above | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_selectmode_flush(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// flush to edges & faces
 | 
					
						
							|  |  |  | 	if(em->selectmode & SCE_SELECT_VERTEX) { | 
					
						
							|  |  |  | 		for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 			if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT; | 
					
						
							|  |  |  | 			else eed->f &= ~SELECT; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for(efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 			if(efa->v4) { | 
					
						
							|  |  |  | 				if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT) efa->f |= SELECT; | 
					
						
							|  |  |  | 				else efa->f &= ~SELECT; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT) efa->f |= SELECT; | 
					
						
							|  |  |  | 				else efa->f &= ~SELECT; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// flush to faces
 | 
					
						
							|  |  |  | 	else if(em->selectmode & SCE_SELECT_EDGE) { | 
					
						
							|  |  |  | 		for(efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 			if(efa->e4) { | 
					
						
							|  |  |  | 				if(efa->e1->f & efa->e2->f & efa->e3->f & efa->e4->f & SELECT) efa->f |= SELECT; | 
					
						
							|  |  |  | 				else efa->f &= ~SELECT; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				if(efa->e1->f & efa->e2->f & efa->e3->f & SELECT) efa->f |= SELECT; | 
					
						
							|  |  |  | 				else efa->f &= ~SELECT; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 	// make sure selected faces have selected edges too, for extrude (hack?)
 | 
					
						
							|  |  |  | 	else if(em->selectmode & SCE_SELECT_FACE) { | 
					
						
							|  |  |  | 		for(efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 			if(efa->f & SELECT) EM_select_face(efa, 1); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(!(em->selectmode & SCE_SELECT_FACE)) | 
					
						
							|  |  |  | 		check_fgons_selection(em); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	EM_nvertices_selected(em); | 
					
						
							|  |  |  | 	EM_nedges_selected(em); | 
					
						
							|  |  |  | 	EM_nfaces_selected(em); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_convertsel(EditMesh *em, short oldmode, short selectmode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	/*clear flags*/ | 
					
						
							|  |  |  | 	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(efa= em->faces.first; efa; efa= efa->next) efa->f1 = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/*have to find out what the selectionmode was previously*/ | 
					
						
							|  |  |  | 	if(oldmode == SCE_SELECT_VERTEX) { | 
					
						
							|  |  |  | 		if(selectmode == SCE_SELECT_EDGE){ | 
					
						
							|  |  |  | 			/*select all edges associated with every selected vertex*/ | 
					
						
							|  |  |  | 			for(eed= em->edges.first; eed; eed= eed->next){ | 
					
						
							|  |  |  | 				if(eed->v1->f&SELECT) eed->f1 = 1; | 
					
						
							|  |  |  | 				else if(eed->v2->f&SELECT) eed->f1 = 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			for(eed= em->edges.first; eed; eed= eed->next){ | 
					
						
							|  |  |  | 				if(eed->f1 == 1) EM_select_edge(eed,1);	 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}		 | 
					
						
							|  |  |  | 		else if(selectmode == SCE_SELECT_FACE){ | 
					
						
							|  |  |  | 			/*select all faces associated with every selected vertex*/ | 
					
						
							|  |  |  | 			for(efa= em->faces.first; efa; efa= efa->next){ | 
					
						
							|  |  |  | 				if(efa->v1->f&SELECT) efa->f1 = 1; | 
					
						
							|  |  |  | 				else if(efa->v2->f&SELECT) efa->f1 = 1; | 
					
						
							|  |  |  | 				else if(efa->v3->f&SELECT) efa->f1 = 1; | 
					
						
							|  |  |  | 				else{  | 
					
						
							|  |  |  | 					if(efa->v4){ | 
					
						
							|  |  |  | 						if(efa->v4->f&SELECT) efa->f1 =1; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			for(efa= em->faces.first; efa; efa= efa->next){ | 
					
						
							|  |  |  | 				if(efa->f1 == 1) EM_select_face(efa,1); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(oldmode == SCE_SELECT_EDGE){ | 
					
						
							|  |  |  | 		if(selectmode == SCE_SELECT_FACE){ | 
					
						
							|  |  |  | 			for(efa= em->faces.first; efa; efa= efa->next){ | 
					
						
							|  |  |  | 				if(efa->e1->f&SELECT) efa->f1 = 1; | 
					
						
							|  |  |  | 				else if(efa->e2->f&SELECT) efa->f1 = 1; | 
					
						
							|  |  |  | 				else if(efa->e3->f&SELECT) efa->f1 = 1; | 
					
						
							|  |  |  | 				else if(efa->e4){ | 
					
						
							|  |  |  | 					if(efa->e4->f&SELECT) efa->f1 = 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			for(efa= em->faces.first; efa; efa= efa->next){ | 
					
						
							|  |  |  | 				if(efa->f1 == 1) EM_select_face(efa,1); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	check_fgons_selection(em); | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	EM_nvertices_selected(em); | 
					
						
							|  |  |  | 	EM_nedges_selected(em); | 
					
						
							|  |  |  | 	EM_nfaces_selected(em); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-30 16:09:56 +00:00
										 |  |  | void EM_selectmode_to_scene(struct Scene *scene, struct Object *obedit) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	scene->toolsettings->selectmode= get_mesh(obedit)->edit_mesh->selectmode; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-15 15:40:31 +00:00
										 |  |  | /* when switching select mode, makes sure selection is consistent for editing */ | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | /* also for paranoia checks to make sure edge or face mode works */ | 
					
						
							|  |  |  | void EM_selectmode_set(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	EM_strip_selections(em); /*strip EditSelections from em->selected that are not relevant to new mode*/ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(em->selectmode & SCE_SELECT_VERTEX) { | 
					
						
							|  |  |  | 		/* vertices -> edges -> faces */ | 
					
						
							|  |  |  | 		for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~SELECT; | 
					
						
							|  |  |  | 		for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~SELECT; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		EM_select_flush(em); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if(em->selectmode & SCE_SELECT_EDGE) { | 
					
						
							|  |  |  | 		/* deselect vertices, and select again based on edge select */ | 
					
						
							|  |  |  | 		for(eve= em->verts.first; eve; eve= eve->next) eve->f &= ~SELECT; | 
					
						
							|  |  |  | 		for(eed= em->edges.first; eed; eed= eed->next)  | 
					
						
							|  |  |  | 			if(eed->f & SELECT) EM_select_edge(eed, 1); | 
					
						
							|  |  |  | 		/* selects faces based on edge status */ | 
					
						
							|  |  |  | 		EM_selectmode_flush(em); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if(em->selectmode & SCE_SELECT_FACE) { | 
					
						
							|  |  |  | 		/* deselect eges, and select again based on face select */ | 
					
						
							|  |  |  | 		for(eed= em->edges.first; eed; eed= eed->next) EM_select_edge(eed, 0); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for(efa= em->faces.first; efa; efa= efa->next)  | 
					
						
							|  |  |  | 			if(efa->f & SELECT) EM_select_face(efa, 1); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	EM_nvertices_selected(em); | 
					
						
							|  |  |  | 	EM_nedges_selected(em); | 
					
						
							|  |  |  | 	EM_nfaces_selected(em); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* paranoia check, actually only for entering editmode. rule:
 | 
					
						
							|  |  |  | - vertex hidden, always means edge is hidden too | 
					
						
							|  |  |  | - edge hidden, always means face is hidden too | 
					
						
							|  |  |  | - face hidden, dont change anything | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | void EM_hide_reset(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(eed= em->edges.first; eed; eed= eed->next)  | 
					
						
							|  |  |  | 		if(eed->v1->h || eed->v2->h) eed->h |= 1; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	for(efa= em->faces.first; efa; efa= efa->next)  | 
					
						
							|  |  |  | 		if((efa->e1->h & 1) || (efa->e2->h & 1) || (efa->e3->h & 1) || (efa->e4 && (efa->e4->h & 1))) | 
					
						
							|  |  |  | 			efa->h= 1; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_data_interp_from_verts(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *eve, float fac) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	void *src[2]; | 
					
						
							|  |  |  | 	float w[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (v1->data && v2->data) { | 
					
						
							|  |  |  | 		src[0]= v1->data; | 
					
						
							|  |  |  | 		src[1]= v2->data; | 
					
						
							|  |  |  | 		w[0] = 1.0f-fac; | 
					
						
							|  |  |  | 		w[1] = fac; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		CustomData_em_interp(&em->vdata, src, w, NULL, 2, eve->data); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_data_interp_from_faces(EditMesh *em, EditFace *efa1, EditFace *efa2, EditFace *efan, int i1, int i2, int i3, int i4) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float w[2][4][4]; | 
					
						
							|  |  |  | 	void *src[2]; | 
					
						
							|  |  |  | 	int count = (efa2)? 2: 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (efa1->data) { | 
					
						
							|  |  |  | 		/* set weights for copying from corners directly to other corners */ | 
					
						
							|  |  |  | 		memset(w, 0, sizeof(w)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		w[i1/4][0][i1%4]= 1.0f; | 
					
						
							|  |  |  | 		w[i2/4][1][i2%4]= 1.0f; | 
					
						
							|  |  |  | 		w[i3/4][2][i3%4]= 1.0f; | 
					
						
							|  |  |  | 		if (i4 != -1) | 
					
						
							|  |  |  | 			w[i4/4][3][i4%4]= 1.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		src[0]= efa1->data; | 
					
						
							|  |  |  | 		src[1]= (efa2)? efa2->data: NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		CustomData_em_interp(&em->fdata, src, NULL, (float*)w, count, efan->data); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EditFace *EM_face_from_faces(EditMesh *em, EditFace *efa1, EditFace *efa2, int i1, int i2, int i3, int i4) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efan; | 
					
						
							|  |  |  | 	EditVert **v[2]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	v[0]= &efa1->v1; | 
					
						
							|  |  |  | 	v[1]= (efa2)? &efa2->v1: NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	efan= addfacelist(em, v[i1/4][i1%4], v[i2/4][i2%4], v[i3/4][i3%4], | 
					
						
							|  |  |  | 		(i4 == -1)? 0: v[i4/4][i4%4], efa1, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	EM_data_interp_from_faces(em, efa1, efa2, efan, i1, i2, i3, i4); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return efan; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void update_data_blocks(EditMesh *em, CustomData *olddata, CustomData *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	void *block; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (data == &em->vdata) { | 
					
						
							|  |  |  | 		for(eve= em->verts.first; eve; eve= eve->next) { | 
					
						
							|  |  |  | 			block = NULL; | 
					
						
							|  |  |  | 			CustomData_em_set_default(data, &block); | 
					
						
							|  |  |  | 			CustomData_em_copy_data(olddata, data, eve->data, &block); | 
					
						
							|  |  |  | 			CustomData_em_free_block(olddata, &eve->data); | 
					
						
							|  |  |  | 			eve->data= block; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (data == &em->fdata) { | 
					
						
							|  |  |  | 		for(efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 			block = NULL; | 
					
						
							|  |  |  | 			CustomData_em_set_default(data, &block); | 
					
						
							|  |  |  | 			CustomData_em_copy_data(olddata, data, efa->data, &block); | 
					
						
							|  |  |  | 			CustomData_em_free_block(olddata, &efa->data); | 
					
						
							|  |  |  | 			efa->data= block; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-23 22:16:45 +00:00
										 |  |  | void EM_add_data_layer(EditMesh *em, CustomData *data, int type, const char *name) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	CustomData olddata; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	olddata= *data; | 
					
						
							|  |  |  | 	olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL; | 
					
						
							| 
									
										
										
										
											2010-08-23 22:16:45 +00:00
										 |  |  | 	CustomData_add_layer_named(data, type, CD_CALLOC, NULL, 0, name); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	update_data_blocks(em, &olddata, data); | 
					
						
							|  |  |  | 	if (olddata.layers) MEM_freeN(olddata.layers); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_free_data_layer(EditMesh *em, CustomData *data, int type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	CustomData olddata; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	olddata= *data; | 
					
						
							|  |  |  | 	olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL; | 
					
						
							|  |  |  | 	CustomData_free_layer_active(data, type, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	update_data_blocks(em, &olddata, data); | 
					
						
							|  |  |  | 	if (olddata.layers) MEM_freeN(olddata.layers); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ********  EXTRUDE ********* */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void add_normal_aligned(float *nor, float *add) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if( INPR(nor, add) < -0.9999f) | 
					
						
							| 
									
										
										
										
											2010-04-23 23:57:00 +00:00
										 |  |  | 		sub_v3_v3(nor, add); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2010-04-21 12:27:48 +00:00
										 |  |  | 		add_v3_v3(nor, add); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void set_edge_directions_f2(EditMesh *em, int val) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	int do_all= 1; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* edge directions are used for extrude, to detect direction of edges that make new faces */ | 
					
						
							|  |  |  | 	/* we have set 'f2' flags in edges that need to get a direction set (e.g. get new face) */ | 
					
						
							|  |  |  | 	/* the val argument differs... so we need it as arg */ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 		if(efa->f & SELECT) { | 
					
						
							|  |  |  | 			do_all= 0; | 
					
						
							|  |  |  | 			if(efa->e1->f2<val) { | 
					
						
							|  |  |  | 				if(efa->e1->v1 == efa->v1) efa->e1->dir= 0; | 
					
						
							|  |  |  | 				else efa->e1->dir= 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(efa->e2->f2<val) { | 
					
						
							|  |  |  | 				if(efa->e2->v1 == efa->v2) efa->e2->dir= 0; | 
					
						
							|  |  |  | 				else efa->e2->dir= 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(efa->e3->f2<val) { | 
					
						
							|  |  |  | 				if(efa->e3->v1 == efa->v3) efa->e3->dir= 0; | 
					
						
							|  |  |  | 				else efa->e3->dir= 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(efa->e4 && efa->e4->f2<val) { | 
					
						
							|  |  |  | 				if(efa->e4->v1 == efa->v4) efa->e4->dir= 0; | 
					
						
							|  |  |  | 				else efa->e4->dir= 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 	/* ok, no faces done... then we at least set it for exterior edges */ | 
					
						
							|  |  |  | 	if(do_all) { | 
					
						
							|  |  |  | 		for(efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 			if(efa->e1->v1 == efa->v1) efa->e1->dir= 0; | 
					
						
							|  |  |  | 			else efa->e1->dir= 1; | 
					
						
							|  |  |  | 			if(efa->e2->v1 == efa->v2) efa->e2->dir= 0; | 
					
						
							|  |  |  | 			else efa->e2->dir= 1; | 
					
						
							|  |  |  | 			if(efa->e3->v1 == efa->v3) efa->e3->dir= 0; | 
					
						
							|  |  |  | 			else efa->e3->dir= 1; | 
					
						
							|  |  |  | 			if(efa->e4) { | 
					
						
							|  |  |  | 				if(efa->e4->v1 == efa->v4) efa->e4->dir= 0; | 
					
						
							|  |  |  | 				else efa->e4->dir= 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}	 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* individual face extrude */ | 
					
						
							|  |  |  | /* will use vertex normals for extrusion directions, so *nor is unaffected */ | 
					
						
							| 
									
										
										
										
											2010-10-16 14:32:17 +00:00
										 |  |  | short extrudeflag_face_indiv(EditMesh *em, short UNUSED(flag), float *UNUSED(nor)) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve, *v1, *v2, *v3, *v4; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa, *nextfa; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	if(em==NULL) return 0; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* selected edges with 1 or more selected face become faces */ | 
					
						
							|  |  |  | 	/* selected faces each makes new faces */ | 
					
						
							|  |  |  | 	/* always remove old faces, keeps volumes manifold */ | 
					
						
							|  |  |  | 	/* select the new extrusion, deselect old */ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* step 1; init, count faces in edges */ | 
					
						
							|  |  |  | 	recalc_editnormals(em); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;	// new select flag
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 		eed->f2= 0; // amount of unselected faces
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for(efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 		if(efa->f & SELECT); | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			efa->e1->f2++; | 
					
						
							|  |  |  | 			efa->e2->f2++; | 
					
						
							|  |  |  | 			efa->e3->f2++; | 
					
						
							|  |  |  | 			if(efa->e4) efa->e4->f2++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* step 2: make new faces from faces */ | 
					
						
							|  |  |  | 	for(efa= em->faces.last; efa; efa= efa->prev) { | 
					
						
							|  |  |  | 		if(efa->f & SELECT) { | 
					
						
							|  |  |  | 			v1= addvertlist(em, efa->v1->co, efa->v1); | 
					
						
							|  |  |  | 			v2= addvertlist(em, efa->v2->co, efa->v2); | 
					
						
							|  |  |  | 			v3= addvertlist(em, efa->v3->co, efa->v3); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			v1->f1= v2->f1= v3->f1= 1; | 
					
						
							|  |  |  | 			VECCOPY(v1->no, efa->n); | 
					
						
							|  |  |  | 			VECCOPY(v2->no, efa->n); | 
					
						
							|  |  |  | 			VECCOPY(v3->no, efa->n); | 
					
						
							|  |  |  | 			if(efa->v4) { | 
					
						
							|  |  |  | 				v4= addvertlist(em, efa->v4->co, efa->v4);  | 
					
						
							|  |  |  | 				v4->f1= 1; | 
					
						
							|  |  |  | 				VECCOPY(v4->no, efa->n); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else v4= NULL; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			/* side faces, clockwise */ | 
					
						
							|  |  |  | 			addfacelist(em, efa->v2, v2, v1, efa->v1, efa, NULL); | 
					
						
							|  |  |  | 			addfacelist(em, efa->v3, v3, v2, efa->v2, efa, NULL); | 
					
						
							|  |  |  | 			if(efa->v4) { | 
					
						
							|  |  |  | 				addfacelist(em, efa->v4, v4, v3, efa->v3, efa, NULL); | 
					
						
							|  |  |  | 				addfacelist(em, efa->v1, v1, v4, efa->v4, efa, NULL); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				addfacelist(em, efa->v1, v1, v3, efa->v3, efa, NULL); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			/* top face */ | 
					
						
							|  |  |  | 			addfacelist(em, v1, v2, v3, v4, efa, NULL); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* step 3: remove old faces */ | 
					
						
							|  |  |  | 	efa= em->faces.first; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		nextfa= efa->next; | 
					
						
							|  |  |  | 		if(efa->f & SELECT) { | 
					
						
							|  |  |  | 			BLI_remlink(&em->faces, efa); | 
					
						
							|  |  |  | 			free_editface(em, efa); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		efa= nextfa; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* step 4: redo selection */ | 
					
						
							|  |  |  | 	EM_clear_flag_all(em, SELECT); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(eve= em->verts.first; eve; eve= eve->next) { | 
					
						
							|  |  |  | 		if(eve->f1)  eve->f |= SELECT; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	EM_select_flush(em); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return 'n'; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* extrudes individual edges */ | 
					
						
							|  |  |  | /* nor is filled with constraint vector */ | 
					
						
							|  |  |  | short extrudeflag_edges_indiv(EditMesh *em, short flag, float *nor)  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(eve= em->verts.first; eve; eve= eve->next) eve->tmp.v = NULL; | 
					
						
							|  |  |  | 	for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 		eed->tmp.f = NULL; | 
					
						
							|  |  |  | 		eed->f2= ((eed->f & flag)!=0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	set_edge_directions_f2(em, 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* sample for next loop */ | 
					
						
							|  |  |  | 	for(efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 		efa->e1->tmp.f = efa; | 
					
						
							|  |  |  | 		efa->e2->tmp.f = efa; | 
					
						
							|  |  |  | 		efa->e3->tmp.f = efa; | 
					
						
							|  |  |  | 		if(efa->e4) efa->e4->tmp.f = efa; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* make the faces */ | 
					
						
							|  |  |  | 	for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 		if(eed->f & flag) { | 
					
						
							|  |  |  | 			if(eed->v1->tmp.v == NULL) | 
					
						
							|  |  |  | 				eed->v1->tmp.v = addvertlist(em, eed->v1->co, eed->v1); | 
					
						
							|  |  |  | 			if(eed->v2->tmp.v == NULL) | 
					
						
							|  |  |  | 				eed->v2->tmp.v = addvertlist(em, eed->v2->co, eed->v2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(eed->dir==1)  | 
					
						
							|  |  |  | 				addfacelist(em, eed->v1, eed->v2,  | 
					
						
							|  |  |  | 							eed->v2->tmp.v, eed->v1->tmp.v,  | 
					
						
							|  |  |  | 							eed->tmp.f, NULL); | 
					
						
							|  |  |  | 			else  | 
					
						
							|  |  |  | 				addfacelist(em, eed->v2, eed->v1,  | 
					
						
							|  |  |  | 							eed->v1->tmp.v, eed->v2->tmp.v,  | 
					
						
							|  |  |  | 							eed->tmp.f, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* for transform */ | 
					
						
							|  |  |  | 			if(eed->tmp.f) { | 
					
						
							|  |  |  | 				efa = eed->tmp.f; | 
					
						
							|  |  |  | 				if (efa->f & SELECT) add_normal_aligned(nor, efa->n); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 	normalize_v3(nor); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* set correct selection */ | 
					
						
							|  |  |  | 	EM_clear_flag_all(em, SELECT); | 
					
						
							|  |  |  | 	for(eve= em->verts.last; eve; eve= eve->prev) { | 
					
						
							|  |  |  | 		if(eve->tmp.v) { | 
					
						
							|  |  |  | 			eve->tmp.v->f |= flag; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 		if(eed->v1->f & eed->v2->f & flag) eed->f |= flag; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // g is grab
 | 
					
						
							|  |  |  | 	return 'n';  // n is for normal constraint
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* extrudes individual vertices */ | 
					
						
							| 
									
										
										
										
											2010-10-16 14:32:17 +00:00
										 |  |  | short extrudeflag_verts_indiv(EditMesh *em, short flag, float *UNUSED(nor))  | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* make the edges */ | 
					
						
							|  |  |  | 	for(eve= em->verts.first; eve; eve= eve->next) { | 
					
						
							|  |  |  | 		if(eve->f & flag) { | 
					
						
							|  |  |  | 			eve->tmp.v = addvertlist(em, eve->co, eve); | 
					
						
							|  |  |  | 			addedgelist(em, eve, eve->tmp.v, NULL); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else eve->tmp.v = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* set correct selection */ | 
					
						
							|  |  |  | 	EM_clear_flag_all(em, SELECT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(eve= em->verts.last; eve; eve= eve->prev)  | 
					
						
							|  |  |  | 		if (eve->tmp.v)  | 
					
						
							|  |  |  | 			eve->tmp.v->f |= flag; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 'g';	// g is grab
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* this is actually a recode of extrudeflag(), using proper edge/face select */ | 
					
						
							|  |  |  | /* hurms, doesnt use 'flag' yet, but its not called by primitive making stuff anyway */ | 
					
						
							| 
									
										
										
										
											2010-10-16 14:32:17 +00:00
										 |  |  | static short extrudeflag_edge(Object *obedit, EditMesh *em, short UNUSED(flag), float *nor, int all) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* all select edges/faces: extrude */ | 
					
						
							|  |  |  | 	/* old select is cleared, in new ones it is set */ | 
					
						
							|  |  |  | 	EditVert *eve, *nextve; | 
					
						
							|  |  |  | 	EditEdge *eed, *nexted; | 
					
						
							|  |  |  | 	EditFace *efa, *nextfa, *efan; | 
					
						
							|  |  |  | 	short del_old= 0; | 
					
						
							|  |  |  | 	ModifierData *md; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	if(em==NULL) return 0; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	md = obedit->modifiers.first; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* selected edges with 0 or 1 selected face become faces */ | 
					
						
							|  |  |  | 	/* selected faces generate new faces */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if *one* selected face has edge with unselected face; remove old selected faces */ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* if selected edge is not used anymore; remove */ | 
					
						
							|  |  |  | 	/* if selected vertex is not used anymore: remove */ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* select the new extrusion, deselect old */ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* step 1; init, count faces in edges */ | 
					
						
							|  |  |  | 	recalc_editnormals(em); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(eve= em->verts.first; eve; eve= eve->next) { | 
					
						
							|  |  |  | 		eve->tmp.v = NULL; | 
					
						
							|  |  |  | 		eve->f1= 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 		eed->f1= 0; // amount of unselected faces
 | 
					
						
							|  |  |  | 		eed->f2= 0; // amount of selected faces
 | 
					
						
							|  |  |  | 		if(eed->f & SELECT) { | 
					
						
							|  |  |  | 			eed->v1->f1= 1; // we call this 'selected vertex' now
 | 
					
						
							|  |  |  | 			eed->v2->f1= 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eed->tmp.f = NULL;		// here we tuck face pointer, as sample
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for(efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 		if(efa->f & SELECT) { | 
					
						
							|  |  |  | 			efa->e1->f2++; | 
					
						
							|  |  |  | 			efa->e2->f2++; | 
					
						
							|  |  |  | 			efa->e3->f2++; | 
					
						
							|  |  |  | 			if(efa->e4) efa->e4->f2++; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			// sample for next loop
 | 
					
						
							|  |  |  | 			efa->e1->tmp.f = efa; | 
					
						
							|  |  |  | 			efa->e2->tmp.f = efa; | 
					
						
							|  |  |  | 			efa->e3->tmp.f = efa; | 
					
						
							|  |  |  | 			if(efa->e4) efa->e4->tmp.f = efa; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			efa->e1->f1++; | 
					
						
							|  |  |  | 			efa->e2->f1++; | 
					
						
							|  |  |  | 			efa->e3->f1++; | 
					
						
							|  |  |  | 			if(efa->e4) efa->e4->f1++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* If a mirror modifier with clipping is on, we need to adjust some 
 | 
					
						
							|  |  |  | 	 * of the cases above to handle edges on the line of symmetry. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	for (; md; md=md->next) { | 
					
						
							|  |  |  | 		if (md->type==eModifierType_Mirror) { | 
					
						
							|  |  |  | 			MirrorModifierData *mmd = (MirrorModifierData*) md;	 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			if(mmd->flag & MOD_MIR_CLIPPING) { | 
					
						
							|  |  |  | 				float mtx[4][4]; | 
					
						
							|  |  |  | 				if (mmd->mirror_ob) { | 
					
						
							|  |  |  | 					float imtx[4][4]; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 					invert_m4_m4(imtx, mmd->mirror_ob->obmat); | 
					
						
							|  |  |  | 					mul_m4_m4m4(mtx, obedit->obmat, imtx); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				for (eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 					if(eed->f2 == 1) { | 
					
						
							|  |  |  | 						float co1[3], co2[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 						copy_v3_v3(co1, eed->v1->co); | 
					
						
							|  |  |  | 						copy_v3_v3(co2, eed->v2->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						if (mmd->mirror_ob) { | 
					
						
							| 
									
										
										
										
											2010-04-12 00:36:50 +00:00
										 |  |  | 							mul_m4_v3(mtx, co1); | 
					
						
							|  |  |  | 							mul_m4_v3(mtx, co2); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						if (mmd->flag & MOD_MIR_AXIS_X) | 
					
						
							|  |  |  | 							if ( (fabs(co1[0]) < mmd->tolerance) && | 
					
						
							|  |  |  | 								 (fabs(co2[0]) < mmd->tolerance) ) | 
					
						
							|  |  |  | 								++eed->f2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						if (mmd->flag & MOD_MIR_AXIS_Y) | 
					
						
							|  |  |  | 							if ( (fabs(co1[1]) < mmd->tolerance) && | 
					
						
							|  |  |  | 								 (fabs(co2[1]) < mmd->tolerance) ) | 
					
						
							|  |  |  | 								++eed->f2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						if (mmd->flag & MOD_MIR_AXIS_Z) | 
					
						
							|  |  |  | 							if ( (fabs(co1[2]) < mmd->tolerance) && | 
					
						
							|  |  |  | 								 (fabs(co2[2]) < mmd->tolerance) ) | 
					
						
							|  |  |  | 								++eed->f2; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	set_edge_directions_f2(em, 2); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* step 1.5: if *one* selected face has edge with unselected face; remove old selected faces */ | 
					
						
							| 
									
										
										
										
											2009-12-15 00:53:34 +00:00
										 |  |  | 	if(all == 0) { | 
					
						
							|  |  |  | 		for(efa= em->faces.last; efa; efa= efa->prev) { | 
					
						
							|  |  |  | 			if(efa->f & SELECT) { | 
					
						
							|  |  |  | 				if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1 || (efa->e4 && efa->e4->f1)) { | 
					
						
							|  |  |  | 					del_old= 1; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 	/* step 2: make new faces from edges */ | 
					
						
							|  |  |  | 	for(eed= em->edges.last; eed; eed= eed->prev) { | 
					
						
							|  |  |  | 		if(eed->f & SELECT) { | 
					
						
							|  |  |  | 			if(eed->f2<2) { | 
					
						
							|  |  |  | 				if(eed->v1->tmp.v == NULL) | 
					
						
							|  |  |  | 					eed->v1->tmp.v = addvertlist(em, eed->v1->co, eed->v1); | 
					
						
							|  |  |  | 				if(eed->v2->tmp.v == NULL) | 
					
						
							|  |  |  | 					eed->v2->tmp.v = addvertlist(em, eed->v2->co, eed->v2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				/* if del_old, the preferred normal direction is exact 
 | 
					
						
							|  |  |  | 				 * opposite as for keep old faces | 
					
						
							|  |  |  | 				 */ | 
					
						
							|  |  |  | 				if(eed->dir!=del_old)  | 
					
						
							|  |  |  | 					addfacelist(em, eed->v1, eed->v2,  | 
					
						
							|  |  |  | 								eed->v2->tmp.v, eed->v1->tmp.v,  | 
					
						
							|  |  |  | 								eed->tmp.f, NULL); | 
					
						
							|  |  |  | 				else  | 
					
						
							|  |  |  | 					addfacelist(em, eed->v2, eed->v1,  | 
					
						
							|  |  |  | 								eed->v1->tmp.v, eed->v2->tmp.v, | 
					
						
							|  |  |  | 								eed->tmp.f, NULL); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* step 3: make new faces from faces */ | 
					
						
							|  |  |  | 	for(efa= em->faces.last; efa; efa= efa->prev) { | 
					
						
							|  |  |  | 		if(efa->f & SELECT) { | 
					
						
							|  |  |  | 			if (efa->v1->tmp.v == NULL) | 
					
						
							|  |  |  | 				efa->v1->tmp.v = addvertlist(em, efa->v1->co, efa->v1); | 
					
						
							|  |  |  | 			if (efa->v2->tmp.v ==NULL) | 
					
						
							|  |  |  | 				efa->v2->tmp.v = addvertlist(em, efa->v2->co, efa->v2); | 
					
						
							|  |  |  | 			if (efa->v3->tmp.v ==NULL) | 
					
						
							|  |  |  | 				efa->v3->tmp.v = addvertlist(em, efa->v3->co, efa->v3); | 
					
						
							|  |  |  | 			if (efa->v4 && (efa->v4->tmp.v == NULL)) | 
					
						
							|  |  |  | 				efa->v4->tmp.v = addvertlist(em, efa->v4->co, efa->v4); | 
					
						
							|  |  |  | 			 | 
					
						
							| 
									
										
										
										
											2010-12-17 06:02:52 +00:00
										 |  |  | 			if(efa->v4) | 
					
						
							|  |  |  | 				efan = addfacelist(em, efa->v1->tmp.v, efa->v2->tmp.v, | 
					
						
							|  |  |  | 							efa->v3->tmp.v, efa->v4->tmp.v, efa, efa); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				efan = addfacelist(em, efa->v1->tmp.v, efa->v2->tmp.v, | 
					
						
							|  |  |  | 							efa->v3->tmp.v, NULL, efa, efa); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* keep old faces means flipping normal, reverse vertex order gives bad UV's & VCols etc - [#25260] */ | 
					
						
							|  |  |  | 			if(del_old==0) { | 
					
						
							|  |  |  | 				flipface(em, efan); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-12-17 06:02:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			if (em->act_face == efa) { | 
					
						
							|  |  |  | 				em->act_face = efan;  | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-12-17 06:02:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			/* for transform */ | 
					
						
							|  |  |  | 			add_normal_aligned(nor, efa->n); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(del_old) { | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/* step 4: remove old faces, if del_old */ | 
					
						
							|  |  |  | 		efa= em->faces.first; | 
					
						
							|  |  |  | 		while(efa) { | 
					
						
							|  |  |  | 			nextfa= efa->next; | 
					
						
							|  |  |  | 			if(efa->f & SELECT) { | 
					
						
							|  |  |  | 				BLI_remlink(&em->faces, efa); | 
					
						
							|  |  |  | 				free_editface(em, efa); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			efa= nextfa; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/* step 5: remove selected unused edges */ | 
					
						
							|  |  |  | 		/* start tagging again */ | 
					
						
							|  |  |  | 		for(eed= em->edges.first; eed; eed= eed->next) 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; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		/* remove */ | 
					
						
							|  |  |  | 		eed= em->edges.first;  | 
					
						
							|  |  |  | 		while(eed) { | 
					
						
							|  |  |  | 			nexted= eed->next; | 
					
						
							|  |  |  | 			if(eed->f & SELECT) { | 
					
						
							|  |  |  | 				if(eed->f1==0) { | 
					
						
							|  |  |  | 					remedge(em, eed); | 
					
						
							|  |  |  | 					free_editedge(em, eed); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			eed= nexted; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		/* step 6: remove selected unused vertices */ | 
					
						
							|  |  |  | 		for(eed= em->edges.first; eed; eed= eed->next)  | 
					
						
							|  |  |  | 			eed->v1->f1= eed->v2->f1= 0; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		eve= em->verts.first; | 
					
						
							|  |  |  | 		while(eve) { | 
					
						
							|  |  |  | 			nextve= eve->next; | 
					
						
							|  |  |  | 			if(eve->f1) { | 
					
						
							|  |  |  | 				// hack... but we need it for step 7, redoing selection
 | 
					
						
							|  |  |  | 				if(eve->tmp.v) eve->tmp.v->tmp.v= eve->tmp.v; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				BLI_remlink(&em->verts, eve); | 
					
						
							|  |  |  | 				free_editvert(em, eve); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			eve= nextve; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 	normalize_v3(nor);	// translation normal grab
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* step 7: redo selection */ | 
					
						
							|  |  |  | 	EM_clear_flag_all(em, SELECT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(eve= em->verts.first; eve; eve= eve->next) { | 
					
						
							|  |  |  | 		if(eve->tmp.v) { | 
					
						
							|  |  |  | 			eve->tmp.v->f |= SELECT; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	EM_select_flush(em); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // grab
 | 
					
						
							|  |  |  | 	return 'n'; // normal constraint 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 00:53:34 +00:00
										 |  |  | short extrudeflag_vert(Object *obedit, EditMesh *em, short flag, float *nor, int all) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* all verts/edges/faces with (f & 'flag'): extrude */ | 
					
						
							|  |  |  | 	/* from old verts, 'flag' is cleared, in new ones it is set */ | 
					
						
							|  |  |  | 	EditVert *eve, *v1, *v2, *v3, *v4, *nextve; | 
					
						
							|  |  |  | 	EditEdge *eed, *e1, *e2, *e3, *e4, *nexted; | 
					
						
							|  |  |  | 	EditFace *efa, *efa2, *nextvl; | 
					
						
							|  |  |  | 	short sel=0, del_old= 0, is_face_sel=0; | 
					
						
							|  |  |  | 	ModifierData *md; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												2.5
Editmesh: add primitive basics back. Had to clean up a load of
crap there... but it's sorta in control, so I think Shul can
pick it up again.
Test: ctrl+0 adds plane, or ctrl+9 adds grid.
Notes for Shul:
- i've added a transform function, which gets correctly passed
  on to the add_prim function, should work for all object 
  transforms. Only the code inside add_prim might be needed
  to check (it uses 4x4 mat now, not a 3x3)
- The old code with buttons has been ifdeffed out, check for
  user input and make it rna properties, which get read
  in the exec(), and handed over to the add_prim. Set them
  default now to the values from old buttons.
- Operator naming is preferred lower case, I gave this
  a new name.
- check a bit on formatting code, but don't use the old code
  as example! Look also at ED_keymap_mesh() for example.
											
										 
											2009-01-14 19:26:11 +00:00
										 |  |  | 	if(em==NULL) return 0; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	md = obedit->modifiers.first; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* clear vert flag f1, we use this to detect a loose selected vertice */ | 
					
						
							|  |  |  | 	eve= em->verts.first; | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							|  |  |  | 		if(eve->f & flag) eve->f1= 1; | 
					
						
							|  |  |  | 		else eve->f1= 0; | 
					
						
							|  |  |  | 		eve= eve->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* clear edges counter flag, if selected we set it at 1 */ | 
					
						
							|  |  |  | 	eed= em->edges.first; | 
					
						
							|  |  |  | 	while(eed) { | 
					
						
							|  |  |  | 		if( (eed->v1->f & flag) && (eed->v2->f & flag) ) { | 
					
						
							|  |  |  | 			eed->f2= 1; | 
					
						
							|  |  |  | 			eed->v1->f1= 0; | 
					
						
							|  |  |  | 			eed->v2->f1= 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else eed->f2= 0; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		eed->f1= 1;		/* this indicates it is an 'old' edge (in this routine we make new ones) */ | 
					
						
							|  |  |  | 		eed->tmp.f = NULL;	/* used as sample */ | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		eed= eed->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* we set a flag in all selected faces, and increase the associated edge counters */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	efa= em->faces.first; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		efa->f1= 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(faceselectedAND(efa, flag)) { | 
					
						
							|  |  |  | 			e1= efa->e1; | 
					
						
							|  |  |  | 			e2= efa->e2; | 
					
						
							|  |  |  | 			e3= efa->e3; | 
					
						
							|  |  |  | 			e4= efa->e4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(e1->f2 < 3) e1->f2++; | 
					
						
							|  |  |  | 			if(e2->f2 < 3) e2->f2++; | 
					
						
							|  |  |  | 			if(e3->f2 < 3) e3->f2++; | 
					
						
							|  |  |  | 			if(e4 && e4->f2 < 3) e4->f2++; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			efa->f1= 1; | 
					
						
							|  |  |  | 			is_face_sel= 1;	// for del_old
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if(faceselectedOR(efa, flag)) { | 
					
						
							|  |  |  | 			e1= efa->e1; | 
					
						
							|  |  |  | 			e2= efa->e2; | 
					
						
							|  |  |  | 			e3= efa->e3; | 
					
						
							|  |  |  | 			e4= efa->e4; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if( (e1->v1->f & flag) && (e1->v2->f & flag) ) e1->f1= 2; | 
					
						
							|  |  |  | 			if( (e2->v1->f & flag) && (e2->v2->f & flag) ) e2->f1= 2; | 
					
						
							|  |  |  | 			if( (e3->v1->f & flag) && (e3->v2->f & flag) ) e3->f1= 2; | 
					
						
							|  |  |  | 			if( e4 && (e4->v1->f & flag) && (e4->v2->f & flag) ) e4->f1= 2; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		// sample for next loop
 | 
					
						
							|  |  |  | 		efa->e1->tmp.f = efa; | 
					
						
							|  |  |  | 		efa->e2->tmp.f = efa; | 
					
						
							|  |  |  | 		efa->e3->tmp.f = efa; | 
					
						
							|  |  |  | 		if(efa->e4) efa->e4->tmp.f = efa; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		efa= efa->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	set_edge_directions_f2(em, 3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* the current state now is:
 | 
					
						
							|  |  |  | 		eve->f1==1: loose selected vertex  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		eed->f2==0 : edge is not selected, no extrude | 
					
						
							|  |  |  | 		eed->f2==1 : edge selected, is not part of a face, extrude | 
					
						
							|  |  |  | 		eed->f2==2 : edge selected, is part of 1 face, extrude | 
					
						
							|  |  |  | 		eed->f2==3 : edge selected, is part of more faces, no extrude | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		eed->f1==0: new edge | 
					
						
							|  |  |  | 		eed->f1==1: edge selected, is part of selected face, when eed->f==3: remove | 
					
						
							|  |  |  | 		eed->f1==2: edge selected, part of a partially selected face | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 		efa->f1==1 : duplicate this face | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* If a mirror modifier with clipping is on, we need to adjust some 
 | 
					
						
							|  |  |  | 	 * of the cases above to handle edges on the line of symmetry. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	for (; md; md=md->next) { | 
					
						
							|  |  |  | 		if (md->type==eModifierType_Mirror) { | 
					
						
							|  |  |  | 			MirrorModifierData *mmd = (MirrorModifierData*) md;	 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			if(mmd->flag & MOD_MIR_CLIPPING) { | 
					
						
							|  |  |  | 				float mtx[4][4]; | 
					
						
							|  |  |  | 				if (mmd->mirror_ob) { | 
					
						
							|  |  |  | 					float imtx[4][4]; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 					invert_m4_m4(imtx, mmd->mirror_ob->obmat); | 
					
						
							|  |  |  | 					mul_m4_m4m4(mtx, obedit->obmat, imtx); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				for (eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 					if(eed->f2 == 2) { | 
					
						
							|  |  |  | 						float co1[3], co2[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 						copy_v3_v3(co1, eed->v1->co); | 
					
						
							|  |  |  | 						copy_v3_v3(co2, eed->v2->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						if (mmd->mirror_ob) { | 
					
						
							| 
									
										
										
										
											2010-04-12 00:36:50 +00:00
										 |  |  | 							mul_m4_v3(mtx, co1); | 
					
						
							|  |  |  | 							mul_m4_v3(mtx, co2); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						if (mmd->flag & MOD_MIR_AXIS_X) | 
					
						
							|  |  |  | 							if ( (fabs(co1[0]) < mmd->tolerance) && | 
					
						
							|  |  |  | 								 (fabs(co2[0]) < mmd->tolerance) ) | 
					
						
							|  |  |  | 								++eed->f2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						if (mmd->flag & MOD_MIR_AXIS_Y) | 
					
						
							|  |  |  | 							if ( (fabs(co1[1]) < mmd->tolerance) && | 
					
						
							|  |  |  | 								 (fabs(co2[1]) < mmd->tolerance) ) | 
					
						
							|  |  |  | 								++eed->f2; | 
					
						
							|  |  |  | 						if (mmd->flag & MOD_MIR_AXIS_Z) | 
					
						
							|  |  |  | 							if ( (fabs(co1[2]) < mmd->tolerance) && | 
					
						
							|  |  |  | 								 (fabs(co2[2]) < mmd->tolerance) ) | 
					
						
							|  |  |  | 								++eed->f2; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* copy all selected vertices, */ | 
					
						
							|  |  |  | 	/* write pointer to new vert in old struct at eve->tmp.v */ | 
					
						
							|  |  |  | 	eve= em->verts.last; | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							|  |  |  | 		eve->f &= ~128;  /* clear, for later test for loose verts */ | 
					
						
							|  |  |  | 		if(eve->f & flag) { | 
					
						
							|  |  |  | 			sel= 1; | 
					
						
							|  |  |  | 			v1= addvertlist(em, 0, NULL); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			VECCOPY(v1->co, eve->co); | 
					
						
							| 
									
										
										
										
											2010-02-13 20:06:56 +00:00
										 |  |  | 			VECCOPY(v1->no, eve->no); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			v1->f= eve->f; | 
					
						
							| 
									
										
										
										
											2011-01-13 19:01:27 +00:00
										 |  |  | 			eve->f &= ~flag; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			eve->tmp.v = v1; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-01-13 19:01:27 +00:00
										 |  |  | 		else eve->tmp.v = NULL; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		eve= eve->prev; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(sel==0) return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* all edges with eed->f2==1 or eed->f2==2 become faces */ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* if del_old==1 then extrude is in partial geometry, to keep it manifold.
 | 
					
						
							|  |  |  | 					 verts with f1==0 and (eve->f & 128)==0) are removed | 
					
						
							| 
									
										
										
										
											2010-03-22 09:30:00 +00:00
										 |  |  | 					 edges with eed->f2>2 are removed | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 					 faces with efa->f1 are removed | 
					
						
							|  |  |  | 	   if del_old==0 the extrude creates a volume. | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 /* find if we delete old faces */ | 
					
						
							| 
									
										
										
										
											2009-12-15 00:53:34 +00:00
										 |  |  | 	if(is_face_sel && all==0) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 			if( (eed->f2==1 || eed->f2==2) ) { | 
					
						
							|  |  |  | 				if(eed->f1==2) { | 
					
						
							|  |  |  | 					del_old= 1; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	eed= em->edges.last; | 
					
						
							|  |  |  | 	while(eed) { | 
					
						
							|  |  |  | 		nexted= eed->prev; | 
					
						
							|  |  |  | 		if( eed->f2<3) { | 
					
						
							|  |  |  | 			eed->v1->f |= 128;  /* = no loose vert! */ | 
					
						
							|  |  |  | 			eed->v2->f |= 128; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if( (eed->f2==1 || eed->f2==2) ) { | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 			/* if del_old, the preferred normal direction is exact opposite as for keep old faces */ | 
					
						
							|  |  |  | 			if(eed->dir != del_old)  | 
					
						
							|  |  |  | 				efa2 = addfacelist(em, eed->v1, eed->v2,  | 
					
						
							|  |  |  | 								  eed->v2->tmp.v, eed->v1->tmp.v,  | 
					
						
							|  |  |  | 								  eed->tmp.f, NULL); | 
					
						
							|  |  |  | 			else  | 
					
						
							|  |  |  | 				efa2 = addfacelist(em, eed->v2, eed->v1,  | 
					
						
							|  |  |  | 								   eed->v1->tmp.v, eed->v2->tmp.v,  | 
					
						
							|  |  |  | 								   eed->tmp.f, NULL); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			/* Needs smarter adaption of existing creases.
 | 
					
						
							|  |  |  | 			 * If addedgelist is used, make sure seams are set to 0 on these | 
					
						
							|  |  |  | 			 * new edges, since we do not want to add any seams on extrusion. | 
					
						
							|  |  |  | 			 */ | 
					
						
							|  |  |  | 			efa2->e1->crease= eed->crease; | 
					
						
							|  |  |  | 			efa2->e2->crease= eed->crease; | 
					
						
							|  |  |  | 			efa2->e3->crease= eed->crease; | 
					
						
							|  |  |  | 			if(efa2->e4) efa2->e4->crease= eed->crease; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		eed= nexted; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-01-13 19:01:27 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	/* duplicate faces, if necessary remove old ones  */ | 
					
						
							|  |  |  | 	efa= em->faces.first; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		nextvl= efa->next; | 
					
						
							|  |  |  | 		if(efa->f1 & 1) { | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			v1 = efa->v1->tmp.v; | 
					
						
							|  |  |  | 			v2 = efa->v2->tmp.v; | 
					
						
							|  |  |  | 			v3 = efa->v3->tmp.v; | 
					
						
							|  |  |  | 			if(efa->v4)  | 
					
						
							|  |  |  | 				v4 = efa->v4->tmp.v;  | 
					
						
							|  |  |  | 			else | 
					
						
							| 
									
										
										
										
											2011-01-13 19:01:27 +00:00
										 |  |  | 				v4= NULL; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/* hmm .. not sure about edges here */ | 
					
						
							|  |  |  | 			if(del_old==0)	// if we keep old, we flip normal
 | 
					
						
							|  |  |  | 				efa2= addfacelist(em, v3, v2, v1, v4, efa, efa);  | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				efa2= addfacelist(em, v1, v2, v3, v4, efa, efa); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			/* for transform */ | 
					
						
							|  |  |  | 			add_normal_aligned(nor, efa->n); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(del_old) { | 
					
						
							|  |  |  | 				BLI_remlink(&em->faces, efa); | 
					
						
							|  |  |  | 				free_editface(em, efa); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		efa= nextvl; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-01-13 19:01:27 +00:00
										 |  |  | 	/* delete edges after copying edges above! */ | 
					
						
							|  |  |  | 	if(del_old) { | 
					
						
							|  |  |  | 		eed= em->edges.first; | 
					
						
							|  |  |  | 		while(eed) { | 
					
						
							|  |  |  | 			nexted= eed->next; | 
					
						
							|  |  |  | 			if(eed->f2==3 && eed->f1==1) { | 
					
						
							|  |  |  | 				remedge(em, eed); | 
					
						
							|  |  |  | 				free_editedge(em, eed); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			eed= nexted; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 	normalize_v3(nor);	// for grab
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* for all vertices with eve->tmp.v!=0 
 | 
					
						
							|  |  |  | 		if eve->f1==1: make edge | 
					
						
							|  |  |  | 		if flag!=128 : if del_old==1: remove | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	eve= em->verts.last; | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							|  |  |  | 		nextve= eve->prev; | 
					
						
							|  |  |  | 		if(eve->tmp.v) { | 
					
						
							|  |  |  | 			if(eve->f1==1) addedgelist(em, eve, eve->tmp.v, NULL); | 
					
						
							|  |  |  | 			else if( (eve->f & 128)==0) { | 
					
						
							|  |  |  | 				if(del_old) { | 
					
						
							|  |  |  | 					BLI_remlink(&em->verts,eve); | 
					
						
							|  |  |  | 					free_editvert(em, eve); | 
					
						
							|  |  |  | 					eve= NULL; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(eve) { | 
					
						
							|  |  |  | 			eve->f &= ~128; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eve= nextve; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// since its vertex select mode now, it also deselects higher order
 | 
					
						
							|  |  |  | 	EM_selectmode_flush(em); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // g is grab, for correct undo print
 | 
					
						
							|  |  |  | 	return 'n'; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* generic extrude */ | 
					
						
							| 
									
										
										
										
											2009-12-15 00:53:34 +00:00
										 |  |  | short extrudeflag(Object *obedit, EditMesh *em, short flag, float *nor, int all) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if(em->selectmode & SCE_SELECT_VERTEX) | 
					
						
							| 
									
										
										
										
											2009-12-15 00:53:34 +00:00
										 |  |  | 		return extrudeflag_vert(obedit, em, flag, nor, all); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	else  | 
					
						
							| 
									
										
										
										
											2009-12-15 00:53:34 +00:00
										 |  |  | 		return extrudeflag_edge(obedit, em, flag, nor, all); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void rotateflag(EditMesh *em, short flag, float *cent, float rotmat[][3]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* all verts with (flag & 'flag') rotate */ | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	eve= em->verts.first; | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							|  |  |  | 		if(eve->f & flag) { | 
					
						
							|  |  |  | 			eve->co[0]-=cent[0]; | 
					
						
							|  |  |  | 			eve->co[1]-=cent[1]; | 
					
						
							|  |  |  | 			eve->co[2]-=cent[2]; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			mul_m3_v3(rotmat,eve->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			eve->co[0]+=cent[0]; | 
					
						
							|  |  |  | 			eve->co[1]+=cent[1]; | 
					
						
							|  |  |  | 			eve->co[2]+=cent[2]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eve= eve->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void translateflag(EditMesh *em, short flag, float *vec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* all verts with (flag & 'flag') translate */ | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	eve= em->verts.first; | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							|  |  |  | 		if(eve->f & flag) { | 
					
						
							|  |  |  | 			eve->co[0]+=vec[0]; | 
					
						
							|  |  |  | 			eve->co[1]+=vec[1]; | 
					
						
							|  |  |  | 			eve->co[2]+=vec[2]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eve= eve->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* helper call for below */ | 
					
						
							|  |  |  | static EditVert *adduplicate_vertex(EditMesh *em, EditVert *eve, int flag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* FIXME: copy deformation weight from eve ok here? */ | 
					
						
							|  |  |  | 	EditVert *v1= addvertlist(em, eve->co, eve); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	v1->f= eve->f; | 
					
						
							| 
									
										
										
										
											2011-01-13 19:01:27 +00:00
										 |  |  | 	eve->f &= ~flag; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	eve->f|= 128; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	eve->tmp.v = v1; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return v1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* old selection has flag 128 set, and flag 'flag' cleared
 | 
					
						
							|  |  |  | new selection has flag 'flag' set */ | 
					
						
							|  |  |  | void adduplicateflag(EditMesh *em, int flag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve, *v1, *v2, *v3, *v4; | 
					
						
							|  |  |  | 	EditEdge *eed, *newed; | 
					
						
							|  |  |  | 	EditFace *efa, *newfa, *act_efa = EM_get_actFace(em, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	EM_clear_flag_all(em, 128); | 
					
						
							| 
									
										
										
										
											2009-04-15 15:40:31 +00:00
										 |  |  | 	EM_selectmode_set(em);	// paranoia check, selection now is consistent
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* vertices first */ | 
					
						
							|  |  |  | 	for(eve= em->verts.last; eve; eve= eve->prev) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(eve->f & flag) | 
					
						
							|  |  |  | 			adduplicate_vertex(em, eve, flag); | 
					
						
							|  |  |  | 		else  | 
					
						
							|  |  |  | 			eve->tmp.v = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* copy edges, note that vertex selection can be independent of edge */ | 
					
						
							|  |  |  | 	for(eed= em->edges.last; eed; eed= eed->prev) { | 
					
						
							|  |  |  | 		if( eed->f & flag ) { | 
					
						
							|  |  |  | 			v1 = eed->v1->tmp.v; | 
					
						
							|  |  |  | 			if(v1==NULL) v1= adduplicate_vertex(em, eed->v1, flag); | 
					
						
							|  |  |  | 			v2 = eed->v2->tmp.v; | 
					
						
							|  |  |  | 			if(v2==NULL) v2= adduplicate_vertex(em, eed->v2, flag); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			newed= addedgelist(em, v1, v2, eed); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			newed->f= eed->f; | 
					
						
							| 
									
										
										
										
											2011-01-13 19:01:27 +00:00
										 |  |  | 			eed->f &= ~flag; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			eed->f |= 128; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* then duplicate faces, again create new vertices if needed */ | 
					
						
							|  |  |  | 	for(efa= em->faces.last; efa; efa= efa->prev) { | 
					
						
							|  |  |  | 		if(efa->f & flag) { | 
					
						
							|  |  |  | 			v1 = efa->v1->tmp.v; | 
					
						
							|  |  |  | 			if(v1==NULL) v1= adduplicate_vertex(em, efa->v1, flag); | 
					
						
							|  |  |  | 			v2 = efa->v2->tmp.v; | 
					
						
							|  |  |  | 			if(v2==NULL) v2= adduplicate_vertex(em, efa->v2, flag); | 
					
						
							|  |  |  | 			v3 = efa->v3->tmp.v; | 
					
						
							|  |  |  | 			if(v3==NULL) v3= adduplicate_vertex(em, efa->v3, flag); | 
					
						
							|  |  |  | 			if(efa->v4) { | 
					
						
							|  |  |  | 				v4 = efa->v4->tmp.v;  | 
					
						
							|  |  |  | 				if(v4==NULL) v4= adduplicate_vertex(em, efa->v4, flag); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else v4= NULL; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			newfa= addfacelist(em, v1, v2, v3, v4, efa, efa);  | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if (efa==act_efa) { | 
					
						
							|  |  |  | 				EM_set_actFace(em, newfa); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			newfa->f= efa->f; | 
					
						
							| 
									
										
										
										
											2011-01-13 19:01:27 +00:00
										 |  |  | 			efa->f &= ~flag; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			efa->f |= 128; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	EM_fgon_flags(em);	// redo flags and indices for fgons
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void delfaceflag(EditMesh *em, int flag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* delete all faces with 'flag', including loose edges and loose vertices */ | 
					
						
							|  |  |  | 	/* this is maybe a bit weird, but this function is used for 'split' and 'separate' */ | 
					
						
							|  |  |  | 	/* in remaining vertices/edges 'flag' is cleared */ | 
					
						
							|  |  |  | 	EditVert *eve,*nextve; | 
					
						
							|  |  |  | 	EditEdge *eed, *nexted; | 
					
						
							|  |  |  | 	EditFace *efa,*nextvl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* to detect loose edges, we put f2 flag on 1 */ | 
					
						
							|  |  |  | 	for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 		if(eed->f & flag) eed->f2= 1; | 
					
						
							|  |  |  | 		else eed->f2= 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* delete faces */ | 
					
						
							|  |  |  | 	efa= em->faces.first; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		nextvl= efa->next; | 
					
						
							|  |  |  | 		if(efa->f & flag) { | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			efa->e1->f2= 1; | 
					
						
							|  |  |  | 			efa->e2->f2= 1; | 
					
						
							|  |  |  | 			efa->e3->f2= 1; | 
					
						
							|  |  |  | 			if(efa->e4) { | 
					
						
							|  |  |  | 				efa->e4->f2= 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 								 | 
					
						
							|  |  |  | 			BLI_remlink(&em->faces, efa); | 
					
						
							|  |  |  | 			free_editface(em, efa); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		efa= nextvl; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* all remaining faces: make sure we keep the edges */ | 
					
						
							|  |  |  | 	for(efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 		efa->e1->f2= 0; | 
					
						
							|  |  |  | 		efa->e2->f2= 0; | 
					
						
							|  |  |  | 		efa->e3->f2= 0; | 
					
						
							|  |  |  | 		if(efa->e4) { | 
					
						
							|  |  |  | 			efa->e4->f2= 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* remove tagged edges, and clear remaining ones */ | 
					
						
							|  |  |  | 	eed= em->edges.first; | 
					
						
							|  |  |  | 	while(eed) { | 
					
						
							|  |  |  | 		nexted= eed->next; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if(eed->f2==1) { | 
					
						
							|  |  |  | 			remedge(em, eed); | 
					
						
							|  |  |  | 			free_editedge(em, eed); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			eed->f &= ~flag; | 
					
						
							|  |  |  | 			eed->v1->f &= ~flag; | 
					
						
							|  |  |  | 			eed->v2->f &= ~flag; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eed= nexted; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* vertices with 'flag' now are the loose ones, and will be removed */ | 
					
						
							|  |  |  | 	eve= em->verts.first; | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							|  |  |  | 		nextve= eve->next; | 
					
						
							|  |  |  | 		if(eve->f & flag) { | 
					
						
							|  |  |  | 			BLI_remlink(&em->verts, eve); | 
					
						
							|  |  |  | 			free_editvert(em, eve); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eve= nextve; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ********************* */ | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | static int check_vnormal_flip(float *n, float *vnorm)  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float inp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	inp= n[0]*vnorm[0]+n[1]*vnorm[1]+n[2]*vnorm[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* angles 90 degrees: dont flip */ | 
					
						
							|  |  |  | 	if(inp> -0.000001) return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* does face centers too */ | 
					
						
							|  |  |  | void recalc_editnormals(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(eve= em->verts.first; eve; eve=eve->next) { | 
					
						
							|  |  |  | 		eve->no[0] = eve->no[1] = eve->no[2] = 0.0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(efa= em->faces.first; efa; efa=efa->next) { | 
					
						
							|  |  |  | 		if(efa->v4) { | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			normal_quad_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); | 
					
						
							|  |  |  | 			cent_quad_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			normal_tri_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co); | 
					
						
							|  |  |  | 			cent_tri_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-03-20 13:35:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if((efa->flag&ME_SMOOTH)!=0) { | 
					
						
							|  |  |  | 			float *n4= (efa->v4)? efa->v4->no: NULL; | 
					
						
							|  |  |  | 			float *c4= (efa->v4)? efa->v4->co: NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			accumulate_vertex_normals(efa->v1->no, efa->v2->no, efa->v3->no, n4, | 
					
						
							|  |  |  | 				efa->n, efa->v1->co, efa->v2->co, efa->v3->co, c4); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(efa= em->faces.first; efa; efa=efa->next) { | 
					
						
							|  |  |  | 		if((efa->flag&ME_SMOOTH)==0) { | 
					
						
							|  |  |  | 			if(is_zero_v3(efa->v1->no)) copy_v3_v3(efa->v1->no, efa->n); | 
					
						
							|  |  |  | 			if(is_zero_v3(efa->v2->no)) copy_v3_v3(efa->v2->no, efa->n); | 
					
						
							|  |  |  | 			if(is_zero_v3(efa->v3->no)) copy_v3_v3(efa->v3->no, efa->n); | 
					
						
							|  |  |  | 			if(efa->v4 && is_zero_v3(efa->v4->no)) copy_v3_v3(efa->v4->no, efa->n); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* following Mesh convention; we use vertex coordinate itself for normal in this case */ | 
					
						
							|  |  |  | 	for(eve= em->verts.first; eve; eve=eve->next) { | 
					
						
							| 
									
										
										
										
											2011-03-20 13:35:35 +00:00
										 |  |  | 		if(normalize_v3(eve->no) == 0.0f) { | 
					
						
							|  |  |  | 			copy_v3_v3(eve->no, eve->co); | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			normalize_v3(eve->no); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int compareface(EditFace *vl1, EditFace *vl2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *v1, *v2, *v3, *v4; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(vl1->v4 && vl2->v4) { | 
					
						
							|  |  |  | 		v1= vl2->v1; | 
					
						
							|  |  |  | 		v2= vl2->v2; | 
					
						
							|  |  |  | 		v3= vl2->v3; | 
					
						
							|  |  |  | 		v4= vl2->v4; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1 || vl1->v4==v1) { | 
					
						
							|  |  |  | 			if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2 || vl1->v4==v2) { | 
					
						
							|  |  |  | 				if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3 || vl1->v4==v3) { | 
					
						
							|  |  |  | 					if(vl1->v1==v4 || vl1->v2==v4 || vl1->v3==v4 || vl1->v4==v4) { | 
					
						
							|  |  |  | 						return 1; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if(vl1->v4==0 && vl2->v4==0) { | 
					
						
							|  |  |  | 		v1= vl2->v1; | 
					
						
							|  |  |  | 		v2= vl2->v2; | 
					
						
							|  |  |  | 		v3= vl2->v3; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1) { | 
					
						
							|  |  |  | 			if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2) { | 
					
						
							|  |  |  | 				if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3) { | 
					
						
							|  |  |  | 					return 1; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-14 10:59:42 +00:00
										 |  |  | /* checks for existence, not tria overlapping inside quad */ | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | EditFace *exist_face(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa, efatest; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	efatest.v1= v1; | 
					
						
							|  |  |  | 	efatest.v2= v2; | 
					
						
							|  |  |  | 	efatest.v3= v3; | 
					
						
							|  |  |  | 	efatest.v4= v4; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	efa= em->faces.first; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		if(compareface(&efatest, efa)) return efa; | 
					
						
							|  |  |  | 		efa= efa->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* evaluate if entire quad is a proper convex quad */ | 
					
						
							|  |  |  | int convex(float *v1, float *v2, float *v3, float *v4) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float nor[3], nor1[3], nor2[3], vec[4][2]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* define projection, do both trias apart, quad is undefined! */ | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 	normal_tri_v3( nor1,v1, v2, v3); | 
					
						
							|  |  |  | 	normal_tri_v3( nor2,v1, v3, v4); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	nor[0]= ABS(nor1[0]) + ABS(nor2[0]); | 
					
						
							|  |  |  | 	nor[1]= ABS(nor1[1]) + ABS(nor2[1]); | 
					
						
							|  |  |  | 	nor[2]= ABS(nor1[2]) + ABS(nor2[2]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(nor[2] >= nor[0] && nor[2] >= nor[1]) { | 
					
						
							|  |  |  | 		vec[0][0]= v1[0]; vec[0][1]= v1[1]; | 
					
						
							|  |  |  | 		vec[1][0]= v2[0]; vec[1][1]= v2[1]; | 
					
						
							|  |  |  | 		vec[2][0]= v3[0]; vec[2][1]= v3[1]; | 
					
						
							|  |  |  | 		vec[3][0]= v4[0]; vec[3][1]= v4[1]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if(nor[1] >= nor[0] && nor[1]>= nor[2]) { | 
					
						
							|  |  |  | 		vec[0][0]= v1[0]; vec[0][1]= v1[2]; | 
					
						
							|  |  |  | 		vec[1][0]= v2[0]; vec[1][1]= v2[2]; | 
					
						
							|  |  |  | 		vec[2][0]= v3[0]; vec[2][1]= v3[2]; | 
					
						
							|  |  |  | 		vec[3][0]= v4[0]; vec[3][1]= v4[2]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		vec[0][0]= v1[1]; vec[0][1]= v1[2]; | 
					
						
							|  |  |  | 		vec[1][0]= v2[1]; vec[1][1]= v2[2]; | 
					
						
							|  |  |  | 		vec[2][0]= v3[1]; vec[2][1]= v3[2]; | 
					
						
							|  |  |  | 		vec[3][0]= v4[1]; vec[3][1]= v4[2]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* linetests, the 2 diagonals have to instersect to be convex */ | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 	if( isect_line_line_v2(vec[0], vec[2], vec[1], vec[3]) > 0 ) return 1; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ********************* Fake Polgon support (FGon) ***************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* results in:
 | 
					
						
							|  |  |  |    - faces having ->fgonf flag set (also for draw) | 
					
						
							|  |  |  |    - edges having ->fgoni index set (for select) | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float EM_face_area(EditFace *efa) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 	if(efa->v4) return area_quad_v3(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); | 
					
						
							|  |  |  | 	else return area_tri_v3(efa->v1->co, efa->v2->co, efa->v3->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float EM_face_perimeter(EditFace *efa) | 
					
						
							|  |  |  | {	 | 
					
						
							|  |  |  | 	if(efa->v4) return | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		len_v3v3(efa->v1->co, efa->v2->co)+ | 
					
						
							|  |  |  | 		len_v3v3(efa->v2->co, efa->v3->co)+ | 
					
						
							|  |  |  | 		len_v3v3(efa->v3->co, efa->v4->co)+ | 
					
						
							|  |  |  | 		len_v3v3(efa->v4->co, efa->v1->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	else return | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		len_v3v3(efa->v1->co, efa->v2->co)+ | 
					
						
							|  |  |  | 		len_v3v3(efa->v2->co, efa->v3->co)+ | 
					
						
							|  |  |  | 		len_v3v3(efa->v3->co, efa->v1->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_fgon_flags(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa, *efan, *efamax; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	ListBase listb={NULL, NULL}; | 
					
						
							|  |  |  | 	float size, maxsize; | 
					
						
							|  |  |  | 	short done, curindex= 1; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// for each face with fgon edge AND not fgon flag set
 | 
					
						
							|  |  |  | 	for(eed= em->edges.first; eed; eed= eed->next) eed->fgoni= 0;  // index
 | 
					
						
							|  |  |  | 	for(efa= em->faces.first; efa; efa= efa->next) efa->fgonf= 0;  // flag
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// for speed & simplicity, put fgon face candidates in new listbase
 | 
					
						
							|  |  |  | 	efa= em->faces.first; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		efan= efa->next; | 
					
						
							|  |  |  | 		if( (efa->e1->h & EM_FGON) || (efa->e2->h & EM_FGON) ||  | 
					
						
							|  |  |  | 			(efa->e3->h & EM_FGON) || (efa->e4 && (efa->e4->h & EM_FGON)) ) { | 
					
						
							|  |  |  | 			BLI_remlink(&em->faces, efa); | 
					
						
							|  |  |  | 			BLI_addtail(&listb, efa); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		efa= efan; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// find an undone face with fgon edge
 | 
					
						
							|  |  |  | 	for(efa= listb.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 		if(efa->fgonf==0) { | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			// init this face
 | 
					
						
							|  |  |  | 			efa->fgonf= EM_FGON; | 
					
						
							|  |  |  | 			if(efa->e1->h & EM_FGON) efa->e1->fgoni= curindex; | 
					
						
							|  |  |  | 			if(efa->e2->h & EM_FGON) efa->e2->fgoni= curindex; | 
					
						
							|  |  |  | 			if(efa->e3->h & EM_FGON) efa->e3->fgoni= curindex; | 
					
						
							|  |  |  | 			if(efa->e4 && (efa->e4->h & EM_FGON)) efa->e4->fgoni= curindex; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			// we search for largest face, to give facedot drawing rights
 | 
					
						
							|  |  |  | 			maxsize= EM_face_area(efa); | 
					
						
							|  |  |  | 			efamax= efa; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			// now flush curendex over edges and set faceflags
 | 
					
						
							|  |  |  | 			done= 1; | 
					
						
							|  |  |  | 			while(done==1) { | 
					
						
							|  |  |  | 				done= 0; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				for(efan= listb.first; efan; efan= efan->next) { | 
					
						
							|  |  |  | 					if(efan->fgonf==0) { | 
					
						
							|  |  |  | 						// if one if its edges has index set, do other too
 | 
					
						
							|  |  |  | 						if( (efan->e1->fgoni==curindex) || (efan->e2->fgoni==curindex) || | 
					
						
							|  |  |  | 							(efan->e3->fgoni==curindex) || (efan->e4 && (efan->e4->fgoni==curindex)) ) { | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 							efan->fgonf= EM_FGON; | 
					
						
							|  |  |  | 							if(efan->e1->h & EM_FGON) efan->e1->fgoni= curindex; | 
					
						
							|  |  |  | 							if(efan->e2->h & EM_FGON) efan->e2->fgoni= curindex; | 
					
						
							|  |  |  | 							if(efan->e3->h & EM_FGON) efan->e3->fgoni= curindex; | 
					
						
							|  |  |  | 							if(efan->e4 && (efan->e4->h & EM_FGON)) efan->e4->fgoni= curindex; | 
					
						
							|  |  |  | 							 | 
					
						
							|  |  |  | 							size= EM_face_area(efan); | 
					
						
							|  |  |  | 							if(size>maxsize) { | 
					
						
							|  |  |  | 								efamax= efan; | 
					
						
							|  |  |  | 								maxsize= size; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							done= 1; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			efamax->fgonf |= EM_FGON_DRAW; | 
					
						
							|  |  |  | 			curindex++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// put fgon face candidates back in listbase
 | 
					
						
							|  |  |  | 	efa= listb.first; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		efan= efa->next; | 
					
						
							|  |  |  | 		BLI_remlink(&listb, efa); | 
					
						
							|  |  |  | 		BLI_addtail(&em->faces, efa); | 
					
						
							|  |  |  | 		efa= efan; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// remove fgon flags when edge not in fgon (anymore)
 | 
					
						
							|  |  |  | 	for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 		if(eed->fgoni==0) eed->h &= ~EM_FGON; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* editmesh vertmap, copied from intern.mesh.c
 | 
					
						
							|  |  |  |  * if do_face_idx_array is 0 it means we need to run it as well as freeing | 
					
						
							|  |  |  |  * */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												2.5: Space Image ported back
Organized as follows:
uvedit/
	uv editing related code
	uvedit_draw.c: drawing code
	uvedit_ops.c: operators, just a few done
	uvedit_unwrap_ops.c: will be operators for unwrapping
	uvedit_paramatrizer.c: lscm/abf/stretch/pack
space_image/
	space_image.c: registration and common getter/setters
	image_draw.c: drawing code, mostly functional
	image_panels.c: panels, all commented out
	image_render.c: render callbacks, non functional
	image_ops.c: operators, only view navigation done
	image_header.c: header, menus mostly done but missing buttons
Notes:
* Header menus consist only of Operator and RNA buttons, if they
  are not implemented they're displayed grayed out. Ideally the full
  header could work like this, but std_libbuttons looks problematic.
* Started using view2d code more than the old code, but for now it
  still does own view2d management due to some very specific
  requirements that the image window has. The drawing code however
  is more clear hopefully, it only uses view2d, and there is no
  switching between 'p' and 'f' view2d's anymore, it is always 'f'.
* In order to make uvedit operators more independent I move some
  image space settings to scene toolsettings, and the current image
  and its buffer is in the context. Especially sync selection and
  select mode belonged there anyway as this cannot work correct with
  different spaces having different settings anyway.
* Image paint is not back yet, did not want to put that together with
  uvedit because there's really no code sharing.. perhaps vertex paint,
  image paint and sculpt would be good to have in one module to share
  brush code, partial redraw, etc better.
											
										 
											2009-01-15 04:38:18 +00:00
										 |  |  | UvVertMap *EM_make_uv_vert_map(EditMesh *em, int selected, int do_face_idx_array, float *limit) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditVert *ev; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	int totverts; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* vars from original func */ | 
					
						
							|  |  |  | 	UvVertMap *vmap; | 
					
						
							|  |  |  | 	UvMapVert *buf; | 
					
						
							|  |  |  | 	MTFace *tf; | 
					
						
							|  |  |  | 	unsigned int a; | 
					
						
							|  |  |  | 	int	i, totuv, nverts; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (do_face_idx_array) | 
					
						
							|  |  |  | 		EM_init_index_arrays(em, 0, 0, 1); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* we need the vert */ | 
					
						
							|  |  |  | 	for (ev= em->verts.first, totverts=0; ev; ev= ev->next, totverts++) { | 
					
						
							|  |  |  | 		ev->tmp.l = totverts; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	totuv = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* generate UvMapVert array */ | 
					
						
							|  |  |  | 	for (efa= em->faces.first; efa; efa= efa->next) | 
					
						
							|  |  |  | 		if(!selected || ((!efa->h) && (efa->f & SELECT))) | 
					
						
							|  |  |  | 			totuv += (efa->v4)? 4: 3; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	if(totuv==0) { | 
					
						
							|  |  |  | 		if (do_face_idx_array) | 
					
						
							|  |  |  | 			EM_free_index_arrays(); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	vmap= (UvVertMap*)MEM_callocN(sizeof(*vmap), "UvVertMap"); | 
					
						
							|  |  |  | 	if (!vmap) { | 
					
						
							|  |  |  | 		if (do_face_idx_array) | 
					
						
							|  |  |  | 			EM_free_index_arrays(); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vmap->vert= (UvMapVert**)MEM_callocN(sizeof(*vmap->vert)*totverts, "UvMapVert*"); | 
					
						
							|  |  |  | 	buf= vmap->buf= (UvMapVert*)MEM_callocN(sizeof(*vmap->buf)*totuv, "UvMapVert"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!vmap->vert || !vmap->buf) { | 
					
						
							|  |  |  | 		free_uv_vert_map(vmap); | 
					
						
							|  |  |  | 		if (do_face_idx_array) | 
					
						
							|  |  |  | 			EM_free_index_arrays(); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (a=0, efa= em->faces.first; efa; a++, efa= efa->next) { | 
					
						
							|  |  |  | 		if(!selected || ((!efa->h) && (efa->f & SELECT))) { | 
					
						
							|  |  |  | 			nverts= (efa->v4)? 4: 3; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			for(i=0; i<nverts; i++) { | 
					
						
							|  |  |  | 				buf->tfindex= i; | 
					
						
							|  |  |  | 				buf->f= a; | 
					
						
							|  |  |  | 				buf->separate = 0; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				buf->next= vmap->vert[(*(&efa->v1 + i))->tmp.l]; | 
					
						
							|  |  |  | 				vmap->vert[(*(&efa->v1 + i))->tmp.l]= buf; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				buf++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* sort individual uvs for each vert */ | 
					
						
							|  |  |  | 	for(a=0, ev=em->verts.first; ev; a++, ev= ev->next) { | 
					
						
							|  |  |  | 		UvMapVert *newvlist= NULL, *vlist=vmap->vert[a]; | 
					
						
							|  |  |  | 		UvMapVert *iterv, *v, *lastv, *next; | 
					
						
							|  |  |  | 		float *uv, *uv2, uvdiff[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		while(vlist) { | 
					
						
							|  |  |  | 			v= vlist; | 
					
						
							|  |  |  | 			vlist= vlist->next; | 
					
						
							|  |  |  | 			v->next= newvlist; | 
					
						
							|  |  |  | 			newvlist= v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			efa = EM_get_face_for_index(v->f); | 
					
						
							|  |  |  | 			tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | 
					
						
							|  |  |  | 			uv = tf->uv[v->tfindex];  | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			lastv= NULL; | 
					
						
							|  |  |  | 			iterv= vlist; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			while(iterv) { | 
					
						
							|  |  |  | 				next= iterv->next; | 
					
						
							|  |  |  | 				efa = EM_get_face_for_index(iterv->f); | 
					
						
							|  |  |  | 				tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); | 
					
						
							|  |  |  | 				uv2 = tf->uv[iterv->tfindex]; | 
					
						
							|  |  |  | 				 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 				sub_v2_v2v2(uvdiff, uv2, uv); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				if(fabs(uv[0]-uv2[0]) < limit[0] && fabs(uv[1]-uv2[1]) < limit[1]) { | 
					
						
							|  |  |  | 					if(lastv) lastv->next= next; | 
					
						
							|  |  |  | 					else vlist= next; | 
					
						
							|  |  |  | 					iterv->next= newvlist; | 
					
						
							|  |  |  | 					newvlist= iterv; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					lastv=iterv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				iterv= next; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			newvlist->separate = 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		vmap->vert[a]= newvlist; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (do_face_idx_array) | 
					
						
							|  |  |  | 		EM_free_index_arrays(); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return vmap; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												2.5: Space Image ported back
Organized as follows:
uvedit/
	uv editing related code
	uvedit_draw.c: drawing code
	uvedit_ops.c: operators, just a few done
	uvedit_unwrap_ops.c: will be operators for unwrapping
	uvedit_paramatrizer.c: lscm/abf/stretch/pack
space_image/
	space_image.c: registration and common getter/setters
	image_draw.c: drawing code, mostly functional
	image_panels.c: panels, all commented out
	image_render.c: render callbacks, non functional
	image_ops.c: operators, only view navigation done
	image_header.c: header, menus mostly done but missing buttons
Notes:
* Header menus consist only of Operator and RNA buttons, if they
  are not implemented they're displayed grayed out. Ideally the full
  header could work like this, but std_libbuttons looks problematic.
* Started using view2d code more than the old code, but for now it
  still does own view2d management due to some very specific
  requirements that the image window has. The drawing code however
  is more clear hopefully, it only uses view2d, and there is no
  switching between 'p' and 'f' view2d's anymore, it is always 'f'.
* In order to make uvedit operators more independent I move some
  image space settings to scene toolsettings, and the current image
  and its buffer is in the context. Especially sync selection and
  select mode belonged there anyway as this cannot work correct with
  different spaces having different settings anyway.
* Image paint is not back yet, did not want to put that together with
  uvedit because there's really no code sharing.. perhaps vertex paint,
  image paint and sculpt would be good to have in one module to share
  brush code, partial redraw, etc better.
											
										 
											2009-01-15 04:38:18 +00:00
										 |  |  | UvMapVert *EM_get_uv_map_vert(UvVertMap *vmap, unsigned int v) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	return vmap->vert[v]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												2.5: Space Image ported back
Organized as follows:
uvedit/
	uv editing related code
	uvedit_draw.c: drawing code
	uvedit_ops.c: operators, just a few done
	uvedit_unwrap_ops.c: will be operators for unwrapping
	uvedit_paramatrizer.c: lscm/abf/stretch/pack
space_image/
	space_image.c: registration and common getter/setters
	image_draw.c: drawing code, mostly functional
	image_panels.c: panels, all commented out
	image_render.c: render callbacks, non functional
	image_ops.c: operators, only view navigation done
	image_header.c: header, menus mostly done but missing buttons
Notes:
* Header menus consist only of Operator and RNA buttons, if they
  are not implemented they're displayed grayed out. Ideally the full
  header could work like this, but std_libbuttons looks problematic.
* Started using view2d code more than the old code, but for now it
  still does own view2d management due to some very specific
  requirements that the image window has. The drawing code however
  is more clear hopefully, it only uses view2d, and there is no
  switching between 'p' and 'f' view2d's anymore, it is always 'f'.
* In order to make uvedit operators more independent I move some
  image space settings to scene toolsettings, and the current image
  and its buffer is in the context. Especially sync selection and
  select mode belonged there anyway as this cannot work correct with
  different spaces having different settings anyway.
* Image paint is not back yet, did not want to put that together with
  uvedit because there's really no code sharing.. perhaps vertex paint,
  image paint and sculpt would be good to have in one module to share
  brush code, partial redraw, etc better.
											
										 
											2009-01-15 04:38:18 +00:00
										 |  |  | void EM_free_uv_vert_map(UvVertMap *vmap) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (vmap) { | 
					
						
							|  |  |  | 		if (vmap->vert) MEM_freeN(vmap->vert); | 
					
						
							|  |  |  | 		if (vmap->buf) MEM_freeN(vmap->buf); | 
					
						
							|  |  |  | 		MEM_freeN(vmap); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-16 13:09:36 +00:00
										 |  |  | /* poll call for mesh operators requiring a view3d context */ | 
					
						
							|  |  |  | int EM_view3d_poll(bContext *C) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(ED_operator_editmesh(C) && ED_operator_view3d_active(C)) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-12-14 23:35:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* higher quality normals */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* NormalCalc */ | 
					
						
							|  |  |  | /* NormalCalc modifier: calculates higher quality normals
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* each edge uses this to  */ | 
					
						
							|  |  |  | typedef struct EdgeFaceRef { | 
					
						
							|  |  |  | 	int f1; /* init as -1 */ | 
					
						
							|  |  |  | 	int f2; | 
					
						
							|  |  |  | } EdgeFaceRef; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_make_hq_normals(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	EdgeHash *edge_hash = BLI_edgehash_new(); | 
					
						
							|  |  |  | 	EdgeHashIterator *edge_iter; | 
					
						
							|  |  |  | 	int edge_ref_count = 0; | 
					
						
							|  |  |  | 	int ed_v1, ed_v2; /* use when getting the key */ | 
					
						
							|  |  |  | 	EdgeFaceRef *edge_ref_array = MEM_callocN(em->totedge * sizeof(EdgeFaceRef), "Edge Connectivity"); | 
					
						
							|  |  |  | 	EdgeFaceRef *edge_ref; | 
					
						
							|  |  |  | 	float edge_normal[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	EM_init_index_arrays(em, 1, 1, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(eve= em->verts.first, i=0; eve; eve= eve->next, i++) { | 
					
						
							|  |  |  | 		zero_v3(eve->no); | 
					
						
							|  |  |  | 		eve->tmp.l= i; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* This function adds an edge hash if its not there, and adds the face index */ | 
					
						
							|  |  |  | #define NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(EDV1, EDV2); \
 | 
					
						
							|  |  |  | 			edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, EDV1, EDV2); \ | 
					
						
							|  |  |  | 			if (!edge_ref) { \ | 
					
						
							|  |  |  | 				edge_ref = &edge_ref_array[edge_ref_count]; edge_ref_count++; \ | 
					
						
							|  |  |  | 				edge_ref->f1=i; \ | 
					
						
							|  |  |  | 				edge_ref->f2=-1; \ | 
					
						
							|  |  |  | 				BLI_edgehash_insert(edge_hash, EDV1, EDV2, edge_ref); \ | 
					
						
							|  |  |  | 			} else { \ | 
					
						
							|  |  |  | 				edge_ref->f2=i; \ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	efa= em->faces.first; | 
					
						
							|  |  |  | 	for(i = 0; i < em->totface; i++, efa= efa->next) { | 
					
						
							|  |  |  | 		if(efa->v4) { | 
					
						
							|  |  |  | 			NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v1->tmp.l, efa->v2->tmp.l); | 
					
						
							|  |  |  | 			NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v2->tmp.l, efa->v3->tmp.l); | 
					
						
							|  |  |  | 			NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v3->tmp.l, efa->v4->tmp.l); | 
					
						
							|  |  |  | 			NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v4->tmp.l, efa->v1->tmp.l); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v1->tmp.l, efa->v2->tmp.l); | 
					
						
							|  |  |  | 			NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v2->tmp.l, efa->v3->tmp.l); | 
					
						
							|  |  |  | 			NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v3->tmp.l, efa->v1->tmp.l); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(edge_iter = BLI_edgehashIterator_new(edge_hash); !BLI_edgehashIterator_isDone(edge_iter); BLI_edgehashIterator_step(edge_iter)) { | 
					
						
							| 
									
										
										
										
											2011-01-18 01:58:19 +00:00
										 |  |  | 		/* Get the edge vert indices, and edge value (the face indices that use it)*/ | 
					
						
							| 
									
										
										
										
											2009-12-14 23:35:13 +00:00
										 |  |  | 		BLI_edgehashIterator_getKey(edge_iter, (int*)&ed_v1, (int*)&ed_v2); | 
					
						
							|  |  |  | 		edge_ref = BLI_edgehashIterator_getValue(edge_iter); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (edge_ref->f2 != -1) { | 
					
						
							| 
									
										
										
										
											2009-12-15 23:35:26 +00:00
										 |  |  | 			EditFace *ef1= EM_get_face_for_index(edge_ref->f1), *ef2= EM_get_face_for_index(edge_ref->f2); | 
					
						
							|  |  |  | 			float angle= angle_normalized_v3v3(ef1->n, ef2->n); | 
					
						
							|  |  |  | 			if(angle > 0.0f) { | 
					
						
							|  |  |  | 				/* We have 2 faces using this edge, calculate the edges normal
 | 
					
						
							|  |  |  | 				 * using the angle between the 2 faces as a weighting */ | 
					
						
							|  |  |  | 				add_v3_v3v3(edge_normal, ef1->n, ef2->n); | 
					
						
							|  |  |  | 				normalize_v3(edge_normal); | 
					
						
							|  |  |  | 				mul_v3_fl(edge_normal, angle); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				/* cant do anything useful here!
 | 
					
						
							|  |  |  | 				   Set the face index for a vert incase it gets a zero normal */ | 
					
						
							|  |  |  | 				EM_get_vert_for_index(ed_v1)->tmp.l= | 
					
						
							|  |  |  | 				EM_get_vert_for_index(ed_v2)->tmp.l= -(edge_ref->f1 + 1); | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-12-14 23:35:13 +00:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			/* only one face attached to that edge */ | 
					
						
							|  |  |  | 			/* an edge without another attached- the weight on this is
 | 
					
						
							|  |  |  | 			 * undefined, M_PI/2 is 90d in radians and that seems good enough */ | 
					
						
							|  |  |  | 			VECCOPY(edge_normal, EM_get_face_for_index(edge_ref->f1)->n) | 
					
						
							|  |  |  | 			mul_v3_fl(edge_normal, M_PI/2); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		add_v3_v3(EM_get_vert_for_index(ed_v1)->no, edge_normal ); | 
					
						
							|  |  |  | 		add_v3_v3(EM_get_vert_for_index(ed_v2)->no, edge_normal ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	BLI_edgehashIterator_free(edge_iter); | 
					
						
							|  |  |  | 	BLI_edgehash_free(edge_hash, NULL); | 
					
						
							|  |  |  | 	MEM_freeN(edge_ref_array); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* normalize vertex normals and assign */ | 
					
						
							| 
									
										
										
										
											2009-12-15 23:35:26 +00:00
										 |  |  | 	for(eve= em->verts.first; eve; eve= eve->next) { | 
					
						
							|  |  |  | 		if(normalize_v3(eve->no) == 0.0f && eve->tmp.l < 0) { | 
					
						
							|  |  |  | 			/* exceptional case, totally flat */ | 
					
						
							|  |  |  | 			efa= EM_get_face_for_index(-(eve->tmp.l) - 1); | 
					
						
							|  |  |  | 			VECCOPY(eve->no, efa->n); | 
					
						
							|  |  |  | 		}	 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-14 23:35:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	EM_free_index_arrays(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_solidify(EditMesh *em, float dist) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							| 
									
										
										
										
											2009-12-15 00:24:30 +00:00
										 |  |  | 	float *vert_angles= MEM_callocN(sizeof(float) * em->totvert * 2, "EM_solidify"); /* 2 in 1 */ | 
					
						
							| 
									
										
										
										
											2009-12-21 01:02:08 +00:00
										 |  |  | 	float *vert_accum= vert_angles + em->totvert; | 
					
						
							| 
									
										
										
										
											2009-12-15 00:24:30 +00:00
										 |  |  | 	float face_angles[4]; | 
					
						
							|  |  |  | 	int i, j; | 
					
						
							| 
									
										
										
										
											2009-12-14 23:35:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for(eve= em->verts.first, i=0; eve; eve= eve->next, i++) { | 
					
						
							|  |  |  | 		eve->tmp.l= i; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	efa= em->faces.first; | 
					
						
							|  |  |  | 	for(i = 0; i < em->totface; i++, efa= efa->next) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(!(efa->f & SELECT)) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 09:39:46 +00:00
										 |  |  | 		if(efa->v4) { | 
					
						
							|  |  |  | 			angle_quad_v3(face_angles, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); | 
					
						
							|  |  |  | 			j= 3; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			angle_tri_v3(face_angles, efa->v1->co, efa->v2->co, efa->v3->co); | 
					
						
							|  |  |  | 			j= 2; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-12-14 23:35:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 09:39:46 +00:00
										 |  |  | 		for(; j>=0; j--) { | 
					
						
							| 
									
										
										
										
											2009-12-15 00:24:30 +00:00
										 |  |  | 			eve= *(&efa->v1 + j); | 
					
						
							|  |  |  | 			vert_accum[eve->tmp.l] += face_angles[j]; | 
					
						
							|  |  |  | 			vert_angles[eve->tmp.l]+= shell_angle_to_dist(angle_normalized_v3v3(eve->no, efa->n)) * face_angles[j]; | 
					
						
							| 
									
										
										
										
											2009-12-14 23:35:13 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(eve= em->verts.first, i=0; eve; eve= eve->next, i++) { | 
					
						
							| 
									
										
										
										
											2009-12-15 00:24:30 +00:00
										 |  |  | 		if(vert_accum[i]) { /* zero if unselected */ | 
					
						
							|  |  |  | 			madd_v3_v3fl(eve->co, eve->no, dist * vert_angles[i] / vert_accum[i]); | 
					
						
							| 
									
										
										
										
											2009-12-14 23:35:13 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MEM_freeN(vert_angles); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* not that optimal!, should be nicer with bmesh */ | 
					
						
							|  |  |  | static void tag_face_edges(EditFace *efa) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(efa->v4) | 
					
						
							|  |  |  | 		efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= efa->e4->tmp.l= 1; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | static int tag_face_edges_test(EditFace *efa) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(efa->v4) | 
					
						
							|  |  |  | 		return (efa->e1->tmp.l || efa->e2->tmp.l || efa->e3->tmp.l || efa->e4->tmp.l) ? 1:0; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return (efa->e1->tmp.l || efa->e2->tmp.l || efa->e3->tmp.l) ? 1:0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-14 17:55:27 +00:00
										 |  |  | static void em_deselect_nth_face(EditMesh *em, int nth, EditFace *efa_act) | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	int ok= 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(efa_act==NULL) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* to detect loose edges, we put f2 flag on 1 */ | 
					
						
							|  |  |  | 	for(eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 		eed->tmp.l= 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 		efa->tmp.l = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	efa_act->tmp.l = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while(ok) { | 
					
						
							|  |  |  | 		ok = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							| 
									
										
										
										
											2010-11-02 11:14:04 +00:00
										 |  |  | 			if(efa->f & SELECT) { | 
					
						
							|  |  |  | 				if(efa->tmp.l==1) { /* initialize */ | 
					
						
							|  |  |  | 					tag_face_edges(efa); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 				if(efa->tmp.l) { | 
					
						
							|  |  |  | 					efa->tmp.l++; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							| 
									
										
										
										
											2010-11-02 11:14:04 +00:00
										 |  |  | 			if(efa->f & SELECT) { | 
					
						
							|  |  |  | 				if(efa->tmp.l==0 && tag_face_edges_test(efa)) { | 
					
						
							|  |  |  | 					efa->tmp.l= 1; | 
					
						
							|  |  |  | 					ok = 1; /* keep looping */ | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 		if(efa->tmp.l > 0 && efa->tmp.l % nth) { | 
					
						
							|  |  |  | 			EM_select_face(efa, 0); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for (efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 		if(efa->f & SELECT) { | 
					
						
							|  |  |  | 			EM_select_face(efa, 1); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	EM_nvertices_selected(em); | 
					
						
							|  |  |  | 	EM_nedges_selected(em); | 
					
						
							|  |  |  | 	EM_nfaces_selected(em); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* not that optimal!, should be nicer with bmesh */ | 
					
						
							|  |  |  | static void tag_edge_verts(EditEdge *eed) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	eed->v1->tmp.l= eed->v2->tmp.l= 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | static int tag_edge_verts_test(EditEdge *eed) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return (eed->v1->tmp.l || eed->v2->tmp.l) ? 1:0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-14 17:55:27 +00:00
										 |  |  | static void em_deselect_nth_edge(EditMesh *em, int nth, EditEdge *eed_act) | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	int ok= 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(eed_act==NULL) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(eve= em->verts.first; eve; eve= eve->next) { | 
					
						
							|  |  |  | 		eve->tmp.l= 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 		eed->tmp.l = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	eed_act->tmp.l = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while(ok) { | 
					
						
							|  |  |  | 		ok = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							| 
									
										
										
										
											2010-11-02 11:14:04 +00:00
										 |  |  | 			if(eed->f & SELECT) { | 
					
						
							|  |  |  | 				if(eed->tmp.l==1) { /* initialize */ | 
					
						
							|  |  |  | 					tag_edge_verts(eed); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 				if(eed->tmp.l) { | 
					
						
							|  |  |  | 					eed->tmp.l++; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							| 
									
										
										
										
											2010-11-02 11:14:04 +00:00
										 |  |  | 			if(eed->f & SELECT) { | 
					
						
							|  |  |  | 				if(eed->tmp.l==0 && tag_edge_verts_test(eed)) { | 
					
						
							|  |  |  | 					eed->tmp.l= 1; | 
					
						
							|  |  |  | 					ok = 1; /* keep looping */ | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 		if(eed->tmp.l > 0 && eed->tmp.l % nth) { | 
					
						
							|  |  |  | 			EM_select_edge(eed, 0); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for (eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 		if(eed->f & SELECT) { | 
					
						
							|  |  |  | 			EM_select_edge(eed, 1); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* grr, should be a function */ | 
					
						
							|  |  |  | 		EditFace *efa; | 
					
						
							|  |  |  | 		for (efa= em->faces.first; efa; efa= efa->next) { | 
					
						
							|  |  |  | 			if(efa->v4) { | 
					
						
							|  |  |  | 				if(efa->e1->f & efa->e2->f & efa->e3->f & efa->e4->f & SELECT ); | 
					
						
							|  |  |  | 				else efa->f &= ~SELECT; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				if(efa->e1->f & efa->e2->f & efa->e3->f & SELECT ); | 
					
						
							|  |  |  | 				else efa->f &= ~SELECT; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	EM_nvertices_selected(em); | 
					
						
							|  |  |  | 	EM_nedges_selected(em); | 
					
						
							|  |  |  | 	EM_nfaces_selected(em); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-14 17:55:27 +00:00
										 |  |  | static void em_deselect_nth_vert(EditMesh *em, int nth, EditVert *eve_act) | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	int ok= 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(eve_act==NULL) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (eve= em->verts.first; eve; eve= eve->next) { | 
					
						
							|  |  |  | 		eve->tmp.l = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	eve_act->tmp.l = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while(ok) { | 
					
						
							|  |  |  | 		ok = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (eve= em->verts.first; eve; eve= eve->next) { | 
					
						
							| 
									
										
										
										
											2010-11-02 11:14:04 +00:00
										 |  |  | 			if(eve->f & SELECT) { | 
					
						
							|  |  |  | 				if(eve->tmp.l) | 
					
						
							|  |  |  | 					eve->tmp.l++; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							| 
									
										
										
										
											2010-11-02 11:14:04 +00:00
										 |  |  | 			if(eed->f & SELECT) { | 
					
						
							|  |  |  | 				if(eed->v1->tmp.l==2 && eed->v2->tmp.l==0) { /* initialize */ | 
					
						
							|  |  |  | 					eed->v2->tmp.l= 1; | 
					
						
							|  |  |  | 					ok = 1; /* keep looping */ | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else if(eed->v2->tmp.l==2 && eed->v1->tmp.l==0) { /* initialize */ | 
					
						
							|  |  |  | 					eed->v1->tmp.l= 1; | 
					
						
							|  |  |  | 					ok = 1; /* keep looping */ | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (eve= em->verts.first; eve; eve= eve->next) { | 
					
						
							|  |  |  | 		if(eve->tmp.l > 0 && eve->tmp.l % nth) { | 
					
						
							|  |  |  | 			eve->f &= ~SELECT; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	EM_deselect_flush(em); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	EM_nvertices_selected(em); | 
					
						
							|  |  |  | 	// EM_nedges_selected(em); // flush does these
 | 
					
						
							|  |  |  | 	// EM_nfaces_selected(em); // flush does these
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-02 11:14:04 +00:00
										 |  |  | static void deselect_nth_active(EditMesh *em, EditVert **eve_p, EditEdge **eed_p, EditFace **efa_p) | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditSelection *ese; | 
					
						
							| 
									
										
										
										
											2010-11-02 11:14:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	*eve_p= NULL; | 
					
						
							|  |  |  | 	*eed_p= NULL; | 
					
						
							|  |  |  | 	*efa_p= NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ese= (EditSelection*)em->selected.last; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | 	if(ese) { | 
					
						
							| 
									
										
										
										
											2010-11-02 11:14:04 +00:00
										 |  |  | 		switch(ese->type) { | 
					
						
							|  |  |  | 		case EDITVERT: | 
					
						
							|  |  |  | 			*eve_p= (EditVert *)ese->data; | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		case EDITEDGE: | 
					
						
							|  |  |  | 			*eed_p= (EditEdge *)ese->data; | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		case EDITFACE: | 
					
						
							|  |  |  | 			*efa_p= (EditFace *)ese->data; | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(em->selectmode & SCE_SELECT_VERTEX) { | 
					
						
							|  |  |  | 		EditVert *eve; | 
					
						
							|  |  |  | 		for (eve= em->verts.first; eve; eve= eve->next) { | 
					
						
							|  |  |  | 			if(eve->f & SELECT) { | 
					
						
							|  |  |  | 				*eve_p= eve; | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-11-02 11:14:04 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-02 11:14:04 +00:00
										 |  |  | 	if(em->selectmode & SCE_SELECT_EDGE) { | 
					
						
							|  |  |  | 		EditEdge *eed; | 
					
						
							|  |  |  | 		for (eed= em->edges.first; eed; eed= eed->next) { | 
					
						
							|  |  |  | 			if(eed->f & SELECT) { | 
					
						
							|  |  |  | 				*eed_p= eed; | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-11-02 11:14:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if(em->selectmode & SCE_SELECT_FACE) { | 
					
						
							|  |  |  | 		EditFace *efa= EM_get_actFace(em, 1); | 
					
						
							|  |  |  | 		if(efa) { | 
					
						
							|  |  |  | 			*efa_p= efa; | 
					
						
							|  |  |  | 			return; | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-11-02 11:14:04 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-02 11:14:04 +00:00
										 |  |  | int EM_deselect_nth(EditMesh *em, int nth) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	deselect_nth_active(em, &eve, &eed, &efa); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(eve) | 
					
						
							|  |  |  | 		em_deselect_nth_vert(em, nth, eve); | 
					
						
							|  |  |  | 	else if (eed) | 
					
						
							|  |  |  | 		em_deselect_nth_edge(em, nth, eed); | 
					
						
							|  |  |  | 	else if (efa) | 
					
						
							|  |  |  | 		em_deselect_nth_face(em, nth, efa); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return 1; | 
					
						
							| 
									
										
										
										
											2009-12-22 19:01:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-13 07:43:39 +00:00
										 |  |  | void EM_project_snap_verts(bContext *C, ARegion *ar, Object *obedit, EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	for(eve= em->verts.first;eve; eve=eve->next) { | 
					
						
							|  |  |  | 		if(eve->f & SELECT) { | 
					
						
							|  |  |  | 			float mval[2], vec[3], no_dummy[3]; | 
					
						
							|  |  |  | 			int dist_dummy; | 
					
						
							|  |  |  | 			mul_v3_m4v3(vec, obedit->obmat, eve->co); | 
					
						
							|  |  |  | 			project_float_noclip(ar, vec, mval); | 
					
						
							|  |  |  | 			if(snapObjectsContext(C, mval, &dist_dummy, vec, no_dummy, SNAP_NOT_OBEDIT)) { | 
					
						
							|  |  |  | 				mul_v3_m4v3(eve->co, obedit->imat, vec); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |