| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * ***** BEGIN GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-14 15:00:47 +10:00
										 |  |  | /** \file blender/editors/util/ed_transverts.c
 | 
					
						
							| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  |  *  \ingroup edutil | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_armature_types.h"
 | 
					
						
							|  |  |  | #include "DNA_curve_types.h"
 | 
					
						
							|  |  |  | #include "DNA_lattice_types.h"
 | 
					
						
							|  |  |  | #include "DNA_meta_types.h"
 | 
					
						
							|  |  |  | #include "DNA_scene_types.h"
 | 
					
						
							|  |  |  | #include "DNA_object_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_blenlib.h"
 | 
					
						
							|  |  |  | #include "BLI_utildefines.h"
 | 
					
						
							|  |  |  | #include "BLI_math.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_curve.h"
 | 
					
						
							|  |  |  | #include "BKE_depsgraph.h"
 | 
					
						
							|  |  |  | #include "BKE_lattice.h"
 | 
					
						
							|  |  |  | #include "BKE_editmesh.h"
 | 
					
						
							|  |  |  | #include "BKE_DerivedMesh.h"
 | 
					
						
							| 
									
										
										
										
											2014-03-31 08:23:40 +11:00
										 |  |  | #include "BKE_context.h"
 | 
					
						
							| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "ED_armature.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "ED_transverts.h"  /* own include */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* copied from editobject.c, now uses (almost) proper depgraph */ | 
					
						
							|  |  |  | void ED_transverts_update_obedit(TransVertStore *tvs, Object *obedit) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-03-31 14:55:55 +11:00
										 |  |  | 	const int mode = tvs->mode; | 
					
						
							| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  | 	BLI_assert(ED_transverts_check_obedit(obedit) == true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DAG_id_tag_update(obedit->data, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (obedit->type == OB_MESH) { | 
					
						
							|  |  |  | 		BMEditMesh *em = BKE_editmesh_from_object(obedit); | 
					
						
							|  |  |  | 		BM_mesh_normals_update(em->bm); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { | 
					
						
							|  |  |  | 		Curve *cu = obedit->data; | 
					
						
							|  |  |  | 		ListBase *nurbs = BKE_curve_editNurbs_get(cu); | 
					
						
							|  |  |  | 		Nurb *nu = nurbs->first; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		while (nu) { | 
					
						
							|  |  |  | 			/* keep handles' vectors unchanged */ | 
					
						
							| 
									
										
										
										
											2014-03-31 14:55:55 +11:00
										 |  |  | 			if (nu->bezt && (mode & TM_SKIP_HANDLES)) { | 
					
						
							| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  | 				int a = nu->pntsu; | 
					
						
							|  |  |  | 				TransVert *tv = tvs->transverts; | 
					
						
							|  |  |  | 				BezTriple *bezt = nu->bezt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				while (a--) { | 
					
						
							| 
									
										
										
										
											2014-03-31 14:55:55 +11:00
										 |  |  | 					if (bezt->hide == 0) { | 
					
						
							|  |  |  | 						bool skip_handle = false; | 
					
						
							|  |  |  | 						if (bezt->f2 & SELECT) | 
					
						
							|  |  |  | 							skip_handle = (mode & TM_SKIP_HANDLES) != 0; | 
					
						
							| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-31 14:55:55 +11:00
										 |  |  | 						if ((bezt->f1 & SELECT) && !skip_handle) { | 
					
						
							|  |  |  | 							BLI_assert(tv->loc == bezt->vec[0]); | 
					
						
							|  |  |  | 							tv++; | 
					
						
							| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-31 14:55:55 +11:00
										 |  |  | 						if (bezt->f2 & SELECT) { | 
					
						
							|  |  |  | 							float v[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							if (((bezt->f1 & SELECT) && !skip_handle) == 0) { | 
					
						
							|  |  |  | 								sub_v3_v3v3(v, tv->loc, tv->oldloc); | 
					
						
							|  |  |  | 								add_v3_v3(bezt->vec[0], v); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							if (((bezt->f3 & SELECT) && !skip_handle) == 0) { | 
					
						
							|  |  |  | 								sub_v3_v3v3(v, tv->loc, tv->oldloc); | 
					
						
							|  |  |  | 								add_v3_v3(bezt->vec[2], v); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							BLI_assert(tv->loc == bezt->vec[1]); | 
					
						
							|  |  |  | 							tv++; | 
					
						
							| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-31 14:55:55 +11:00
										 |  |  | 						if ((bezt->f3 & SELECT) && !skip_handle) { | 
					
						
							|  |  |  | 							BLI_assert(tv->loc == bezt->vec[2]); | 
					
						
							|  |  |  | 							tv++; | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					bezt++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			BKE_nurb_test2D(nu); | 
					
						
							|  |  |  | 			BKE_nurb_handles_test(nu, true); /* test for bezier too */ | 
					
						
							|  |  |  | 			nu = nu->next; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (obedit->type == OB_ARMATURE) { | 
					
						
							|  |  |  | 		bArmature *arm = obedit->data; | 
					
						
							|  |  |  | 		EditBone *ebo; | 
					
						
							|  |  |  | 		TransVert *tv = tvs->transverts; | 
					
						
							|  |  |  | 		int a = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Ensure all bone tails are correctly adjusted */ | 
					
						
							|  |  |  | 		for (ebo = arm->edbo->first; ebo; ebo = ebo->next) { | 
					
						
							|  |  |  | 			/* adjust tip if both ends selected */ | 
					
						
							|  |  |  | 			if ((ebo->flag & BONE_ROOTSEL) && (ebo->flag & BONE_TIPSEL)) { | 
					
						
							|  |  |  | 				if (tv) { | 
					
						
							|  |  |  | 					float diffvec[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					sub_v3_v3v3(diffvec, tv->loc, tv->oldloc); | 
					
						
							|  |  |  | 					add_v3_v3(ebo->tail, diffvec); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					a++; | 
					
						
							|  |  |  | 					if (a < tvs->transverts_tot) tv++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Ensure all bones are correctly adjusted */ | 
					
						
							|  |  |  | 		for (ebo = arm->edbo->first; ebo; ebo = ebo->next) { | 
					
						
							|  |  |  | 			if ((ebo->flag & BONE_CONNECTED) && ebo->parent) { | 
					
						
							|  |  |  | 				/* If this bone has a parent tip that has been moved */ | 
					
						
							|  |  |  | 				if (ebo->parent->flag & BONE_TIPSEL) { | 
					
						
							|  |  |  | 					copy_v3_v3(ebo->head, ebo->parent->tail); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				/* If this bone has a parent tip that has NOT been moved */ | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					copy_v3_v3(ebo->parent->tail, ebo->head); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (arm->flag & ARM_MIRROR_EDIT) | 
					
						
							|  |  |  | 			transform_armature_mirror_update(obedit); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (obedit->type == OB_LATTICE) { | 
					
						
							|  |  |  | 		Lattice *lt = obedit->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (lt->editlatt->latt->flag & LT_OUTSIDE) | 
					
						
							|  |  |  | 			outside_lattice(lt->editlatt->latt); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void set_mapped_co(void *vuserdata, int index, const float co[3], | 
					
						
							|  |  |  |                           const float UNUSED(no[3]), const short UNUSED(no_s[3])) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	void **userdata = vuserdata; | 
					
						
							|  |  |  | 	BMEditMesh *em = userdata[0]; | 
					
						
							|  |  |  | 	TransVert *tv = userdata[1]; | 
					
						
							|  |  |  | 	BMVert *eve = BM_vert_at_index(em->bm, index); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (BM_elem_index_get(eve) != TM_INDEX_SKIP) { | 
					
						
							|  |  |  | 		tv = &tv[BM_elem_index_get(eve)]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* be clever, get the closest vertex to the original,
 | 
					
						
							|  |  |  | 		 * behaves most logically when the mirror modifier is used for eg [#33051]*/ | 
					
						
							|  |  |  | 		if ((tv->flag & TX_VERT_USE_MAPLOC) == 0) { | 
					
						
							|  |  |  | 			/* first time */ | 
					
						
							|  |  |  | 			copy_v3_v3(tv->maploc, co); | 
					
						
							|  |  |  | 			tv->flag |= TX_VERT_USE_MAPLOC; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			/* find best location to use */ | 
					
						
							|  |  |  | 			if (len_squared_v3v3(eve->co, co) < len_squared_v3v3(eve->co, tv->maploc)) { | 
					
						
							|  |  |  | 				copy_v3_v3(tv->maploc, co); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ED_transverts_check_obedit(Object *obedit) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return (ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ED_transverts_create_from_obedit(TransVertStore *tvs, Object *obedit, const int mode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Nurb *nu; | 
					
						
							|  |  |  | 	BezTriple *bezt; | 
					
						
							|  |  |  | 	BPoint *bp; | 
					
						
							|  |  |  | 	TransVert *tv = NULL; | 
					
						
							|  |  |  | 	MetaElem *ml; | 
					
						
							|  |  |  | 	BMVert *eve; | 
					
						
							|  |  |  | 	EditBone *ebo; | 
					
						
							|  |  |  | 	int a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tvs->transverts_tot = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (obedit->type == OB_MESH) { | 
					
						
							|  |  |  | 		BMEditMesh *em = BKE_editmesh_from_object(obedit); | 
					
						
							|  |  |  | 		BMesh *bm = em->bm; | 
					
						
							|  |  |  | 		BMIter iter; | 
					
						
							|  |  |  | 		void *userdata[2] = {em, NULL}; | 
					
						
							|  |  |  | 		/*int proptrans = 0; */ /*UNUSED*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* abuses vertex index all over, set, just set dirty here,
 | 
					
						
							|  |  |  | 		 * perhaps this could use its own array instead? - campbell */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* transform now requires awareness for select mode, so we tag the f1 flags in verts */ | 
					
						
							|  |  |  | 		tvs->transverts_tot = 0; | 
					
						
							|  |  |  | 		if (em->selectmode & SCE_SELECT_VERTEX) { | 
					
						
							|  |  |  | 			BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { | 
					
						
							|  |  |  | 				if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT)) { | 
					
						
							|  |  |  | 					BM_elem_index_set(eve, TM_INDEX_ON); /* set_dirty! */ | 
					
						
							|  |  |  | 					tvs->transverts_tot++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					BM_elem_index_set(eve, TM_INDEX_OFF);  /* set_dirty! */ | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (em->selectmode & SCE_SELECT_EDGE) { | 
					
						
							|  |  |  | 			BMEdge *eed; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { | 
					
						
							|  |  |  | 				BM_elem_index_set(eve, TM_INDEX_OFF);  /* set_dirty! */ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { | 
					
						
							|  |  |  | 				if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_SELECT)) { | 
					
						
							|  |  |  | 					BM_elem_index_set(eed->v1, TM_INDEX_ON);  /* set_dirty! */ | 
					
						
							|  |  |  | 					BM_elem_index_set(eed->v2, TM_INDEX_ON);  /* set_dirty! */ | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { | 
					
						
							|  |  |  | 				if (BM_elem_index_get(eve) == TM_INDEX_ON) tvs->transverts_tot++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			BMFace *efa; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { | 
					
						
							|  |  |  | 				BM_elem_index_set(eve, TM_INDEX_OFF);  /* set_dirty! */ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { | 
					
						
							|  |  |  | 				if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | 
					
						
							|  |  |  | 					BMIter liter; | 
					
						
							|  |  |  | 					BMLoop *l; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { | 
					
						
							|  |  |  | 						BM_elem_index_set(l->v, TM_INDEX_ON); /* set_dirty! */ | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { | 
					
						
							|  |  |  | 				if (BM_elem_index_get(eve) == TM_INDEX_ON) tvs->transverts_tot++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		/* for any of the 3 loops above which all dirty the indices */ | 
					
						
							|  |  |  | 		bm->elem_index_dirty |= BM_VERT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* and now make transverts */ | 
					
						
							|  |  |  | 		if (tvs->transverts_tot) { | 
					
						
							|  |  |  | 			tv = tvs->transverts = MEM_callocN(tvs->transverts_tot * sizeof(TransVert), __func__); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			a = 0; | 
					
						
							|  |  |  | 			BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { | 
					
						
							|  |  |  | 				if (BM_elem_index_get(eve)) { | 
					
						
							|  |  |  | 					BM_elem_index_set(eve, a);  /* set_dirty! */ | 
					
						
							|  |  |  | 					copy_v3_v3(tv->oldloc, eve->co); | 
					
						
							|  |  |  | 					tv->loc = eve->co; | 
					
						
							|  |  |  | 					tv->flag = (BM_elem_index_get(eve) == TM_INDEX_ON) ? SELECT : 0; | 
					
						
							| 
									
										
										
										
											2014-03-31 14:55:55 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					if (mode & TM_CALC_NORMALS) { | 
					
						
							|  |  |  | 						tv->flag |= TX_VERT_USE_NORMAL; | 
					
						
							|  |  |  | 						copy_v3_v3(tv->normal, eve->no); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  | 					tv++; | 
					
						
							|  |  |  | 					a++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					BM_elem_index_set(eve, TM_INDEX_SKIP);  /* set_dirty! */ | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			/* set dirty already, above */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			userdata[1] = tvs->transverts; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (tvs->transverts && em->derivedCage) { | 
					
						
							|  |  |  | 			BM_mesh_elem_table_ensure(bm, BM_VERT); | 
					
						
							|  |  |  | 			em->derivedCage->foreachMappedVert(em->derivedCage, set_mapped_co, userdata, DM_FOREACH_NOP); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (obedit->type == OB_ARMATURE) { | 
					
						
							|  |  |  | 		bArmature *arm = obedit->data; | 
					
						
							|  |  |  | 		int totmalloc = BLI_countlist(arm->edbo); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		totmalloc *= 2;  /* probably overkill but bones can have 2 trans verts each */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tv = tvs->transverts = MEM_callocN(totmalloc * sizeof(TransVert), __func__); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (ebo = arm->edbo->first; ebo; ebo = ebo->next) { | 
					
						
							|  |  |  | 			if (ebo->layer & arm->layer) { | 
					
						
							|  |  |  | 				short tipsel = (ebo->flag & BONE_TIPSEL); | 
					
						
							|  |  |  | 				short rootsel = (ebo->flag & BONE_ROOTSEL); | 
					
						
							|  |  |  | 				short rootok = (!(ebo->parent && (ebo->flag & BONE_CONNECTED) && (ebo->parent->flag & BONE_TIPSEL))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if ((tipsel && rootsel) || (rootsel)) { | 
					
						
							|  |  |  | 					/* Don't add the tip (unless mode & TM_ALL_JOINTS, for getting all joints),
 | 
					
						
							|  |  |  | 					 * otherwise we get zero-length bones as tips will snap to the same | 
					
						
							|  |  |  | 					 * location as heads. | 
					
						
							|  |  |  | 					 */ | 
					
						
							|  |  |  | 					if (rootok) { | 
					
						
							|  |  |  | 						copy_v3_v3(tv->oldloc, ebo->head); | 
					
						
							|  |  |  | 						tv->loc = ebo->head; | 
					
						
							|  |  |  | 						tv->flag = SELECT; | 
					
						
							|  |  |  | 						tv++; | 
					
						
							|  |  |  | 						tvs->transverts_tot++; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if ((mode & TM_ALL_JOINTS) && (tipsel)) { | 
					
						
							|  |  |  | 						copy_v3_v3(tv->oldloc, ebo->tail); | 
					
						
							|  |  |  | 						tv->loc = ebo->tail; | 
					
						
							|  |  |  | 						tv->flag = SELECT; | 
					
						
							|  |  |  | 						tv++; | 
					
						
							|  |  |  | 						tvs->transverts_tot++; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else if (tipsel) { | 
					
						
							|  |  |  | 					copy_v3_v3(tv->oldloc, ebo->tail); | 
					
						
							|  |  |  | 					tv->loc = ebo->tail; | 
					
						
							|  |  |  | 					tv->flag = SELECT; | 
					
						
							|  |  |  | 					tv++; | 
					
						
							|  |  |  | 					tvs->transverts_tot++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { | 
					
						
							|  |  |  | 		Curve *cu = obedit->data; | 
					
						
							|  |  |  | 		int totmalloc = 0; | 
					
						
							|  |  |  | 		ListBase *nurbs = BKE_curve_editNurbs_get(cu); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (nu = nurbs->first; nu; nu = nu->next) { | 
					
						
							|  |  |  | 			if (nu->type == CU_BEZIER) | 
					
						
							|  |  |  | 				totmalloc += 3 * nu->pntsu; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				totmalloc += nu->pntsu * nu->pntsv; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		tv = tvs->transverts = MEM_callocN(totmalloc * sizeof(TransVert), __func__); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		nu = nurbs->first; | 
					
						
							|  |  |  | 		while (nu) { | 
					
						
							|  |  |  | 			if (nu->type == CU_BEZIER) { | 
					
						
							|  |  |  | 				a = nu->pntsu; | 
					
						
							|  |  |  | 				bezt = nu->bezt; | 
					
						
							|  |  |  | 				while (a--) { | 
					
						
							|  |  |  | 					if (bezt->hide == 0) { | 
					
						
							| 
									
										
										
										
											2014-03-31 14:55:55 +11:00
										 |  |  | 						bool skip_handle = false; | 
					
						
							| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  | 						if (bezt->f2 & SELECT) | 
					
						
							| 
									
										
										
										
											2014-03-31 14:55:55 +11:00
										 |  |  | 							skip_handle = (mode & TM_SKIP_HANDLES) != 0; | 
					
						
							| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						if ((bezt->f1 & SELECT) && !skip_handle) { | 
					
						
							|  |  |  | 							copy_v3_v3(tv->oldloc, bezt->vec[0]); | 
					
						
							|  |  |  | 							tv->loc = bezt->vec[0]; | 
					
						
							|  |  |  | 							tv->flag = bezt->f1 & SELECT; | 
					
						
							| 
									
										
										
										
											2014-03-31 14:55:55 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							if (mode & TM_CALC_NORMALS) { | 
					
						
							|  |  |  | 								tv->flag |= TX_VERT_USE_NORMAL; | 
					
						
							|  |  |  | 								BKE_nurb_bezt_calc_plane(nu, bezt, tv->normal); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  | 							tv++; | 
					
						
							|  |  |  | 							tvs->transverts_tot++; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						if (bezt->f2 & SELECT) { | 
					
						
							|  |  |  | 							copy_v3_v3(tv->oldloc, bezt->vec[1]); | 
					
						
							|  |  |  | 							tv->loc = bezt->vec[1]; | 
					
						
							|  |  |  | 							tv->flag = bezt->f2 & SELECT; | 
					
						
							| 
									
										
										
										
											2014-03-31 14:55:55 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							if (mode & TM_CALC_NORMALS) { | 
					
						
							|  |  |  | 								tv->flag |= TX_VERT_USE_NORMAL; | 
					
						
							|  |  |  | 								BKE_nurb_bezt_calc_plane(nu, bezt, tv->normal); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  | 							tv++; | 
					
						
							|  |  |  | 							tvs->transverts_tot++; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						if ((bezt->f3 & SELECT) && !skip_handle) { | 
					
						
							|  |  |  | 							copy_v3_v3(tv->oldloc, bezt->vec[2]); | 
					
						
							|  |  |  | 							tv->loc = bezt->vec[2]; | 
					
						
							|  |  |  | 							tv->flag = bezt->f3 & SELECT; | 
					
						
							| 
									
										
										
										
											2014-03-31 14:55:55 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							if (mode & TM_CALC_NORMALS) { | 
					
						
							|  |  |  | 								tv->flag |= TX_VERT_USE_NORMAL; | 
					
						
							|  |  |  | 								BKE_nurb_bezt_calc_plane(nu, bezt, tv->normal); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  | 							tv++; | 
					
						
							|  |  |  | 							tvs->transverts_tot++; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					bezt++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				a = nu->pntsu * nu->pntsv; | 
					
						
							|  |  |  | 				bp = nu->bp; | 
					
						
							|  |  |  | 				while (a--) { | 
					
						
							|  |  |  | 					if (bp->hide == 0) { | 
					
						
							|  |  |  | 						if (bp->f1 & SELECT) { | 
					
						
							|  |  |  | 							copy_v3_v3(tv->oldloc, bp->vec); | 
					
						
							|  |  |  | 							tv->loc = bp->vec; | 
					
						
							|  |  |  | 							tv->flag = bp->f1 & SELECT; | 
					
						
							|  |  |  | 							tv++; | 
					
						
							|  |  |  | 							tvs->transverts_tot++; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					bp++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			nu = nu->next; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (obedit->type == OB_MBALL) { | 
					
						
							|  |  |  | 		MetaBall *mb = obedit->data; | 
					
						
							|  |  |  | 		int totmalloc = BLI_countlist(mb->editelems); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tv = tvs->transverts = MEM_callocN(totmalloc * sizeof(TransVert), __func__); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ml = mb->editelems->first; | 
					
						
							|  |  |  | 		while (ml) { | 
					
						
							|  |  |  | 			if (ml->flag & SELECT) { | 
					
						
							|  |  |  | 				tv->loc = &ml->x; | 
					
						
							|  |  |  | 				copy_v3_v3(tv->oldloc, tv->loc); | 
					
						
							|  |  |  | 				tv->flag = SELECT; | 
					
						
							|  |  |  | 				tv++; | 
					
						
							|  |  |  | 				tvs->transverts_tot++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			ml = ml->next; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (obedit->type == OB_LATTICE) { | 
					
						
							|  |  |  | 		Lattice *lt = obedit->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		bp = lt->editlatt->latt->def; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tv = tvs->transverts = MEM_callocN(a * sizeof(TransVert), __func__); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		while (a--) { | 
					
						
							|  |  |  | 			if (bp->f1 & SELECT) { | 
					
						
							|  |  |  | 				if (bp->hide == 0) { | 
					
						
							|  |  |  | 					copy_v3_v3(tv->oldloc, bp->vec); | 
					
						
							|  |  |  | 					tv->loc = bp->vec; | 
					
						
							|  |  |  | 					tv->flag = bp->f1 & SELECT; | 
					
						
							|  |  |  | 					tv++; | 
					
						
							|  |  |  | 					tvs->transverts_tot++; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			bp++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!tvs->transverts_tot && tvs->transverts) { | 
					
						
							|  |  |  | 		/* prevent memory leak. happens for curves/latticies due to */ | 
					
						
							|  |  |  | 		/* difficult condition of adding points to trans data */ | 
					
						
							|  |  |  | 		MEM_freeN(tvs->transverts); | 
					
						
							|  |  |  | 		tvs->transverts = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-03-31 14:55:55 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	tvs->mode = mode; | 
					
						
							| 
									
										
										
										
											2013-11-20 02:40:29 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ED_transverts_free(TransVertStore *tvs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	MEM_SAFE_FREE(tvs->transverts); | 
					
						
							|  |  |  | 	tvs->transverts_tot = 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-03-31 08:23:40 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | int ED_transverts_poll(bContext *C) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *obedit = CTX_data_edit_object(C); | 
					
						
							|  |  |  | 	if (obedit) { | 
					
						
							|  |  |  | 		if (ED_transverts_check_obedit(obedit)) { | 
					
						
							|  |  |  | 			return true; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } |