diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index a6c9fa60eee..37aa7dbfa25 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -1165,10 +1165,10 @@ static bool snap_object_context_runtime_init(SnapObjectContext *sctx, } } } + sctx->runtime.hit_list = hit_list; sctx->ret.ray_depth_max = sctx->ret.ray_depth_max_in_front = ray_depth; sctx->ret.index = -1; - sctx->ret.hit_list = hit_list; sctx->ret.ob = nullptr; sctx->ret.data = nullptr; sctx->ret.dist_px_sq = dist_px_sq; @@ -1424,6 +1424,16 @@ eSnapMode snap_object_project_view3d_ex(SnapObjectContext *sctx, /* Remove what has already been computed. */ sctx->runtime.snap_to_flag &= ~(SCE_SNAP_TO_FACE | SCE_SNAP_INDIVIDUAL_NEAREST); + SnapObjectContext::Output ret_bak{}; + if (!(sctx->runtime.snap_to_flag & SCE_SNAP_TO_EDGE) && + (sctx->runtime.snap_to_flag & + (SCE_SNAP_TO_EDGE_MIDPOINT | SCE_SNAP_TO_EDGE_ENDPOINT | SCE_SNAP_TO_EDGE_PERPENDICULAR))) + { + /* 'Snap to Edge' may occur even if it is not included among the selected snap types. + * Save a backup to restore the previous result if needed. */ + ret_bak = sctx->ret; + } + if (use_occlusion_plane && has_hit) { /* Compute the new clip_pane but do not add it yet. */ BLI_ASSERT_UNIT_V3(sctx->ret.no); @@ -1454,11 +1464,18 @@ eSnapMode snap_object_project_view3d_ex(SnapObjectContext *sctx, elem = elem_test; } - if ((elem == SCE_SNAP_TO_EDGE) && - (snap_to_flag & - (SCE_SNAP_TO_EDGE_ENDPOINT | SCE_SNAP_TO_EDGE_MIDPOINT | SCE_SNAP_TO_EDGE_PERPENDICULAR))) - { - elem = snap_edge_points(sctx, square_f(*dist_px)); + if (elem == SCE_SNAP_TO_EDGE) { + if (snap_to_flag & + (SCE_SNAP_TO_EDGE_ENDPOINT | SCE_SNAP_TO_EDGE_MIDPOINT | SCE_SNAP_TO_EDGE_PERPENDICULAR)) + { + elem = snap_edge_points(sctx, square_f(*dist_px)); + } + + if (!(elem & snap_to_flag)) { + /* Restore the previous snap. */ + elem = SCE_SNAP_TO_NONE; + sctx->ret = ret_bak; + } } if (elem != SCE_SNAP_TO_NONE) { diff --git a/source/blender/editors/transform/transform_snap_object.hh b/source/blender/editors/transform/transform_snap_object.hh index b196d53d391..b472a7e3c50 100644 --- a/source/blender/editors/transform/transform_snap_object.hh +++ b/source/blender/editors/transform/transform_snap_object.hh @@ -86,6 +86,8 @@ struct SnapObjectContext { /* Read/write. */ uint object_index; + /* List of #SnapObjectHitDepth (caller must free). */ + ListBase *hit_list; eSnapOcclusionTest occlusion_test_edit; @@ -94,7 +96,7 @@ struct SnapObjectContext { } runtime; /* Output. */ - struct { + struct Output { /* Location of snapped point on target surface. */ float3 loc; /* Normal of snapped point on target surface. */ @@ -103,8 +105,6 @@ struct SnapObjectContext { int index; /* Matrix of target object (may not be #Object.object_to_world with dupli-instances). */ float4x4 obmat; - /* List of #SnapObjectHitDepth (caller must free). */ - ListBase *hit_list; /* Snapped object. */ const Object *ob; /* Snapped data. */ diff --git a/source/blender/editors/transform/transform_snap_object_mesh.cc b/source/blender/editors/transform/transform_snap_object_mesh.cc index a927afc18ee..eaa94f890a1 100644 --- a/source/blender/editors/transform/transform_snap_object_mesh.cc +++ b/source/blender/editors/transform/transform_snap_object_mesh.cc @@ -140,7 +140,7 @@ static bool raycastMesh(SnapObjectContext *sctx, } BLI_assert(treedata.raycast_callback != nullptr); - if (sctx->ret.hit_list) { + if (sctx->runtime.hit_list) { RayCastAll_Data data; data.bvhdata = &treedata; @@ -149,7 +149,7 @@ static bool raycastMesh(SnapObjectContext *sctx, data.len_diff = len_diff; data.local_scale = local_scale; data.ob_uuid = ob_index; - data.hit_list = sctx->ret.hit_list; + data.hit_list = sctx->runtime.hit_list; void *hit_last_prev = data.hit_list->last; BLI_bvhtree_ray_cast_all(