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
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/transform/transform_snap.c')
-rw-r--r--source/blender/editors/transform/transform_snap.c272
1 files changed, 174 insertions, 98 deletions
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 354b6920b7a..50c4bc1a416 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -92,7 +92,7 @@
/********************* PROTOTYPES ***********************/
-void setSnappingCallback(TransInfo *t, short snap_target);
+void setSnappingCallback(TransInfo *t);
void ApplySnapTranslation(TransInfo *t, float vec[3]);
void ApplySnapRotation(TransInfo *t, float *vec);
@@ -125,10 +125,20 @@ int BIF_snappingSupported(Object *obedit)
return status;
}
+int validSnap(TransInfo *t)
+{
+ return (t->tsnap.status & (POINT_INIT|TARGET_INIT)) == (POINT_INIT|TARGET_INIT) ||
+ (t->tsnap.status & (MULTI_POINTS|TARGET_INIT)) == (MULTI_POINTS|TARGET_INIT);
+}
+
+int activeSnap(TransInfo *t)
+{
+ return (t->modifiers & (MOD_SNAP|MOD_SNAP_INVERT)) == MOD_SNAP || (t->modifiers & (MOD_SNAP|MOD_SNAP_INVERT)) == MOD_SNAP_INVERT;
+}
+
void drawSnapping(const struct bContext *C, TransInfo *t)
{
- if ((t->tsnap.status & (SNAP_ON|POINT_INIT|TARGET_INIT)) == (SNAP_ON|POINT_INIT|TARGET_INIT) &&
- (t->modifiers & MOD_SNAP_GEARS))
+ if (validSnap(t) && activeSnap(t))
{
char col[4] = {1, 0, 1};
@@ -136,6 +146,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
glColor4ub(col[0], col[1], col[2], 128);
if (t->spacetype == SPACE_VIEW3D) {
+ TransSnapPoint *p;
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
float tmat[4][4], imat[4][4];
@@ -143,14 +154,18 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
glDisable(GL_DEPTH_TEST);
- size = get_drawsize(t->ar, t->tsnap.snapPoint);
-
- size *= 0.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
+ size = 0.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
copy_m4_m4(tmat, rv3d->viewmat);
invert_m4_m4(imat, tmat);
- drawcircball(GL_LINE_LOOP, t->tsnap.snapPoint, size, imat);
+ for (p = t->tsnap.points.first; p; p = p->next) {
+ drawcircball(GL_LINE_LOOP, p->co, size * get_drawsize(t->ar, p->co), imat);
+ }
+
+ if (t->tsnap.status & POINT_INIT) {
+ drawcircball(GL_LINE_LOOP, t->tsnap.snapPoint, size * get_drawsize(t->ar, t->tsnap.snapPoint), imat);
+ }
/* draw normal if needed */
if (usingSnappingNormal(t) && validSnappingNormal(t))
@@ -207,7 +222,8 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
int handleSnapping(TransInfo *t, wmEvent *event)
{
int status = 0;
-
+
+#if 0 // XXX need a proper selector for all snap mode
if (BIF_snappingSupported(t->obedit) && event->type == TABKEY && event->shift)
{
/* toggle snap and reinit */
@@ -215,6 +231,7 @@ int handleSnapping(TransInfo *t, wmEvent *event)
initSnapping(t, NULL);
status = 1;
}
+#endif
return status;
}
@@ -222,7 +239,7 @@ int handleSnapping(TransInfo *t, wmEvent *event)
void applyProject(TransInfo *t)
{
/* XXX FLICKER IN OBJECT MODE */
- if ((t->tsnap.project) && (t->tsnap.status & SNAP_ON) && (t->modifiers & MOD_SNAP_GEARS))
+ if ((t->tsnap.project) && activeSnap(t))
{
TransData *td = t->data;
float tvec[3];
@@ -258,7 +275,7 @@ void applyProject(TransInfo *t)
project_float(t->ar, iloc, mval);
- if (snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.mode))
+ if (snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.target))
{
// if(t->flag & (T_EDIT|T_POSE)) {
// mul_m4_v3(imat, loc);
@@ -288,21 +305,20 @@ void applySnapping(TransInfo *t, float *vec)
t->tsnap.applySnap(t, vec);
}
- else if ((t->tsnap.status & SNAP_ON) &&
- (t->modifiers & MOD_SNAP_GEARS))
+ else if ((t->tsnap.mode != SCE_SNAP_MODE_INCREMENT) && activeSnap(t))
{
double current = PIL_check_seconds_timer();
// Time base quirky code to go around findnearest slowness
/* !TODO! add exception for object mode, no need to slow it down then */
- if (current - t->tsnap.last >= 0.1)
+ if (current - t->tsnap.last >= 0.01)
{
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))
+ if (validSnap(t))
{
t->tsnap.applySnap(t, vec);
}
@@ -312,10 +328,11 @@ void applySnapping(TransInfo *t, float *vec)
void resetSnapping(TransInfo *t)
{
t->tsnap.status = 0;
- t->tsnap.mode = 0;
t->tsnap.align = 0;
- t->tsnap.modePoint = 0;
- t->tsnap.modeTarget = 0;
+ t->tsnap.project = 0;
+ t->tsnap.mode = 0;
+ t->tsnap.modeSelect = 0;
+ t->tsnap.target = 0;
t->tsnap.last = 0;
t->tsnap.applySnap = NULL;
@@ -331,7 +348,7 @@ int usingSnappingNormal(TransInfo *t)
int validSnappingNormal(TransInfo *t)
{
- if ((t->tsnap.status & (POINT_INIT|TARGET_INIT)) == (POINT_INIT|TARGET_INIT))
+ if (validSnap(t))
{
if (dot_v3v3(t->tsnap.snapNormal, t->tsnap.snapNormal) > 0)
{
@@ -342,125 +359,134 @@ int validSnappingNormal(TransInfo *t)
return 0;
}
-void initSnapping(TransInfo *t, wmOperator *op)
+void initSnappingMode(TransInfo *t)
{
ToolSettings *ts = t->settings;
Object *obedit = t->obedit;
Scene *scene = t->scene;
- int snapping = 0;
- short snap_mode = t->settings->snap_target;
-
- resetSnapping(t);
-
- if (op && RNA_struct_find_property(op->ptr, "snap") && RNA_property_is_set(op->ptr, "snap"))
- {
- if (RNA_boolean_get(op->ptr, "snap"))
- {
- snapping = 1;
- snap_mode = RNA_enum_get(op->ptr, "snap_mode");
-
- t->tsnap.status |= SNAP_FORCED|POINT_INIT;
- RNA_float_get_array(op->ptr, "snap_point", t->tsnap.snapPoint);
-
- /* snap align only defined in specific cases */
- if (RNA_struct_find_property(op->ptr, "snap_align"))
- {
- t->tsnap.align = RNA_boolean_get(op->ptr, "snap_align");
- RNA_float_get_array(op->ptr, "snap_normal", t->tsnap.snapNormal);
- normalize_v3(t->tsnap.snapNormal);
- }
- if (RNA_struct_find_property(op->ptr, "snap_project"))
- {
- t->tsnap.project = RNA_boolean_get(op->ptr, "snap_project");
- }
- }
- }
- else
- {
- snapping = ((ts->snap_flag & SCE_SNAP) == SCE_SNAP);
- t->tsnap.align = ((t->settings->snap_flag & SCE_SNAP_ROTATE) == SCE_SNAP_ROTATE);
- t->tsnap.project = ((t->settings->snap_flag & SCE_SNAP_PROJECT) == SCE_SNAP_PROJECT);
- }
-
/* force project off when not supported */
if (ts->snap_mode != SCE_SNAP_MODE_FACE)
{
t->tsnap.project = 0;
}
-
+
+ t->tsnap.mode = ts->snap_mode;
+
if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && // Only 3D view or UV
- (t->flag & T_CAMERA) == 0) { // Not with camera selected
- setSnappingCallback(t, snap_mode);
+ (t->flag & T_CAMERA) == 0) { // Not with camera selected in camera view
+ setSnappingCallback(t);
/* Edit mode */
if (t->tsnap.applySnap != NULL && // A snapping function actually exist
- (snapping) && // Only if the snap flag is on
(obedit != NULL && ELEM3(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE)) ) // Temporary limited to edit mode meshes, armature, curves
{
- t->tsnap.status |= SNAP_ON;
- t->tsnap.modePoint = SNAP_GEO;
-
if (t->flag & T_PROP_EDIT)
{
- t->tsnap.mode = SNAP_NOT_OBEDIT;
+ t->tsnap.modeSelect = SNAP_NOT_OBEDIT;
}
else
{
- t->tsnap.mode = SNAP_ALL;
+ t->tsnap.modeSelect = SNAP_ALL;
}
}
/* Particles edit mode*/
else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
- (snapping) && // Only if the snap flag is on
- (obedit == NULL && BASACT->object && BASACT->object->mode & OB_MODE_PARTICLE_EDIT ))
+ (obedit == NULL && BASACT && BASACT->object && BASACT->object->mode & OB_MODE_PARTICLE_EDIT ))
{
- t->tsnap.status |= SNAP_ON;
- t->tsnap.modePoint = SNAP_GEO;
- t->tsnap.mode = SNAP_ALL;
+ t->tsnap.modeSelect = SNAP_ALL;
}
/* Object mode */
else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
- (snapping) && // Only if the snap flag is on
(obedit == NULL) ) // Object Mode
{
- t->tsnap.status |= SNAP_ON;
- t->tsnap.modePoint = SNAP_GEO;
- t->tsnap.mode = SNAP_NOT_SELECTED;
+ t->tsnap.modeSelect = SNAP_NOT_SELECTED;
}
else
- {
+ {
/* Grid if snap is not possible */
- t->tsnap.modePoint = SNAP_GRID;
+ t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
}
}
else
{
/* Always grid outside of 3D view */
- t->tsnap.modePoint = SNAP_GRID;
+ t->tsnap.mode = SCE_SNAP_MODE_INCREMENT;
+ }
+}
+
+void initSnapping(TransInfo *t, wmOperator *op)
+{
+ ToolSettings *ts = t->settings;
+ short snap_target = t->settings->snap_target;
+
+ resetSnapping(t);
+
+ /* if snap property exists */
+ if (op && RNA_struct_find_property(op->ptr, "snap") && RNA_property_is_set(op->ptr, "snap"))
+ {
+ if (RNA_boolean_get(op->ptr, "snap"))
+ {
+ t->modifiers |= MOD_SNAP;
+
+ if (RNA_property_is_set(op->ptr, "snap_target"))
+ {
+ snap_target = RNA_enum_get(op->ptr, "snap_target");
+ }
+
+ if (RNA_property_is_set(op->ptr, "snap_point"))
+ {
+ RNA_float_get_array(op->ptr, "snap_point", t->tsnap.snapPoint);
+ t->tsnap.status |= SNAP_FORCED|POINT_INIT;
+ }
+
+ /* snap align only defined in specific cases */
+ if (RNA_struct_find_property(op->ptr, "snap_align"))
+ {
+ t->tsnap.align = RNA_boolean_get(op->ptr, "snap_align");
+ RNA_float_get_array(op->ptr, "snap_normal", t->tsnap.snapNormal);
+ normalize_v3(t->tsnap.snapNormal);
+ }
+
+ if (RNA_struct_find_property(op->ptr, "snap_project"))
+ {
+ t->tsnap.project = RNA_boolean_get(op->ptr, "snap_project");
+ }
+ }
}
+ /* use scene defaults only when transform is modal */
+ else if (t->flag & T_MODAL)
+ {
+ if (ts->snap_flag & SCE_SNAP) {
+ t->modifiers |= MOD_SNAP;
+ }
+
+ t->tsnap.align = ((t->settings->snap_flag & SCE_SNAP_ROTATE) == SCE_SNAP_ROTATE);
+ t->tsnap.project = ((t->settings->snap_flag & SCE_SNAP_PROJECT) == SCE_SNAP_PROJECT);
+ t->tsnap.peel = ((t->settings->snap_flag & SCE_SNAP_PROJECT) == SCE_SNAP_PROJECT);
+ }
+
+ t->tsnap.target = snap_target;
+
+ initSnappingMode(t);
}
-void setSnappingCallback(TransInfo *t, short snap_target)
+void setSnappingCallback(TransInfo *t)
{
t->tsnap.calcSnap = CalcSnapGeometry;
- switch(snap_target)
+ switch(t->tsnap.target)
{
case SCE_SNAP_TARGET_CLOSEST:
- t->tsnap.modeTarget = SNAP_CLOSEST;
t->tsnap.targetSnap = TargetSnapClosest;
break;
case SCE_SNAP_TARGET_CENTER:
- t->tsnap.modeTarget = SNAP_CENTER;
t->tsnap.targetSnap = TargetSnapCenter;
break;
case SCE_SNAP_TARGET_MEDIAN:
- t->tsnap.modeTarget = SNAP_MEDIAN;
t->tsnap.targetSnap = TargetSnapMedian;
break;
case SCE_SNAP_TARGET_ACTIVE:
- t->tsnap.modeTarget = SNAP_ACTIVE;
t->tsnap.targetSnap = TargetSnapActive;
break;
@@ -477,8 +503,8 @@ void setSnappingCallback(TransInfo *t, short snap_target)
t->tsnap.distance = RotationBetween;
// Can't do TARGET_CENTER with rotation, use TARGET_MEDIAN instead
- if (snap_target == SCE_SNAP_TARGET_CENTER) {
- t->tsnap.modeTarget = SNAP_MEDIAN;
+ if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) {
+ t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
t->tsnap.targetSnap = TargetSnapMedian;
}
break;
@@ -487,8 +513,8 @@ void setSnappingCallback(TransInfo *t, short snap_target)
t->tsnap.distance = ResizeBetween;
// Can't do TARGET_CENTER with resize, use TARGET_MEDIAN instead
- if (snap_target == SCE_SNAP_TARGET_CENTER) {
- t->tsnap.modeTarget = SNAP_MEDIAN;
+ if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) {
+ t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
t->tsnap.targetSnap = TargetSnapMedian;
}
break;
@@ -498,30 +524,82 @@ void setSnappingCallback(TransInfo *t, short snap_target)
}
}
+void addSnapPoint(TransInfo *t)
+{
+ if (t->tsnap.status & POINT_INIT) {
+ TransSnapPoint *p = MEM_callocN(sizeof(TransSnapPoint), "SnapPoint");
+
+ VECCOPY(p->co, t->tsnap.snapPoint);
+
+ BLI_addtail(&t->tsnap.points, p);
+
+ t->tsnap.status |= MULTI_POINTS;
+ }
+}
+
+void removeSnapPoint(TransInfo *t)
+{
+ if (t->tsnap.status & MULTI_POINTS) {
+ BLI_freelinkN(&t->tsnap.points, t->tsnap.points.last);
+
+ if (t->tsnap.points.first == NULL)
+ t->tsnap.status &= ~MULTI_POINTS;
+ }
+}
+
+void getSnapPoint(TransInfo *t, float vec[3])
+{
+ if (t->tsnap.points.first) {
+ TransSnapPoint *p;
+ int total = 0;
+
+ vec[0] = vec[1] = vec[2] = 0;
+
+ for (p = t->tsnap.points.first; p; p = p->next, total++) {
+ add_v3_v3(vec, p->co);
+ }
+
+ if (t->tsnap.status & POINT_INIT) {
+ add_v3_v3(vec, t->tsnap.snapPoint);
+ total++;
+ }
+
+ mul_v3_fl(vec, 1.0f / total);
+ } else {
+ VECCOPY(vec, t->tsnap.snapPoint)
+ }
+}
+
/********************** APPLY **************************/
void ApplySnapTranslation(TransInfo *t, float vec[3])
{
- sub_v3_v3v3(vec, t->tsnap.snapPoint, t->tsnap.snapTarget);
+ float point[3];
+ getSnapPoint(t, point);
+ sub_v3_v3v3(vec, point, t->tsnap.snapTarget);
}
void ApplySnapRotation(TransInfo *t, float *vec)
{
- if (t->tsnap.modeTarget == SNAP_CLOSEST) {
+ if (t->tsnap.target == SCE_SNAP_TARGET_CLOSEST) {
*vec = t->tsnap.dist;
}
else {
- *vec = RotationBetween(t, t->tsnap.snapTarget, t->tsnap.snapPoint);
+ float point[3];
+ getSnapPoint(t, point);
+ *vec = RotationBetween(t, t->tsnap.snapTarget, point);
}
}
void ApplySnapResize(TransInfo *t, float vec[3])
{
- if (t->tsnap.modeTarget == SNAP_CLOSEST) {
+ if (t->tsnap.target == SCE_SNAP_TARGET_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);
+ float point[3];
+ getSnapPoint(t, point);
+ vec[0] = vec[1] = vec[2] = ResizeBetween(t, t->tsnap.snapTarget, point);
}
}
@@ -629,7 +707,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec)
mval[0] = t->mval[0];
mval[1] = t->mval[1];
- if (t->settings->snap_mode == SCE_SNAP_MODE_VOLUME)
+ if (t->tsnap.mode == SCE_SNAP_MODE_VOLUME)
{
ListBase depth_peels;
DepthPeel *p1, *p2;
@@ -722,7 +800,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec)
}
else
{
- found = snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.mode);
+ found = snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.modeSelect);
}
if (found == 1)
@@ -761,8 +839,6 @@ void CalcSnapGeometry(TransInfo *t, float *vec)
t->tsnap.snapPoint[0] *= aspx;
t->tsnap.snapPoint[1] *= aspy;
- mul_m4_v3(t->obedit->obmat, t->tsnap.snapPoint);
-
t->tsnap.status |= POINT_INIT;
}
else
@@ -821,7 +897,7 @@ void TargetSnapActive(TransInfo *t)
/* No active, default to median */
else
{
- t->tsnap.modeTarget = SNAP_MEDIAN;
+ t->tsnap.target = SCE_SNAP_TARGET_MEDIAN;
t->tsnap.targetSnap = TargetSnapMedian;
TargetSnapMedian(t);
}
@@ -1845,7 +1921,7 @@ void snapGrid(TransInfo *t, float *val) {
GearsType action;
// Only do something if using Snap to Grid
- if (t->tsnap.modePoint != SNAP_GRID)
+ if (t->tsnap.mode != SCE_SNAP_MODE_INCREMENT)
return;
if(t->mode==TFM_ROTATION || t->mode==TFM_WARP || t->mode==TFM_TILT || t->mode==TFM_TRACKBALL || t->mode==TFM_BONE_ROLL)
@@ -1856,10 +1932,10 @@ void snapGrid(TransInfo *t, float *val) {
invert = U.flag & USER_AUTOGRABGRID;
if(invert) {
- action = (t->modifiers & MOD_SNAP_GEARS) ? NO_GEARS: BIG_GEARS;
+ action = activeSnap(t) ? NO_GEARS: BIG_GEARS;
}
else {
- action = (t->modifiers & MOD_SNAP_GEARS) ? BIG_GEARS : NO_GEARS;
+ action = activeSnap(t) ? BIG_GEARS : NO_GEARS;
}
if (action == BIG_GEARS && (t->modifiers & MOD_PRECISION)) {