| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  |  * $Id$ | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** 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) 2001-2002 by NaN Holding BV. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): Blender Foundation, full recode 2002-2008 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-27 20:29:51 +00:00
										 |  |  | /** \file blender/editors/mesh/editmesh.c
 | 
					
						
							|  |  |  |  *  \ingroup edmesh | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <math.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-10 05:41:51 +00:00
										 |  |  | #include "DNA_scene_types.h"
 | 
					
						
							|  |  |  | #include "DNA_object_types.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | #include "DNA_key_types.h"
 | 
					
						
							| 
									
										
										
										
											2010-08-10 05:41:51 +00:00
										 |  |  | #include "DNA_meshdata_types.h"
 | 
					
						
							|  |  |  | #include "DNA_modifier_types.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #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"
 | 
					
						
							|  |  |  | #include "BLI_dynstr.h"
 | 
					
						
							|  |  |  | #include "BLI_rand.h"
 | 
					
						
							| 
									
										
										
										
											2011-01-07 18:36:47 +00:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-10 05:41:51 +00:00
										 |  |  | #include "BKE_DerivedMesh.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | #include "BKE_context.h"
 | 
					
						
							|  |  |  | #include "BKE_depsgraph.h"
 | 
					
						
							|  |  |  | #include "BKE_global.h"
 | 
					
						
							|  |  |  | #include "BKE_key.h"
 | 
					
						
							|  |  |  | #include "BKE_main.h"
 | 
					
						
							|  |  |  | #include "BKE_material.h"
 | 
					
						
							|  |  |  | #include "BKE_mesh.h"
 | 
					
						
							| 
									
										
										
										
											2009-08-15 19:48:50 +00:00
										 |  |  | #include "BKE_paint.h"
 | 
					
						
							| 
									
										
										
										
											2010-10-23 12:09:24 +00:00
										 |  |  | #include "BKE_report.h"
 | 
					
						
							| 
									
										
										
										
											2010-11-04 16:00:28 +00:00
										 |  |  | #include "BKE_multires.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "ED_mesh.h"
 | 
					
						
							| 
									
										
										
										
											2009-01-29 18:54:22 +00:00
										 |  |  | #include "ED_object.h"
 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | #include "ED_screen.h"
 | 
					
						
							| 
									
										
										
										
											2009-07-08 16:17:47 +00:00
										 |  |  | #include "ED_util.h"
 | 
					
						
							| 
									
										
										
										
											2009-01-05 15:19:31 +00:00
										 |  |  | #include "ED_view3d.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | #include "RNA_access.h"
 | 
					
						
							|  |  |  | #include "RNA_define.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "WM_api.h"
 | 
					
						
							|  |  |  | #include "WM_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | /* own include */ | 
					
						
							| 
									
										
										
										
											2009-01-01 13:15:35 +00:00
										 |  |  | #include "mesh_intern.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* 
 | 
					
						
							|  |  |  | editmesh.c: | 
					
						
							|  |  |  | 	- add/alloc/free data | 
					
						
							|  |  |  | 	- hashtables | 
					
						
							|  |  |  | 	- enter/exit editmode | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* XXX */ | 
					
						
							| 
									
										
										
										
											2010-10-16 14:32:17 +00:00
										 |  |  | static void BIF_undo_push(const char *UNUSED(arg)) {} | 
					
						
							|  |  |  | static void error(const char *UNUSED(arg)) {} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ***************** HASH ********************* */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define EDHASHSIZE		(512*512)
 | 
					
						
							|  |  |  | #define EDHASH(a, b)	(a % EDHASHSIZE)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************ ADD / REMOVE / FIND ****************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-16 14:32:17 +00:00
										 |  |  | static void *calloc_em(EditMesh *UNUSED(em), size_t size, size_t nr) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	return calloc(size, nr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* used to bypass normal calloc with fast one */ | 
					
						
							|  |  |  | static void *(*callocvert)(EditMesh *, size_t, size_t) = calloc_em; | 
					
						
							|  |  |  | static void *(*callocedge)(EditMesh *, size_t, size_t) = calloc_em; | 
					
						
							|  |  |  | static void *(*callocface)(EditMesh *, size_t, size_t) = calloc_em; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EditVert *addvertlist(EditMesh *em, float *vec, EditVert *example) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	static int hashnr= 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	eve= callocvert(em, sizeof(EditVert), 1); | 
					
						
							|  |  |  | 	BLI_addtail(&em->verts, eve); | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	em->totvert++; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	if(vec) VECCOPY(eve->co, vec); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	eve->hash= hashnr++; | 
					
						
							|  |  |  | 	if( hashnr>=EDHASHSIZE) hashnr= 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* new verts get keyindex of -1 since they did not
 | 
					
						
							|  |  |  | 	 * have a pre-editmode vertex order | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	eve->keyindex = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(example) { | 
					
						
							|  |  |  | 		CustomData_em_copy_data(&em->vdata, &em->vdata, example->data, &eve->data); | 
					
						
							|  |  |  | 		eve->bweight = example->bweight; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		CustomData_em_set_default(&em->vdata, &eve->data); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return eve; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void free_editvert (EditMesh *em, EditVert *eve) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	EM_remove_selection(em, eve, EDITVERT); | 
					
						
							|  |  |  | 	CustomData_em_free_block(&em->vdata, &eve->data); | 
					
						
							|  |  |  | 	if(eve->fast==0) | 
					
						
							|  |  |  | 		free(eve); | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	em->totvert--; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EditEdge *findedgelist(EditMesh *em, EditVert *v1, EditVert *v2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *v3; | 
					
						
							|  |  |  | 	struct HashEdge *he; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* swap ? */ | 
					
						
							|  |  |  | 	if( v1 > v2) { | 
					
						
							|  |  |  | 		v3= v2;  | 
					
						
							|  |  |  | 		v2= v1;  | 
					
						
							|  |  |  | 		v1= v3; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(em->hashedgetab==NULL) | 
					
						
							|  |  |  | 		em->hashedgetab= MEM_callocN(EDHASHSIZE*sizeof(struct HashEdge), "hashedgetab"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	he= em->hashedgetab + EDHASH(v1->hash, v2->hash); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	while(he) { | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if(he->eed && he->eed->v1==v1 && he->eed->v2==v2) return he->eed; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		he= he->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void insert_hashedge(EditMesh *em, EditEdge *eed) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* assuming that eed is not in the list yet, and that a find has been done before */ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	struct HashEdge *first, *he; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	first= em->hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( first->eed==0 ) { | 
					
						
							|  |  |  | 		first->eed= eed; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		he= &eed->hash;  | 
					
						
							|  |  |  | 		he->eed= eed; | 
					
						
							|  |  |  | 		he->next= first->next; | 
					
						
							|  |  |  | 		first->next= he; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void remove_hashedge(EditMesh *em, EditEdge *eed) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* assuming eed is in the list */ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	struct HashEdge *first, *he, *prev=NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	he=first= em->hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while(he) { | 
					
						
							|  |  |  | 		if(he->eed == eed) { | 
					
						
							|  |  |  | 			/* remove from list */ | 
					
						
							|  |  |  | 			if(he==first) { | 
					
						
							|  |  |  | 				if(first->next) { | 
					
						
							|  |  |  | 					he= first->next; | 
					
						
							|  |  |  | 					first->eed= he->eed; | 
					
						
							|  |  |  | 					first->next= he->next; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else he->eed= 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				prev->next= he->next; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		prev= he; | 
					
						
							|  |  |  | 		he= he->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EditEdge *addedgelist(EditMesh *em, EditVert *v1, EditVert *v2, EditEdge *example) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *v3; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	int swap= 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(v1==v2) return NULL; | 
					
						
							|  |  |  | 	if(v1==NULL || v2==NULL) return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* swap ? */ | 
					
						
							|  |  |  | 	if(v1>v2) { | 
					
						
							|  |  |  | 		v3= v2;  | 
					
						
							|  |  |  | 		v2= v1;  | 
					
						
							|  |  |  | 		v1= v3; | 
					
						
							|  |  |  | 		swap= 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* find in hashlist */ | 
					
						
							|  |  |  | 	eed= findedgelist(em, v1, v2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(eed==NULL) { | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		eed= (EditEdge *)callocedge(em, sizeof(EditEdge), 1); | 
					
						
							|  |  |  | 		eed->v1= v1; | 
					
						
							|  |  |  | 		eed->v2= v2; | 
					
						
							|  |  |  | 		BLI_addtail(&em->edges, eed); | 
					
						
							|  |  |  | 		eed->dir= swap; | 
					
						
							|  |  |  | 		insert_hashedge(em, eed); | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 		em->totedge++; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		/* copy edge data:
 | 
					
						
							|  |  |  | 		   rule is to do this with addedgelist call, before addfacelist */ | 
					
						
							|  |  |  | 		if(example) { | 
					
						
							|  |  |  | 			eed->crease= example->crease; | 
					
						
							|  |  |  | 			eed->bweight= example->bweight; | 
					
						
							|  |  |  | 			eed->sharp = example->sharp; | 
					
						
							|  |  |  | 			eed->seam = example->seam; | 
					
						
							|  |  |  | 			eed->h |= (example->h & EM_FGON); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-01-13 19:01:27 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	return eed; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void remedge(EditMesh *em, EditEdge *eed) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BLI_remlink(&em->edges, eed); | 
					
						
							|  |  |  | 	remove_hashedge(em, eed); | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	em->totedge--; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void free_editedge(EditMesh *em, EditEdge *eed) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EM_remove_selection(em, eed, EDITEDGE); | 
					
						
							|  |  |  | 	if(eed->fast==0){  | 
					
						
							|  |  |  | 		free(eed); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void free_editface(EditMesh *em, EditFace *efa) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EM_remove_selection(em, efa, EDITFACE); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (em->act_face==efa) { | 
					
						
							|  |  |  | 		EM_set_actFace(em, em->faces.first == efa ? NULL : em->faces.first); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	CustomData_em_free_block(&em->fdata, &efa->data); | 
					
						
							|  |  |  | 	if(efa->fast==0) | 
					
						
							|  |  |  | 		free(efa); | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	em->totface--; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void free_vertlist(EditMesh *em, ListBase *edve)  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve, *next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!edve) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	eve= edve->first; | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							|  |  |  | 		next= eve->next; | 
					
						
							|  |  |  | 		free_editvert(em, eve); | 
					
						
							|  |  |  | 		eve= next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	edve->first= edve->last= NULL; | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	em->totvert= em->totvertsel= 0; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void free_edgelist(EditMesh *em, ListBase *lb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *eed, *next; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	eed= lb->first; | 
					
						
							|  |  |  | 	while(eed) { | 
					
						
							|  |  |  | 		next= eed->next; | 
					
						
							|  |  |  | 		free_editedge(em, eed); | 
					
						
							|  |  |  | 		eed= next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	lb->first= lb->last= NULL; | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	em->totedge= em->totedgesel= 0; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void free_facelist(EditMesh *em, ListBase *lb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa, *next; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	efa= lb->first; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		next= efa->next; | 
					
						
							|  |  |  | 		free_editface(em, efa); | 
					
						
							|  |  |  | 		efa= next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	lb->first= lb->last= NULL; | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	em->totface= em->totfacesel= 0; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EditFace *addfacelist(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, EditFace *example, EditFace *exampleEdges) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	EditEdge *e1, *e2=0, *e3=0, *e4=0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* added sanity check... seems to happen for some tools, or for enter editmode for corrupted meshes */ | 
					
						
							|  |  |  | 	if(v1==v4 || v2==v4 || v3==v4) v4= NULL; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* add face to list and do the edges */ | 
					
						
							|  |  |  | 	if(exampleEdges) { | 
					
						
							|  |  |  | 		e1= addedgelist(em, v1, v2, exampleEdges->e1); | 
					
						
							|  |  |  | 		e2= addedgelist(em, v2, v3, exampleEdges->e2); | 
					
						
							|  |  |  | 		if(v4) e3= addedgelist(em, v3, v4, exampleEdges->e3);  | 
					
						
							|  |  |  | 		else e3= addedgelist(em, v3, v1, exampleEdges->e3); | 
					
						
							|  |  |  | 		if(v4) e4= addedgelist(em, v4, v1, exampleEdges->e4); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		e1= addedgelist(em, v1, v2, NULL); | 
					
						
							|  |  |  | 		e2= addedgelist(em, v2, v3, NULL); | 
					
						
							|  |  |  | 		if(v4) e3= addedgelist(em, v3, v4, NULL);  | 
					
						
							|  |  |  | 		else e3= addedgelist(em, v3, v1, NULL); | 
					
						
							|  |  |  | 		if(v4) e4= addedgelist(em, v4, v1, NULL); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(v1==v2 || v2==v3 || v1==v3) return NULL; | 
					
						
							|  |  |  | 	if(e2==0) return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	efa= (EditFace *)callocface(em, sizeof(EditFace), 1); | 
					
						
							|  |  |  | 	efa->v1= v1; | 
					
						
							|  |  |  | 	efa->v2= v2; | 
					
						
							|  |  |  | 	efa->v3= v3; | 
					
						
							|  |  |  | 	efa->v4= v4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	efa->e1= e1; | 
					
						
							|  |  |  | 	efa->e2= e2; | 
					
						
							|  |  |  | 	efa->e3= e3; | 
					
						
							|  |  |  | 	efa->e4= e4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(example) { | 
					
						
							|  |  |  | 		efa->mat_nr= example->mat_nr; | 
					
						
							|  |  |  | 		efa->flag= example->flag; | 
					
						
							|  |  |  | 		CustomData_em_copy_data(&em->fdata, &em->fdata, example->data, &efa->data); | 
					
						
							| 
									
										
										
										
											2011-01-02 17:08:25 +00:00
										 |  |  | 		CustomData_em_validate_data(&em->fdata, efa->data, efa->v4 ? 4 : 3); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 		efa->mat_nr= em->mat_nr; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		CustomData_em_set_default(&em->fdata, &efa->data); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_addtail(&em->faces, efa); | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	em->totface++; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	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
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return efa; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************ end add/new/find ************  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************ Edit{Vert,Edge,Face} utilss ***************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* some nice utility functions */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EditVert *editedge_getOtherVert(EditEdge *eed, EditVert *eve) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (eve==eed->v1) { | 
					
						
							|  |  |  | 		return eed->v2; | 
					
						
							|  |  |  | 	} else if (eve==eed->v2) { | 
					
						
							|  |  |  | 		return eed->v1; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EditVert *editedge_getSharedVert(EditEdge *eed, EditEdge *eed2)  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (eed->v1==eed2->v1 || eed->v1==eed2->v2) { | 
					
						
							|  |  |  | 		return eed->v1; | 
					
						
							|  |  |  | 	} else if (eed->v2==eed2->v1 || eed->v2==eed2->v2) { | 
					
						
							|  |  |  | 		return eed->v2; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int editedge_containsVert(EditEdge *eed, EditVert *eve)  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return (eed->v1==eve || eed->v2==eve); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int editface_containsVert(EditFace *efa, EditVert *eve)  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return (efa->v1==eve || efa->v2==eve || efa->v3==eve || (efa->v4 && efa->v4==eve)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int editface_containsEdge(EditFace *efa, EditEdge *eed)  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return (efa->e1==eed || efa->e2==eed || efa->e3==eed || (efa->e4 && efa->e4==eed)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************ stuct EditMesh manipulation ***************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* fake callocs for fastmalloc below */ | 
					
						
							| 
									
										
										
										
											2010-10-16 14:32:17 +00:00
										 |  |  | static void *calloc_fastvert(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr)) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve= em->curvert++; | 
					
						
							|  |  |  | 	eve->fast= 1; | 
					
						
							|  |  |  | 	return eve; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-10-16 14:32:17 +00:00
										 |  |  | static void *calloc_fastedge(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr)) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditEdge *eed= em->curedge++; | 
					
						
							|  |  |  | 	eed->fast= 1; | 
					
						
							|  |  |  | 	return eed; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-10-16 14:32:17 +00:00
										 |  |  | static void *calloc_fastface(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr)) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa= em->curface++; | 
					
						
							|  |  |  | 	efa->fast= 1; | 
					
						
							|  |  |  | 	return efa; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* allocate 1 chunk for all vertices, edges, faces. These get tagged to
 | 
					
						
							|  |  |  |    prevent it from being freed | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | static void init_editmesh_fastmalloc(EditMesh *em, int totvert, int totedge, int totface) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(totvert) em->allverts= MEM_callocN(totvert*sizeof(EditVert), "allverts"); | 
					
						
							|  |  |  | 	else em->allverts= NULL; | 
					
						
							|  |  |  | 	em->curvert= em->allverts; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(totedge==0) totedge= 4*totface;	// max possible
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(totedge) em->alledges= MEM_callocN(totedge*sizeof(EditEdge), "alledges"); | 
					
						
							|  |  |  | 	else em->alledges= NULL; | 
					
						
							|  |  |  | 	em->curedge= em->alledges; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(totface) em->allfaces= MEM_callocN(totface*sizeof(EditFace), "allfaces"); | 
					
						
							|  |  |  | 	else em->allfaces= NULL; | 
					
						
							|  |  |  | 	em->curface= em->allfaces; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	callocvert= calloc_fastvert; | 
					
						
							|  |  |  | 	callocedge= calloc_fastedge; | 
					
						
							|  |  |  | 	callocface= calloc_fastface; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void end_editmesh_fastmalloc(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	callocvert= calloc_em; | 
					
						
							|  |  |  | 	callocedge= calloc_em; | 
					
						
							|  |  |  | 	callocface= calloc_em; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* do not free editmesh itself here */ | 
					
						
							|  |  |  | void free_editMesh(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(em==NULL) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(em->verts.first) free_vertlist(em, &em->verts); | 
					
						
							|  |  |  | 	if(em->edges.first) free_edgelist(em, &em->edges); | 
					
						
							|  |  |  | 	if(em->faces.first) free_facelist(em, &em->faces); | 
					
						
							|  |  |  | 	if(em->selected.first) BLI_freelistN(&(em->selected)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	CustomData_free(&em->vdata, 0); | 
					
						
							|  |  |  | 	CustomData_free(&em->fdata, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(em->derivedFinal) { | 
					
						
							|  |  |  | 		if (em->derivedFinal!=em->derivedCage) { | 
					
						
							|  |  |  | 			em->derivedFinal->needsFree= 1; | 
					
						
							|  |  |  | 			em->derivedFinal->release(em->derivedFinal); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		em->derivedFinal= NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(em->derivedCage) { | 
					
						
							|  |  |  | 		em->derivedCage->needsFree= 1; | 
					
						
							|  |  |  | 		em->derivedCage->release(em->derivedCage); | 
					
						
							|  |  |  | 		em->derivedCage= NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* DEBUG: hashtabs are slowest part of enter/exit editmode. here a testprint */ | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 	if(em->hashedgetab) { | 
					
						
							|  |  |  | 		HashEdge *he, *hen; | 
					
						
							|  |  |  | 		int a, used=0, max=0, nr; | 
					
						
							|  |  |  | 		he= em->hashedgetab; | 
					
						
							|  |  |  | 		for(a=0; a<EDHASHSIZE; a++, he++) { | 
					
						
							|  |  |  | 			if(he->eed) used++; | 
					
						
							|  |  |  | 			hen= he->next; | 
					
						
							|  |  |  | 			nr= 0; | 
					
						
							|  |  |  | 			while(hen) { | 
					
						
							|  |  |  | 				nr++; | 
					
						
							|  |  |  | 				hen= hen->next; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(max<nr) max= nr; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		printf("hastab used %d max %d\n", used, max); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	if(em->hashedgetab) MEM_freeN(em->hashedgetab); | 
					
						
							|  |  |  | 	em->hashedgetab= NULL; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(em->allverts) MEM_freeN(em->allverts); | 
					
						
							|  |  |  | 	if(em->alledges) MEM_freeN(em->alledges); | 
					
						
							|  |  |  | 	if(em->allfaces) MEM_freeN(em->allfaces); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	em->allverts= em->curvert= NULL; | 
					
						
							|  |  |  | 	em->alledges= em->curedge= NULL; | 
					
						
							|  |  |  | 	em->allfaces= em->curface= NULL; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	mesh_octree_table(NULL, NULL, NULL, 'e'); | 
					
						
							| 
									
										
										
										
											2010-03-31 07:22:18 +00:00
										 |  |  | 	mesh_mirrtopo_table(NULL, 'e'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	em->totvert= em->totedge= em->totface= 0; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // XXX	if(em->retopo_paint_data) retopo_free_paint_data(em->retopo_paint_data);
 | 
					
						
							|  |  |  | 	em->retopo_paint_data= NULL; | 
					
						
							|  |  |  | 	em->act_face = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void editMesh_set_hash(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	if(em->hashedgetab) MEM_freeN(em->hashedgetab); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	em->hashedgetab= NULL; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(eed=em->edges.first; eed; eed= eed->next)  { | 
					
						
							|  |  |  | 		if( findedgelist(em, eed->v1, eed->v2)==NULL ) | 
					
						
							|  |  |  | 			insert_hashedge(em, eed); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************ IN & OUT EDITMODE ***************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void edge_normal_compare(EditEdge *eed, EditFace *efa1) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditFace *efa2; | 
					
						
							|  |  |  | 	float cent1[3], cent2[3]; | 
					
						
							|  |  |  | 	float inp; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	efa2 = eed->tmp.f; | 
					
						
							|  |  |  | 	if(efa1==efa2) return; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	inp= efa1->n[0]*efa2->n[0] + efa1->n[1]*efa2->n[1] + efa1->n[2]*efa2->n[2]; | 
					
						
							|  |  |  | 	if(inp<0.999 && inp >-0.999) eed->f2= 1; | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 	if(efa1->v4) cent_quad_v3(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co, efa1->v4->co); | 
					
						
							|  |  |  | 	else cent_tri_v3(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co); | 
					
						
							|  |  |  | 	if(efa2->v4) cent_quad_v3(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co, efa2->v4->co); | 
					
						
							|  |  |  | 	else cent_tri_v3(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 	sub_v3_v3v3(cent1, cent2, cent1); | 
					
						
							|  |  |  | 	normalize_v3(cent1); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	inp= cent1[0]*efa1->n[0] + cent1[1]*efa1->n[1] + cent1[2]*efa1->n[2];  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(inp < -0.001 ) eed->f1= 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	float noLen,no[3]; | 
					
						
							|  |  |  | 	int adjCount; | 
					
						
							|  |  |  | } EdgeDrawFlagInfo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int edgeDrawFlagInfo_cmp(const void *av, const void *bv) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const EdgeDrawFlagInfo *a = av; | 
					
						
							|  |  |  | 	const EdgeDrawFlagInfo *b = bv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (a->noLen<b->noLen) return -1; | 
					
						
							|  |  |  | 	else if (a->noLen>b->noLen) return 1; | 
					
						
							|  |  |  | 	else return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-31 13:30:56 +00:00
										 |  |  | static void edge_drawflags(Mesh *me, EditMesh *em) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	EditEdge *eed, *e1, *e2, *e3, *e4; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* - count number of times edges are used in faces: 0 en 1 time means draw edge
 | 
					
						
							|  |  |  | 	 * - edges more than 1 time used: in *tmp.f is pointer to first face | 
					
						
							|  |  |  | 	 * - check all faces, when normal differs to much: draw (flag becomes 1) | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* later on: added flags for 'cylinder' and 'sphere' intersection tests in old
 | 
					
						
							|  |  |  | 	   game engine (2.04) | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	recalc_editnormals(em); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* init */ | 
					
						
							|  |  |  | 	eve= em->verts.first; | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							|  |  |  | 		eve->f1= 1;		/* during test it's set at zero */ | 
					
						
							|  |  |  | 		eve= eve->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	eed= em->edges.first; | 
					
						
							|  |  |  | 	while(eed) { | 
					
						
							|  |  |  | 		eed->f2= eed->f1= 0; | 
					
						
							|  |  |  | 		eed->tmp.f = 0; | 
					
						
							|  |  |  | 		eed= eed->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	efa= em->faces.first; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		e1= efa->e1; | 
					
						
							|  |  |  | 		e2= efa->e2; | 
					
						
							|  |  |  | 		e3= efa->e3; | 
					
						
							|  |  |  | 		e4= efa->e4; | 
					
						
							|  |  |  | 		if(e1->f2<4) e1->f2+= 1; | 
					
						
							|  |  |  | 		if(e2->f2<4) e2->f2+= 1; | 
					
						
							|  |  |  | 		if(e3->f2<4) e3->f2+= 1; | 
					
						
							|  |  |  | 		if(e4 && e4->f2<4) e4->f2+= 1; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if(e1->tmp.f == 0) e1->tmp.f = (void *) efa; | 
					
						
							|  |  |  | 		if(e2->tmp.f == 0) e2->tmp.f = (void *) efa; | 
					
						
							|  |  |  | 		if(e3->tmp.f ==0) e3->tmp.f = (void *) efa; | 
					
						
							|  |  |  | 		if(e4 && (e4->tmp.f == 0)) e4->tmp.f = (void *) efa; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		efa= efa->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-31 13:30:56 +00:00
										 |  |  | 	if(me->drawflag & ME_ALLEDGES) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		efa= em->faces.first; | 
					
						
							|  |  |  | 		while(efa) { | 
					
						
							|  |  |  | 			if(efa->e1->f2>=2) efa->e1->f2= 1; | 
					
						
							|  |  |  | 			if(efa->e2->f2>=2) efa->e2->f2= 1; | 
					
						
							|  |  |  | 			if(efa->e3->f2>=2) efa->e3->f2= 1; | 
					
						
							|  |  |  | 			if(efa->e4 && efa->e4->f2>=2) efa->e4->f2= 1; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			efa= efa->next; | 
					
						
							|  |  |  | 		}		 | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/* handle single-edges for 'test cylinder flag' (old engine) */ | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		eed= em->edges.first; | 
					
						
							|  |  |  | 		while(eed) { | 
					
						
							|  |  |  | 			if(eed->f2==1) eed->f1= 1; | 
					
						
							|  |  |  | 			eed= eed->next; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* all faces, all edges with flag==2: compare normal */ | 
					
						
							|  |  |  | 		efa= em->faces.first; | 
					
						
							|  |  |  | 		while(efa) { | 
					
						
							|  |  |  | 			if(efa->e1->f2==2) edge_normal_compare(efa->e1, efa); | 
					
						
							|  |  |  | 			else efa->e1->f2= 1; | 
					
						
							|  |  |  | 			if(efa->e2->f2==2) edge_normal_compare(efa->e2, efa); | 
					
						
							|  |  |  | 			else efa->e2->f2= 1; | 
					
						
							|  |  |  | 			if(efa->e3->f2==2) edge_normal_compare(efa->e3, efa); | 
					
						
							|  |  |  | 			else efa->e3->f2= 1; | 
					
						
							|  |  |  | 			if(efa->e4) { | 
					
						
							|  |  |  | 				if(efa->e4->f2==2) edge_normal_compare(efa->e4, efa); | 
					
						
							|  |  |  | 				else efa->e4->f2= 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			efa= efa->next; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/* sphere collision flag */ | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		eed= em->edges.first; | 
					
						
							|  |  |  | 		while(eed) { | 
					
						
							|  |  |  | 			if(eed->f1!=1) { | 
					
						
							|  |  |  | 				eed->v1->f1= eed->v2->f1= 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			eed= eed->next; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* turns Mesh into editmesh */ | 
					
						
							| 
									
										
										
										
											2008-12-31 17:11:42 +00:00
										 |  |  | void make_editMesh(Scene *scene, Object *ob) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-31 17:11:42 +00:00
										 |  |  | 	Mesh *me= ob->data; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	MFace *mface; | 
					
						
							|  |  |  | 	MVert *mvert; | 
					
						
							|  |  |  | 	MSelect *mselect; | 
					
						
							|  |  |  | 	KeyBlock *actkey; | 
					
						
							| 
									
										
										
										
											2008-12-31 17:11:42 +00:00
										 |  |  | 	EditMesh *em; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditVert *eve, **evlist, *eve1, *eve2, *eve3, *eve4; | 
					
						
							| 
									
										
										
										
											2010-01-19 12:24:28 +00:00
										 |  |  | 	EditFace *efa, *efa_last_sel= NULL; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditSelection *ese; | 
					
						
							| 
									
										
										
										
											2009-10-22 09:31:07 +00:00
										 |  |  | 	float *co, (*keyco)[3]= NULL; | 
					
						
							| 
									
										
										
										
											2009-08-29 15:20:36 +00:00
										 |  |  | 	int tot, a, eekadoodle= 0; | 
					
						
							| 
									
										
										
										
											2010-11-14 23:37:03 +00:00
										 |  |  | 	const short is_paint_sel= paint_facesel_test(ob); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-31 17:11:42 +00:00
										 |  |  | 	if(me->edit_mesh==NULL) | 
					
						
							|  |  |  | 		me->edit_mesh= MEM_callocN(sizeof(EditMesh), "editmesh"); | 
					
						
							|  |  |  | 	else  | 
					
						
							|  |  |  | 		/* because of reload */ | 
					
						
							|  |  |  | 		free_editMesh(me->edit_mesh); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	em= me->edit_mesh; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-06-23 00:41:55 +00:00
										 |  |  | 	em->selectmode= scene->toolsettings->selectmode; // warning needs to be synced
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	em->act_face = NULL; | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	em->totvert= tot= me->totvert; | 
					
						
							|  |  |  | 	em->totedge= me->totedge; | 
					
						
							|  |  |  | 	em->totface= me->totface; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	if(tot==0) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-11-05 14:54:02 +00:00
										 |  |  | 	if(ob->actcol > 0) | 
					
						
							|  |  |  | 		em->mat_nr= ob->actcol-1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	/* initialize fastmalloc for editmesh */ | 
					
						
							|  |  |  | 	init_editmesh_fastmalloc(em, me->totvert, me->totedge, me->totface); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-31 17:11:42 +00:00
										 |  |  | 	actkey = ob_get_keyblock(ob); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	if(actkey) { | 
					
						
							|  |  |  | 		/* undo-ing in past for previous editmode sessions gives corrupt 'keyindex' values */ | 
					
						
							|  |  |  | 		undo_editmode_clear(); | 
					
						
							| 
									
										
										
										
											2009-10-22 09:31:07 +00:00
										 |  |  | 		keyco= actkey->data; | 
					
						
							| 
									
										
										
										
											2009-10-22 17:12:28 +00:00
										 |  |  | 		em->shapenr= ob->shapenr; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* make editverts */ | 
					
						
							|  |  |  | 	CustomData_copy(&me->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0); | 
					
						
							|  |  |  | 	mvert= me->mvert; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist"); | 
					
						
							|  |  |  | 	for(a=0; a<tot; a++, mvert++) { | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2009-08-29 15:20:36 +00:00
										 |  |  | 		co= mvert->co; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-15 13:33:56 +00:00
										 |  |  | 		/* edit the shape key coordinate if available */ | 
					
						
							| 
									
										
										
										
											2009-10-22 09:31:07 +00:00
										 |  |  | 		if(keyco && a < actkey->totelem) | 
					
						
							|  |  |  | 			co= keyco[a]; | 
					
						
							| 
									
										
										
										
											2009-10-15 13:33:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		eve= addvertlist(em, co, NULL); | 
					
						
							|  |  |  | 		evlist[a]= eve; | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2009-10-15 13:33:56 +00:00
										 |  |  | 		/* face select sets selection in next loop */ | 
					
						
							| 
									
										
										
										
											2010-11-14 23:37:03 +00:00
										 |  |  | 		if(!is_paint_sel) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			eve->f |= (mvert->flag & 1); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if (mvert->flag & ME_HIDE) eve->h= 1;		 | 
					
						
							|  |  |  | 		eve->no[0]= mvert->no[0]/32767.0; | 
					
						
							|  |  |  | 		eve->no[1]= mvert->no[1]/32767.0; | 
					
						
							|  |  |  | 		eve->no[2]= mvert->no[2]/32767.0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		eve->bweight= ((float)mvert->bweight)/255.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* lets overwrite the keyindex of the editvert
 | 
					
						
							|  |  |  | 		 * with the order it used to be in before | 
					
						
							|  |  |  | 		 * editmode | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		eve->keyindex = a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		CustomData_to_em_block(&me->vdata, &em->vdata, a, &eve->data); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(actkey && actkey->totelem!=me->totvert); | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		MEdge *medge= me->medge; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		CustomData_copy(&me->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0); | 
					
						
							|  |  |  | 		/* make edges */ | 
					
						
							|  |  |  | 		for(a=0; a<me->totedge; a++, medge++) { | 
					
						
							|  |  |  | 			eed= addedgelist(em, evlist[medge->v1], evlist[medge->v2], NULL); | 
					
						
							|  |  |  | 			/* eed can be zero when v1 and v2 are identical, dxf import does this... */ | 
					
						
							|  |  |  | 			if(eed) { | 
					
						
							|  |  |  | 				eed->crease= ((float)medge->crease)/255.0f; | 
					
						
							|  |  |  | 				eed->bweight= ((float)medge->bweight)/255.0f; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				if(medge->flag & ME_SEAM) eed->seam= 1; | 
					
						
							|  |  |  | 				if(medge->flag & ME_SHARP) eed->sharp = 1; | 
					
						
							|  |  |  | 				if(medge->flag & SELECT) eed->f |= SELECT; | 
					
						
							|  |  |  | 				if(medge->flag & ME_FGON) eed->h= EM_FGON;	// 2 different defines!
 | 
					
						
							|  |  |  | 				if(medge->flag & ME_HIDE) eed->h |= 1; | 
					
						
							|  |  |  | 				if(em->selectmode==SCE_SELECT_EDGE)  | 
					
						
							|  |  |  | 					EM_select_edge(eed, eed->f & SELECT);		// force edge selection to vertices, seems to be needed ...
 | 
					
						
							|  |  |  | 				CustomData_to_em_block(&me->edata,&em->edata, a, &eed->data); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		CustomData_copy(&me->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* make faces */ | 
					
						
							|  |  |  | 		mface= me->mface; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for(a=0; a<me->totface; a++, mface++) { | 
					
						
							|  |  |  | 			eve1= evlist[mface->v1]; | 
					
						
							|  |  |  | 			eve2= evlist[mface->v2]; | 
					
						
							|  |  |  | 			if(!mface->v3) eekadoodle= 1; | 
					
						
							|  |  |  | 			eve3= evlist[mface->v3]; | 
					
						
							|  |  |  | 			if(mface->v4) eve4= evlist[mface->v4]; else eve4= NULL; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			efa= addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(efa) { | 
					
						
							|  |  |  | 				CustomData_to_em_block(&me->fdata, &em->fdata, a, &efa->data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				efa->mat_nr= mface->mat_nr; | 
					
						
							|  |  |  | 				efa->flag= mface->flag & ~ME_HIDE; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				/* select and hide face flag */ | 
					
						
							|  |  |  | 				if(mface->flag & ME_HIDE) { | 
					
						
							|  |  |  | 					efa->h= 1; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					if (a==me->act_face) { | 
					
						
							|  |  |  | 						EM_set_actFace(em, efa); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 					/* dont allow hidden and selected */ | 
					
						
							|  |  |  | 					if(mface->flag & ME_FACE_SEL) { | 
					
						
							|  |  |  | 						efa->f |= SELECT; | 
					
						
							|  |  |  | 						 | 
					
						
							| 
									
										
										
										
											2010-11-14 23:37:03 +00:00
										 |  |  | 						if(is_paint_sel) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 							EM_select_face(efa, 1); /* flush down */ | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2010-01-19 12:24:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						efa_last_sel= efa; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2010-02-05 15:07:44 +00:00
										 |  |  | 	if(EM_get_actFace(em, 0)==NULL && efa_last_sel) { | 
					
						
							| 
									
										
										
										
											2010-01-19 12:24:28 +00:00
										 |  |  | 		EM_set_actFace(em, efa_last_sel); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	if(eekadoodle) | 
					
						
							|  |  |  | 		error("This Mesh has old style edgecodes, please put it in the bugtracker!"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	MEM_freeN(evlist); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	end_editmesh_fastmalloc();	// resets global function pointers
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(me->mselect){ | 
					
						
							|  |  |  | 		//restore editselections
 | 
					
						
							|  |  |  | 		EM_init_index_arrays(em, 1,1,1); | 
					
						
							|  |  |  | 		mselect = me->mselect; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for(a=0; a<me->totselect; a++, mselect++){ | 
					
						
							|  |  |  | 			/*check if recorded selection is still valid, if so copy into editmesh*/ | 
					
						
							|  |  |  | 			if( (mselect->type == EDITVERT && me->mvert[mselect->index].flag & SELECT) || (mselect->type == EDITEDGE && me->medge[mselect->index].flag & SELECT) || (mselect->type == EDITFACE && me->mface[mselect->index].flag & ME_FACE_SEL) ){ | 
					
						
							|  |  |  | 				ese = MEM_callocN(sizeof(EditSelection), "Edit Selection"); | 
					
						
							|  |  |  | 				ese->type = mselect->type;	 | 
					
						
							|  |  |  | 				if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(mselect->index); else | 
					
						
							|  |  |  | 				if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(mselect->index); else | 
					
						
							|  |  |  | 				if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(mselect->index); | 
					
						
							|  |  |  | 				BLI_addtail(&(em->selected),ese); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		EM_free_index_arrays(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* this creates coherent selections. also needed for older files */ | 
					
						
							|  |  |  | 	EM_selectmode_set(em); | 
					
						
							|  |  |  | 	/* paranoia check to enforce hide rules */ | 
					
						
							|  |  |  | 	EM_hide_reset(em); | 
					
						
							|  |  |  | 	/* sets helper flags which arent saved */ | 
					
						
							|  |  |  | 	EM_fgon_flags(em); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (EM_get_actFace(em, 0)==NULL) { | 
					
						
							|  |  |  | 		EM_set_actFace(em, em->faces.first ); /* will use the first face, this is so we alwats have an active face */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* makes Mesh out of editmesh */ | 
					
						
							| 
									
										
										
										
											2010-12-03 12:30:59 +00:00
										 |  |  | void load_editMesh(Scene *scene, Object *obedit) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-12-03 12:30:59 +00:00
										 |  |  | 	Mesh *me= obedit->data; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	MVert *mvert, *oldverts; | 
					
						
							|  |  |  | 	MEdge *medge; | 
					
						
							|  |  |  | 	MFace *mface; | 
					
						
							|  |  |  | 	MSelect *mselect; | 
					
						
							| 
									
										
										
										
											2008-12-31 17:11:42 +00:00
										 |  |  | 	EditMesh *em= me->edit_mesh; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	EditFace *efa, *efa_act; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditSelection *ese; | 
					
						
							| 
									
										
										
										
											2009-08-29 15:20:36 +00:00
										 |  |  | 	float *fp, *newkey, *oldkey, nor[3]; | 
					
						
							|  |  |  | 	int i, a, ototvert; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* this one also tests of edges are not in faces: */ | 
					
						
							|  |  |  | 	/* eed->f2==0: not in face, f2==1: draw it */ | 
					
						
							|  |  |  | 	/* eed->f1 : flag for dynaface (cylindertest, old engine) */ | 
					
						
							|  |  |  | 	/* eve->f1 : flag for dynaface (sphere test, old engine) */ | 
					
						
							|  |  |  | 	/* eve->f2 : being used in vertexnormals */ | 
					
						
							| 
									
										
										
										
											2009-01-31 13:30:56 +00:00
										 |  |  | 	edge_drawflags(me, em); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	EM_stats_update(em); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* new Vertex block */ | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	if(em->totvert==0) mvert= NULL; | 
					
						
							|  |  |  | 	else mvert= MEM_callocN(em->totvert*sizeof(MVert), "loadeditMesh vert"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* new Edge block */ | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	if(em->totedge==0) medge= NULL; | 
					
						
							|  |  |  | 	else medge= MEM_callocN(em->totedge*sizeof(MEdge), "loadeditMesh edge"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* new Face block */ | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	if(em->totface==0) mface= NULL; | 
					
						
							|  |  |  | 	else mface= MEM_callocN(em->totface*sizeof(MFace), "loadeditMesh face"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* lets save the old verts just in case we are actually working on
 | 
					
						
							|  |  |  | 	 * a key ... we now do processing of the keys at the end */ | 
					
						
							|  |  |  | 	oldverts= me->mvert; | 
					
						
							|  |  |  | 	ototvert= me->totvert; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* don't free this yet */ | 
					
						
							|  |  |  | 	CustomData_set_layer(&me->vdata, CD_MVERT, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* free custom data */ | 
					
						
							|  |  |  | 	CustomData_free(&me->vdata, me->totvert); | 
					
						
							|  |  |  | 	CustomData_free(&me->edata, me->totedge); | 
					
						
							|  |  |  | 	CustomData_free(&me->fdata, me->totface); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* add new custom data */ | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	me->totvert= em->totvert; | 
					
						
							|  |  |  | 	me->totedge= em->totedge; | 
					
						
							|  |  |  | 	me->totface= em->totface; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	CustomData_copy(&em->vdata, &me->vdata, CD_MASK_MESH, CD_CALLOC, me->totvert); | 
					
						
							|  |  |  | 	CustomData_copy(&em->edata, &me->edata, CD_MASK_MESH, CD_CALLOC, me->totedge); | 
					
						
							|  |  |  | 	CustomData_copy(&em->fdata, &me->fdata, CD_MASK_MESH, CD_CALLOC, me->totface); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert); | 
					
						
							|  |  |  | 	CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge); | 
					
						
							|  |  |  | 	CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface); | 
					
						
							|  |  |  | 	mesh_update_customdata_pointers(me); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* the vertices, use ->tmp.l as counter */ | 
					
						
							|  |  |  | 	eve= em->verts.first; | 
					
						
							|  |  |  | 	a= 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							| 
									
										
										
										
											2009-08-29 15:20:36 +00:00
										 |  |  | 		VECCOPY(mvert->co, eve->co); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* vertex normal */ | 
					
						
							|  |  |  | 		VECCOPY(nor, eve->no); | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		mul_v3_fl(nor, 32767.0); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		VECCOPY(mvert->no, nor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* note: it used to remove me->dvert when it was not in use, cancelled
 | 
					
						
							|  |  |  | 		   that... annoying when you have a fresh vgroup */ | 
					
						
							|  |  |  | 		CustomData_from_em_block(&em->vdata, &me->vdata, eve->data, a); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		eve->tmp.l = a++;  /* counter */ | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		mvert->flag= 0; | 
					
						
							|  |  |  | 		mvert->flag |= (eve->f & SELECT); | 
					
						
							|  |  |  | 		if (eve->h) mvert->flag |= ME_HIDE; | 
					
						
							| 
									
										
										
										
											2009-01-31 13:30:56 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		mvert->bweight= (char)(255.0*eve->bweight); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		eve= eve->next; | 
					
						
							|  |  |  | 		mvert++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* the edges */ | 
					
						
							|  |  |  | 	a= 0; | 
					
						
							|  |  |  | 	eed= em->edges.first; | 
					
						
							|  |  |  | 	while(eed) { | 
					
						
							|  |  |  | 		medge->v1= (unsigned int) eed->v1->tmp.l; | 
					
						
							|  |  |  | 		medge->v2= (unsigned int) eed->v2->tmp.l; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		medge->flag= (eed->f & SELECT) | ME_EDGERENDER; | 
					
						
							|  |  |  | 		if(eed->f2<2) medge->flag |= ME_EDGEDRAW; | 
					
						
							|  |  |  | 		if(eed->f2==0) medge->flag |= ME_LOOSEEDGE; | 
					
						
							|  |  |  | 		if(eed->sharp) medge->flag |= ME_SHARP; | 
					
						
							|  |  |  | 		if(eed->seam) medge->flag |= ME_SEAM; | 
					
						
							|  |  |  | 		if(eed->h & EM_FGON) medge->flag |= ME_FGON;	// different defines yes
 | 
					
						
							|  |  |  | 		if(eed->h & 1) medge->flag |= ME_HIDE; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		medge->crease= (char)(255.0*eed->crease); | 
					
						
							|  |  |  | 		medge->bweight= (char)(255.0*eed->bweight); | 
					
						
							|  |  |  | 		CustomData_from_em_block(&em->edata, &me->edata, eed->data, a);		 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		eed->tmp.l = a++; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		medge++; | 
					
						
							|  |  |  | 		eed= eed->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* the faces */ | 
					
						
							|  |  |  | 	a = 0; | 
					
						
							|  |  |  | 	efa= em->faces.first; | 
					
						
							|  |  |  | 	efa_act= EM_get_actFace(em, 0); | 
					
						
							|  |  |  | 	i = 0; | 
					
						
							|  |  |  | 	me->act_face = -1; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		mface= &((MFace *) me->mface)[i]; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		mface->v1= (unsigned int) efa->v1->tmp.l; | 
					
						
							|  |  |  | 		mface->v2= (unsigned int) efa->v2->tmp.l; | 
					
						
							|  |  |  | 		mface->v3= (unsigned int) efa->v3->tmp.l; | 
					
						
							|  |  |  | 		if (efa->v4) mface->v4 = (unsigned int) efa->v4->tmp.l; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		mface->mat_nr= efa->mat_nr; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		mface->flag= efa->flag; | 
					
						
							|  |  |  | 		/* bit 0 of flag is already taken for smooth... */ | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if(efa->h) { | 
					
						
							|  |  |  | 			mface->flag |= ME_HIDE; | 
					
						
							|  |  |  | 			mface->flag &= ~ME_FACE_SEL; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			if(efa->f & 1) mface->flag |= ME_FACE_SEL; | 
					
						
							|  |  |  | 			else mface->flag &= ~ME_FACE_SEL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		/* watch: efa->e1->f2==0 means loose edge */  | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		if(efa->e1->f2==1) { | 
					
						
							|  |  |  | 			efa->e1->f2= 2; | 
					
						
							|  |  |  | 		}			 | 
					
						
							|  |  |  | 		if(efa->e2->f2==1) { | 
					
						
							|  |  |  | 			efa->e2->f2= 2; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(efa->e3->f2==1) { | 
					
						
							|  |  |  | 			efa->e3->f2= 2; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if(efa->e4 && efa->e4->f2==1) { | 
					
						
							|  |  |  | 			efa->e4->f2= 2; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		CustomData_from_em_block(&em->fdata, &me->fdata, efa->data, i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* no index '0' at location 3 or 4 */ | 
					
						
							|  |  |  | 		test_index_face(mface, &me->fdata, i, efa->v4?4:3); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if (efa_act == efa) | 
					
						
							|  |  |  | 			me->act_face = a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		efa->tmp.l = a++; | 
					
						
							|  |  |  | 		i++; | 
					
						
							|  |  |  | 		efa= efa->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* patch hook indices and vertex parents */ | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		Object *ob; | 
					
						
							|  |  |  | 		ModifierData *md; | 
					
						
							|  |  |  | 		EditVert **vertMap = NULL; | 
					
						
							| 
									
										
										
										
											2010-12-03 12:30:59 +00:00
										 |  |  | 		int j; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		for (ob=G.main->object.first; ob; ob=ob->id.next) { | 
					
						
							| 
									
										
										
										
											2008-12-31 17:11:42 +00:00
										 |  |  | 			if (ob->parent==ob && ELEM(ob->partype, PARVERT1,PARVERT3)) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				 | 
					
						
							|  |  |  | 				/* duplicate code from below, make it function later...? */ | 
					
						
							|  |  |  | 				if (!vertMap) { | 
					
						
							|  |  |  | 					vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap"); | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 					for (eve=em->verts.first; eve; eve=eve->next) { | 
					
						
							|  |  |  | 						if (eve->keyindex!=-1) | 
					
						
							|  |  |  | 							vertMap[eve->keyindex] = eve; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if(ob->par1 < ototvert) { | 
					
						
							|  |  |  | 					eve = vertMap[ob->par1]; | 
					
						
							|  |  |  | 					if(eve) ob->par1= eve->tmp.l; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if(ob->par2 < ototvert) { | 
					
						
							|  |  |  | 					eve = vertMap[ob->par2]; | 
					
						
							|  |  |  | 					if(eve) ob->par2= eve->tmp.l; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if(ob->par3 < ototvert) { | 
					
						
							|  |  |  | 					eve = vertMap[ob->par3]; | 
					
						
							|  |  |  | 					if(eve) ob->par3= eve->tmp.l; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (ob->data==me) { | 
					
						
							|  |  |  | 				for (md=ob->modifiers.first; md; md=md->next) { | 
					
						
							|  |  |  | 					if (md->type==eModifierType_Hook) { | 
					
						
							|  |  |  | 						HookModifierData *hmd = (HookModifierData*) md; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						if (!vertMap) { | 
					
						
							|  |  |  | 							vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							for (eve=em->verts.first; eve; eve=eve->next) { | 
					
						
							|  |  |  | 								if (eve->keyindex!=-1) | 
					
						
							|  |  |  | 									vertMap[eve->keyindex] = eve; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						 | 
					
						
							|  |  |  | 						for (i=j=0; i<hmd->totindex; i++) { | 
					
						
							|  |  |  | 							if(hmd->indexar[i] < ototvert) { | 
					
						
							|  |  |  | 								eve = vertMap[hmd->indexar[i]]; | 
					
						
							|  |  |  | 								 | 
					
						
							|  |  |  | 								if (eve) { | 
					
						
							|  |  |  | 									hmd->indexar[j++] = eve->tmp.l; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							else j++; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						hmd->totindex = j; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (vertMap) MEM_freeN(vertMap); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* are there keys? */ | 
					
						
							|  |  |  | 	if(me->key) { | 
					
						
							| 
									
										
										
										
											2009-10-22 17:12:28 +00:00
										 |  |  | 		KeyBlock *currkey; | 
					
						
							|  |  |  | 		KeyBlock *actkey= BLI_findlink(&me->key->block, em->shapenr-1); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 11:10:02 +00:00
										 |  |  | 		float (*ofs)[3] = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* editing the base key should update others */ | 
					
						
							|  |  |  | 		if(me->key->type==KEY_RELATIVE && oldverts) { | 
					
						
							|  |  |  | 			int act_is_basis = 0; | 
					
						
							|  |  |  | 			/* find if this key is a basis for any others */ | 
					
						
							|  |  |  | 			for(currkey = me->key->block.first; currkey; currkey= currkey->next) { | 
					
						
							|  |  |  | 				if(em->shapenr-1 == currkey->relative) { | 
					
						
							|  |  |  | 					act_is_basis = 1; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(act_is_basis) { /* active key is a base */ | 
					
						
							|  |  |  | 				i=0; | 
					
						
							|  |  |  | 				ofs= MEM_callocN(sizeof(float) * 3 * em->totvert,  "currkey->data"); | 
					
						
							|  |  |  | 				eve= em->verts.first; | 
					
						
							|  |  |  | 				mvert = me->mvert; | 
					
						
							|  |  |  | 				while(eve) { | 
					
						
							| 
									
										
										
										
											2011-02-11 17:56:25 +00:00
										 |  |  | 					if(eve->keyindex>=0) | 
					
						
							|  |  |  | 						VECSUB(ofs[i], mvert->co, oldverts[eve->keyindex].co); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-02 11:10:02 +00:00
										 |  |  | 					eve= eve->next; | 
					
						
							|  |  |  | 					i++; | 
					
						
							|  |  |  | 					mvert++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		/* Lets reorder the key data so that things line up roughly
 | 
					
						
							|  |  |  | 		 * with the way things were before editmode */ | 
					
						
							|  |  |  | 		currkey = me->key->block.first; | 
					
						
							|  |  |  | 		while(currkey) { | 
					
						
							| 
									
										
										
										
											2010-02-02 11:10:02 +00:00
										 |  |  | 			int apply_offset = (ofs && (currkey != actkey) && (em->shapenr-1 == currkey->relative)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 			fp= newkey= MEM_callocN(me->key->elemsize*em->totvert,  "currkey->data"); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			oldkey = currkey->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			eve= em->verts.first; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			i = 0; | 
					
						
							|  |  |  | 			mvert = me->mvert; | 
					
						
							|  |  |  | 			while(eve) { | 
					
						
							|  |  |  | 				if (eve->keyindex >= 0 && eve->keyindex < currkey->totelem) { // valid old vertex
 | 
					
						
							|  |  |  | 					if(currkey == actkey) { | 
					
						
							| 
									
										
										
										
											2009-10-22 09:31:07 +00:00
										 |  |  | 						if(actkey == me->key->refkey) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 							VECCOPY(fp, mvert->co); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						else { | 
					
						
							|  |  |  | 							VECCOPY(fp, mvert->co); | 
					
						
							|  |  |  | 							if(oldverts) { | 
					
						
							|  |  |  | 								VECCOPY(mvert->co, oldverts[eve->keyindex].co); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					else { | 
					
						
							|  |  |  | 						if(oldkey) { | 
					
						
							|  |  |  | 							VECCOPY(fp, oldkey + 3 * eve->keyindex); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					VECCOPY(fp, mvert->co); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2010-02-02 11:10:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				/* propagate edited basis offsets to other shapes */ | 
					
						
							|  |  |  | 				if(apply_offset) { | 
					
						
							|  |  |  | 					VECADD(fp, fp, ofs[i]); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 				fp+= 3; | 
					
						
							|  |  |  | 				++i; | 
					
						
							|  |  |  | 				++mvert; | 
					
						
							|  |  |  | 				eve= eve->next; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 			currkey->totelem= em->totvert; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			if(currkey->data) MEM_freeN(currkey->data); | 
					
						
							|  |  |  | 			currkey->data = newkey; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			currkey= currkey->next; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-02-02 11:10:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if(ofs) MEM_freeN(ofs); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(oldverts) MEM_freeN(oldverts); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	i = 0; | 
					
						
							|  |  |  | 	for(ese=em->selected.first; ese; ese=ese->next) i++; | 
					
						
							|  |  |  | 	me->totselect = i; | 
					
						
							|  |  |  | 	if(i==0) mselect= NULL; | 
					
						
							|  |  |  | 	else mselect= MEM_callocN(i*sizeof(MSelect), "loadeditMesh selections"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(me->mselect) MEM_freeN(me->mselect); | 
					
						
							|  |  |  | 	me->mselect= mselect; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	for(ese=em->selected.first; ese; ese=ese->next){ | 
					
						
							|  |  |  | 		mselect->type = ese->type; | 
					
						
							|  |  |  | 		if(ese->type == EDITVERT) mselect->index = ((EditVert*)ese->data)->tmp.l; | 
					
						
							|  |  |  | 		else if(ese->type == EDITEDGE) mselect->index = ((EditEdge*)ese->data)->tmp.l; | 
					
						
							|  |  |  | 		else if(ese->type == EDITFACE) mselect->index = ((EditFace*)ese->data)->tmp.l; | 
					
						
							|  |  |  | 		mselect++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* to be sure: clear ->tmp.l pointers */ | 
					
						
							|  |  |  | 	eve= em->verts.first; | 
					
						
							|  |  |  | 	while(eve) { | 
					
						
							|  |  |  | 		eve->tmp.l = 0; | 
					
						
							|  |  |  | 		eve= eve->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	eed= em->edges.first; | 
					
						
							|  |  |  | 	while(eed) {  | 
					
						
							|  |  |  | 		eed->tmp.l = 0; | 
					
						
							|  |  |  | 		eed= eed->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	efa= em->faces.first; | 
					
						
							|  |  |  | 	while(efa) { | 
					
						
							|  |  |  | 		efa->tmp.l = 0; | 
					
						
							|  |  |  | 		efa= efa->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* remake softbody of all users */ | 
					
						
							|  |  |  | 	if(me->id.us>1) { | 
					
						
							|  |  |  | 		Base *base; | 
					
						
							|  |  |  | 		for(base= scene->base.first; base; base= base->next) | 
					
						
							|  |  |  | 			if(base->object->data==me) | 
					
						
							|  |  |  | 				base->object->recalc |= OB_RECALC_DATA; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); | 
					
						
							| 
									
										
										
										
											2010-11-04 16:00:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* topology could be changed, ensure mdisps are ok */ | 
					
						
							| 
									
										
										
										
											2011-01-30 17:55:48 +00:00
										 |  |  | 	multires_topology_changed(scene, obedit); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-31 17:11:42 +00:00
										 |  |  | void remake_editMesh(Scene *scene, Object *ob) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-31 17:11:42 +00:00
										 |  |  | 	make_editMesh(scene, ob); | 
					
						
							| 
									
										
										
										
											2010-12-05 18:59:23 +00:00
										 |  |  | 	DAG_id_tag_update(&ob->id, OB_RECALC_DATA); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	BIF_undo_push("Undo all changes"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | /* *************** Operator: separate parts *************/ | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | static EnumPropertyItem prop_separate_types[] = { | 
					
						
							| 
									
										
										
										
											2009-06-16 00:52:21 +00:00
										 |  |  | 	{0, "SELECTED", 0, "Selection", ""}, | 
					
						
							|  |  |  | 	{1, "MATERIAL", 0, "By Material", ""}, | 
					
						
							|  |  |  | 	{2, "LOOSE", 0, "By loose parts", ""}, | 
					
						
							|  |  |  | 	{0, NULL, 0, NULL, NULL} | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | /* return 1: success */ | 
					
						
							| 
									
										
										
										
											2010-10-23 10:41:28 +00:00
										 |  |  | static int mesh_separate_selected(wmOperator *op, Main *bmain, Scene *scene, Base *editbase) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	EditMesh *em, *emnew; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditVert *eve, *v1; | 
					
						
							|  |  |  | 	EditEdge *eed, *e1; | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	EditFace *efa, *f1; | 
					
						
							|  |  |  | 	Object *obedit; | 
					
						
							|  |  |  | 	Mesh *me, *menew; | 
					
						
							|  |  |  | 	Base *basenew; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	if(editbase==NULL) return 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	obedit= editbase->object; | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	me= obedit->data; | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	em= BKE_mesh_get_editmesh(me); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	if(me->key) { | 
					
						
							| 
									
										
										
										
											2010-10-23 10:41:28 +00:00
										 |  |  | 		BKE_report(op->reports, RPT_WARNING, "Can't separate mesh with shape keys."); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 		BKE_mesh_end_editmesh(me, em); | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	if(em->selected.first)  | 
					
						
							|  |  |  | 		BLI_freelistN(&(em->selected)); /* clear the selection order */ | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2009-04-15 15:40:31 +00:00
										 |  |  | 	EM_selectmode_set(em);	// enforce full consistent selection flags 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	EM_stats_update(em); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-03-30 07:28:37 +00:00
										 |  |  | 	if(em->totvertsel==0) { | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 		BKE_mesh_end_editmesh(me, em); | 
					
						
							| 
									
										
										
										
											2009-03-30 07:28:37 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* we are going to work as follows:
 | 
					
						
							|  |  |  | 	 * 1. add a linked duplicate object: this will be the new one, we remember old pointer | 
					
						
							|  |  |  | 	 * 2. give new object empty mesh and put in editmode | 
					
						
							|  |  |  | 	 * 3: do a split if needed on current editmesh. | 
					
						
							|  |  |  | 	 * 4. copy over: all NOT selected verts, edges, faces | 
					
						
							|  |  |  | 	 * 5. call load_editMesh() on the new object | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 */ | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	/* 1 */ | 
					
						
							| 
									
										
										
										
											2010-08-01 12:47:49 +00:00
										 |  |  | 	basenew= ED_object_add_duplicate(bmain, scene, editbase, 0);	/* 0 = fully linked */ | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	ED_base_object_select(basenew, BA_DESELECT); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	/* 2 */ | 
					
						
							| 
									
										
										
										
											2009-10-09 21:45:14 +00:00
										 |  |  | 	basenew->object->data= menew= add_mesh(me->id.name+2);	/* empty */ | 
					
						
							| 
									
										
										
										
											2009-10-08 09:22:39 +00:00
										 |  |  | 	assign_matarar(basenew->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */ | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	me->id.us--; | 
					
						
							|  |  |  | 	make_editMesh(scene, basenew->object); | 
					
						
							|  |  |  | 	emnew= menew->edit_mesh; | 
					
						
							| 
									
										
										
										
											2009-10-09 21:45:14 +00:00
										 |  |  | 	CustomData_copy(&em->vdata, &emnew->vdata, CD_MASK_EDITMESH, CD_DEFAULT, 0); | 
					
						
							|  |  |  | 	CustomData_copy(&em->edata, &emnew->edata, CD_MASK_EDITMESH, CD_DEFAULT, 0); | 
					
						
							|  |  |  | 	CustomData_copy(&em->fdata, &emnew->fdata, CD_MASK_EDITMESH, CD_DEFAULT, 0); | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* 3 */ | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	/* SPLIT: first make duplicate */ | 
					
						
							|  |  |  | 	adduplicateflag(em, SELECT); | 
					
						
							|  |  |  | 	/* SPLIT: old faces have 3x flag 128 set, delete these ones */ | 
					
						
							|  |  |  | 	delfaceflag(em, 128); | 
					
						
							|  |  |  | 	/* since we do tricky things with verts/edges/faces, this makes sure all is selected coherent */ | 
					
						
							|  |  |  | 	EM_selectmode_set(em); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	/* 4 */ | 
					
						
							|  |  |  | 	/* move over: everything that is selected */ | 
					
						
							|  |  |  | 	for(eve= em->verts.first; eve; eve= v1) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		v1= eve->next; | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 		if(eve->f & SELECT) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			BLI_remlink(&em->verts, eve); | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 			BLI_addtail(&emnew->verts, eve); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	for(eed= em->edges.first; eed; eed= e1) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		e1= eed->next; | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 		if(eed->f & SELECT) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			BLI_remlink(&em->edges, eed); | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 			BLI_addtail(&emnew->edges, eed); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	for(efa= em->faces.first; efa; efa= f1) { | 
					
						
							|  |  |  | 		f1= efa->next; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		if (efa == em->act_face && (efa->f & SELECT)) { | 
					
						
							|  |  |  | 			EM_set_actFace(em, NULL); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 		if(efa->f & SELECT) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			BLI_remlink(&em->faces, efa); | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 			BLI_addtail(&emnew->faces, efa); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* 5 */ | 
					
						
							|  |  |  | 	load_editMesh(scene, basenew->object); | 
					
						
							|  |  |  | 	free_editMesh(emnew); | 
					
						
							| 
									
										
										
										
											2009-10-09 21:45:14 +00:00
										 |  |  | 	MEM_freeN(menew->edit_mesh); | 
					
						
							|  |  |  | 	menew->edit_mesh= NULL; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	/* hashedges are invalid now, make new! */ | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	editMesh_set_hash(em); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-05 18:59:23 +00:00
										 |  |  | 	DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);	 | 
					
						
							|  |  |  | 	DAG_id_tag_update(&basenew->object->id, OB_RECALC_DATA);	 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(me, em); | 
					
						
							| 
									
										
										
										
											2009-03-30 07:28:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	return 1; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | /* return 1: success */ | 
					
						
							| 
									
										
										
										
											2010-10-23 10:41:28 +00:00
										 |  |  | static int mesh_separate_material(wmOperator *op, Main *bmain, Scene *scene, Base *editbase) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	Mesh *me= editbase->object->data; | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	EditMesh *em= BKE_mesh_get_editmesh(me); | 
					
						
							| 
									
										
										
										
											2008-12-31 17:11:42 +00:00
										 |  |  | 	unsigned char curr_mat; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	for (curr_mat = 1; curr_mat < editbase->object->totcol; ++curr_mat) { | 
					
						
							|  |  |  | 		/* clear selection, we're going to use that to select material group */ | 
					
						
							|  |  |  | 		EM_clear_flag_all(em, SELECT); | 
					
						
							|  |  |  | 		/* select the material */ | 
					
						
							| 
									
										
										
										
											2009-06-24 14:07:48 +00:00
										 |  |  | 		EM_select_by_material(em, curr_mat); | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 		/* and now separate */ | 
					
						
							| 
									
										
										
										
											2010-10-23 10:41:28 +00:00
										 |  |  | 		if(0==mesh_separate_selected(op, bmain, scene, editbase)) { | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 			BKE_mesh_end_editmesh(me, em); | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2009-03-30 07:28:37 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-03-30 07:28:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(me, em); | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	return 1; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | /* return 1: success */ | 
					
						
							| 
									
										
										
										
											2010-10-23 10:41:28 +00:00
										 |  |  | static int mesh_separate_loose(wmOperator *op, Main *bmain, Scene *scene, Base *editbase) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	Mesh *me; | 
					
						
							|  |  |  | 	EditMesh *em; | 
					
						
							|  |  |  | 	int doit= 1; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	me= editbase->object->data; | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	em= BKE_mesh_get_editmesh(me); | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	if(me->key) { | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 		error("Can't separate with vertex keys"); | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 		BKE_mesh_end_editmesh(me, em); | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	EM_clear_flag_all(em, SELECT); | 
					
						
							| 
									
										
										
										
											2010-06-14 16:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	while(doit) { | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		/* Select a random vert to start with */ | 
					
						
							| 
									
										
										
										
											2010-06-14 16:58:31 +00:00
										 |  |  | 		EditVert *eve; | 
					
						
							|  |  |  | 		int tot; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* check if all verts that are visible have been done */ | 
					
						
							|  |  |  | 		for(eve=em->verts.first; eve; eve= eve->next) | 
					
						
							|  |  |  | 			if(!eve->h) break; | 
					
						
							|  |  |  | 		if(eve==NULL) break; /* only hidden verts left, quit early */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* first non hidden vert */ | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		eve->f |= SELECT; | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 		selectconnected_mesh_all(em); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2010-01-30 19:42:03 +00:00
										 |  |  | 		/* don't separate the very last part */ | 
					
						
							|  |  |  | 		for(eve=em->verts.first; eve; eve= eve->next) | 
					
						
							|  |  |  | 			if((eve->f & SELECT)==0) break; | 
					
						
							|  |  |  | 		if(eve==NULL) break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-14 16:58:31 +00:00
										 |  |  | 		tot= BLI_countlist(&em->verts); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 		/* and now separate */ | 
					
						
							| 
									
										
										
										
											2010-10-23 10:41:28 +00:00
										 |  |  | 		doit= mesh_separate_selected(op, bmain, scene, editbase); | 
					
						
							| 
									
										
										
										
											2010-06-14 16:58:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* with hidden verts this can happen */ | 
					
						
							|  |  |  | 		if(tot == BLI_countlist(&em->verts)) | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-03-30 07:28:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-11 08:26:51 +00:00
										 |  |  | 	BKE_mesh_end_editmesh(me, em); | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | static int mesh_separate_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-08-01 12:47:49 +00:00
										 |  |  | 	Main *bmain= CTX_data_main(C); | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	Scene *scene= CTX_data_scene(C); | 
					
						
							|  |  |  | 	Base *base= CTX_data_active_base(C); | 
					
						
							| 
									
										
										
											
												RNA
* Enums can now be dynamically created in the _itemf callback,
  using RNA_enum_item(s)_add, RNA_enum_item_end. All places asking
  for enum items now need to potentially free the items.
* This callback now also gets context, this was added specifically
  for operators. This doesn't fit design well at all, needed to do
  some ugly hacks, but can't find a good solution at the moment.
* All enums must have a default list of items too, even with an
  _itemf callback, for docs and fallback in case there is no context.
* Used by MESH_OT_merge, MESH_OT_select_similar, TFM_OT_select_orientation.
* Also changes some operator properties that were enums to booleas
  (unselected, deselect), to make them consistent with other ops.
											
										 
											2009-07-10 19:56:13 +00:00
										 |  |  | 	int retval= 0, type= RNA_enum_get(op->ptr, "type"); | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
											
												RNA
* Enums can now be dynamically created in the _itemf callback,
  using RNA_enum_item(s)_add, RNA_enum_item_end. All places asking
  for enum items now need to potentially free the items.
* This callback now also gets context, this was added specifically
  for operators. This doesn't fit design well at all, needed to do
  some ugly hacks, but can't find a good solution at the moment.
* All enums must have a default list of items too, even with an
  _itemf callback, for docs and fallback in case there is no context.
* Used by MESH_OT_merge, MESH_OT_select_similar, TFM_OT_select_orientation.
* Also changes some operator properties that were enums to booleas
  (unselected, deselect), to make them consistent with other ops.
											
										 
											2009-07-10 19:56:13 +00:00
										 |  |  | 	if(type == 0) | 
					
						
							| 
									
										
										
										
											2010-10-23 10:41:28 +00:00
										 |  |  | 		retval= mesh_separate_selected(op, bmain, scene, base); | 
					
						
							| 
									
										
										
											
												RNA
* Enums can now be dynamically created in the _itemf callback,
  using RNA_enum_item(s)_add, RNA_enum_item_end. All places asking
  for enum items now need to potentially free the items.
* This callback now also gets context, this was added specifically
  for operators. This doesn't fit design well at all, needed to do
  some ugly hacks, but can't find a good solution at the moment.
* All enums must have a default list of items too, even with an
  _itemf callback, for docs and fallback in case there is no context.
* Used by MESH_OT_merge, MESH_OT_select_similar, TFM_OT_select_orientation.
* Also changes some operator properties that were enums to booleas
  (unselected, deselect), to make them consistent with other ops.
											
										 
											2009-07-10 19:56:13 +00:00
										 |  |  | 	else if(type == 1) | 
					
						
							| 
									
										
										
										
											2010-10-23 10:41:28 +00:00
										 |  |  | 		retval= mesh_separate_material(op, bmain, scene, base); | 
					
						
							| 
									
										
										
											
												RNA
* Enums can now be dynamically created in the _itemf callback,
  using RNA_enum_item(s)_add, RNA_enum_item_end. All places asking
  for enum items now need to potentially free the items.
* This callback now also gets context, this was added specifically
  for operators. This doesn't fit design well at all, needed to do
  some ugly hacks, but can't find a good solution at the moment.
* All enums must have a default list of items too, even with an
  _itemf callback, for docs and fallback in case there is no context.
* Used by MESH_OT_merge, MESH_OT_select_similar, TFM_OT_select_orientation.
* Also changes some operator properties that were enums to booleas
  (unselected, deselect), to make them consistent with other ops.
											
										 
											2009-07-10 19:56:13 +00:00
										 |  |  | 	else if(type == 2) | 
					
						
							| 
									
										
										
										
											2010-10-23 10:41:28 +00:00
										 |  |  | 		retval= mesh_separate_loose(op, bmain, scene, base); | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	    | 
					
						
							|  |  |  | 	if(retval) { | 
					
						
							| 
									
										
											  
											
												2.5
Notifiers
---------
Various fixes for wrong use of notifiers, and some new notifiers
to make things a bit more clear and consistent, with two notable
changes:
* Geometry changes are now done with NC_GEOM, rather than
  NC_OBJECT|ND_GEOM_, so an object does need to be available.
* Space data now use NC_SPACE|ND_SPACE_*, instead of data
  notifiers or even NC_WINDOW in some cases. Note that NC_SPACE
  should only be used for notifying about changes in space data,
  we don't want to go back to allqueue(REDRAW..).
Depsgraph
---------
The dependency graph now has a different flush call:
DAG_object_flush_update(scene, ob, flag)
is replaced by:
DAG_id_flush_update(id, flag)
It still works basically the same, one difference is that it now
also accepts object data (e.g. Mesh), again to avoid requiring an
Object to be available. Other ID types will simply do nothing at
the moment.
Docs
----
I made some guidelines for how/when to do which kinds of updates
and notifiers. I can't specify totally exact how to make these
decisions, but these are basically the guidelines I use. So, new
and updated docs are here:
http://wiki.blender.org/index.php/BlenderDev/Blender2.5/NotifiersUpdates
http://wiki.blender.org/index.php/BlenderDev/Blender2.5/DataNotifiers
											
										 
											2009-09-04 20:51:09 +00:00
										 |  |  | 		WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data); | 
					
						
							| 
									
										
										
										
											2010-09-17 06:52:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// XXX: new object was created, but selection wasn't actually changed
 | 
					
						
							|  |  |  | 		//      need this for outliner update without adding new ND. nazgul.
 | 
					
						
							|  |  |  | 		WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 		return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | void MESH_OT_separate(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	/* identifiers */ | 
					
						
							| 
									
										
										
										
											2009-07-08 21:31:28 +00:00
										 |  |  | 	ot->name= "Separate"; | 
					
						
							| 
									
										
										
										
											2010-02-10 21:15:44 +00:00
										 |  |  | 	ot->description= "Separate selected geometry into a new mesh"; | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	ot->idname= "MESH_OT_separate"; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->invoke= WM_menu_invoke; | 
					
						
							|  |  |  | 	ot->exec= mesh_separate_exec; | 
					
						
							|  |  |  | 	ot->poll= ED_operator_editmesh; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2009-01-30 15:01:14 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2010-01-15 22:40:33 +00:00
										 |  |  | 	ot->prop= RNA_def_enum(ot->srna, "type", prop_separate_types, 0, "Type", ""); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ******************************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* *************** UNDO ***************************** */ | 
					
						
							|  |  |  | /* new mesh undo, based on pushing editmesh data itself */ | 
					
						
							|  |  |  | /* reuses same code as for global and curve undo... unify that (ton) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* only one 'hack', to save memory it doesn't store the first push, but does a remake editmesh */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* a compressed version of editmesh data */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct EditVertC | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float no[3]; | 
					
						
							|  |  |  | 	float co[3]; | 
					
						
							|  |  |  | 	unsigned char f, h; | 
					
						
							|  |  |  | 	short bweight; | 
					
						
							|  |  |  | 	int keyindex; | 
					
						
							|  |  |  | } EditVertC; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct EditEdgeC | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int v1, v2; | 
					
						
							|  |  |  | 	unsigned char f, h, seam, sharp, pad; | 
					
						
							|  |  |  | 	short crease, bweight, fgoni; | 
					
						
							|  |  |  | } EditEdgeC; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct EditFaceC | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int v1, v2, v3, v4; | 
					
						
							| 
									
										
										
										
											2009-07-13 00:40:20 +00:00
										 |  |  | 	unsigned char flag, f, h, fgonf, pad1; | 
					
						
							|  |  |  | 	short mat_nr; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } EditFaceC; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct EditSelectionC{ | 
					
						
							|  |  |  | 	short type; | 
					
						
							|  |  |  | 	int index; | 
					
						
							|  |  |  | }EditSelectionC; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct UndoMesh { | 
					
						
							|  |  |  | 	EditVertC *verts; | 
					
						
							|  |  |  | 	EditEdgeC *edges; | 
					
						
							|  |  |  | 	EditFaceC *faces; | 
					
						
							|  |  |  | 	EditSelectionC *selected; | 
					
						
							|  |  |  | 	int totvert, totedge, totface, totsel; | 
					
						
							| 
									
										
										
										
											2010-01-26 17:39:45 +00:00
										 |  |  | 	int selectmode, shapenr; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	char retopo_mode; | 
					
						
							|  |  |  | 	CustomData vdata, edata, fdata; | 
					
						
							|  |  |  | } UndoMesh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* for callbacks */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void free_undoMesh(void *umv) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	UndoMesh *um= umv; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(um->verts) MEM_freeN(um->verts); | 
					
						
							|  |  |  | 	if(um->edges) MEM_freeN(um->edges); | 
					
						
							|  |  |  | 	if(um->faces) MEM_freeN(um->faces); | 
					
						
							|  |  |  | 	if(um->selected) MEM_freeN(um->selected); | 
					
						
							|  |  |  | // XXX	if(um->retopo_paint_data) retopo_free_paint_data(um->retopo_paint_data);
 | 
					
						
							|  |  |  | 	CustomData_free(&um->vdata, um->totvert); | 
					
						
							|  |  |  | 	CustomData_free(&um->edata, um->totedge); | 
					
						
							|  |  |  | 	CustomData_free(&um->fdata, um->totface); | 
					
						
							|  |  |  | 	MEM_freeN(um); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-01 13:15:35 +00:00
										 |  |  | static void *editMesh_to_undoMesh(void *emv) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-01 13:15:35 +00:00
										 |  |  | 	EditMesh *em= (EditMesh *)emv; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	UndoMesh *um; | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	EditSelection *ese; | 
					
						
							|  |  |  | 	EditVertC *evec=NULL; | 
					
						
							|  |  |  | 	EditEdgeC *eedc=NULL; | 
					
						
							|  |  |  | 	EditFaceC *efac=NULL; | 
					
						
							|  |  |  | 	EditSelectionC *esec=NULL; | 
					
						
							|  |  |  | 	int a; | 
					
						
							| 
									
										
										
										
											2009-01-01 13:15:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	um= MEM_callocN(sizeof(UndoMesh), "undomesh"); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-31 17:11:42 +00:00
										 |  |  | 	um->selectmode = em->selectmode; | 
					
						
							| 
									
										
										
										
											2010-01-26 17:39:45 +00:00
										 |  |  | 	um->shapenr = em->shapenr; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	for(eve=em->verts.first; eve; eve= eve->next) um->totvert++; | 
					
						
							|  |  |  | 	for(eed=em->edges.first; eed; eed= eed->next) um->totedge++; | 
					
						
							|  |  |  | 	for(efa=em->faces.first; efa; efa= efa->next) um->totface++; | 
					
						
							|  |  |  | 	for(ese=em->selected.first; ese; ese=ese->next) um->totsel++;  | 
					
						
							|  |  |  | 	/* malloc blocks */ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(um->totvert) evec= um->verts= MEM_callocN(um->totvert*sizeof(EditVertC), "allvertsC"); | 
					
						
							|  |  |  | 	if(um->totedge) eedc= um->edges= MEM_callocN(um->totedge*sizeof(EditEdgeC), "alledgesC"); | 
					
						
							|  |  |  | 	if(um->totface) efac= um->faces= MEM_callocN(um->totface*sizeof(EditFaceC), "allfacesC"); | 
					
						
							|  |  |  | 	if(um->totsel) esec= um->selected= MEM_callocN(um->totsel*sizeof(EditSelectionC), "allselections"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(um->totvert) CustomData_copy(&em->vdata, &um->vdata, CD_MASK_EDITMESH, CD_CALLOC, um->totvert); | 
					
						
							|  |  |  | 	if(um->totedge) CustomData_copy(&em->edata, &um->edata, CD_MASK_EDITMESH, CD_CALLOC, um->totedge); | 
					
						
							|  |  |  | 	if(um->totface) CustomData_copy(&em->fdata, &um->fdata, CD_MASK_EDITMESH, CD_CALLOC, um->totface); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* now copy vertices */ | 
					
						
							|  |  |  | 	a = 0; | 
					
						
							|  |  |  | 	for(eve=em->verts.first; eve; eve= eve->next, evec++, a++) { | 
					
						
							|  |  |  | 		VECCOPY(evec->co, eve->co); | 
					
						
							|  |  |  | 		VECCOPY(evec->no, eve->no); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		evec->f= eve->f; | 
					
						
							|  |  |  | 		evec->h= eve->h; | 
					
						
							|  |  |  | 		evec->keyindex= eve->keyindex; | 
					
						
							|  |  |  | 		eve->tmp.l = a; /*store index*/ | 
					
						
							|  |  |  | 		evec->bweight= (short)(eve->bweight*255.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		CustomData_from_em_block(&em->vdata, &um->vdata, eve->data, a); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* copy edges */ | 
					
						
							|  |  |  | 	a = 0; | 
					
						
							|  |  |  | 	for(eed=em->edges.first; eed; eed= eed->next, eedc++, a++)  { | 
					
						
							|  |  |  | 		eedc->v1= (int)eed->v1->tmp.l; | 
					
						
							|  |  |  | 		eedc->v2= (int)eed->v2->tmp.l; | 
					
						
							|  |  |  | 		eedc->f= eed->f; | 
					
						
							|  |  |  | 		eedc->h= eed->h; | 
					
						
							|  |  |  | 		eedc->seam= eed->seam; | 
					
						
							|  |  |  | 		eedc->sharp= eed->sharp; | 
					
						
							|  |  |  | 		eedc->crease= (short)(eed->crease*255.0); | 
					
						
							|  |  |  | 		eedc->bweight= (short)(eed->bweight*255.0); | 
					
						
							|  |  |  | 		eedc->fgoni= eed->fgoni; | 
					
						
							|  |  |  | 		eed->tmp.l = a; /*store index*/ | 
					
						
							|  |  |  | 		CustomData_from_em_block(&em->edata, &um->edata, eed->data, a); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* copy faces */ | 
					
						
							|  |  |  | 	a = 0; | 
					
						
							|  |  |  | 	for(efa=em->faces.first; efa; efa= efa->next, efac++, a++) { | 
					
						
							|  |  |  | 		efac->v1= (int)efa->v1->tmp.l; | 
					
						
							|  |  |  | 		efac->v2= (int)efa->v2->tmp.l; | 
					
						
							|  |  |  | 		efac->v3= (int)efa->v3->tmp.l; | 
					
						
							|  |  |  | 		if(efa->v4) efac->v4= (int)efa->v4->tmp.l; | 
					
						
							|  |  |  | 		else efac->v4= -1; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		efac->mat_nr= efa->mat_nr; | 
					
						
							|  |  |  | 		efac->flag= efa->flag; | 
					
						
							|  |  |  | 		efac->f= efa->f; | 
					
						
							|  |  |  | 		efac->h= efa->h; | 
					
						
							|  |  |  | 		efac->fgonf= efa->fgonf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		efa->tmp.l = a; /*store index*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		CustomData_from_em_block(&em->fdata, &um->fdata, efa->data, a); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	a = 0; | 
					
						
							|  |  |  | 	for(ese=em->selected.first; ese; ese=ese->next, esec++){ | 
					
						
							|  |  |  | 		esec->type = ese->type; | 
					
						
							|  |  |  | 		if(ese->type == EDITVERT) a = esec->index = ((EditVert*)ese->data)->tmp.l;  | 
					
						
							|  |  |  | 		else if(ese->type == EDITEDGE) a = esec->index = ((EditEdge*)ese->data)->tmp.l;  | 
					
						
							|  |  |  | 		else if(ese->type == EDITFACE) a = esec->index = ((EditFace*)ese->data)->tmp.l; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // XXX	um->retopo_paint_data= retopo_paint_data_copy(em->retopo_paint_data);
 | 
					
						
							| 
									
										
										
										
											2009-01-01 13:15:35 +00:00
										 |  |  | //	um->retopo_mode= scene->toolsettings->retopo_mode;
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	return um; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-01 13:15:35 +00:00
										 |  |  | static void undoMesh_to_editMesh(void *umv, void *emv) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-01 13:15:35 +00:00
										 |  |  | 	EditMesh *em= (EditMesh *)emv; | 
					
						
							|  |  |  | 	UndoMesh *um= (UndoMesh *)umv; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	EditVert *eve, **evar=NULL; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	EditSelection *ese; | 
					
						
							|  |  |  | 	EditVertC *evec; | 
					
						
							|  |  |  | 	EditEdgeC *eedc; | 
					
						
							|  |  |  | 	EditFaceC *efac; | 
					
						
							|  |  |  | 	EditSelectionC *esec; | 
					
						
							|  |  |  | 	int a=0; | 
					
						
							| 
									
										
										
										
											2009-01-01 13:15:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	free_editMesh(em); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* malloc blocks */ | 
					
						
							|  |  |  | 	memset(em, 0, sizeof(EditMesh)); | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	em->selectmode = um->selectmode; | 
					
						
							| 
									
										
										
										
											2010-01-26 17:39:45 +00:00
										 |  |  | 	em->shapenr = um->shapenr; | 
					
						
							| 
									
										
										
										
											2009-01-31 19:40:40 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	init_editmesh_fastmalloc(em, um->totvert, um->totedge, um->totface); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	CustomData_free(&em->vdata, 0); | 
					
						
							|  |  |  | 	CustomData_free(&em->edata, 0); | 
					
						
							|  |  |  | 	CustomData_free(&em->fdata, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	CustomData_copy(&um->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0); | 
					
						
							|  |  |  | 	CustomData_copy(&um->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0); | 
					
						
							|  |  |  | 	CustomData_copy(&um->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* now copy vertices */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(um->totvert) evar= MEM_mallocN(um->totvert*sizeof(EditVert *), "vertex ar"); | 
					
						
							|  |  |  | 	for(a=0, evec= um->verts; a<um->totvert; a++, evec++) { | 
					
						
							|  |  |  | 		eve= addvertlist(em, evec->co, NULL); | 
					
						
							|  |  |  | 		evar[a]= eve; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		VECCOPY(eve->no, evec->no); | 
					
						
							|  |  |  | 		eve->f= evec->f; | 
					
						
							|  |  |  | 		eve->h= evec->h; | 
					
						
							|  |  |  | 		eve->keyindex= evec->keyindex; | 
					
						
							|  |  |  | 		eve->bweight= ((float)evec->bweight)/255.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		CustomData_to_em_block(&um->vdata, &em->vdata, a, &eve->data); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* copy edges */ | 
					
						
							|  |  |  | 	for(a=0, eedc= um->edges; a<um->totedge; a++, eedc++) { | 
					
						
							|  |  |  | 		eed= addedgelist(em, evar[eedc->v1], evar[eedc->v2], NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		eed->f= eedc->f; | 
					
						
							|  |  |  | 		eed->h= eedc->h; | 
					
						
							|  |  |  | 		eed->seam= eedc->seam; | 
					
						
							|  |  |  | 		eed->sharp= eedc->sharp; | 
					
						
							|  |  |  | 		eed->fgoni= eedc->fgoni; | 
					
						
							|  |  |  | 		eed->crease= ((float)eedc->crease)/255.0f; | 
					
						
							|  |  |  | 		eed->bweight= ((float)eedc->bweight)/255.0f; | 
					
						
							|  |  |  | 		CustomData_to_em_block(&um->edata, &em->edata, a, &eed->data); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* copy faces */ | 
					
						
							|  |  |  | 	for(a=0, efac= um->faces; a<um->totface; a++, efac++) { | 
					
						
							|  |  |  | 		if(efac->v4 != -1) | 
					
						
							|  |  |  | 			efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], evar[efac->v4], NULL, NULL); | 
					
						
							|  |  |  | 		else  | 
					
						
							|  |  |  | 			efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], NULL, NULL ,NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		efa->mat_nr= efac->mat_nr; | 
					
						
							|  |  |  | 		efa->flag= efac->flag; | 
					
						
							|  |  |  | 		efa->f= efac->f; | 
					
						
							|  |  |  | 		efa->h= efac->h; | 
					
						
							|  |  |  | 		efa->fgonf= efac->fgonf; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		CustomData_to_em_block(&um->fdata, &em->fdata, a, &efa->data); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	end_editmesh_fastmalloc(); | 
					
						
							|  |  |  | 	if(evar) MEM_freeN(evar); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 	em->totvert = um->totvert; | 
					
						
							|  |  |  | 	em->totedge = um->totedge; | 
					
						
							|  |  |  | 	em->totface = um->totface; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	/*restore stored editselections*/ | 
					
						
							|  |  |  | 	if(um->totsel){ | 
					
						
							|  |  |  | 		EM_init_index_arrays(em, 1,1,1); | 
					
						
							|  |  |  | 		for(a=0, esec= um->selected; a<um->totsel; a++, esec++){ | 
					
						
							|  |  |  | 			ese = MEM_callocN(sizeof(EditSelection), "Edit Selection"); | 
					
						
							|  |  |  | 			ese->type = esec->type; | 
					
						
							|  |  |  | 			if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(esec->index); else | 
					
						
							|  |  |  | 			if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(esec->index); else | 
					
						
							|  |  |  | 			if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(esec->index); | 
					
						
							|  |  |  | 			BLI_addtail(&(em->selected),ese); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		EM_free_index_arrays(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-25 22:38:07 +00:00
										 |  |  | 	/* restore total selections */ | 
					
						
							|  |  |  | 	EM_nvertices_selected(em); | 
					
						
							|  |  |  | 	EM_nedges_selected(em); | 
					
						
							|  |  |  | 	EM_nfaces_selected(em); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | // XXX	retopo_free_paint();
 | 
					
						
							|  |  |  | //	em->retopo_paint_data= retopo_paint_data_copy(um->retopo_paint_data);
 | 
					
						
							|  |  |  | //	scene->toolsettings->retopo_mode= um->retopo_mode;
 | 
					
						
							|  |  |  | //	if(scene->toolsettings->retopo_mode) {
 | 
					
						
							|  |  |  | // XXX		if(G.vd->depths) G.vd->depths->damaged= 1;
 | 
					
						
							|  |  |  | //		retopo_queue_updates(G.vd);
 | 
					
						
							|  |  |  | //		retopo_paint_view_update(G.vd);
 | 
					
						
							|  |  |  | //	}
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-01 13:15:35 +00:00
										 |  |  | static void *getEditMesh(bContext *C) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *obedit= CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2009-01-23 14:43:25 +00:00
										 |  |  | 	if(obedit && obedit->type==OB_MESH) { | 
					
						
							| 
									
										
										
										
											2009-01-01 13:15:35 +00:00
										 |  |  | 		Mesh *me= obedit->data; | 
					
						
							|  |  |  | 		return me->edit_mesh; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* and this is all the undo system needs to know */ | 
					
						
							| 
									
										
										
										
											2010-11-17 09:45:45 +00:00
										 |  |  | void undo_push_mesh(bContext *C, const char *name) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-01 13:15:35 +00:00
										 |  |  | 	undo_editmode_push(C, name, getEditMesh, free_undoMesh, undoMesh_to_editMesh, editMesh_to_undoMesh, NULL); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* *************** END UNDO *************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static EditVert **g_em_vert_array = NULL; | 
					
						
							|  |  |  | static EditEdge **g_em_edge_array = NULL; | 
					
						
							|  |  |  | static EditFace **g_em_face_array = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_init_index_arrays(EditMesh *em, int forVert, int forEdge, int forFace) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	EditVert *eve; | 
					
						
							|  |  |  | 	EditEdge *eed; | 
					
						
							|  |  |  | 	EditFace *efa; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (forVert) { | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 		em->totvert= BLI_countlist(&em->verts); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-08 15:34:41 +00:00
										 |  |  | 		if(em->totvert) { | 
					
						
							|  |  |  | 			g_em_vert_array = MEM_mallocN(sizeof(*g_em_vert_array)*em->totvert, "em_v_arr"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for (i=0,eve=em->verts.first; eve; i++,eve=eve->next) | 
					
						
							|  |  |  | 				g_em_vert_array[i] = eve; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (forEdge) { | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 		em->totedge= BLI_countlist(&em->edges); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-08 15:34:41 +00:00
										 |  |  | 		if(em->totedge) { | 
					
						
							|  |  |  | 			g_em_edge_array = MEM_mallocN(sizeof(*g_em_edge_array)*em->totedge, "em_e_arr"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for (i=0,eed=em->edges.first; eed; i++,eed=eed->next) | 
					
						
							|  |  |  | 				g_em_edge_array[i] = eed; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (forFace) { | 
					
						
							| 
									
										
										
										
											2009-01-15 15:01:39 +00:00
										 |  |  | 		em->totface= BLI_countlist(&em->faces); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-08 15:34:41 +00:00
										 |  |  | 		if(em->totface) { | 
					
						
							|  |  |  | 			g_em_face_array = MEM_mallocN(sizeof(*g_em_face_array)*em->totface, "em_f_arr"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for (i=0,efa=em->faces.first; efa; i++,efa=efa->next) | 
					
						
							|  |  |  | 				g_em_face_array[i] = efa; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EM_free_index_arrays(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (g_em_vert_array) MEM_freeN(g_em_vert_array); | 
					
						
							|  |  |  | 	if (g_em_edge_array) MEM_freeN(g_em_edge_array); | 
					
						
							|  |  |  | 	if (g_em_face_array) MEM_freeN(g_em_face_array); | 
					
						
							|  |  |  | 	g_em_vert_array = NULL; | 
					
						
							|  |  |  | 	g_em_edge_array = NULL; | 
					
						
							|  |  |  | 	g_em_face_array = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EditVert *EM_get_vert_for_index(int index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return g_em_vert_array?g_em_vert_array[index]:NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EditEdge *EM_get_edge_for_index(int index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return g_em_edge_array?g_em_edge_array[index]:NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EditFace *EM_get_face_for_index(int index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return g_em_face_array?g_em_face_array[index]:NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* can we edit UV's for this mesh?*/ | 
					
						
							|  |  |  | int EM_texFaceCheck(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* some of these checks could be a touch overkill */ | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	if (	(em) && | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			(em->faces.first) && | 
					
						
							|  |  |  | 			(CustomData_has_layer(&em->fdata, CD_MTFACE))) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* can we edit colors for this mesh?*/ | 
					
						
							|  |  |  | int EM_vertColorCheck(EditMesh *em) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* some of these checks could be a touch overkill */ | 
					
						
							| 
									
										
										
										
											2009-01-02 19:10:35 +00:00
										 |  |  | 	if (	(em) && | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 			(em->faces.first) && | 
					
						
							|  |  |  | 			(CustomData_has_layer(&em->fdata, CD_MCOL))) | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 16:03:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | void em_setup_viewcontext(bContext *C, ViewContext *vc) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-13 15:18:41 +00:00
										 |  |  | 	view3d_set_viewcontext(C, vc); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-31 17:11:42 +00:00
										 |  |  | 	if(vc->obedit) { | 
					
						
							|  |  |  | 		Mesh *me= vc->obedit->data; | 
					
						
							|  |  |  | 		vc->em= me->edit_mesh; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-12-30 16:03:29 +00:00
										 |  |  | } |