diff options
Diffstat (limited to 'source/blender/editors/transform/transform_snap.c')
-rw-r--r-- | source/blender/editors/transform/transform_snap.c | 310 |
1 files changed, 75 insertions, 235 deletions
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index c6d7b92fb42..a700dd320b7 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -22,34 +22,22 @@ */ #include <float.h> -#include <math.h> -#include <stdio.h> -#include <stdlib.h> #include "PIL_time.h" -#include "DNA_meshdata_types.h" /* Temporary, for snapping to other unselected meshes */ -#include "DNA_node_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" -#include "DNA_space_types.h" -#include "DNA_view3d_types.h" #include "DNA_windowmanager_types.h" #include "BLI_blenlib.h" #include "BLI_math.h" -#include "BLI_utildefines.h" #include "GPU_immediate.h" #include "GPU_state.h" #include "BKE_context.h" -#include "BKE_duplilist.h" #include "BKE_editmesh.h" #include "BKE_layer.h" -#include "BKE_main.h" #include "BKE_object.h" +#include "BKE_scene.h" #include "BKE_sequencer.h" #include "RNA_access.h" @@ -57,14 +45,10 @@ #include "WM_types.h" #include "ED_gizmo_library.h" -#include "ED_image.h" #include "ED_markers.h" #include "ED_node.h" #include "ED_transform_snap_object_context.h" #include "ED_uvedit.h" -#include "ED_view3d.h" - -#include "DEG_depsgraph.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -86,10 +70,6 @@ static void setSnappingCallback(TransInfo *t); -static void ApplySnapTranslation(TransInfo *t, float vec[3]); -static void ApplySnapRotation(TransInfo *t, float *vec); -static void ApplySnapResize(TransInfo *t, float vec[2]); - /* static void CalcSnapGrid(TransInfo *t, float *vec); */ static void CalcSnapGeometry(TransInfo *t, float *vec); @@ -98,10 +78,6 @@ static void TargetSnapCenter(TransInfo *t); static void TargetSnapClosest(TransInfo *t); static void TargetSnapActive(TransInfo *t); -static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3]); -static float TranslationBetween(TransInfo *t, const float p1[3], const float p2[3]); -static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3]); - /** \} */ /* -------------------------------------------------------------------- */ @@ -125,6 +101,24 @@ int BIF_snappingSupported(Object *obedit) } #endif +static bool snap_use_backface_culling(const TransInfo *t) +{ + BLI_assert(t->spacetype == SPACE_VIEW3D); + View3D *v3d = t->view; + if ((v3d->shading.type == OB_SOLID) && (v3d->shading.flag & V3D_SHADING_BACKFACE_CULLING)) { + return true; + } + if (v3d->shading.type == OB_RENDER && + (t->scene->display.shading.flag & V3D_SHADING_BACKFACE_CULLING) && + BKE_scene_uses_blender_workbench(t->scene)) { + return true; + } + if (t->settings->snap_flag & SCE_SNAP_BACKFACE_CULLING) { + return true; + } + return false; +} + bool validSnap(const TransInfo *t) { return (t->tsnap.status & (POINT_INIT | TARGET_INIT)) == (POINT_INIT | TARGET_INIT) || @@ -149,6 +143,12 @@ bool transformModeUseSnap(const TransInfo *t) if (t->mode == TFM_RESIZE) { return (ts->snap_transform_mode_flag & SCE_SNAP_TRANSFORM_MODE_SCALE) != 0; } + if (t->mode == TFM_VERT_SLIDE) { + return true; + } + if (t->mode == TFM_EDGE_SLIDE) { + return true; + } return false; } @@ -334,8 +334,7 @@ void applyProject(TransInfo *t) .snap_select = t->tsnap.modeSelect, .use_object_edit_cage = (t->flag & T_EDIT) != 0, .use_occlusion_test = false, - .use_backface_culling = (t->scene->toolsettings->snap_flag & - SCE_SNAP_BACKFACE_CULLING) != 0, + .use_backface_culling = t->tsnap.use_backface_culling, }, mval_fl, NULL, @@ -482,7 +481,6 @@ void resetSnapping(TransInfo *t) t->tsnap.modeSelect = 0; t->tsnap.target = 0; t->tsnap.last = 0; - t->tsnap.applySnap = NULL; t->tsnap.snapNormal[0] = 0; t->tsnap.snapNormal[1] = 0; @@ -563,35 +561,32 @@ static void initSnappingMode(TransInfo *t) 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 in camera view */ - { + if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && (t->flag & T_CAMERA) == 0) { + /* Only 3D view or UV. */ + /* Not with camera selected in camera view. */ + setSnappingCallback(t); - /* Edit mode */ - if (t->tsnap.applySnap != NULL && // A snapping function actually exist - ((obedit_type != -1) && - /* Temporary limited to edit mode meshes, armature, curves, metaballs. */ - ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL))) { - /* Exclude editmesh if using proportional edit */ + if ((obedit_type != -1) && + ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) { + /* Edit mode */ + /* Temporary limited to edit mode meshes, armature, curves, metaballs. */ + if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) { + /* Exclude editmesh if using proportional edit */ t->tsnap.modeSelect = SNAP_NOT_ACTIVE; } else { t->tsnap.modeSelect = t->tsnap.snap_self ? SNAP_ALL : SNAP_NOT_ACTIVE; } } - /* Particles edit mode*/ - else if (t->tsnap.applySnap != NULL && // A snapping function actually exist - ((obedit_type == -1) && base_act && base_act->object && - base_act->object->mode & OB_MODE_PARTICLE_EDIT)) { + else if ((obedit_type == -1) && base_act && base_act->object && + (base_act->object->mode & OB_MODE_PARTICLE_EDIT)) { + /* Particles edit mode. */ t->tsnap.modeSelect = SNAP_ALL; } - /* Object mode */ - else if (t->tsnap.applySnap != NULL && // A snapping function actually exist - (obedit_type == -1)) // Object Mode - { - + else if (obedit_type == -1) { + /* Object mode */ if (t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) { /* In "Edit Strokes" mode, * snap tool can perform snap to selected or active objects (see T49632) @@ -611,14 +606,7 @@ static void initSnappingMode(TransInfo *t) } else if (t->spacetype == SPACE_NODE) { setSnappingCallback(t); - - if (t->tsnap.applySnap != NULL) { - t->tsnap.modeSelect = SNAP_NOT_SELECTED; - } - else { - /* Grid if snap is not possible */ - t->tsnap.mode = SCE_SNAP_MODE_INCREMENT; - } + t->tsnap.modeSelect = SNAP_NOT_SELECTED; } else if (t->spacetype == SPACE_SEQ) { /* We do our own snapping currently, so nothing here */ @@ -631,15 +619,19 @@ static void initSnappingMode(TransInfo *t) if (t->spacetype == SPACE_VIEW3D) { if (t->tsnap.object_context == NULL) { + t->tsnap.use_backface_culling = snap_use_backface_culling(t); t->tsnap.object_context = ED_transform_snap_object_context_create_view3d( t->scene, 0, t->region, t->view); - ED_transform_snap_object_context_set_editmesh_callbacks( - t->tsnap.object_context, - (bool (*)(BMVert *, void *))BM_elem_cb_check_hflag_disabled, - bm_edge_is_snap_target, - bm_face_is_snap_target, - POINTER_FROM_UINT((BM_ELEM_SELECT | BM_ELEM_HIDDEN))); + if (t->data_type == TC_MESH_VERTS) { + /* Ignore elements being transformed. */ + ED_transform_snap_object_context_set_editmesh_callbacks( + t->tsnap.object_context, + (bool (*)(BMVert *, void *))BM_elem_cb_check_hflag_disabled, + bm_edge_is_snap_target, + bm_face_is_snap_target, + POINTER_FROM_UINT((BM_ELEM_SELECT | BM_ELEM_HIDDEN))); + } } } } @@ -723,8 +715,13 @@ static void setSnappingCallback(TransInfo *t) t->tsnap.targetSnap = TargetSnapClosest; break; case SCE_SNAP_TARGET_CENTER: - t->tsnap.targetSnap = TargetSnapCenter; - break; + if (!ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) { + t->tsnap.targetSnap = TargetSnapCenter; + break; + } + /* Can't do TARGET_CENTER with these modes, + * use TARGET_MEDIAN instead. */ + ATTR_FALLTHROUGH; case SCE_SNAP_TARGET_MEDIAN: t->tsnap.targetSnap = TargetSnapMedian; break; @@ -732,36 +729,6 @@ static void setSnappingCallback(TransInfo *t) t->tsnap.targetSnap = TargetSnapActive; 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 (t->tsnap.target == SCE_SNAP_TARGET_CENTER) { - t->tsnap.target = SCE_SNAP_TARGET_MEDIAN; - t->tsnap.targetSnap = TargetSnapMedian; - } - break; - case TFM_RESIZE: - t->tsnap.applySnap = ApplySnapResize; - t->tsnap.distance = ResizeBetween; - - // Can't do TARGET_CENTER with resize, use TARGET_MEDIAN instead - if (t->tsnap.target == SCE_SNAP_TARGET_CENTER) { - t->tsnap.target = SCE_SNAP_TARGET_MEDIAN; - t->tsnap.targetSnap = TargetSnapMedian; - } - break; - default: - t->tsnap.applySnap = NULL; - break; - } } void addSnapPoint(TransInfo *t) @@ -862,145 +829,6 @@ void getSnapPoint(const TransInfo *t, float vec[3]) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Apply Snap - * \{ */ - -static void ApplySnapTranslation(TransInfo *t, float vec[3]) -{ - float point[3]; - getSnapPoint(t, point); - - if (t->spacetype == SPACE_NODE) { - char border = t->tsnap.snapNodeBorder; - if (border & (NODE_LEFT | NODE_RIGHT)) { - vec[0] = point[0] - t->tsnap.snapTarget[0]; - } - if (border & (NODE_BOTTOM | NODE_TOP)) { - vec[1] = point[1] - t->tsnap.snapTarget[1]; - } - } - else { - if (t->spacetype == SPACE_VIEW3D) { - if (t->options & CTX_PAINT_CURVE) { - if (ED_view3d_project_float_global(t->region, point, point, V3D_PROJ_TEST_NOP) != - V3D_PROJ_RET_OK) { - zero_v3(point); /* no good answer here... */ - } - } - } - - sub_v3_v3v3(vec, point, t->tsnap.snapTarget); - } -} - -static void ApplySnapRotation(TransInfo *t, float *value) -{ - float point[3]; - getSnapPoint(t, point); - - float dist = RotationBetween(t, t->tsnap.snapTarget, point); - *value = dist; -} - -static void ApplySnapResize(TransInfo *t, float vec[3]) -{ - float point[3]; - getSnapPoint(t, point); - - float dist = ResizeBetween(t, t->tsnap.snapTarget, point); - if (dist != TRANSFORM_DIST_INVALID) { - copy_v3_fl(vec, dist); - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Distance - * \{ */ - -static float TranslationBetween(TransInfo *UNUSED(t), const float p1[3], const float p2[3]) -{ - return len_squared_v3v3(p1, p2); -} - -static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3]) -{ - float angle, start[3], end[3]; - - sub_v3_v3v3(start, p1, t->center_global); - sub_v3_v3v3(end, p2, t->center_global); - - // 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, NULL, axis, NULL); - - project_v3_v3v3(tmp, end, axis); - sub_v3_v3v3(end, end, tmp); - - project_v3_v3v3(tmp, start, axis); - sub_v3_v3v3(start, start, tmp); - - normalize_v3(end); - normalize_v3(start); - - cross_v3_v3v3(tmp, start, end); - - if (dot_v3v3(tmp, axis) < 0.0f) { - angle = -acosf(dot_v3v3(start, end)); - } - else { - angle = acosf(dot_v3v3(start, end)); - } - } - else { - float mtx[3][3]; - - copy_m3_m4(mtx, t->viewmat); - - mul_m3_v3(mtx, end); - mul_m3_v3(mtx, start); - - angle = atan2f(start[1], start[0]) - atan2f(end[1], end[0]); - } - - if (angle > (float)M_PI) { - angle = angle - 2 * (float)M_PI; - } - else if (angle < -((float)M_PI)) { - angle = 2.0f * (float)M_PI + angle; - } - - return angle; -} - -static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3]) -{ - float d1[3], d2[3], len_d1; - - sub_v3_v3v3(d1, p1, t->center_global); - sub_v3_v3v3(d2, p2, t->center_global); - - if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { - mul_m3_v3(t->con.pmtx, d1); - mul_m3_v3(t->con.pmtx, d2); - } - - project_v3_v3v3(d1, d1, d2); - - len_d1 = len_v3(d1); - - /* Use 'invalid' dist when `center == p1` (after projecting), - * in this case scale will _never_ move the point in relation to the center, - * so it makes no sense to take it into account when scaling. see: T46503 */ - return len_d1 != 0.0f ? len_v3(d2) / len_d1 : TRANSFORM_DIST_INVALID; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Calc Snap (Generic) * \{ */ @@ -1311,13 +1139,12 @@ short snapObjectsTransform( return ED_transform_snap_object_project_view3d_ex( t->tsnap.object_context, t->depsgraph, - t->scene->toolsettings->snap_mode, + t->settings->snap_mode, &(const struct SnapObjectParams){ .snap_select = t->tsnap.modeSelect, .use_object_edit_cage = (t->flag & T_EDIT) != 0, - .use_occlusion_test = t->scene->toolsettings->snap_mode != SCE_SNAP_MODE_FACE, - .use_backface_culling = (t->scene->toolsettings->snap_flag & - SCE_SNAP_BACKFACE_CULLING) != 0, + .use_occlusion_test = t->settings->snap_mode != SCE_SNAP_MODE_FACE, + .use_backface_culling = t->tsnap.use_backface_culling, }, mval, target, @@ -1737,3 +1564,16 @@ static void applyGridIncrement( } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Generic callbacks + * \{ */ + +float transform_snap_distance_len_squared_fn(TransInfo *UNUSED(t), + const float p1[3], + const float p2[3]) +{ + return len_squared_v3v3(p1, p2); +} + +/** \} */ |