2006-10-25 23:57:00 +00:00
|
|
|
/**
|
|
|
|
* $Id:
|
|
|
|
*
|
2008-04-16 22:40:48 +00:00
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
2006-10-25 23:57:00 +00:00
|
|
|
*
|
|
|
|
* 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
|
2008-04-16 22:40:48 +00:00
|
|
|
* of the License, or (at your option) any later version.
|
2006-10-25 23:57:00 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*
|
2008-04-16 22:40:48 +00:00
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
2006-10-25 23:57:00 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#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"
|
2007-02-28 17:16:17 +00:00
|
|
|
#include "DNA_meshdata_types.h" // Temporary, for snapping to other unselected meshes
|
2006-11-07 11:24:11 +00:00
|
|
|
#include "DNA_space_types.h"
|
2007-03-24 20:57:15 +00:00
|
|
|
#include "DNA_screen_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"
|
2007-02-28 17:16:17 +00:00
|
|
|
#include "BIF_screen.h"
|
2007-09-25 07:42:55 +00:00
|
|
|
#include "BIF_editsima.h"
|
|
|
|
#include "BIF_drawimage.h"
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
#include "BIF_editmesh.h"
|
2006-10-25 23:57:00 +00:00
|
|
|
|
|
|
|
#include "BKE_global.h"
|
|
|
|
#include "BKE_utildefines.h"
|
2007-03-24 20:57:15 +00:00
|
|
|
#include "BKE_DerivedMesh.h"
|
|
|
|
#include "BKE_object.h"
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
#include "BKE_anim.h" /* for duplis */
|
2006-10-25 23:57:00 +00:00
|
|
|
|
2007-02-28 17:16:17 +00:00
|
|
|
#include "BSE_view.h"
|
|
|
|
|
2007-03-24 20:57:15 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
2006-10-25 23:57:00 +00:00
|
|
|
#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);
|
2008-02-03 00:42:00 +00:00
|
|
|
void ApplySnapResize(TransInfo *t, float *vec);
|
2006-12-18 23:48:32 +00:00
|
|
|
|
|
|
|
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);
|
2008-01-20 22:43:48 +00:00
|
|
|
void TargetSnapActive(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]);
|
2008-02-03 00:42:00 +00:00
|
|
|
float ResizeBetween(TransInfo *t, float p1[3], float p2[3]);
|
2006-12-23 00:52:34 +00:00
|
|
|
|
2008-01-20 22:43:48 +00:00
|
|
|
/* Modes */
|
|
|
|
#define NOT_SELECTED 0
|
|
|
|
#define NOT_ACTIVE 1
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
int snapObjects(int *dist, float *loc, float *no, int mode);
|
|
|
|
|
2007-02-28 17:16:17 +00:00
|
|
|
|
2006-10-25 23:57:00 +00:00
|
|
|
/****************** IMPLEMENTATIONS *********************/
|
|
|
|
|
2008-01-13 22:20:18 +00:00
|
|
|
int BIF_snappingSupported(void)
|
|
|
|
{
|
|
|
|
int status = 0;
|
|
|
|
|
|
|
|
if (G.obedit == NULL || G.obedit->type==OB_MESH) /* only support object or mesh */
|
|
|
|
{
|
|
|
|
status = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2006-10-25 23:57:00 +00:00
|
|
|
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-21 20:45:57 +00:00
|
|
|
|
2007-09-25 07:42:55 +00:00
|
|
|
char col[4];
|
2006-12-19 22:25:07 +00:00
|
|
|
BIF_GetThemeColor3ubv(TH_TRANSFORM, col);
|
|
|
|
glColor4ub(col[0], col[1], col[2], 128);
|
|
|
|
|
2007-09-25 07:42:55 +00:00
|
|
|
if (t->spacetype==SPACE_VIEW3D) {
|
|
|
|
float unitmat[4][4];
|
|
|
|
float size;
|
|
|
|
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
|
2008-02-21 14:28:20 +00:00
|
|
|
size = get_drawsize(G.vd, t->tsnap.snapPoint);
|
2007-09-25 07:42:55 +00:00
|
|
|
|
|
|
|
size *= 0.5f * BIF_GetThemeValuef(TH_VERTEX_SIZE);
|
|
|
|
|
|
|
|
glPushMatrix();
|
|
|
|
|
|
|
|
glTranslatef(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]);
|
|
|
|
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
/* draw normal if needed */
|
|
|
|
if (usingSnappingNormal(t) && validSnappingNormal(t))
|
|
|
|
{
|
|
|
|
glBegin(GL_LINES);
|
|
|
|
glVertex3f(0, 0, 0);
|
|
|
|
glVertex3f(t->tsnap.snapNormal[0], t->tsnap.snapNormal[1], t->tsnap.snapNormal[2]);
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
|
2007-09-25 07:42:55 +00:00
|
|
|
/* 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);
|
|
|
|
drawcircball(GL_LINE_LOOP, unitmat[3], size, unitmat);
|
|
|
|
|
|
|
|
glPopMatrix();
|
|
|
|
|
|
|
|
if(G.vd->zbuf) glEnable(GL_DEPTH_TEST);
|
|
|
|
} else if (t->spacetype==SPACE_IMAGE) {
|
|
|
|
/*This will not draw, and Im nor sure why - campbell */
|
|
|
|
|
|
|
|
/*
|
|
|
|
float xuser_asp, yuser_asp;
|
|
|
|
int wi, hi;
|
|
|
|
float w, h;
|
|
|
|
|
|
|
|
calc_image_view(G.sima, 'f'); // float
|
|
|
|
myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
aspect_sima(G.sima, &xuser_asp, &yuser_asp);
|
|
|
|
|
|
|
|
transform_width_height_tface_uv(&wi, &hi);
|
|
|
|
w = (((float)wi)/256.0f)*G.sima->zoom * xuser_asp;
|
|
|
|
h = (((float)hi)/256.0f)*G.sima->zoom * yuser_asp;
|
|
|
|
|
|
|
|
cpack(0xFFFFFF);
|
|
|
|
glTranslatef(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], 0.0f);
|
|
|
|
|
|
|
|
//glRectf(0,0,1,1);
|
|
|
|
|
|
|
|
setlinestyle(0);
|
|
|
|
cpack(0x0);
|
|
|
|
fdrawline(-0.020/w, 0, -0.1/w, 0);
|
|
|
|
fdrawline(0.1/w, 0, .020/w, 0);
|
|
|
|
fdrawline(0, -0.020/h, 0, -0.1/h);
|
|
|
|
fdrawline(0, 0.1/h, 0, 0.020/h);
|
|
|
|
|
|
|
|
glTranslatef(-t->tsnap.snapPoint[0], -t->tsnap.snapPoint[1], 0.0f);
|
|
|
|
setlinestyle(0);
|
|
|
|
*/
|
|
|
|
|
|
|
|
}
|
2006-10-25 23:57:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int handleSnapping(TransInfo *t, int event)
|
|
|
|
{
|
|
|
|
int status = 0;
|
|
|
|
|
2008-01-13 22:20:18 +00:00
|
|
|
if (BIF_snappingSupported() && event == TABKEY && (G.qual & LR_SHIFTKEY) == LR_SHIFTKEY)
|
|
|
|
{
|
|
|
|
/* toggle snap and reinit */
|
|
|
|
G.scene->snap_flag ^= SCE_SNAP;
|
|
|
|
initSnapping(t);
|
|
|
|
status = 1;
|
|
|
|
}
|
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
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
/* !TODO! add exception for object mode, no need to slow it down then */
|
|
|
|
if (current - t->tsnap.last >= 0.1)
|
2006-12-18 23:48:32 +00:00
|
|
|
{
|
|
|
|
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;
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
|
|
|
|
t->tsnap.snapNormal[0] = 0;
|
|
|
|
t->tsnap.snapNormal[1] = 0;
|
|
|
|
t->tsnap.snapNormal[2] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int usingSnappingNormal(TransInfo *t)
|
|
|
|
{
|
|
|
|
if (G.scene->snap_flag & SCE_SNAP_ROTATE)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int validSnappingNormal(TransInfo *t)
|
|
|
|
{
|
|
|
|
if ((t->tsnap.status & (POINT_INIT|TARGET_INIT)) == (POINT_INIT|TARGET_INIT))
|
|
|
|
{
|
|
|
|
if (Inpf(t->tsnap.snapNormal, t->tsnap.snapNormal) > 0)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2006-10-25 23:57:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void initSnapping(TransInfo *t)
|
|
|
|
{
|
2006-12-18 23:48:32 +00:00
|
|
|
resetSnapping(t);
|
2006-10-25 23:57:00 +00:00
|
|
|
|
2008-04-08 13:40:05 +00:00
|
|
|
if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && // Only 3D view or UV
|
|
|
|
(t->flag & T_CAMERA) == 0) { // Not with camera selected
|
2007-01-30 15:48:09 +00:00
|
|
|
setSnappingCallback(t);
|
|
|
|
|
2008-01-13 22:20:18 +00:00
|
|
|
/* Edit mode */
|
2007-01-30 15:48:09 +00:00
|
|
|
if (t->tsnap.applySnap != NULL && // A snapping function actually exist
|
2008-01-13 22:20:18 +00:00
|
|
|
(G.scene->snap_flag & SCE_SNAP) && // Only if the snap flag is on
|
2007-01-30 15:48:09 +00:00
|
|
|
(G.obedit != NULL && G.obedit->type==OB_MESH) && // Temporary limited to edit mode meshes
|
2008-01-13 22:20:18 +00:00
|
|
|
((t->flag & T_PROP_EDIT) == 0) ) // No PET, obviously
|
|
|
|
{
|
|
|
|
t->tsnap.status |= SNAP_ON;
|
|
|
|
t->tsnap.modePoint = SNAP_GEO;
|
|
|
|
}
|
|
|
|
/* Object mode */
|
|
|
|
else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
|
2007-09-25 04:11:57 +00:00
|
|
|
(G.scene->snap_flag & SCE_SNAP) && // Only if the snap flag is on
|
2008-01-13 22:20:18 +00:00
|
|
|
(G.obedit == NULL) ) // Object Mode
|
2007-01-30 15:48:09 +00:00
|
|
|
{
|
|
|
|
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-09-25 04:11:57 +00:00
|
|
|
switch(G.scene->snap_target)
|
2006-12-19 22:25:07 +00:00
|
|
|
{
|
2007-09-25 04:11:57 +00:00
|
|
|
case SCE_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;
|
2007-09-25 04:11:57 +00:00
|
|
|
case SCE_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;
|
2007-09-25 04:11:57 +00:00
|
|
|
case SCE_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;
|
2008-01-20 22:43:48 +00:00
|
|
|
case SCE_SNAP_TARGET_ACTIVE:
|
|
|
|
t->tsnap.modeTarget = SNAP_ACTIVE;
|
|
|
|
t->tsnap.targetSnap = TargetSnapActive;
|
|
|
|
break;
|
|
|
|
|
2006-12-19 22:25:07 +00:00
|
|
|
}
|
|
|
|
|
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-09-25 04:11:57 +00:00
|
|
|
if (G.scene->snap_target == SCE_SNAP_TARGET_CENTER) {
|
2006-12-23 00:52:34 +00:00
|
|
|
t->tsnap.modeTarget = SNAP_MEDIAN;
|
|
|
|
t->tsnap.targetSnap = TargetSnapMedian;
|
|
|
|
}
|
|
|
|
break;
|
2008-02-03 00:42:00 +00:00
|
|
|
case TFM_RESIZE:
|
|
|
|
t->tsnap.applySnap = ApplySnapResize;
|
|
|
|
t->tsnap.distance = ResizeBetween;
|
|
|
|
|
|
|
|
// Can't do TARGET_CENTER with resize, use TARGET_MEDIAN instead
|
|
|
|
if (G.scene->snap_target == SCE_SNAP_TARGET_CENTER) {
|
|
|
|
t->tsnap.modeTarget = SNAP_MEDIAN;
|
|
|
|
t->tsnap.targetSnap = TargetSnapMedian;
|
|
|
|
}
|
|
|
|
break;
|
2006-12-23 00:52:34 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-03 00:42:00 +00:00
|
|
|
void ApplySnapResize(TransInfo *t, float vec[3])
|
|
|
|
{
|
|
|
|
if (t->tsnap.modeTarget == SNAP_CLOSEST) {
|
|
|
|
vec[0] = vec[1] = vec[2] = t->tsnap.dist;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
vec[0] = vec[1] = vec[2] = ResizeBetween(t, t->tsnap.snapTarget, t->tsnap.snapPoint);
|
|
|
|
}
|
|
|
|
}
|
2006-12-23 00:52:34 +00:00
|
|
|
|
|
|
|
/********************** 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];
|
|
|
|
|
2008-06-22 20:40:13 +00:00
|
|
|
t->con.applyRot(t, NULL, axis, NULL);
|
2006-12-23 00:52:34 +00:00
|
|
|
|
|
|
|
Projf(tmp, end, axis);
|
|
|
|
VecSubf(end, end, tmp);
|
|
|
|
|
|
|
|
Projf(tmp, start, axis);
|
|
|
|
VecSubf(start, start, tmp);
|
|
|
|
|
2007-04-04 13:18:41 +00:00
|
|
|
Normalize(end);
|
|
|
|
Normalize(start);
|
2006-12-23 00:52:34 +00:00
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2008-02-03 00:42:00 +00:00
|
|
|
float ResizeBetween(TransInfo *t, float p1[3], float p2[3])
|
|
|
|
{
|
|
|
|
float d1[3], d2[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(d1, p1, center);
|
|
|
|
VecSubf(d2, p2, center);
|
|
|
|
|
|
|
|
if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
|
2008-02-03 17:08:54 +00:00
|
|
|
Mat3MulVecfl(t->con.pmtx, d1);
|
|
|
|
Mat3MulVecfl(t->con.pmtx, d2);
|
2008-02-03 00:42:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return VecLength(d2) / VecLength(d1);
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
2008-01-20 22:43:48 +00:00
|
|
|
/* Object mode */
|
2008-01-13 22:20:18 +00:00
|
|
|
if (G.obedit == NULL)
|
|
|
|
{
|
|
|
|
if (t->spacetype == SPACE_VIEW3D)
|
|
|
|
{
|
|
|
|
float vec[3];
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
float no[3];
|
2008-01-13 22:20:18 +00:00
|
|
|
int found = 0;
|
|
|
|
int dist = 40; // Use a user defined value here
|
|
|
|
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
found = snapObjects(&dist, vec, no, NOT_SELECTED);
|
2008-01-13 22:20:18 +00:00
|
|
|
if (found == 1)
|
|
|
|
{
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
float tangent[3];
|
|
|
|
|
|
|
|
VecSubf(tangent, vec, t->tsnap.snapPoint);
|
|
|
|
tangent[2] = 0;
|
|
|
|
|
|
|
|
if (Inpf(tangent, tangent) > 0)
|
|
|
|
{
|
|
|
|
VECCOPY(t->tsnap.snapTangent, tangent);
|
|
|
|
}
|
2008-01-13 22:20:18 +00:00
|
|
|
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
VECCOPY(t->tsnap.snapPoint, vec);
|
|
|
|
VECCOPY(t->tsnap.snapNormal, no);
|
|
|
|
|
2008-01-13 22:20:18 +00:00
|
|
|
t->tsnap.status |= POINT_INIT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
t->tsnap.status &= ~POINT_INIT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-01-20 22:43:48 +00:00
|
|
|
/* Mesh edit mode */
|
2008-01-13 22:20:18 +00:00
|
|
|
else if (G.obedit != NULL && G.obedit->type==OB_MESH)
|
2006-12-18 23:48:32 +00:00
|
|
|
{
|
2007-09-25 07:42:55 +00:00
|
|
|
if (t->spacetype == SPACE_VIEW3D)
|
2006-12-18 23:48:32 +00:00
|
|
|
{
|
2007-02-28 17:16:17 +00:00
|
|
|
float vec[3];
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
float no[3];
|
2007-02-28 17:16:17 +00:00
|
|
|
int found = 0;
|
2006-12-28 22:42:58 +00:00
|
|
|
int dist = 40; // Use a user defined value here
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
|
|
|
|
found = snapObjects(&dist, vec, no, NOT_ACTIVE);
|
2007-02-28 17:16:17 +00:00
|
|
|
if (found == 1)
|
2006-12-19 22:25:07 +00:00
|
|
|
{
|
2007-02-28 17:16:17 +00:00
|
|
|
VECCOPY(t->tsnap.snapPoint, vec);
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
VECCOPY(t->tsnap.snapNormal, no);
|
2006-12-19 22:25:07 +00:00
|
|
|
|
|
|
|
t->tsnap.status |= POINT_INIT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
t->tsnap.status &= ~POINT_INIT;
|
|
|
|
}
|
2006-12-18 23:48:32 +00:00
|
|
|
}
|
2007-09-25 07:42:55 +00:00
|
|
|
else if (t->spacetype == SPACE_IMAGE)
|
2007-09-26 06:46:08 +00:00
|
|
|
{ /* same as above but for UV's */
|
2007-09-25 07:42:55 +00:00
|
|
|
MTFace *nearesttf=NULL;
|
2008-02-27 19:35:27 +00:00
|
|
|
float aspx, aspy;
|
2007-09-26 06:46:08 +00:00
|
|
|
int face_corner;
|
2007-09-25 07:42:55 +00:00
|
|
|
|
|
|
|
find_nearest_uv(&nearesttf, NULL, NULL, &face_corner);
|
2008-02-27 19:35:27 +00:00
|
|
|
|
2007-09-25 07:42:55 +00:00
|
|
|
if (nearesttf != NULL)
|
|
|
|
{
|
|
|
|
VECCOPY2D(t->tsnap.snapPoint, nearesttf->uv[face_corner]);
|
2008-02-27 19:35:27 +00:00
|
|
|
|
|
|
|
transform_aspect_ratio_tface_uv(&aspx, &aspy);
|
|
|
|
t->tsnap.snapPoint[0] *= aspx;
|
|
|
|
t->tsnap.snapPoint[1] *= aspy;
|
|
|
|
|
2007-09-25 07:42:55 +00:00
|
|
|
//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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************** 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-20 22:43:48 +00:00
|
|
|
void TargetSnapActive(TransInfo *t)
|
|
|
|
{
|
|
|
|
// Only need to calculate once
|
|
|
|
if ((t->tsnap.status & TARGET_INIT) == 0)
|
|
|
|
{
|
|
|
|
TransData *td = NULL;
|
|
|
|
TransData *active_td = NULL;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++)
|
|
|
|
{
|
|
|
|
if (td->flag & TD_ACTIVE)
|
|
|
|
{
|
|
|
|
active_td = td;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (active_td)
|
|
|
|
{
|
|
|
|
VECCOPY(t->tsnap.snapTarget, active_td->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;
|
|
|
|
}
|
|
|
|
/* No active, default to median */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
t->tsnap.modeTarget = SNAP_MEDIAN;
|
|
|
|
t->tsnap.targetSnap = TargetSnapMedian;
|
|
|
|
TargetSnapMedian(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-19 22:25:07 +00:00
|
|
|
void TargetSnapMedian(TransInfo *t)
|
|
|
|
{
|
|
|
|
// Only need to calculate once
|
|
|
|
if ((t->tsnap.status & TARGET_INIT) == 0)
|
|
|
|
{
|
|
|
|
TransData *td = NULL;
|
2007-12-13 21:10:00 +00:00
|
|
|
int i;
|
2006-12-19 22:25:07 +00:00
|
|
|
|
|
|
|
t->tsnap.snapTarget[0] = 0;
|
|
|
|
t->tsnap.snapTarget[1] = 0;
|
|
|
|
t->tsnap.snapTarget[2] = 0;
|
|
|
|
|
2007-12-13 21:10:00 +00:00
|
|
|
for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++)
|
2006-12-19 22:25:07 +00:00
|
|
|
{
|
2008-01-13 22:20:18 +00:00
|
|
|
VecAddf(t->tsnap.snapTarget, t->tsnap.snapTarget, td->center);
|
2006-12-19 22:25:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2008-01-13 22:20:18 +00:00
|
|
|
/* Object mode */
|
|
|
|
if (t->flag & T_OBJECT)
|
2006-12-18 23:48:32 +00:00
|
|
|
{
|
2008-01-13 22:20:18 +00:00
|
|
|
int i;
|
|
|
|
for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++)
|
|
|
|
{
|
|
|
|
struct BoundBox *bb = object_get_boundbox(td->ob);
|
|
|
|
|
2008-01-13 22:57:36 +00:00
|
|
|
/* use boundbox if possible */
|
|
|
|
if (bb)
|
|
|
|
{
|
|
|
|
int j;
|
|
|
|
|
|
|
|
for (j = 0; j < 8; j++) {
|
|
|
|
float loc[3];
|
|
|
|
float dist;
|
|
|
|
|
|
|
|
VECCOPY(loc, bb->vec[j]);
|
|
|
|
Mat4MulVecfl(td->ext->obmat, loc);
|
|
|
|
|
|
|
|
dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
|
|
|
|
|
|
|
|
if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist))
|
|
|
|
{
|
|
|
|
VECCOPY(t->tsnap.snapTarget, loc);
|
|
|
|
closest = td;
|
|
|
|
t->tsnap.dist = dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* use element center otherwise */
|
|
|
|
else
|
|
|
|
{
|
2008-01-13 22:20:18 +00:00
|
|
|
float loc[3];
|
|
|
|
float dist;
|
|
|
|
|
2008-01-13 22:57:36 +00:00
|
|
|
VECCOPY(loc, td->center);
|
2008-01-13 22:20:18 +00:00
|
|
|
|
|
|
|
dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
|
|
|
|
|
|
|
|
if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist))
|
|
|
|
{
|
|
|
|
VECCOPY(t->tsnap.snapTarget, loc);
|
|
|
|
closest = td;
|
|
|
|
t->tsnap.dist = dist;
|
|
|
|
}
|
|
|
|
}
|
2006-12-28 22:42:58 +00:00
|
|
|
}
|
2006-12-18 23:48:32 +00:00
|
|
|
}
|
|
|
|
else
|
2008-01-13 22:20:18 +00:00
|
|
|
{
|
2007-12-13 21:10:00 +00:00
|
|
|
int i;
|
|
|
|
for(td = t->data, i = 0 ; i < t->total && td->flag & TD_SELECTED ; i++, td++)
|
2006-12-18 23:48:32 +00:00
|
|
|
{
|
2006-12-23 00:52:34 +00:00
|
|
|
float loc[3];
|
2006-12-18 23:48:32 +00:00
|
|
|
float dist;
|
|
|
|
|
2008-01-13 22:20:18 +00:00
|
|
|
VECCOPY(loc, td->center);
|
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
|
|
|
}
|
2007-02-28 17:16:17 +00:00
|
|
|
/*================================================================*/
|
|
|
|
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
int snapDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth, short EditMesh)
|
|
|
|
{
|
|
|
|
int retval = 0;
|
|
|
|
int totvert = dm->getNumVerts(dm);
|
|
|
|
int totface = dm->getNumFaces(dm);
|
|
|
|
|
|
|
|
if (totvert > 0) {
|
|
|
|
float imat[4][4];
|
|
|
|
float timat[3][3]; /* transpose inverse matrix for normals */
|
|
|
|
float ray_start_local[3], ray_normal_local[3];
|
|
|
|
int test = 1;
|
|
|
|
|
|
|
|
Mat4Invert(imat, obmat);
|
|
|
|
|
|
|
|
Mat3CpyMat4(timat, imat);
|
|
|
|
Mat3Transp(timat);
|
|
|
|
|
|
|
|
VECCOPY(ray_start_local, ray_start);
|
|
|
|
VECCOPY(ray_normal_local, ray_normal);
|
|
|
|
|
|
|
|
Mat4MulVecfl(imat, ray_start_local);
|
|
|
|
Mat4Mul3Vecfl(imat, ray_normal_local);
|
|
|
|
|
|
|
|
|
2008-06-22 23:21:29 +00:00
|
|
|
/* If number of vert is more than an arbitrary limit,
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
* test against boundbox first
|
|
|
|
* */
|
|
|
|
if (totface > 16) {
|
|
|
|
struct BoundBox *bb = object_get_boundbox(ob);
|
|
|
|
test = ray_hit_boundbox(bb, ray_start_local, ray_normal_local);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (test == 1) {
|
|
|
|
|
2008-06-22 23:21:29 +00:00
|
|
|
switch (G.scene->snap_mode)
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
{
|
2008-06-22 23:21:29 +00:00
|
|
|
case SCE_SNAP_MODE_FACE:
|
|
|
|
{
|
|
|
|
MVert *verts = dm->getVertArray(dm);
|
|
|
|
MFace *faces = dm->getFaceArray(dm);
|
|
|
|
int *index_array = NULL;
|
|
|
|
int index = 0;
|
|
|
|
int i;
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
|
2008-06-22 23:21:29 +00:00
|
|
|
if (EditMesh)
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
{
|
2008-06-22 23:21:29 +00:00
|
|
|
index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX);
|
|
|
|
EM_init_index_arrays(0, 0, 1);
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
}
|
2008-06-22 23:21:29 +00:00
|
|
|
|
|
|
|
for( i = 0; i < totface; i++) {
|
|
|
|
EditFace *efa = NULL;
|
|
|
|
MFace *f = faces + i;
|
|
|
|
float lambda;
|
|
|
|
int result;
|
2007-03-24 20:57:15 +00:00
|
|
|
|
2008-06-22 23:21:29 +00:00
|
|
|
test = 1; /* reset for every face */
|
|
|
|
|
|
|
|
if (EditMesh)
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
{
|
2008-06-22 23:21:29 +00:00
|
|
|
if (index_array)
|
|
|
|
{
|
|
|
|
index = index_array[i];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
index = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index == ORIGINDEX_NONE)
|
|
|
|
{
|
|
|
|
test = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
efa = EM_get_face_for_index(index);
|
|
|
|
|
2008-10-02 17:20:58 +00:00
|
|
|
if (efa && (efa->h || (efa->v1->f & SELECT) || (efa->v2->f & SELECT) || (efa->v3->f & SELECT) || (efa->v4 && efa->v4->f & SELECT)))
|
2008-06-22 23:21:29 +00:00
|
|
|
{
|
|
|
|
test = 0;
|
|
|
|
}
|
|
|
|
}
|
2007-03-24 20:57:15 +00:00
|
|
|
}
|
|
|
|
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
|
2008-06-22 23:21:29 +00:00
|
|
|
if (test)
|
|
|
|
{
|
|
|
|
result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL);
|
2008-06-15 17:54:42 +00:00
|
|
|
|
2008-06-22 23:21:29 +00:00
|
|
|
if (result) {
|
|
|
|
float location[3], normal[3];
|
|
|
|
float intersect[3];
|
|
|
|
float new_depth;
|
|
|
|
int screen_loc[2];
|
|
|
|
int new_dist;
|
2007-03-24 20:57:15 +00:00
|
|
|
|
2008-06-22 23:21:29 +00:00
|
|
|
VECCOPY(intersect, ray_normal_local);
|
|
|
|
VecMulf(intersect, lambda);
|
|
|
|
VecAddf(intersect, intersect, ray_start_local);
|
2007-03-24 20:57:15 +00:00
|
|
|
|
2008-06-22 23:21:29 +00:00
|
|
|
VECCOPY(location, intersect);
|
|
|
|
|
|
|
|
if (f->v4)
|
|
|
|
CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal);
|
|
|
|
else
|
|
|
|
CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal);
|
|
|
|
|
|
|
|
Mat4MulVecfl(obmat, location);
|
|
|
|
|
|
|
|
new_depth = VecLenf(location, ray_start);
|
|
|
|
|
|
|
|
project_int(location, screen_loc);
|
|
|
|
new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]);
|
|
|
|
|
|
|
|
if (new_dist <= *dist && new_depth < *depth)
|
|
|
|
{
|
|
|
|
*depth = new_depth;
|
|
|
|
retval = 1;
|
|
|
|
|
|
|
|
VECCOPY(loc, location);
|
|
|
|
VECCOPY(no, normal);
|
|
|
|
|
|
|
|
Mat3MulVecfl(timat, no);
|
|
|
|
Normalize(no);
|
|
|
|
|
|
|
|
*dist = new_dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (f->v4 && result == 0)
|
|
|
|
{
|
|
|
|
result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL);
|
2007-03-24 20:57:15 +00:00
|
|
|
|
2008-06-22 23:21:29 +00:00
|
|
|
if (result) {
|
|
|
|
float location[3], normal[3];
|
|
|
|
float intersect[3];
|
|
|
|
float new_depth;
|
|
|
|
int screen_loc[2];
|
|
|
|
int new_dist;
|
|
|
|
|
|
|
|
VECCOPY(intersect, ray_normal_local);
|
|
|
|
VecMulf(intersect, lambda);
|
|
|
|
VecAddf(intersect, intersect, ray_start_local);
|
|
|
|
|
|
|
|
VECCOPY(location, intersect);
|
|
|
|
|
|
|
|
if (f->v4)
|
|
|
|
CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal);
|
|
|
|
else
|
|
|
|
CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal);
|
|
|
|
|
|
|
|
Mat4MulVecfl(obmat, location);
|
|
|
|
|
|
|
|
new_depth = VecLenf(location, ray_start);
|
|
|
|
|
|
|
|
project_int(location, screen_loc);
|
|
|
|
new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]);
|
|
|
|
|
|
|
|
if (new_dist <= *dist && new_depth < *depth)
|
|
|
|
{
|
|
|
|
*depth = new_depth;
|
|
|
|
retval = 1;
|
|
|
|
|
|
|
|
VECCOPY(loc, location);
|
|
|
|
VECCOPY(no, normal);
|
|
|
|
|
|
|
|
Mat3MulVecfl(timat, no);
|
|
|
|
Normalize(no);
|
|
|
|
|
|
|
|
*dist = new_dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
}
|
|
|
|
}
|
2008-06-22 23:21:29 +00:00
|
|
|
|
|
|
|
if (EditMesh)
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
{
|
2008-06-22 23:21:29 +00:00
|
|
|
EM_free_index_arrays();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SCE_SNAP_MODE_VERTEX:
|
|
|
|
{
|
|
|
|
MVert *verts = dm->getVertArray(dm);
|
|
|
|
int *index_array = NULL;
|
|
|
|
int index = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (EditMesh)
|
|
|
|
{
|
|
|
|
index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
|
|
|
|
EM_init_index_arrays(1, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
for( i = 0; i < totvert; i++) {
|
|
|
|
EditVert *eve = NULL;
|
|
|
|
MVert *v = verts + i;
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
|
2008-06-22 23:21:29 +00:00
|
|
|
test = 1; /* reset for every vert */
|
|
|
|
|
|
|
|
if (EditMesh)
|
|
|
|
{
|
|
|
|
if (index_array)
|
|
|
|
{
|
|
|
|
index = index_array[i];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
index = i;
|
|
|
|
}
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
|
2008-06-22 23:21:29 +00:00
|
|
|
if (index == ORIGINDEX_NONE)
|
|
|
|
{
|
|
|
|
test = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eve = EM_get_vert_for_index(index);
|
|
|
|
|
2008-10-02 17:20:58 +00:00
|
|
|
if (eve && (eve->h || (eve->f & SELECT)))
|
2008-06-22 23:21:29 +00:00
|
|
|
{
|
|
|
|
test = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (test)
|
|
|
|
{
|
|
|
|
float dvec[3];
|
|
|
|
|
|
|
|
VecSubf(dvec, v->co, ray_start_local);
|
|
|
|
|
|
|
|
if (Inpf(ray_normal_local, dvec) > 0)
|
|
|
|
{
|
|
|
|
float location[3];
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
float new_depth;
|
|
|
|
int screen_loc[2];
|
2008-06-15 17:54:42 +00:00
|
|
|
int new_dist;
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
|
2008-06-22 23:21:29 +00:00
|
|
|
VECCOPY(location, v->co);
|
|
|
|
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
Mat4MulVecfl(obmat, location);
|
|
|
|
|
2008-06-22 23:21:29 +00:00
|
|
|
new_depth = VecLenf(location, ray_start);
|
2007-03-24 20:57:15 +00:00
|
|
|
|
2008-06-15 17:54:42 +00:00
|
|
|
project_int(location, screen_loc);
|
|
|
|
new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]);
|
|
|
|
|
|
|
|
if (new_dist <= *dist && new_depth < *depth)
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
{
|
|
|
|
*depth = new_depth;
|
2007-03-24 20:57:15 +00:00
|
|
|
retval = 1;
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
|
|
|
|
VECCOPY(loc, location);
|
|
|
|
|
2008-06-22 23:21:29 +00:00
|
|
|
NormalShortToFloat(no, v->no);
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
Mat3MulVecfl(timat, no);
|
|
|
|
Normalize(no);
|
|
|
|
|
2008-06-15 17:54:42 +00:00
|
|
|
*dist = new_dist;
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
}
|
2007-03-24 20:57:15 +00:00
|
|
|
}
|
|
|
|
}
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
}
|
2008-06-22 23:21:29 +00:00
|
|
|
|
|
|
|
if (EditMesh)
|
|
|
|
{
|
|
|
|
EM_free_index_arrays();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SCE_SNAP_MODE_EDGE:
|
|
|
|
{
|
|
|
|
MVert *verts = dm->getVertArray(dm);
|
|
|
|
MEdge *edges = dm->getEdgeArray(dm);
|
|
|
|
int totedge = dm->getNumEdges(dm);
|
|
|
|
int *index_array = NULL;
|
|
|
|
int index = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (EditMesh)
|
|
|
|
{
|
|
|
|
index_array = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
|
|
|
|
EM_init_index_arrays(0, 1, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
for( i = 0; i < totedge; i++) {
|
|
|
|
EditEdge *eed = NULL;
|
|
|
|
MEdge *e = edges + i;
|
|
|
|
|
|
|
|
test = 1; /* reset for every vert */
|
|
|
|
|
|
|
|
if (EditMesh)
|
|
|
|
{
|
|
|
|
if (index_array)
|
|
|
|
{
|
|
|
|
index = index_array[i];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
index = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index == ORIGINDEX_NONE)
|
|
|
|
{
|
|
|
|
test = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eed = EM_get_edge_for_index(index);
|
|
|
|
|
2008-10-02 17:20:58 +00:00
|
|
|
if (eed && (eed->h || (eed->v1->f & SELECT) || (eed->v2->f & SELECT)))
|
2008-06-22 23:21:29 +00:00
|
|
|
{
|
|
|
|
test = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (test)
|
|
|
|
{
|
|
|
|
float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3];
|
|
|
|
int result;
|
|
|
|
|
|
|
|
VECCOPY(ray_end, ray_normal_local);
|
|
|
|
VecMulf(ray_end, 2000);
|
|
|
|
VecAddf(ray_end, ray_start_local, ray_end);
|
|
|
|
|
|
|
|
result = LineIntersectLine(verts[e->v1].co, verts[e->v2].co, ray_start_local, ray_end, intersect, dvec); /* dvec used but we don't care about result */
|
|
|
|
|
|
|
|
if (result)
|
|
|
|
{
|
|
|
|
float edge_loc[3], vec[3];
|
|
|
|
float mul;
|
|
|
|
|
|
|
|
/* check for behind ray_start */
|
|
|
|
VecSubf(dvec, intersect, ray_start_local);
|
|
|
|
|
|
|
|
VecSubf(edge_loc, verts[e->v1].co, verts[e->v2].co);
|
|
|
|
VecSubf(vec, intersect, verts[e->v2].co);
|
|
|
|
|
|
|
|
mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc);
|
|
|
|
|
|
|
|
if (mul > 1) {
|
|
|
|
mul = 1;
|
|
|
|
VECCOPY(intersect, verts[e->v1].co);
|
|
|
|
}
|
|
|
|
else if (mul < 0) {
|
|
|
|
mul = 0;
|
|
|
|
VECCOPY(intersect, verts[e->v2].co);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Inpf(ray_normal_local, dvec) > 0)
|
|
|
|
{
|
|
|
|
float location[3];
|
|
|
|
float new_depth;
|
|
|
|
int screen_loc[2];
|
|
|
|
int new_dist;
|
|
|
|
|
|
|
|
VECCOPY(location, intersect);
|
|
|
|
|
|
|
|
Mat4MulVecfl(obmat, location);
|
|
|
|
|
|
|
|
new_depth = VecLenf(location, ray_start);
|
|
|
|
|
|
|
|
project_int(location, screen_loc);
|
|
|
|
new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]);
|
|
|
|
|
|
|
|
if (new_dist <= *dist && new_depth < *depth)
|
|
|
|
{
|
|
|
|
float n1[3], n2[3];
|
|
|
|
|
|
|
|
*depth = new_depth;
|
|
|
|
retval = 1;
|
|
|
|
|
|
|
|
VecSubf(edge_loc, verts[e->v1].co, verts[e->v2].co);
|
|
|
|
VecSubf(vec, intersect, verts[e->v2].co);
|
|
|
|
|
|
|
|
mul = Inpf(vec, edge_loc) / Inpf(edge_loc, edge_loc);
|
|
|
|
|
|
|
|
NormalShortToFloat(n1, verts[e->v1].no);
|
|
|
|
NormalShortToFloat(n2, verts[e->v2].no);
|
|
|
|
VecLerpf(no, n2, n1, mul);
|
|
|
|
Normalize(no);
|
|
|
|
|
|
|
|
VECCOPY(loc, location);
|
|
|
|
|
|
|
|
Mat3MulVecfl(timat, no);
|
|
|
|
Normalize(no);
|
|
|
|
|
|
|
|
*dist = new_dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (EditMesh)
|
|
|
|
{
|
|
|
|
EM_free_index_arrays();
|
|
|
|
}
|
|
|
|
break;
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
int snapObjects(int *dist, float *loc, float *no, int mode) {
|
|
|
|
Base *base;
|
|
|
|
float depth = FLT_MAX;
|
|
|
|
int retval = 0;
|
|
|
|
short mval[2];
|
|
|
|
float ray_start[3], ray_normal[3];
|
|
|
|
|
|
|
|
getmouseco_areawin(mval);
|
|
|
|
viewray(mval, ray_start, ray_normal);
|
2007-03-24 20:57:15 +00:00
|
|
|
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
if (mode == NOT_ACTIVE)
|
|
|
|
{
|
2008-06-16 16:48:09 +00:00
|
|
|
DerivedMesh *dm;
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
Object *ob = G.obedit;
|
|
|
|
|
2008-06-16 16:48:09 +00:00
|
|
|
dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
|
|
|
|
retval = snapDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth, 1);
|
|
|
|
|
|
|
|
dm->release(dm);
|
|
|
|
}
|
|
|
|
|
|
|
|
base= FIRSTBASE;
|
|
|
|
for ( base = FIRSTBASE; base != NULL; base = base->next ) {
|
2008-09-16 19:10:58 +00:00
|
|
|
if ( BASE_SELECTABLE(base) && (base->flag & (BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA)) == 0 && ((mode == NOT_SELECTED && (base->flag & (SELECT|BA_WAS_SEL)) == 0) || (mode == NOT_ACTIVE && base != BASACT)) ) {
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
Object *ob = base->object;
|
|
|
|
|
|
|
|
if (ob->transflag & OB_DUPLI)
|
|
|
|
{
|
|
|
|
DupliObject *dupli_ob;
|
|
|
|
ListBase *lb = object_duplilist(G.scene, ob);
|
|
|
|
|
|
|
|
for(dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next)
|
|
|
|
{
|
|
|
|
Object *ob = dupli_ob->ob;
|
|
|
|
|
|
|
|
if (ob->type == OB_MESH) {
|
|
|
|
DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
|
|
|
|
int val;
|
|
|
|
|
|
|
|
val = snapDerivedMesh(ob, dm, dupli_ob->mat, ray_start, ray_normal, mval, loc, no, dist, &depth, 0);
|
|
|
|
|
|
|
|
retval = retval || val;
|
|
|
|
|
|
|
|
dm->release(dm);
|
2007-02-28 17:16:17 +00:00
|
|
|
}
|
|
|
|
}
|
Merge from Apricot Revisions 14897, 14913, 14914, 14915, 14929, 15009, 15046
---------------------------------------------------
Snappy stuff
* Align rotation with snapping target: rotate the object, aligning it with the target (object mode only - temporarily) (New icon in the header when snap is turned on)
* Snap to different mesh elements (face, edge, vertice): snapping target slide on faces and edge or use exact position of vertice. When using Align rotation with edge snapping, the normal is interpolated as you slide along.
Snaps correctly to derived mesh (sculpt, modifiers, ...) and duplis. In object and edit mode.
NOTE: The snapping code is now based on faces, so even if you're snapping to vertices or edges, it will not work on meshes without faces. This might change if needed.
2008-06-09 18:41:16 +00:00
|
|
|
|
|
|
|
free_object_duplilist(lb);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ob->type == OB_MESH) {
|
|
|
|
DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
|
|
|
|
int val;
|
|
|
|
|
|
|
|
val = snapDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, loc, no, dist, &depth, 0);
|
|
|
|
|
|
|
|
retval = retval || val;
|
|
|
|
|
|
|
|
dm->release(dm);
|
2007-02-28 17:16:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
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);
|
|
|
|
}
|
|
|
|
}
|