diff options
-rwxr-xr-x | source/blender/include/transform.h | 27 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_view3d_types.h | 1 | ||||
-rw-r--r-- | source/blender/src/header_view3d.c | 17 | ||||
-rwxr-xr-x | source/blender/src/transform.c | 11 | ||||
-rwxr-xr-x | source/blender/src/transform_generics.c | 60 | ||||
-rw-r--r-- | source/blender/src/transform_snap.c | 238 |
6 files changed, 291 insertions, 63 deletions
diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index ec55b768381..d91fe81d991 100755 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -59,6 +59,13 @@ typedef struct NumInput { Negative : number is negative */ +typedef struct TransSnap { + int status; + float snapPoint[3]; + void (*applySnap)(struct TransInfo *, float *); + void (*calcSnap)(struct TransInfo *, float *); +} TransSnap; + typedef struct TransCon { char text[50]; /* Description of the Constraint for header_print */ float mtx[3][3]; /* Matrix of the Constraint space */ @@ -147,6 +154,7 @@ typedef struct TransInfo { TransDataExtension *ext; /* transformed data extension (array) */ TransData2D *data2d; /* transformed data for 2d (array) */ TransCon con; /* transformed constraint */ + TransSnap tsnap; NumInput num; /* numerical input */ char redraw; /* redraw flag */ float propsize; /* proportional circle radius */ @@ -331,6 +339,23 @@ void postSelectConstraint(TransInfo *t); void setNearestAxis(TransInfo *t); +/*********************** Snapping ********************************/ + +typedef enum { + NO_GEARS = 0, + BIG_GEARS = 1, + SMALL_GEARS = 2 +} GearsType; + +void snapGrid(TransInfo *t, float *val); +void snapGridAction(TransInfo *t, float *val, GearsType action); + +void initSnapping(struct TransInfo *t); +void applySnapping(TransInfo *t, float *vec); +void resetSnapping(TransInfo *t); +int handleSnapping(TransInfo *t, int event); +void drawSnapping(TransInfo *t); + /*********************** Generics ********************************/ void initTrans(TransInfo *t); @@ -356,8 +381,6 @@ void calculateCenterCursor(TransInfo *t); void calculatePropRatio(TransInfo *t); -void snapGrid(TransInfo *t, float *val); - void getViewVector(float coord[3], float vec[3]); TransInfo * BIF_GetTransInfo(void); diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index b62c815b2b2..dda40b67bf7 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -158,6 +158,7 @@ typedef struct View3D { /* View3d->flag2 (short) */ #define V3D_OPP_DIRECTION_NAME 1 #define V3D_FLYMODE 2 +#define V3D_TRANSFORM_SNAP 4 /* View3D->around */ #define V3D_CENTRE 0 diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 93b9832b5b8..478f96d331c 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -2152,6 +2152,9 @@ static void do_view3d_edit_objectmenu(void *arg, int event) if(session) b_verse_push_object(session, ob); break; #endif + case 17: /* Transform snap to grid */ + G.vd->flag2 ^= V3D_TRANSFORM_SNAP; + break; } allqueue(REDRAWVIEW3D, 0); } @@ -2177,6 +2180,12 @@ static uiBlock *view3d_edit_objectmenu(void *arg_unused) } #endif + if (G.vd->flag2 & V3D_TRANSFORM_SNAP) + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Transform Snap", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); + else + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Transform Snap", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Properties|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 15, ""); uiDefIconTextBlockBut(block, view3d_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, ""); uiDefIconTextBlockBut(block, view3d_object_mirrormenu, NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, menuwidth, 19, ""); @@ -2712,6 +2721,9 @@ static void do_view3d_edit_meshmenu(void *arg, int event) if(session) b_verse_push_object(session, G.obedit); break; #endif + case 17: /* Transform snap to grid */ + G.vd->flag2 ^= V3D_TRANSFORM_SNAP; + break; } allqueue(REDRAWVIEW3D, 0); } @@ -2739,6 +2751,11 @@ static uiBlock *view3d_edit_meshmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + if (G.vd->flag2 & V3D_TRANSFORM_SNAP) + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Transform Snap", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); + else + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Transform Snap", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 17, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Properties...|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); uiDefIconTextBlockBut(block, view3d_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, ""); uiDefIconTextBlockBut(block, view3d_edit_mirrormenu, NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, 120, 19, ""); diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index 1e5f481ac8b..14a41b0a5dc 100755 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -699,6 +699,7 @@ static void transformEvent(unsigned short event, short val) { break; } Trans.redraw |= handleNumInput(&(Trans.num), event); + Trans.redraw |= handleSnapping(&Trans, event); arrows_move_cursor(event); } else { @@ -2053,6 +2054,8 @@ void initTranslation(TransInfo *t) t->snap[0] = 0.0f; t->snap[1] = t->snap[2] = 1.0f; } + + initSnapping(t); } static void headerTranslation(TransInfo *t, float vec[3], char *str) { @@ -2152,14 +2155,16 @@ int Translation(TransInfo *t, short mval[2]) float pvec[3] = {0.0f, 0.0f, 0.0f}; t->con.applyVec(t, NULL, t->vec, tvec, pvec); VECCOPY(t->vec, tvec); + applySnapping(t, t->vec); headerTranslation(t, pvec, str); } else { snapGrid(t, t->vec); applyNumInput(&t->num, t->vec); + applySnapping(t, t->vec); headerTranslation(t, t->vec, str); } - + applyTranslation(t, t->vec); /* evil hack - redo translation if cliiping needeed */ @@ -2169,9 +2174,11 @@ int Translation(TransInfo *t, short mval[2]) recalcData(t); headerprint(str); - + viewRedrawForce(t); + drawSnapping(t); + return 1; } diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index 09ad6e7a788..0ed75810b42 100755 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -480,6 +480,7 @@ void initTrans (TransInfo *t) t->around = V3D_CENTRE; setTransformViewMatrices(t); + resetSnapping(t); } /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */ @@ -532,65 +533,6 @@ void postTrans (TransInfo *t) } } -static void apply_grid3(TransInfo *t, float *val, int max_index, float fac1, float fac2, float fac3) -{ - /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */ - int invert; - int ctrl; - int i; - float asp= 1.0f; - - if(t->mode==TFM_ROTATION || t->mode==TFM_WARP || t->mode==TFM_TILT || t->mode==TFM_TRACKBALL) - 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; - - for (i=0; i<=max_index; i++) { - - /* evil hack - snapping needs to be adapted for image aspect ratio */ - if((t->spacetype==SPACE_IMAGE) && (t->mode==TFM_TRANSLATION)) { - float aspx, aspy; - transform_aspect_ratio_tface_uv(&aspx, &aspy); - if(i==0) asp= aspx; - else asp= aspy; - } - - if(invert) { - if(G.qual & LR_CTRLKEY) ctrl= 0; - else ctrl= 1; - } - else ctrl= (G.qual & LR_CTRLKEY); - - if(ctrl && (G.qual & LR_SHIFTKEY)) { - if(fac3!= 0.0) { - for (i=0; i<=max_index; i++) { - val[i]= fac3*asp*(float)floor(val[i]/(fac3*asp) +.5); - } - } - } - else if(ctrl) { - if(fac2!= 0.0) { - for (i=0; i<=max_index; i++) { - val[i]= fac2*asp*(float)floor(val[i]/(fac2*asp) +.5); - } - } - } - else { - if(fac1!= 0.0) { - for (i=0; i<=max_index; i++) { - val[i]= fac1*asp*(float)floor(val[i]/(fac1*asp) +.5); - } - } - } - } -} - -void snapGrid(TransInfo *t, float *val) { - apply_grid3(t, val, t->idx_max, t->snap[0], t->snap[1], t->snap[2]); -} - void applyTransObjects(TransInfo *t) { TransData *td; diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c new file mode 100644 index 00000000000..53d1822ae70 --- /dev/null +++ b/source/blender/src/transform_snap.c @@ -0,0 +1,238 @@ +/** + * $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> + +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_userdef_types.h" +#include "DNA_view3d_types.h" + +#include "BLI_arithb.h" + +#include "BDR_drawobject.h" + +#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 */ + +#define SNAP_ON 1 + +/********************* PROTOTYPES ***********************/ + +void setSnappingCallback(TransInfo *t); +void SnapTranslation(TransInfo *t, float vec[3]); +void SnapRotation(TransInfo *t, float *vec); + +void CalcSnapGrid(TransInfo *t, float vec[3]); + + +/****************** IMPLEMENTATIONS *********************/ + +void drawSnapping(TransInfo *t) +{ + if (t->tsnap.status & SNAP_ON) { + // Do something nice + } +} + +int handleSnapping(TransInfo *t, int event) +{ + int status = 0; + + switch(event) { + case ACCENTGRAVEKEY: + t->tsnap.status ^= SNAP_ON; + status = 1; + break; + } + + return status; +} + +void applySnapping(TransInfo *t, float *vec) +{ + if ((t->tsnap.status & SNAP_ON) && t->tsnap.applySnap != NULL) + { + t->tsnap.applySnap(t, vec); + } +} + +void resetSnapping(TransInfo *t) +{ + t->tsnap.status = 0; + t->tsnap.applySnap = NULL; +} + +void initSnapping(TransInfo *t) +{ + setSnappingCallback(t); + + if (G.vd->flag2 & V3D_TRANSFORM_SNAP) + { + t->tsnap.status |= SNAP_ON; + } + else + { + t->tsnap.status &= ~SNAP_ON; + } +} + +void setSnappingCallback(TransInfo *t) +{ + switch (t->mode) + { + case TFM_TRANSLATION: + t->tsnap.applySnap = SnapTranslation; + t->tsnap.calcSnap = CalcSnapGrid; + break; + case TFM_ROTATION: + t->tsnap.applySnap = NULL; //SnapRotation; + //t->tsnap.calcSnap = CalcSnapGrid; + break; + case TFM_RESIZE: + t->tsnap.applySnap = NULL; + break; + default: + t->tsnap.applySnap = NULL; + break; + } +} + +void SnapTranslation(TransInfo *t, float vec[3]) +{ + float 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); + } + + VecAddf(t->tsnap.snapPoint, vec, center); + + t->tsnap.calcSnap(t, t->tsnap.snapPoint); + + VecSubf(vec, t->tsnap.snapPoint, center); + + if (t->con.mode & CON_APPLY) + { + Mat3MulVecfl(t->con.pmtx, vec); + } +} + +void SnapRotation(TransInfo *t, float *vec) +{ + TransData *td; + + td = t->data; + + VECCOPY(t->tsnap.snapPoint, td->loc); + t->tsnap.calcSnap(t, t->tsnap.snapPoint); + + +} + +void CalcSnapGrid(TransInfo *t, float vec[3]) +{ + snapGridAction(t, vec, BIG_GEARS); +} + +/*================================================================*/ + +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; + + if(t->mode==TFM_ROTATION || t->mode==TFM_WARP || t->mode==TFM_TILT || t->mode==TFM_TRACKBALL) + 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); + } +} |