Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorMartin Poirier <theeth@yahoo.com>2006-12-23 03:52:34 +0300
committerMartin Poirier <theeth@yahoo.com>2006-12-23 03:52:34 +0300
commit1ad1522d10a0efbb5929826af4801724adf4a357 (patch)
tree298d8e6b9d75707e410d2fb59e756291350499d0 /source
parent48b62511bf9535dcaf484f5324c1776975b8791f (diff)
=== Transform Snap ===
==== Rotation Snap ==== Snap is no longer limited to Translation, it works in Rotation too. There's some bugs left with rotation snap when using constraints, I'll be ironing that next. ==== Bug Fixes ==== * Fix manipulators to always use Grid. * Fix initialization bug (took two transform call to do a correct snap init when changing between Grid and Snap)
Diffstat (limited to 'source')
-rwxr-xr-xsource/blender/include/transform.h30
-rwxr-xr-xsource/blender/src/transform.c6
-rwxr-xr-xsource/blender/src/transform_generics.c1
-rw-r--r--source/blender/src/transform_snap.c162
4 files changed, 141 insertions, 58 deletions
diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h
index 2ce022a650a..7a29f15ce0b 100755
--- a/source/blender/include/transform.h
+++ b/source/blender/include/transform.h
@@ -60,14 +60,17 @@ typedef struct NumInput {
*/
typedef struct TransSnap {
- int mode;
- int status;
- float snapPoint[3];
- float snapTarget[3];
- double last;
- void (*applySnap)(struct TransInfo *, float *);
- void (*calcSnap)(struct TransInfo *, float *);
- void (*targetSnap)(struct TransInfo *);
+ short modePoint;
+ short modeTarget;
+ int status;
+ float snapPoint[3];
+ float snapTarget[3];
+ float dist; // Distance from snapPoint to snapTarget
+ double last;
+ void (*applySnap)(struct TransInfo *, float *);
+ void (*calcSnap)(struct TransInfo *, float *);
+ void (*targetSnap)(struct TransInfo *);
+ float (*distance)(struct TransInfo *, float p1[3], float p2[3]); // Get the transform distance between two points (used by Closest snap)
} TransSnap;
typedef struct TransCon {
@@ -257,9 +260,14 @@ typedef struct TransInfo {
#define TARGET_INIT 2
#define POINT_INIT 4
-/* transsnap->mode */
-#define SNAP_GRID 1
-#define SNAP_GEO 2
+/* transsnap->modePoint */
+#define SNAP_GRID 0
+#define SNAP_GEO 1
+
+/* transsnap->modeTarget */
+#define SNAP_CLOSEST 0
+#define SNAP_CENTER 1
+#define SNAP_MEDIAN 2
void checkFirstTime(void);
diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c
index 7a9efd723ae..facee8ed8d9 100755
--- a/source/blender/src/transform.c
+++ b/source/blender/src/transform.c
@@ -756,6 +756,8 @@ void initTransform(int mode, int context) {
createTransData(&Trans); // make TransData structs from selection
+ initSnapping(&Trans); // Initialize snapping data AFTER mode flags
+
if (Trans.total == 0) {
postTrans(&Trans);
return;
@@ -940,6 +942,8 @@ void initManipulator(int mode)
}
Trans.flag |= T_USES_MANIPULATOR;
+
+ Trans.tsnap.modePoint = SNAP_GRID; // Always use snap to grid with manipulators
}
void ManipulatorTransform()
@@ -1896,6 +1900,8 @@ int Rotation(TransInfo *t, short mval[2])
if (t->con.applyRot) {
t->con.applyRot(t, NULL, axis);
}
+
+ applySnapping(t, &final);
if (hasNumInput(&t->num)) {
char c[20];
diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c
index 1746daae7f2..bdb2075b65c 100755
--- a/source/blender/src/transform_generics.c
+++ b/source/blender/src/transform_generics.c
@@ -494,7 +494,6 @@ void initTrans (TransInfo *t)
t->around = V3D_CENTRE;
setTransformViewMatrices(t);
- initSnapping(t);
}
/* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c
index 3a4bb5087a4..2ba69d8d524 100644
--- a/source/blender/src/transform_snap.c
+++ b/source/blender/src/transform_snap.c
@@ -75,6 +75,9 @@ void TargetSnapMedian(TransInfo *t);
void TargetSnapCenter(TransInfo *t);
void TargetSnapClosest(TransInfo *t);
+float RotationBetween(TransInfo *t, float p1[3], float p2[3]);
+float TranslationBetween(TransInfo *t, float p1[3], float p2[3]);
+
/****************** IMPLEMENTATIONS *********************/
void drawSnapping(TransInfo *t)
@@ -139,6 +142,8 @@ void applySnapping(TransInfo *t, float *vec)
void resetSnapping(TransInfo *t)
{
t->tsnap.status = 0;
+ t->tsnap.modePoint = 0;
+ t->tsnap.modeTarget = 0;
t->tsnap.last = 0;
t->tsnap.applySnap = NULL;
}
@@ -150,51 +155,63 @@ void initSnapping(TransInfo *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
- (t->spacetype==SPACE_VIEW3D) && // Only 3D view (not UV)
+ (t->spacetype == SPACE_VIEW3D) && // Only 3D view (not UV)
(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.mode = SNAP_GEO;
+ t->tsnap.modePoint = SNAP_GEO;
}
else
{
- t->tsnap.mode = SNAP_GRID;
+ t->tsnap.modePoint = SNAP_GRID;
}
}
void setSnappingCallback(TransInfo *t)
{
- switch (t->mode)
- {
- case TFM_TRANSLATION:
- t->tsnap.applySnap = ApplySnapTranslation;
- t->tsnap.calcSnap = CalcSnapGeometry;
- break;
- case TFM_ROTATION:
- t->tsnap.applySnap = NULL;
- break;
- case TFM_RESIZE:
- t->tsnap.applySnap = NULL;
- break;
- default:
- t->tsnap.applySnap = NULL;
- break;
- }
+ t->tsnap.calcSnap = CalcSnapGeometry;
+
switch(G.vd->flag2 & V3D_SNAP_TARGET)
{
case V3D_SNAP_TARGET_CLOSEST:
+ t->tsnap.modeTarget = SNAP_CLOSEST;
t->tsnap.targetSnap = TargetSnapClosest;
break;
case V3D_SNAP_TARGET_CENTER:
+ t->tsnap.modeTarget = SNAP_CENTER;
t->tsnap.targetSnap = TargetSnapCenter;
break;
case V3D_SNAP_TARGET_MEDIAN:
+ t->tsnap.modeTarget = SNAP_MEDIAN;
t->tsnap.targetSnap = TargetSnapMedian;
break;
}
+ 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
+ if ((G.vd->flag2 & V3D_SNAP_TARGET) == V3D_SNAP_TARGET_CENTER) {
+ t->tsnap.modeTarget = SNAP_MEDIAN;
+ t->tsnap.targetSnap = TargetSnapMedian;
+ }
+ break;
+ case TFM_RESIZE:
+ t->tsnap.applySnap = NULL;
+ break;
+ default:
+ t->tsnap.applySnap = NULL;
+ break;
+ }
}
/********************** APPLY **************************/
@@ -204,9 +221,78 @@ void ApplySnapTranslation(TransInfo *t, float vec[3])
VecSubf(vec, t->tsnap.snapPoint, t->tsnap.snapTarget);
}
-void ApplySnapRotation(TransInfo *t, float vec[3])
+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])
+{
+ return VecLenf(p1, p2);
+}
+
+float RotationBetween(TransInfo *t, float p1[3], float p2[3])
{
- // FOO
+ 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];
+
+ Mat3CpyMat4(mtx, t->viewinv);
+
+ Mat3MulVecfl(mtx, end);
+ Mat3MulVecfl(mtx, start);
+
+ angle = atan2(end[1],end[0]) - atan2(start[1],start[0]);
+ }
+
+ if (angle > M_PI) {
+ angle = 2 * M_PI - angle;
+ }
+ else if (angle < -(M_PI)) {
+ angle = 2 * M_PI + angle;
+ }
+
+ return angle;
}
/********************** CALC **************************/
@@ -319,7 +405,6 @@ void TargetSnapClosest(TransInfo *t)
if (t->tsnap.status & POINT_INIT)
{
TransData *closest = NULL, *td = NULL;
- float closestDist = 0;
// Base case, only one selected item
if (t->total == 1)
@@ -329,40 +414,25 @@ void TargetSnapClosest(TransInfo *t)
// More than one selected item
else
{
- float point[3];
-
- VECCOPY(point, t->tsnap.snapPoint);
-
- if(t->flag & (T_EDIT|T_POSE)) {
- Object *ob= G.obedit?G.obedit:t->poseobj;
- float imat[4][4];
- Mat4Invert(imat, ob->obmat);
- Mat4MulVecfl(imat, point);
- }
-
for (td = t->data; td != NULL && td->flag & TD_SELECTED ; td++)
{
- float vdist[3];
+ float loc[3];
float dist;
- VecSubf(vdist, td->iloc, point);
- dist = Inpf(vdist, vdist);
+ VECCOPY(loc, td->iloc);
+ Mat4MulVecfl(G.obedit->obmat, loc);
+
+ dist = t->tsnap.distance(t, td->iloc, t->tsnap.snapPoint);
- if (closest == NULL || dist < closestDist)
+ if (closest == NULL || fabs(dist) < fabs(t->tsnap.dist))
{
+ VECCOPY(t->tsnap.snapTarget, loc);
closest = td;
- closestDist = dist;
+ t->tsnap.dist = dist;
}
}
}
- VECCOPY(t->tsnap.snapTarget, closest->iloc);
-
- 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;
}
}
@@ -388,7 +458,7 @@ void snapGrid(TransInfo *t, float *val) {
GearsType action;
// Only do something if using Snap to Grid
- if ((t->tsnap.mode & SNAP_GRID) == 0)
+ if (t->tsnap.modePoint != SNAP_GRID)
return;
if(t->mode==TFM_ROTATION || t->mode==TFM_WARP || t->mode==TFM_TILT || t->mode==TFM_TRACKBALL || t->mode==TFM_BONE_ROLL)