| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * $Id:  | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. The Blender | 
					
						
							|  |  |  |  * Foundation also sells licenses for use in proprietary software under | 
					
						
							|  |  |  |  * the Blender License.  See http://www.blender.org/BL/ for information
 | 
					
						
							|  |  |  |  * about this. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is: all of this file. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): Martin Poirier | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL/BL DUAL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  |   | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <math.h>
 | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "PIL_time.h"
 | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_object_types.h"
 | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | #include "DNA_scene_types.h"
 | 
					
						
							| 
									
										
										
										
											2006-11-07 11:24:11 +00:00
										 |  |  | #include "DNA_space_types.h"
 | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | #include "DNA_userdef_types.h"
 | 
					
						
							|  |  |  | #include "DNA_view3d_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_arithb.h"
 | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | #include "BLI_editVert.h"
 | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "BDR_drawobject.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | #include "editmesh.h"
 | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | #include "BIF_editsima.h"
 | 
					
						
							|  |  |  | #include "BIF_gl.h"
 | 
					
						
							|  |  |  | #include "BIF_glutil.h"
 | 
					
						
							|  |  |  | #include "BIF_mywindow.h"
 | 
					
						
							|  |  |  | #include "BIF_resources.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_global.h"
 | 
					
						
							|  |  |  | #include "BKE_utildefines.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "transform.h"
 | 
					
						
							|  |  |  | #include "mydevice.h"		/* for KEY defines	*/
 | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | #include "blendef.h" /* for selection modes */
 | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /********************* PROTOTYPES ***********************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void setSnappingCallback(TransInfo *t); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | void ApplySnapTranslation(TransInfo *t, float vec[3]); | 
					
						
							|  |  |  | void ApplySnapRotation(TransInfo *t, float *vec); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CalcSnapGrid(TransInfo *t, float *vec); | 
					
						
							|  |  |  | void CalcSnapGeometry(TransInfo *t, float *vec); | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | void TargetSnapMedian(TransInfo *t); | 
					
						
							|  |  |  | void TargetSnapCenter(TransInfo *t); | 
					
						
							|  |  |  | void TargetSnapClosest(TransInfo *t); | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | float RotationBetween(TransInfo *t, float p1[3], float p2[3]); | 
					
						
							|  |  |  | float TranslationBetween(TransInfo *t, float p1[3], float p2[3]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | /****************** IMPLEMENTATIONS *********************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void drawSnapping(TransInfo *t) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-12-20 19:47:12 +00:00
										 |  |  | 	if ((t->tsnap.status & (SNAP_ON|POINT_INIT|TARGET_INIT)) == (SNAP_ON|POINT_INIT|TARGET_INIT) && | 
					
						
							|  |  |  | 		(G.qual & LR_CTRLKEY)) { | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 		float unitmat[4][4]; | 
					
						
							| 
									
										
										
										
											2006-12-21 20:45:57 +00:00
										 |  |  | 		float size; | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 		char col[4]; | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2006-12-21 20:45:57 +00:00
										 |  |  | 		size = get_drawsize(G.vd); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		size *= 0.5f * BIF_GetThemeValuef(TH_VERTEX_SIZE); | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 		BIF_GetThemeColor3ubv(TH_TRANSFORM, col); | 
					
						
							|  |  |  | 		glColor4ub(col[0], col[1], col[2], 128); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		glPushMatrix(); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		glTranslatef(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		/* sets view screen aligned */ | 
					
						
							|  |  |  | 		glRotatef( -360.0f*saacos(G.vd->viewquat[0])/(float)M_PI, G.vd->viewquat[1], G.vd->viewquat[2], G.vd->viewquat[3]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Mat4One(unitmat); | 
					
						
							| 
									
										
										
										
											2006-12-21 20:45:57 +00:00
										 |  |  | 		drawcircball(GL_LINE_LOOP, unitmat[3], size, unitmat); | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 		glPopMatrix(); | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int  handleSnapping(TransInfo *t, int event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int status = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2006-12-20 19:47:12 +00:00
										 |  |  | 	// Put keyhandling code here
 | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	return status; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void applySnapping(TransInfo *t, float *vec) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-12-20 19:47:12 +00:00
										 |  |  | 	if ((t->tsnap.status & SNAP_ON) && | 
					
						
							|  |  |  | 		(G.qual & LR_CTRLKEY)) | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 		double current = PIL_check_seconds_timer(); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		// Time base quirky code to go around findnearest slowness
 | 
					
						
							|  |  |  | 		if (current - t->tsnap.last  >= 0.25) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			t->tsnap.calcSnap(t, vec); | 
					
						
							|  |  |  | 			t->tsnap.targetSnap(t); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 			t->tsnap.last = current; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if ((t->tsnap.status & (POINT_INIT|TARGET_INIT)) == (POINT_INIT|TARGET_INIT)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			t->tsnap.applySnap(t, vec); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void resetSnapping(TransInfo *t) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	t->tsnap.status = 0; | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 	t->tsnap.modePoint = 0; | 
					
						
							|  |  |  | 	t->tsnap.modeTarget = 0; | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 	t->tsnap.last = 0; | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 	t->tsnap.applySnap = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void initSnapping(TransInfo *t) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 	resetSnapping(t); | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2007-01-30 15:48:09 +00:00
										 |  |  | 	if (t->spacetype == SPACE_VIEW3D) { // Only 3D view (not UV)
 | 
					
						
							|  |  |  | 		setSnappingCallback(t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (t->tsnap.applySnap != NULL && // A snapping function actually exist
 | 
					
						
							|  |  |  | 			(G.obedit != NULL && G.obedit->type==OB_MESH) && // Temporary limited to edit mode meshes
 | 
					
						
							|  |  |  | 			(G.vd->flag2 & V3D_TRANSFORM_SNAP) && // Only if the snap flag is on
 | 
					
						
							|  |  |  | 			(t->flag & T_PROP_EDIT) == 0) // No PET, obviously
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			t->tsnap.status |= SNAP_ON; | 
					
						
							|  |  |  | 			t->tsnap.modePoint = SNAP_GEO; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{	 | 
					
						
							|  |  |  | 			/* Grid if snap is not possible */ | 
					
						
							|  |  |  | 			t->tsnap.modePoint = SNAP_GRID; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2007-01-30 15:48:09 +00:00
										 |  |  | 		/* Always grid outside of 3D view */ | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 		t->tsnap.modePoint = SNAP_GRID; | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void setSnappingCallback(TransInfo *t) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 	t->tsnap.calcSnap = CalcSnapGeometry; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-07 19:33:00 +00:00
										 |  |  | 	switch(G.vd->snap_target) | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		case V3D_SNAP_TARGET_CLOSEST: | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 			t->tsnap.modeTarget = SNAP_CLOSEST; | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 			t->tsnap.targetSnap = TargetSnapClosest; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case V3D_SNAP_TARGET_CENTER: | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 			t->tsnap.modeTarget = SNAP_CENTER; | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 			t->tsnap.targetSnap = TargetSnapCenter; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case V3D_SNAP_TARGET_MEDIAN: | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 			t->tsnap.modeTarget = SNAP_MEDIAN; | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 			t->tsnap.targetSnap = TargetSnapMedian; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 	switch (t->mode) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	case TFM_TRANSLATION: | 
					
						
							|  |  |  | 		t->tsnap.applySnap = ApplySnapTranslation; | 
					
						
							|  |  |  | 		t->tsnap.distance = TranslationBetween; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case TFM_ROTATION: | 
					
						
							|  |  |  | 		t->tsnap.applySnap = ApplySnapRotation; | 
					
						
							|  |  |  | 		t->tsnap.distance = RotationBetween; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		// Can't do TARGET_CENTER with rotation, use TARGET_MEDIAN instead
 | 
					
						
							| 
									
										
										
										
											2007-01-07 19:33:00 +00:00
										 |  |  | 		if (G.vd->snap_target == V3D_SNAP_TARGET_CENTER) { | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 			t->tsnap.modeTarget = SNAP_MEDIAN; | 
					
						
							|  |  |  | 			t->tsnap.targetSnap = TargetSnapMedian; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		t->tsnap.applySnap = NULL; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | /********************** APPLY **************************/ | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | void ApplySnapTranslation(TransInfo *t, float vec[3]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	VecSubf(vec, t->tsnap.snapPoint, t->tsnap.snapTarget); | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | void ApplySnapRotation(TransInfo *t, float *vec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (t->tsnap.modeTarget == SNAP_CLOSEST) { | 
					
						
							|  |  |  | 		*vec = t->tsnap.dist; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		*vec = RotationBetween(t, t->tsnap.snapTarget, t->tsnap.snapPoint); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************** DISTANCE **************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float TranslationBetween(TransInfo *t, float p1[3], float p2[3]) | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 	return VecLenf(p1, p2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | float RotationBetween(TransInfo *t, float p1[3], float p2[3]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float angle, start[3], end[3], center[3]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	VECCOPY(center, t->center);	 | 
					
						
							|  |  |  | 	if(t->flag & (T_EDIT|T_POSE)) { | 
					
						
							|  |  |  | 		Object *ob= G.obedit?G.obedit:t->poseobj; | 
					
						
							|  |  |  | 		Mat4MulVecfl(ob->obmat, center); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	VecSubf(start, p1, center); | 
					
						
							|  |  |  | 	VecSubf(end, p2, center);	 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	// Angle around a constraint axis (error prone, will need debug)
 | 
					
						
							|  |  |  | 	if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { | 
					
						
							|  |  |  | 		float axis[3], tmp[3]; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		t->con.applyRot(t, NULL, axis); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Projf(tmp, end, axis); | 
					
						
							|  |  |  | 		VecSubf(end, end, tmp); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		Projf(tmp, start, axis); | 
					
						
							|  |  |  | 		VecSubf(start, start, tmp); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		Normalise(end); | 
					
						
							|  |  |  | 		Normalise(start); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		Crossf(tmp, start, end); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if (Inpf(tmp, axis) < 0.0) | 
					
						
							|  |  |  | 			angle = -acos(Inpf(start, end)); | 
					
						
							|  |  |  | 		else	 | 
					
						
							|  |  |  | 			angle = acos(Inpf(start, end)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		float mtx[3][3]; | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2006-12-23 01:55:13 +00:00
										 |  |  | 		Mat3CpyMat4(mtx, t->viewmat); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 		Mat3MulVecfl(mtx, end); | 
					
						
							|  |  |  | 		Mat3MulVecfl(mtx, start); | 
					
						
							| 
									
										
										
										
											2006-12-23 01:55:13 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		angle = atan2(start[1],start[0]) - atan2(end[1],end[0]); | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (angle > M_PI) { | 
					
						
							| 
									
										
										
										
											2006-12-23 01:55:13 +00:00
										 |  |  | 		angle = angle - 2 * M_PI; | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (angle < -(M_PI)) { | 
					
						
							|  |  |  | 		angle = 2 * M_PI + angle; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return angle; | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************** CALC **************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CalcSnapGrid(TransInfo *t, float *vec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	snapGridAction(t, t->tsnap.snapPoint, BIG_GEARS); | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | void CalcSnapGeometry(TransInfo *t, float *vec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (G.obedit != NULL && G.obedit->type==OB_MESH) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 		/*if (G.scene->selectmode & B_SEL_VERT)*/ | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 			EditVert *nearest=NULL; | 
					
						
							| 
									
										
										
										
											2006-12-28 22:42:58 +00:00
										 |  |  | 			int dist = 40; // Use a user defined value here
 | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 			// use findnearestverts in vert mode, others in other modes
 | 
					
						
							| 
									
										
										
										
											2006-12-28 22:42:58 +00:00
										 |  |  | 			nearest = findnearestvert(&dist, SELECT, 1); | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 			 | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 			if (nearest != NULL) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				VECCOPY(t->tsnap.snapPoint, nearest->co); | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				Mat4MulVecfl(G.obedit->obmat, t->tsnap.snapPoint); | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				t->tsnap.status |=  POINT_INIT; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				t->tsnap.status &= ~POINT_INIT; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 		/*
 | 
					
						
							|  |  |  | 		if (G.scene->selectmode & B_SEL_EDGE) | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 			EditEdge *nearest=NULL; | 
					
						
							|  |  |  | 			int dist = 50; // Use a user defined value here
 | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			// use findnearestverts in vert mode, others in other modes
 | 
					
						
							|  |  |  | 			nearest = findnearestedge(&dist); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			if (nearest != NULL) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				VecAddf(t->tsnap.snapPoint, nearest->v1->co, nearest->v2->co); | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				VecMulf(t->tsnap.snapPoint, 0.5f);  | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				Mat4MulVecfl(G.obedit->obmat, t->tsnap.snapPoint); | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				t->tsnap.status |=  POINT_INIT; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				t->tsnap.status &= ~POINT_INIT; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 		*/ | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************** TARGET **************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TargetSnapCenter(TransInfo *t) | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 	// Only need to calculate once
 | 
					
						
							|  |  |  | 	if ((t->tsnap.status & TARGET_INIT) == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		VECCOPY(t->tsnap.snapTarget, t->center);	 | 
					
						
							|  |  |  | 		if(t->flag & (T_EDIT|T_POSE)) { | 
					
						
							|  |  |  | 			Object *ob= G.obedit?G.obedit:t->poseobj; | 
					
						
							|  |  |  | 			Mat4MulVecfl(ob->obmat, t->tsnap.snapTarget); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		t->tsnap.status |= TARGET_INIT;		 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TargetSnapMedian(TransInfo *t) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// Only need to calculate once
 | 
					
						
							|  |  |  | 	if ((t->tsnap.status & TARGET_INIT) == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		TransData *td = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t->tsnap.snapTarget[0] = 0; | 
					
						
							|  |  |  | 		t->tsnap.snapTarget[1] = 0; | 
					
						
							|  |  |  | 		t->tsnap.snapTarget[2] = 0; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for (td = t->data; td != NULL && td->flag & TD_SELECTED ; td++) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			VecAddf(t->tsnap.snapTarget, t->tsnap.snapTarget, td->iloc); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		VecMulf(t->tsnap.snapTarget, 1.0 / t->total); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if(t->flag & (T_EDIT|T_POSE)) { | 
					
						
							|  |  |  | 			Object *ob= G.obedit?G.obedit:t->poseobj; | 
					
						
							|  |  |  | 			Mat4MulVecfl(ob->obmat, t->tsnap.snapTarget); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		t->tsnap.status |= TARGET_INIT;		 | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TargetSnapClosest(TransInfo *t) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-12-19 22:25:07 +00:00
										 |  |  | 	// Only valid if a snap point has been selected
 | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 	if (t->tsnap.status & POINT_INIT) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		TransData *closest = NULL, *td = NULL; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		// Base case, only one selected item
 | 
					
						
							|  |  |  | 		if (t->total == 1) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2006-12-28 22:42:58 +00:00
										 |  |  | 			VECCOPY(t->tsnap.snapTarget, t->data[0].iloc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(t->flag & (T_EDIT|T_POSE)) { | 
					
						
							|  |  |  | 				Object *ob= G.obedit?G.obedit:t->poseobj; | 
					
						
							|  |  |  | 				Mat4MulVecfl(ob->obmat, t->tsnap.snapTarget); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		// More than one selected item
 | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 			for (td = t->data; td != NULL && td->flag & TD_SELECTED ; td++) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 				float loc[3]; | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 				float dist; | 
					
						
							|  |  |  | 				 | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 				VECCOPY(loc, td->iloc); | 
					
						
							| 
									
										
										
										
											2006-12-28 22:42:58 +00:00
										 |  |  | 				 | 
					
						
							|  |  |  | 				if(t->flag & (T_EDIT|T_POSE)) { | 
					
						
							|  |  |  | 					Object *ob= G.obedit?G.obedit:t->poseobj; | 
					
						
							|  |  |  | 					Mat4MulVecfl(ob->obmat, loc); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 				 | 
					
						
							| 
									
										
										
										
											2006-12-23 01:55:13 +00:00
										 |  |  | 				dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 				 | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 				if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist)) | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 					VECCOPY(t->tsnap.snapTarget, loc); | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 					closest = td; | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 					t->tsnap.dist = dist;  | 
					
						
							| 
									
										
										
										
											2006-12-18 23:48:32 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		t->tsnap.status |= TARGET_INIT; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*================================================================*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], GearsType action); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void snapGridAction(TransInfo *t, float *val, GearsType action) { | 
					
						
							|  |  |  | 	float fac[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fac[NO_GEARS]    = t->snap[0]; | 
					
						
							|  |  |  | 	fac[BIG_GEARS]   = t->snap[1]; | 
					
						
							|  |  |  | 	fac[SMALL_GEARS] = t->snap[2]; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	applyGrid(t, val, t->idx_max, fac, action); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void snapGrid(TransInfo *t, float *val) { | 
					
						
							|  |  |  | 	int invert; | 
					
						
							|  |  |  | 	GearsType action; | 
					
						
							| 
									
										
										
										
											2007-01-30 15:48:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-20 19:47:12 +00:00
										 |  |  | 	// Only do something if using Snap to Grid
 | 
					
						
							| 
									
										
										
										
											2006-12-23 00:52:34 +00:00
										 |  |  | 	if (t->tsnap.modePoint != SNAP_GRID) | 
					
						
							| 
									
										
										
										
											2006-12-20 19:47:12 +00:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-03 19:54:27 +00:00
										 |  |  | 	if(t->mode==TFM_ROTATION || t->mode==TFM_WARP || t->mode==TFM_TILT || t->mode==TFM_TRACKBALL || t->mode==TFM_BONE_ROLL) | 
					
						
							| 
									
										
										
										
											2006-10-25 23:57:00 +00:00
										 |  |  | 		invert = U.flag & USER_AUTOROTGRID; | 
					
						
							|  |  |  | 	else if(t->mode==TFM_RESIZE || t->mode==TFM_SHEAR || t->mode==TFM_BONESIZE || t->mode==TFM_SHRINKFATTEN || t->mode==TFM_CURVE_SHRINKFATTEN) | 
					
						
							|  |  |  | 		invert = U.flag & USER_AUTOSIZEGRID; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		invert = U.flag & USER_AUTOGRABGRID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(invert) { | 
					
						
							|  |  |  | 		action = (G.qual & LR_CTRLKEY) ? NO_GEARS: BIG_GEARS; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		action = (G.qual & LR_CTRLKEY) ? BIG_GEARS : NO_GEARS; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (action == BIG_GEARS && (G.qual & LR_SHIFTKEY)) { | 
					
						
							|  |  |  | 		action = SMALL_GEARS; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	snapGridAction(t, val, action); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], GearsType action) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	float asp[3] = {1.0f, 1.0f, 1.0f}; // TODO: Remove hard coded limit here (3)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Early bailing out if no need to snap
 | 
					
						
							|  |  |  | 	if (fac[action] == 0.0) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* evil hack - snapping needs to be adapted for image aspect ratio */ | 
					
						
							|  |  |  | 	if((t->spacetype==SPACE_IMAGE) && (t->mode==TFM_TRANSLATION)) { | 
					
						
							|  |  |  | 		transform_aspect_ratio_tface_uv(asp, asp+1); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i=0; i<=max_index; i++) { | 
					
						
							|  |  |  | 		val[i]= fac[action]*asp[i]*(float)floor(val[i]/(fac[action]*asp[i]) +.5); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |