diff --git a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.cc b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.cc index 479e90511e6..be00466b24f 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.cc +++ b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.cc @@ -278,7 +278,7 @@ static int gizmo_move_modal(bContext *C, SnapObjectParams params{}; params.snap_target_select = SCE_SNAP_TARGET_ALL; params.edit_mode_type = SNAP_GEOM_EDIT; - params.use_occlusion_test = true; + params.occlusion_test = SNAP_OCCLUSION_AS_SEEM; if (ED_transform_snap_object_project_view3d( inter->snap_context_v3d, CTX_data_ensure_evaluated_depsgraph(C), diff --git a/source/blender/editors/include/ED_transform_snap_object_context.hh b/source/blender/editors/include/ED_transform_snap_object_context.hh index 1e49ed7b8b7..1b348923d45 100644 --- a/source/blender/editors/include/ED_transform_snap_object_context.hh +++ b/source/blender/editors/include/ED_transform_snap_object_context.hh @@ -33,6 +33,12 @@ enum eSnapEditType { SNAP_GEOM_EDIT = 2, /* Bmesh for mesh-type. */ }; +enum eSnapOcclusionTest { + SNAP_OCCLUSION_NEVER = 0, + SNAP_OCCLUSION_AS_SEEM = 1, + SNAP_OCCLUSION_ALWAYS = 2, +}; + /** used for storing multiple hits */ struct SnapObjectHitDepth { SnapObjectHitDepth *next, *prev; @@ -53,12 +59,12 @@ struct SnapObjectParams { eSnapTargetOP snap_target_select; /** Geometry for snapping in edit mode. */ eSnapEditType edit_mode_type; + /** Snap to or ignore the frontmost object. */ + eSnapOcclusionTest occlusion_test; /** Grid unit size. "0.0" is automatic. */ float grid_size; /** Break nearest face snapping into steps to improve transformations across U-shaped targets. */ short face_nearest_steps; - /** Snap to the closest element, use when using more than one snap type. */ - bool use_occlusion_test : 1; /** Exclude back facing geometry from snapping. */ bool use_backface_culling : 1; /** Enable to force nearest face snapping to snap to target the source was initially near. */ diff --git a/source/blender/editors/mesh/editmesh_utils.cc b/source/blender/editors/mesh/editmesh_utils.cc index 06c8a557b1f..e3c72d16f2a 100644 --- a/source/blender/editors/mesh/editmesh_utils.cc +++ b/source/blender/editors/mesh/editmesh_utils.cc @@ -1943,7 +1943,7 @@ void EDBM_project_snap_verts( SnapObjectParams params{}; params.snap_target_select = target_op; params.edit_mode_type = SNAP_GEOM_FINAL; - params.use_occlusion_test = true; + params.occlusion_test = SNAP_OCCLUSION_AS_SEEM; if (ED_transform_snap_object_project_view3d(snap_context, depsgraph, region, diff --git a/source/blender/editors/space_view3d/view3d_cursor_snap.cc b/source/blender/editors/space_view3d/view3d_cursor_snap.cc index 83b0788cad3..ae80f5b0226 100644 --- a/source/blender/editors/space_view3d/view3d_cursor_snap.cc +++ b/source/blender/editors/space_view3d/view3d_cursor_snap.cc @@ -563,9 +563,16 @@ static bool v3d_cursor_is_snap_invert(SnapCursorDataIntern *data_intern, uint8_t static eSnapMode v3d_cursor_snap_elements(ToolSettings *tool_settings) { - return eSnapMode(tool_settings->snap_mode_tools == SCE_SNAP_TO_NONE ? - tool_settings->snap_mode : - tool_settings->snap_mode_tools); + if (tool_settings->snap_mode_tools == SCE_SNAP_TO_NONE) { + /* Use the snap modes defined in the scene instead. */ + eSnapMode snap_mode = eSnapMode(tool_settings->snap_mode); + if ((snap_mode & SCE_SNAP_TO_INCREMENT) && (tool_settings->snap_flag & SCE_SNAP_ABS_GRID)) { + /* Convert snap to increment to snap to grid. */ + snap_mode |= SCE_SNAP_TO_GRID; + } + return snap_mode; + } + return eSnapMode(tool_settings->snap_mode_tools); } static void v3d_cursor_snap_context_ensure(Scene *scene) @@ -615,7 +622,7 @@ static void v3d_cursor_snap_update(V3DSnapCursorState *state, snap_data->is_snap_invert = v3d_cursor_is_snap_invert(data_intern, event_modifier); #endif - if (snap_data->is_snap_invert != !(tool_settings->snap_flag & SCE_SNAP)) { + if (snap_data->is_snap_invert != (tool_settings->snap_flag & SCE_SNAP) == 0) { snap_data->is_enabled = false; if (!calc_plane_omat) { snap_data->type_target = SCE_SNAP_TO_NONE; @@ -663,15 +670,14 @@ static void v3d_cursor_snap_update(V3DSnapCursorState *state, SNAP_GEOM_CAGE : SNAP_GEOM_EDIT; - bool use_occlusion_test = (state->flag & V3D_SNAPCURSOR_OCCLUSION_ALWAYS_TRUE) ? false : - true; - float dist_px = 12.0f * U.pixelsize; SnapObjectParams params{}; params.snap_target_select = SCE_SNAP_TARGET_ALL; params.edit_mode_type = edit_mode_type; - params.use_occlusion_test = use_occlusion_test; + params.occlusion_test = (state->flag & V3D_SNAPCURSOR_OCCLUSION_ALWAYS_TRUE) ? + SNAP_OCCLUSION_ALWAYS : + SNAP_OCCLUSION_AS_SEEM; snap_elem = ED_transform_snap_object_project_view3d_ex(data_intern->snap_context_v3d, depsgraph, region, @@ -688,6 +694,22 @@ static void v3d_cursor_snap_update(V3DSnapCursorState *state, nullptr, obmat, face_nor); + if ((snap_elem & data_intern->snap_elem_hidden) && (snap_elements & SCE_SNAP_TO_GRID)) { + BLI_assert(snap_elem != SCE_SNAP_TO_GRID); + params.occlusion_test = SNAP_OCCLUSION_NEVER; + snap_elem = ED_transform_snap_object_project_view3d(data_intern->snap_context_v3d, + depsgraph, + region, + v3d, + SCE_SNAP_TO_GRID, + ¶ms, + co, + mval_fl, + prev_co, + &dist_px, + co, + no); + } } } #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK diff --git a/source/blender/editors/space_view3d/view3d_edit.cc b/source/blender/editors/space_view3d/view3d_edit.cc index 43c0a6bde23..0d7fff6cf84 100644 --- a/source/blender/editors/space_view3d/view3d_edit.cc +++ b/source/blender/editors/space_view3d/view3d_edit.cc @@ -915,7 +915,7 @@ void ED_view3d_cursor3d_position_rotation(bContext *C, SnapObjectParams params{}; params.snap_target_select = SCE_SNAP_TARGET_ALL; params.edit_mode_type = SNAP_GEOM_FINAL; - params.use_occlusion_test = true; + params.occlusion_test = SNAP_OCCLUSION_AS_SEEM; if (ED_transform_snap_object_project_view3d_ex(snap_context, CTX_data_ensure_evaluated_depsgraph(C), region, diff --git a/source/blender/editors/transform/transform_snap.cc b/source/blender/editors/transform/transform_snap.cc index 453e82eb6dd..93d0df0be9e 100644 --- a/source/blender/editors/transform/transform_snap.cc +++ b/source/blender/editors/transform/transform_snap.cc @@ -427,7 +427,7 @@ static bool applyFaceProject(TransInfo *t, TransDataContainer *tc, TransData *td SnapObjectParams snap_object_params{}; snap_object_params.snap_target_select = t->tsnap.target_operation; snap_object_params.edit_mode_type = (t->flag & T_EDIT) != 0 ? SNAP_GEOM_EDIT : SNAP_GEOM_FINAL; - snap_object_params.use_occlusion_test = false; + snap_object_params.occlusion_test = SNAP_OCCLUSION_ALWAYS; snap_object_params.use_backface_culling = (t->tsnap.flag & SCE_SNAP_BACKFACE_CULLING) != 0; eSnapMode hit = ED_transform_snap_object_project_view3d(t->tsnap.object_context, @@ -490,7 +490,7 @@ static void applyFaceNearest(TransInfo *t, TransDataContainer *tc, TransData *td SnapObjectParams snap_object_params{}; snap_object_params.snap_target_select = t->tsnap.target_operation; snap_object_params.edit_mode_type = (t->flag & T_EDIT) != 0 ? SNAP_GEOM_EDIT : SNAP_GEOM_FINAL; - snap_object_params.use_occlusion_test = false; + snap_object_params.occlusion_test = SNAP_OCCLUSION_ALWAYS; snap_object_params.use_backface_culling = false; snap_object_params.face_nearest_steps = t->tsnap.face_nearest_steps; snap_object_params.keep_on_same_target = t->tsnap.flag & SCE_SNAP_KEEP_ON_SAME_OBJECT; @@ -1603,7 +1603,7 @@ static eSnapMode snapObjectsTransform( t->snap_spatial[0] * t->snap_spatial_precision : t->snap_spatial[0]; snap_object_params.edit_mode_type = (t->flag & T_EDIT) != 0 ? SNAP_GEOM_EDIT : SNAP_GEOM_FINAL; - snap_object_params.use_occlusion_test = true; + snap_object_params.occlusion_test = SNAP_OCCLUSION_AS_SEEM; snap_object_params.use_backface_culling = (t->tsnap.flag & SCE_SNAP_BACKFACE_CULLING) != 0; float *prev_co = (t->tsnap.status & SNAP_SOURCE_FOUND) ? t->tsnap.snap_source : t->center_global; diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index dbec9e69799..42643fb51f0 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -125,8 +125,8 @@ void SnapData::clip_planes_enable(SnapObjectContext *sctx, { float4x4 tobmat = math::transpose(this->obmat_); if (!skip_occlusion_plane) { - const bool is_in_front = sctx->runtime.params.use_occlusion_test && ob_eval && - (ob_eval->dtx & OB_DRAW_IN_FRONT) != 0; + const bool is_in_front = (sctx->runtime.params.occlusion_test == SNAP_OCCLUSION_AS_SEEM) && + ob_eval && (ob_eval->dtx & OB_DRAW_IN_FRONT) != 0; if (!is_in_front && sctx->runtime.has_occlusion_plane) { this->clip_planes.append(tobmat * sctx->runtime.occlusion_plane); } @@ -583,7 +583,9 @@ static eSnapMode raycast_obj_fn(SnapObjectContext *sctx, bool retval = false; if (ob_data == nullptr) { - if (sctx->runtime.use_occlusion_test_edit && ELEM(ob_eval->dt, OB_BOUNDBOX, OB_WIRE)) { + if ((sctx->runtime.occlusion_test_edit == SNAP_OCCLUSION_AS_SEEM) && + ELEM(ob_eval->dt, OB_BOUNDBOX, OB_WIRE)) + { /* Do not hit objects that are in wire or bounding box display mode. */ return SCE_SNAP_TO_NONE; } @@ -596,7 +598,9 @@ static eSnapMode raycast_obj_fn(SnapObjectContext *sctx, return SCE_SNAP_TO_NONE; } } - else if (sctx->runtime.params.use_occlusion_test && ELEM(ob_eval->dt, OB_BOUNDBOX, OB_WIRE)) { + else if ((sctx->runtime.params.occlusion_test == SNAP_OCCLUSION_AS_SEEM) && + ELEM(ob_eval->dt, OB_BOUNDBOX, OB_WIRE)) + { /* Do not hit objects that are in wire or bounding box display mode. */ return SCE_SNAP_TO_NONE; } @@ -1057,6 +1061,7 @@ static bool snap_object_context_runtime_init(SnapObjectContext *sctx, const ARegion *region, const View3D *v3d, eSnapMode snap_to_flag, + eSnapOcclusionTest occlusion_test, const SnapObjectParams *params, const float ray_start[3], const float ray_dir[3], @@ -1065,8 +1070,7 @@ static bool snap_object_context_runtime_init(SnapObjectContext *sctx, const float init_co[3], const float prev_co[3], const float dist_px_sq, - ListBase *hit_list, - bool use_occlusion_test) + ListBase *hit_list) { if (snap_to_flag & (SCE_SNAP_TO_GRID | SCE_SNAP_TO_EDGE_PERPENDICULAR | SCE_SNAP_INDIVIDUAL_NEAREST)) @@ -1094,9 +1098,9 @@ static bool snap_object_context_runtime_init(SnapObjectContext *sctx, sctx->runtime.v3d = v3d; sctx->runtime.snap_to_flag = snap_to_flag; sctx->runtime.params = *params; - sctx->runtime.params.use_occlusion_test = use_occlusion_test; - sctx->runtime.use_occlusion_test_edit = use_occlusion_test && - (snap_to_flag & SCE_SNAP_TO_FACE) == 0; + sctx->runtime.params.occlusion_test = occlusion_test; + sctx->runtime.occlusion_test_edit = (snap_to_flag & SCE_SNAP_TO_FACE) ? SNAP_OCCLUSION_ALWAYS : + occlusion_test; sctx->runtime.has_occlusion_plane = false; sctx->runtime.has_occlusion_plane_in_front = false; sctx->runtime.object_index = 0; @@ -1188,6 +1192,7 @@ bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx, nullptr, v3d, SCE_SNAP_TO_FACE, + params->occlusion_test, params, ray_start, ray_normal, @@ -1197,8 +1202,7 @@ bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx, nullptr, nullptr, 0, - nullptr, - params->use_occlusion_test)) + nullptr)) { return false; } @@ -1240,6 +1244,7 @@ bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx, nullptr, v3d, SCE_SNAP_TO_FACE, + params->occlusion_test, params, ray_start, ray_normal, @@ -1248,8 +1253,7 @@ bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx, nullptr, nullptr, 0, - r_hit_list, - params->use_occlusion_test)) + r_hit_list)) { return false; } @@ -1316,12 +1320,16 @@ eSnapMode ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, bool use_occlusion_plane = false; /* It is required `mval` to calculate the occlusion plane. */ - if (mval && (snap_to_flag & SCE_SNAP_TO_GEOM)) { - const bool is_allways_occluded = !params->use_occlusion_test; - use_occlusion_plane = is_allways_occluded || !XRAY_ENABLED(v3d); + if (mval && (snap_to_flag & (SCE_SNAP_TO_GEOM | SCE_SNAP_TO_GRID))) { + if (params->occlusion_test == SNAP_OCCLUSION_AS_SEEM) { + use_occlusion_plane = !XRAY_ENABLED(v3d); + } + else if (params->occlusion_test == SNAP_OCCLUSION_ALWAYS) { + use_occlusion_plane = true; + } } - if (use_occlusion_plane || (snap_to_flag & (SCE_SNAP_TO_FACE | SCE_SNAP_TO_GRID))) { + if (use_occlusion_plane || (snap_to_flag & SCE_SNAP_TO_FACE)) { /* Calculate the direction (`ray_dir`) and starting point (`ray_start`) of the ray from the * viewport to a 3D point under the mouse cursor (`mval`), taking into account potential view * clipping. @@ -1357,6 +1365,8 @@ eSnapMode ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, region, v3d, snap_to_flag, + use_occlusion_plane ? params->occlusion_test : + SNAP_OCCLUSION_NEVER, params, sctx->runtime.ray_start, sctx->runtime.ray_dir, @@ -1365,8 +1375,7 @@ eSnapMode ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, init_co, prev_co, dist_px ? square_f(*dist_px) : FLT_MAX, - nullptr, - use_occlusion_plane)) + nullptr)) { return retval; } diff --git a/source/blender/editors/transform/transform_snap_object.hh b/source/blender/editors/transform/transform_snap_object.hh index c912c946bce..a64aa0b0613 100644 --- a/source/blender/editors/transform/transform_snap_object.hh +++ b/source/blender/editors/transform/transform_snap_object.hh @@ -67,9 +67,10 @@ struct SnapObjectContext { /* Read/write. */ uint object_index; + eSnapOcclusionTest occlusion_test_edit; + bool has_occlusion_plane; bool has_occlusion_plane_in_front; - bool use_occlusion_test_edit; } runtime; /* Output. */ diff --git a/source/blender/editors/transform/transform_snap_object_mesh.cc b/source/blender/editors/transform/transform_snap_object_mesh.cc index aa916ffc403..5af0d5108e2 100644 --- a/source/blender/editors/transform/transform_snap_object_mesh.cc +++ b/source/blender/editors/transform/transform_snap_object_mesh.cc @@ -98,8 +98,8 @@ static bool raycastMesh(SnapObjectContext *sctx, /* Local scale in normal direction. */ ray_normal_local = math::normalize_and_get_length(ray_normal_local, local_scale); - const bool is_in_front = sctx->runtime.params.use_occlusion_test && - (ob_eval->dtx & OB_DRAW_IN_FRONT) != 0; + const bool is_in_front = (sctx->runtime.params.occlusion_test == SNAP_OCCLUSION_AS_SEEM) && + (ob_eval->dtx & OB_DRAW_IN_FRONT); const float depth_max = is_in_front ? sctx->ret.ray_depth_max_in_front : sctx->ret.ray_depth_max; local_depth = depth_max; if (local_depth != BVH_RAYCAST_DIST_MAX) {