From d33614550f236e9087aefde9a518f24045fc3d09 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 9 Jun 2023 09:19:11 -0300 Subject: [PATCH 1/4] UI: Snapping Redesign: Presets and filter support This commit adds presets for the snapping menu and object selection mode filters for each type of element to snap. --- scripts/presets/snapping/Default.py | 29 ++++ scripts/presets/snapping/Retopology.py | 19 +++ scripts/startup/bl_operators/presets.py | 33 ++++ scripts/startup/bl_ui/space_view3d.py | 82 ++++++---- .../blenloader/intern/versioning_300.cc | 2 +- .../blenloader/intern/versioning_400.cc | 14 ++ source/blender/editors/curve/editcurve.c | 3 +- .../gizmo_library/gizmo_types/move3d_gizmo.c | 1 - .../editors/gpencil_legacy/gpencil_utils.c | 4 +- .../ED_transform_snap_object_context.h | 10 +- source/blender/editors/mesh/editmesh_utils.c | 23 ++- .../editors/space_view3d/view3d_cursor_snap.c | 1 - .../editors/space_view3d/view3d_edit.c | 1 - .../space_view3d/view3d_gizmo_ruler.cc | 1 - .../space_view3d/view3d_navigate_walk.c | 5 +- source/blender/editors/transform/transform.c | 12 +- source/blender/editors/transform/transform.h | 6 +- .../transform/transform_mode_snapsource.c | 8 +- .../blender/editors/transform/transform_ops.c | 13 +- .../editors/transform/transform_snap.cc | 149 +++++++++++------- .../transform/transform_snap_object.cc | 64 ++++---- source/blender/makesdna/DNA_scene_defaults.h | 8 +- source/blender/makesdna/DNA_scene_types.h | 36 ++--- source/blender/makesrna/intern/rna_scene.c | 92 +++++++---- .../blender/makesrna/intern/rna_scene_api.c | 4 +- .../windowmanager/xr/intern/wm_xr_operators.c | 6 +- 26 files changed, 395 insertions(+), 231 deletions(-) create mode 100644 scripts/presets/snapping/Default.py create mode 100644 scripts/presets/snapping/Retopology.py diff --git a/scripts/presets/snapping/Default.py b/scripts/presets/snapping/Default.py new file mode 100644 index 00000000000..bc2b421d65c --- /dev/null +++ b/scripts/presets/snapping/Default.py @@ -0,0 +1,29 @@ + +attributes = ( + "snap_target", + "snap_elements", + "snap_filter_active", + "snap_filter_edit", + "snap_filter_nonedit", + "snap_filter_nonselectable", + "use_snap_grid_absolute", + "use_snap_peel_object", + "use_snap_to_same_target", + "snap_face_nearest_steps", + "use_snap_align_rotation", + "use_snap_backface_culling", + "use_snap_translate", + "use_snap_rotate", + "use_snap_scale", + "show_snap_filter", +) + +import bpy +toolsettings = bpy.context.scene.tool_settings +props = bpy.types.ToolSettings.bl_rna.properties +for attr in attributes: + prop = props[attr] + if prop.is_enum_flag: + setattr(toolsettings, attr, prop.default_flag) + else: + setattr(toolsettings, attr, prop.default) diff --git a/scripts/presets/snapping/Retopology.py b/scripts/presets/snapping/Retopology.py new file mode 100644 index 00000000000..7ce1cdfb77c --- /dev/null +++ b/scripts/presets/snapping/Retopology.py @@ -0,0 +1,19 @@ +import bpy +toolsettings = bpy.context.scene.tool_settings + +toolsettings.snap_target = 'MEDIAN' +toolsettings.snap_elements = {'FACE_PROJECT', 'FACE_NEAREST', 'VERTEX'} +toolsettings.snap_filter_active = {'FACE', 'EDGE_MIDPOINT', 'VOLUME', 'EDGE', 'EDGE_PERPENDICULAR', 'VERTEX'} +toolsettings.snap_filter_edit = {'FACE', 'EDGE_MIDPOINT', 'VOLUME', 'FACE_PROJECT', 'EDGE', 'EDGE_PERPENDICULAR', 'FACE_NEAREST', 'VERTEX'} +toolsettings.snap_filter_nonedit = {'FACE_PROJECT', 'FACE_NEAREST'} +toolsettings.snap_filter_nonselectable = {'FACE', 'EDGE_MIDPOINT', 'VOLUME', 'FACE_PROJECT', 'EDGE', 'EDGE_PERPENDICULAR', 'FACE_NEAREST', 'VERTEX'} +toolsettings.use_snap_grid_absolute = False +toolsettings.use_snap_peel_object = False +toolsettings.use_snap_to_same_target = False +toolsettings.snap_face_nearest_steps = 1 +toolsettings.use_snap_align_rotation = False +toolsettings.use_snap_backface_culling = False +toolsettings.use_snap_translate = True +toolsettings.use_snap_rotate = False +toolsettings.use_snap_scale = False +toolsettings.show_snap_filter = {'NONEDITED', 'ACTIVE'} diff --git a/scripts/startup/bl_operators/presets.py b/scripts/startup/bl_operators/presets.py index 0a9cef8f43b..e16e62c385a 100644 --- a/scripts/startup/bl_operators/presets.py +++ b/scripts/startup/bl_operators/presets.py @@ -413,6 +413,38 @@ class AddPresetHairDynamics(AddPresetBase, Operator): ] +class AddPresetSnapping(AddPresetBase, Operator): + """Add or remove a Snapping Preset""" + bl_idname = "scene.preset_add" + bl_label = "Add Snapping Preset" + preset_menu = "VIEW3D_MT_snapping_presets" + + preset_defines = [ + "toolsettings = bpy.context.scene.tool_settings" + ] + + preset_values = [ + "toolsettings.snap_target", + "toolsettings.snap_elements", + "toolsettings.snap_filter_active", + "toolsettings.snap_filter_edit", + "toolsettings.snap_filter_nonedit", + "toolsettings.snap_filter_nonselectable", + "toolsettings.use_snap_grid_absolute", + "toolsettings.use_snap_peel_object", + "toolsettings.use_snap_to_same_target", + "toolsettings.snap_face_nearest_steps", + "toolsettings.use_snap_align_rotation", + "toolsettings.use_snap_backface_culling", + "toolsettings.use_snap_translate", + "toolsettings.use_snap_rotate", + "toolsettings.use_snap_scale", + "toolsettings.show_snap_filter", + ] + + preset_subdir = "snapping" + + class AddPresetTextEditor(AddPresetBase, Operator): """Add or remove a Text Editor Preset""" bl_idname = "text_editor.preset_add" @@ -710,6 +742,7 @@ classes = ( AddPresetOperator, AddPresetRender, AddPresetCameraSafeAreas, + AddPresetSnapping, AddPresetTextEditor, AddPresetTrackingCamera, AddPresetTrackingSettings, diff --git a/scripts/startup/bl_ui/space_view3d.py b/scripts/startup/bl_ui/space_view3d.py index e96c3ed2793..68ea9ad6f0a 100644 --- a/scripts/startup/bl_ui/space_view3d.py +++ b/scripts/startup/bl_ui/space_view3d.py @@ -7060,11 +7060,48 @@ class VIEW3D_PT_overlay_weight_paint(Panel): col.prop(overlay, "show_paint_wire") +class VIEW3D_MT_snapping_presets(Menu): + bl_label = "Presets" + preset_subdir = "snapping" + preset_operator = "script.execute_preset" + draw = Menu.draw_preset + + class VIEW3D_PT_snapping(Panel): bl_space_type = 'VIEW_3D' bl_region_type = 'HEADER' bl_label = "Snapping" + @staticmethod + def draw_elements(layout, ts, prop): + def draw_filters(row, value): + if 'ACTIVE' in ts.show_snap_filter: + row.prop_enum(ts, "snap_filter_active", value, text="", icon='EDITMODE_HLT') + if 'EDITED' in ts.show_snap_filter: + row.prop_enum(ts, "snap_filter_edit", value, text="", icon='OUTLINER_DATA_MESH') + if 'NONEDITED' in ts.show_snap_filter: + row.prop_enum(ts, "snap_filter_nonedit", value, text="", icon='OUTLINER_OB_MESH') + if 'NONSELECTABLE' in ts.show_snap_filter: + row.prop_enum(ts, "snap_filter_nonselectable", value, text="", icon='RESTRICT_SELECT_ON') + + if not ts.show_snap_filter: + layout.prop(ts, prop) + return + + row = layout.row() + row.column().prop(ts, prop) + row_col = row.column() + for item in bpy.types.ToolSettings.bl_rna.properties[prop].enum_items: + row = row_col.row(align=True) + if item.identifier == 'INCREMENT': + row.ui_units_y = 0.92 + row.separator() + continue + + row.active = item.identifier in ts.snap_elements + row.scale_y = 0.92 + draw_filters(row, item.identifier) + def draw(self, context): tool_settings = context.tool_settings obj = context.active_object @@ -7073,15 +7110,26 @@ class VIEW3D_PT_snapping(Panel): layout = self.layout col = layout.column() + row = layout.row(align=True) + row.alignment = 'RIGHT' + row.menu("VIEW3D_MT_snapping_presets", text=VIEW3D_MT_snapping_presets.bl_label) + row.operator("scene.preset_add", text="", icon='ADD') + row.operator("scene.preset_add", text="", icon='REMOVE').remove_active = True + row.separator() + row.prop_menu_enum(tool_settings, "show_snap_filter", text="", icon='FILTER') + + col = layout.column() col.label(text="Snap With") row = col.row(align=True) row.prop(tool_settings, "snap_target", expand=True) + col.separator() col.label(text="Snap To") - col.prop(tool_settings, "snap_elements_base", expand=True) + self.draw_elements(col, tool_settings, "snap_elements_base") + col.separator() col.label(text="Snap Individual Elements To") - col.prop(tool_settings, "snap_elements_individual", expand=True) + self.draw_elements(col, tool_settings, "snap_elements_individual") col.separator() @@ -7103,35 +7151,6 @@ class VIEW3D_PT_snapping(Panel): col.separator() - if obj: - col.label(text="Target Selection") - col_targetsel = col.column(align=True) - if object_mode == 'EDIT' and obj.type not in {'LATTICE', 'META', 'FONT'}: - col_targetsel.prop( - tool_settings, - "use_snap_self", - text="Include Active", - icon='EDITMODE_HLT', - ) - col_targetsel.prop( - tool_settings, - "use_snap_edit", - text="Include Edited", - icon='OUTLINER_DATA_MESH', - ) - col_targetsel.prop( - tool_settings, - "use_snap_nonedit", - text="Include Non-Edited", - icon='OUTLINER_OB_MESH', - ) - col_targetsel.prop( - tool_settings, - "use_snap_selectable", - text="Exclude Non-Selectable", - icon='RESTRICT_SELECT_OFF', - ) - col.label(text="Affect") row = col.row(align=True) row.prop(tool_settings, "use_snap_translate", text="Move", toggle=True) @@ -8354,6 +8373,7 @@ classes = ( VIEW3D_MT_wpaint_vgroup_lock_pie, VIEW3D_MT_sculpt_face_sets_edit_pie, VIEW3D_MT_sculpt_curves, + VIEW3D_MT_snapping_presets, VIEW3D_PT_active_tool, VIEW3D_PT_active_tool_duplicate, VIEW3D_PT_view3d_properties, diff --git a/source/blender/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc index 98700c1baff..bc5b1995ed2 100644 --- a/source/blender/blenloader/intern/versioning_300.cc +++ b/source/blender/blenloader/intern/versioning_300.cc @@ -3874,7 +3874,7 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) /* Minimum of snap steps for face nearest is 1. */ tool_settings->snap_face_nearest_steps = 1; /* Set snap to edited and non-edited as default. */ - tool_settings->snap_flag |= SCE_SNAP_TO_INCLUDE_EDITED | SCE_SNAP_TO_INCLUDE_NONEDITED; + tool_settings->snap_flag |= SCE_SNAP_INCLUDE_EDITED | SCE_SNAP_INCLUDE_NONEDITED; } } } diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index bb6b5ee76ad..aec8f7c09eb 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -10,6 +10,7 @@ #include "CLG_log.h" +#include "DNA_defaults.h" #include "DNA_movieclip_types.h" #include "BLI_assert.h" @@ -182,13 +183,26 @@ void blo_do_versions_400(FileData * /*fd*/, Library * /*lib*/, Main *bmain) if (!MAIN_VERSION_ATLEAST(bmain, 400, 5)) { LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + const ToolSettings *ts_default = DNA_struct_default_get(ToolSettings); ToolSettings *ts = scene->toolsettings; + eSnapFlag view_filter_flag = (SCE_SNAP_INCLUDE_ACTIVE | SCE_SNAP_INCLUDE_EDITED | + SCE_SNAP_INCLUDE_NONEDITED | SCE_SNAP_INCLUDE_NONSELECTABLE); + if (ts->snap_mode_tools != SCE_SNAP_MODE_NONE) { ts->snap_mode_tools = SCE_SNAP_MODE_GEOM; } + ts->snap_mode = ts_default->snap_mode; + ts->snap_filter_active = ts_default->snap_filter_active; + ts->snap_filter_edit = ts_default->snap_filter_edit; + ts->snap_filter_nonedit = ts_default->snap_filter_nonedit; + ts->snap_filter_nonselectable = ts_default->snap_filter_nonselectable; + ts->snap_flag &= ~view_filter_flag; + ts->snap_flag |= ts_default->snap_flag & view_filter_flag; + #define SCE_SNAP_PROJECT (1 << 3) if (ts->snap_flag & SCE_SNAP_PROJECT) { + ts->snap_flag &= ~SCE_SNAP_PROJECT; ts->snap_mode |= SCE_SNAP_MODE_FACE_RAYCAST; } #undef SCE_SNAP_PROJECT diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 0c1afc8f52a..e0dd1809874 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -5644,9 +5644,8 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event) vc.v3d, SCE_SNAP_MODE_FACE, &(const struct SnapObjectParams){ - .snap_target_select = (vc.obedit != NULL) ? SCE_SNAP_TARGET_NOT_ACTIVE : - SCE_SNAP_TARGET_ALL, .edit_mode_type = SNAP_GEOM_FINAL, + .exclude_active = (vc.obedit != NULL) ? SCE_SNAP_MODE_GEOM_ALL : SCE_SNAP_MODE_NONE, }, NULL, mval, diff --git a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c index 016e92ed4bd..46262b59340 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c @@ -282,7 +282,6 @@ static int gizmo_move_modal(bContext *C, CTX_wm_view3d(C), (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE), &(const struct SnapObjectParams){ - .snap_target_select = SCE_SNAP_TARGET_ALL, .edit_mode_type = SNAP_GEOM_EDIT, .use_occlusion_test = true, }, diff --git a/source/blender/editors/gpencil_legacy/gpencil_utils.c b/source/blender/editors/gpencil_legacy/gpencil_utils.c index c32a7e40fa7..0425e693200 100644 --- a/source/blender/editors/gpencil_legacy/gpencil_utils.c +++ b/source/blender/editors/gpencil_legacy/gpencil_utils.c @@ -1152,9 +1152,7 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, if (ED_transform_snap_object_project_ray(sctx, depsgraph, v3d, - &(const struct SnapObjectParams){ - .snap_target_select = SCE_SNAP_TARGET_ALL, - }, + &(const struct SnapObjectParams){0}, &ray_start[0], &ray_normal[0], &depth, diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h index 353c7be6dab..3c1e0f77030 100644 --- a/source/blender/editors/include/ED_transform_snap_object_context.h +++ b/source/blender/editors/include/ED_transform_snap_object_context.h @@ -54,10 +54,16 @@ struct SnapObjectHitDepth { /** parameters that define which objects will be used to snap. */ struct SnapObjectParams { - /* Special context sensitive handling for the active or selected object. */ - eSnapTargetOP snap_target_select; /* Geometry for snapping in edit mode. */ eSnapEditType edit_mode_type; + + /* Filters. */ + eSnapMode exclude_active; + eSnapMode exclude_selected; + eSnapMode exclude_edited; + eSnapMode exclude_nonedited; + eSnapMode exclude_nonselectable; + /* snap to the closest element, use when using more than one snap type */ bool use_occlusion_test : 1; /* exclude back facing geometry from snapping */ diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 92b6ccfc342..e86eec8ef27 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -1925,17 +1925,18 @@ void EDBM_project_snap_verts( ED_view3d_init_mats_rv3d(obedit, region->regiondata); Scene *scene = CTX_data_scene(C); + ToolSettings *ts = scene->toolsettings; SnapObjectContext *snap_context = ED_transform_snap_object_context_create(scene, 0); - eSnapTargetOP target_op = SCE_SNAP_TARGET_NOT_ACTIVE; - const int snap_flag = scene->toolsettings->snap_flag; + struct SnapObjectParams snap_params = {0}; + snap_params.edit_mode_type = SNAP_GEOM_FINAL; + snap_params.exclude_active = SCE_SNAP_MODE_GEOM_ALL; + snap_params.exclude_edited = ~ts->snap_filter_edit; + snap_params.exclude_nonedited = ~ts->snap_filter_nonedit; + snap_params.exclude_nonselectable = ~ts->snap_filter_nonselectable; + snap_params.use_occlusion_test = true; - SET_FLAG_FROM_TEST( - target_op, !(snap_flag & SCE_SNAP_TO_INCLUDE_EDITED), SCE_SNAP_TARGET_NOT_EDITED); - SET_FLAG_FROM_TEST( - target_op, !(snap_flag & SCE_SNAP_TO_INCLUDE_NONEDITED), SCE_SNAP_TARGET_NOT_NONEDITED); - SET_FLAG_FROM_TEST( - target_op, (snap_flag & SCE_SNAP_TO_ONLY_SELECTABLE), SCE_SNAP_TARGET_ONLY_SELECTABLE); + const int snap_flag = scene->toolsettings->snap_flag; BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { @@ -1947,11 +1948,7 @@ void EDBM_project_snap_verts( region, CTX_wm_view3d(C), SCE_SNAP_MODE_FACE, - &(const struct SnapObjectParams){ - .snap_target_select = target_op, - .edit_mode_type = SNAP_GEOM_FINAL, - .use_occlusion_test = true, - }, + &snap_params, NULL, mval, NULL, diff --git a/source/blender/editors/space_view3d/view3d_cursor_snap.c b/source/blender/editors/space_view3d/view3d_cursor_snap.c index e044c888160..0b23e281d64 100644 --- a/source/blender/editors/space_view3d/view3d_cursor_snap.c +++ b/source/blender/editors/space_view3d/view3d_cursor_snap.c @@ -660,7 +660,6 @@ static void v3d_cursor_snap_update(V3DSnapCursorState *state, v3d, snap_elements, &(const struct SnapObjectParams){ - .snap_target_select = SCE_SNAP_TARGET_ALL, .edit_mode_type = edit_mode_type, .use_occlusion_test = use_occlusion_test, }, diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 4184f4c8579..ab443c05d76 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -913,7 +913,6 @@ void ED_view3d_cursor3d_position_rotation(bContext *C, v3d, SCE_SNAP_MODE_FACE, &(const struct SnapObjectParams){ - .snap_target_select = SCE_SNAP_TARGET_ALL, .edit_mode_type = SNAP_GEOM_FINAL, .use_occlusion_test = true, }, diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.cc b/source/blender/editors/space_view3d/view3d_gizmo_ruler.cc index 5a0541a591f..0f70e308d96 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.cc +++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.cc @@ -367,7 +367,6 @@ static bool view3d_ruler_item_mousemove(const bContext *C, float3 &co_other = ruler_item->co[inter->co_index == 0 ? 2 : 0]; SnapObjectParams snap_object_params{}; - snap_object_params.snap_target_select = SCE_SNAP_TARGET_ALL; snap_object_params.edit_mode_type = SNAP_GEOM_CAGE; eSnapMode hit = ED_transform_snap_object_project_view3d(snap_context, diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c index b7f9814a40c..d102b737fd4 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_walk.c +++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c @@ -408,7 +408,6 @@ static bool walk_floor_distance_get(RegionView3D *rv3d, walk->depsgraph, walk->v3d, &(const struct SnapObjectParams){ - .snap_target_select = SCE_SNAP_TARGET_ALL, /* Avoid having to convert the edit-mesh to a regular mesh. */ .edit_mode_type = SNAP_GEOM_EDIT, }, @@ -449,9 +448,7 @@ static bool walk_ray_cast(RegionView3D *rv3d, ret = ED_transform_snap_object_project_ray(walk->snap_context, walk->depsgraph, walk->v3d, - &(const struct SnapObjectParams){ - .snap_target_select = SCE_SNAP_TARGET_ALL, - }, + &(const struct SnapObjectParams){0}, ray_start, ray_normal, NULL, diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 415160025b7..a9acdd872cf 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1658,16 +1658,12 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) if ((prop = RNA_struct_find_property(op->ptr, "snap_elements"))) { RNA_property_enum_set(op->ptr, prop, t->tsnap.mode); - RNA_boolean_set( - op->ptr, "use_snap_project", (t->tsnap.mode & SCE_SNAP_MODE_FACE_RAYCAST) != 0); RNA_enum_set(op->ptr, "snap_target", t->tsnap.source_operation); - eSnapTargetOP target = t->tsnap.target_operation; - RNA_boolean_set(op->ptr, "use_snap_self", (target & SCE_SNAP_TARGET_NOT_ACTIVE) == 0); - RNA_boolean_set(op->ptr, "use_snap_edit", (target & SCE_SNAP_TARGET_NOT_EDITED) == 0); - RNA_boolean_set(op->ptr, "use_snap_nonedit", (target & SCE_SNAP_TARGET_NOT_NONEDITED) == 0); - RNA_boolean_set( - op->ptr, "use_snap_selectable", (target & SCE_SNAP_TARGET_ONLY_SELECTABLE) != 0); + RNA_boolean_set(op->ptr, "use_snap_self", t->tsnap.exclude_active == 0); + RNA_boolean_set(op->ptr, "use_snap_edit", t->tsnap.exclude_edited == 0); + RNA_boolean_set(op->ptr, "use_snap_nonedit", t->tsnap.exclude_nonedited == 0); + RNA_boolean_set(op->ptr, "use_snap_nonselectable", t->tsnap.exclude_nonselectable == 0); } /* Update `ToolSettings` for properties that change during modal. */ diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 508c85b04f3..2cf96ce909e 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -298,7 +298,11 @@ typedef struct TransSnap { /* Part of source to snap to target */ eSnapSourceOP source_operation; /* Determines which objects are possible target */ - eSnapTargetOP target_operation; + eSnapMode exclude_active; + eSnapMode exclude_selected; + eSnapMode exclude_edited; + eSnapMode exclude_nonedited; + eSnapMode exclude_nonselectable; short face_nearest_steps; eTSnap status; /* Snapped Element Type (currently for objects only). */ diff --git a/source/blender/editors/transform/transform_mode_snapsource.c b/source/blender/editors/transform/transform_mode_snapsource.c index 4148a9a47de..41509dd1697 100644 --- a/source/blender/editors/transform/transform_mode_snapsource.c +++ b/source/blender/editors/transform/transform_mode_snapsource.c @@ -37,7 +37,7 @@ struct SnapSouceCustomData { TransModeInfo *mode_info_prev; void *customdata_mode_prev; - eSnapTargetOP target_operation_prev; + eSnapMode exclude_selected_prev; struct { void (*apply)(TransInfo *t, MouseInput *mi, const double mval[2], float output[3]); @@ -55,7 +55,7 @@ static void snapsource_end(TransInfo *t) t->mode_info = customdata->mode_info_prev; t->custom.mode.data = customdata->customdata_mode_prev; - t->tsnap.target_operation = customdata->target_operation_prev; + t->tsnap.exclude_selected = customdata->exclude_selected_prev; t->mouse.apply = customdata->mouse_prev.apply; t->mouse.post = customdata->mouse_prev.post; @@ -165,7 +165,7 @@ void transform_mode_snap_source_init(TransInfo *t, wmOperator *UNUSED(op)) struct SnapSouceCustomData *customdata = MEM_callocN(sizeof(*customdata), __func__); customdata->mode_info_prev = t->mode_info; - customdata->target_operation_prev = t->tsnap.target_operation; + customdata->exclude_selected_prev = t->tsnap.exclude_selected; customdata->mouse_prev.apply = t->mouse.apply; customdata->mouse_prev.post = t->mouse.post; @@ -179,7 +179,7 @@ void transform_mode_snap_source_init(TransInfo *t, wmOperator *UNUSED(op)) } t->mode_info = &TransMode_snapsource; - t->tsnap.target_operation = SCE_SNAP_TARGET_ALL; + t->tsnap.exclude_selected = SCE_SNAP_MODE_NONE; t->tsnap.status &= ~SNAP_SOURCE_FOUND; if ((t->tsnap.mode & ~(SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) == 0) { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 3f239dde427..ba6809f331d 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -606,15 +606,6 @@ static bool transform_poll_property(const bContext *C, wmOperator *op, const Pro } } - /* Snapping. */ - { - if (STREQ(prop_id, "use_snap_project")) { - if (RNA_boolean_get(op->ptr, "snap") == false) { - return false; - } - } - } - return true; } @@ -705,8 +696,6 @@ void Transform_Properties(wmOperatorType *ot, int flags) ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_ENUM_FLAG); - RNA_def_boolean(ot->srna, "use_snap_project", false, "Project Individual Elements", ""); - /* TODO(@gfxcoder): Rename `snap_target` to `snap_source` to avoid previous ambiguity of * "target" (now, "source" is geometry to be moved and "target" is geometry to which moved * geometry is snapped). Use "Source snap point" and "Point on source that will snap to @@ -722,7 +711,7 @@ void Transform_Properties(wmOperatorType *ot, int flags) prop = RNA_def_boolean(ot->srna, "use_snap_nonedit", true, "Target: Include Non-Edited", ""); RNA_def_property_flag(prop, PROP_HIDDEN); prop = RNA_def_boolean( - ot->srna, "use_snap_selectable", false, "Target: Exclude Non-Selectable", ""); + ot->srna, "use_snap_selectable", true, "Target: Include Non-Selectable", ""); RNA_def_property_flag(prop, PROP_HIDDEN); prop = RNA_def_float_vector( diff --git a/source/blender/editors/transform/transform_snap.cc b/source/blender/editors/transform/transform_snap.cc index 23b4e9dc667..446e5dfeb85 100644 --- a/source/blender/editors/transform/transform_snap.cc +++ b/source/blender/editors/transform/transform_snap.cc @@ -77,7 +77,6 @@ static void snap_source_active_fn(TransInfo *t); /** \name Implementations * \{ */ -static bool snapNodeTest(View2D *v2d, bNode *node, eSnapTargetOP snap_target_select); static NodeBorder snapNodeBorder(eSnapMode snap_node_mode); #if 0 @@ -362,11 +361,31 @@ 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.exclude_active = t->tsnap.exclude_active & ~SCE_SNAP_MODE_FACE; + snap_object_params.exclude_selected = t->tsnap.exclude_selected & ~SCE_SNAP_MODE_FACE; + snap_object_params.exclude_edited = t->tsnap.exclude_edited & ~SCE_SNAP_MODE_FACE; + snap_object_params.exclude_nonedited = t->tsnap.exclude_nonedited & ~SCE_SNAP_MODE_FACE; + snap_object_params.exclude_nonselectable = t->tsnap.exclude_nonselectable & ~SCE_SNAP_MODE_FACE; snap_object_params.use_occlusion_test = false; snap_object_params.use_backface_culling = (t->tsnap.flag & SCE_SNAP_BACKFACE_CULLING) != 0; + SET_FLAG_FROM_TEST(snap_object_params.exclude_active, + snap_object_params.exclude_active & SCE_SNAP_MODE_FACE_RAYCAST, + SCE_SNAP_MODE_FACE); + SET_FLAG_FROM_TEST(snap_object_params.exclude_selected, + snap_object_params.exclude_selected & SCE_SNAP_MODE_FACE_RAYCAST, + SCE_SNAP_MODE_FACE); + SET_FLAG_FROM_TEST(snap_object_params.exclude_edited, + snap_object_params.exclude_edited & SCE_SNAP_MODE_FACE_RAYCAST, + SCE_SNAP_MODE_FACE); + SET_FLAG_FROM_TEST(snap_object_params.exclude_nonedited, + snap_object_params.exclude_nonedited & SCE_SNAP_MODE_FACE_RAYCAST, + SCE_SNAP_MODE_FACE); + SET_FLAG_FROM_TEST(snap_object_params.exclude_nonselectable, + snap_object_params.exclude_nonselectable & SCE_SNAP_MODE_FACE_RAYCAST, + SCE_SNAP_MODE_FACE); + eSnapMode hit = ED_transform_snap_object_project_view3d(t->tsnap.object_context, t->depsgraph, t->region, @@ -425,8 +444,12 @@ 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.exclude_active = t->tsnap.exclude_active; + snap_object_params.exclude_selected = t->tsnap.exclude_selected; + snap_object_params.exclude_edited = t->tsnap.exclude_edited; + snap_object_params.exclude_nonedited = t->tsnap.exclude_nonedited; + snap_object_params.exclude_nonselectable = t->tsnap.exclude_nonselectable; snap_object_params.use_occlusion_test = false; snap_object_params.use_backface_culling = false; snap_object_params.face_nearest_steps = t->tsnap.face_nearest_steps; @@ -545,7 +568,11 @@ void resetSnapping(TransInfo *t) t->tsnap.status = SNAP_RESETTED; t->tsnap.snapElem = SCE_SNAP_MODE_NONE; t->tsnap.mode = SCE_SNAP_MODE_NONE; - t->tsnap.target_operation = SCE_SNAP_TARGET_ALL; + t->tsnap.exclude_active = SCE_SNAP_MODE_NONE; + t->tsnap.exclude_selected = SCE_SNAP_MODE_NONE; + t->tsnap.exclude_edited = SCE_SNAP_MODE_NONE; + t->tsnap.exclude_nonedited = SCE_SNAP_MODE_NONE; + t->tsnap.exclude_nonselectable = SCE_SNAP_MODE_NONE; t->tsnap.source_operation = SCE_SNAP_SOURCE_CLOSEST; t->tsnap.last = 0; @@ -671,20 +698,26 @@ static eSnapMode snap_mode_from_spacetype(TransInfo *t) return SCE_SNAP_MODE_INCREMENT; } -static eSnapTargetOP snap_target_select_from_spacetype(TransInfo *t) +static void snap_target_select_from_spacetype(TransInfo *t, + eSnapMode *r_exclude_active, + eSnapMode *r_exclude_selected, + eSnapMode *r_exclude_edited, + eSnapMode *r_exclude_nonedited, + eSnapMode *r_exclude_nonselectable) { BKE_view_layer_synced_ensure(t->scene, t->view_layer); Base *base_act = BKE_view_layer_active_base_get(t->view_layer); - eSnapTargetOP ret = SCE_SNAP_TARGET_ALL; - - /* `t->tsnap.target_operation` not initialized yet. */ - BLI_assert(t->tsnap.target_operation == SCE_SNAP_TARGET_ALL); + *r_exclude_active = SCE_SNAP_MODE_NONE; + *r_exclude_selected = SCE_SNAP_MODE_NONE; + *r_exclude_edited = SCE_SNAP_MODE_NONE; + *r_exclude_nonedited = SCE_SNAP_MODE_NONE; + *r_exclude_nonselectable = SCE_SNAP_MODE_NONE; if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && !(t->options & CTX_CAMERA)) { if (base_act && (base_act->object->mode & OB_MODE_PARTICLE_EDIT)) { /* Particles edit mode. */ - return ret; + return; } if (t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) { @@ -693,7 +726,7 @@ static eSnapTargetOP snap_target_select_from_spacetype(TransInfo *t) * TODO: perform self snap in gpencil_strokes. * * When we're moving the origins, allow snapping onto our own geometry (see #69132). */ - return ret; + return; } const int obedit_type = t->obedit_type; @@ -703,28 +736,27 @@ static eSnapTargetOP snap_target_select_from_spacetype(TransInfo *t) /* Editing a mesh */ if ((t->flag & T_PROP_EDIT) != 0) { /* Exclude editmesh when using proportional edit */ - ret |= SCE_SNAP_TARGET_NOT_EDITED; + *r_exclude_edited = SCE_SNAP_MODE_GEOM_ALL; } /* UV editing must never snap to the selection as this is what is transformed. */ if (t->spacetype == SPACE_IMAGE) { - ret |= SCE_SNAP_TARGET_NOT_SELECTED; + *r_exclude_selected = SCE_SNAP_MODE_GEOM_ALL; } } else if (ELEM(obedit_type, OB_ARMATURE, OB_CURVES_LEGACY, OB_SURF, OB_LATTICE, OB_MBALL)) { /* Temporary limited to edit mode armature, curves, surfaces, lattices, and metaballs. */ - ret |= SCE_SNAP_TARGET_NOT_SELECTED; + *r_exclude_selected = SCE_SNAP_MODE_GEOM_ALL; } } else { /* Object or pose mode. */ - ret |= SCE_SNAP_TARGET_NOT_SELECTED | SCE_SNAP_TARGET_NOT_ACTIVE; + *r_exclude_active = SCE_SNAP_MODE_GEOM_ALL; + *r_exclude_selected = SCE_SNAP_MODE_GEOM_ALL; } } else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) { - ret |= SCE_SNAP_TARGET_NOT_SELECTED; + *r_exclude_selected = SCE_SNAP_MODE_GEOM_ALL; } - - return ret; } static void snap_object_context_init(TransInfo *t) @@ -793,9 +825,15 @@ void initSnapping(TransInfo *t, wmOperator *op) resetSnapping(t); t->tsnap.mode = snap_mode_from_spacetype(t); t->tsnap.flag = snap_flag_from_spacetype(t); - t->tsnap.target_operation = snap_target_select_from_spacetype(t); t->tsnap.face_nearest_steps = max_ii(ts->snap_face_nearest_steps, 1); + snap_target_select_from_spacetype(t, + &t->tsnap.exclude_active, + &t->tsnap.exclude_selected, + &t->tsnap.exclude_edited, + &t->tsnap.exclude_nonedited, + &t->tsnap.exclude_nonselectable); + /* if snap property exists */ PropertyRNA *prop; if (op && (prop = RNA_struct_find_property(op->ptr, "snap")) && @@ -835,44 +873,37 @@ void initSnapping(TransInfo *t, wmOperator *op) normalize_v3(t->tsnap.snapNormal); } - if ((prop = RNA_struct_find_property(op->ptr, "use_snap_project")) && - RNA_property_is_set(op->ptr, prop)) - { - SET_FLAG_FROM_TEST( - t->tsnap.mode, RNA_property_boolean_get(op->ptr, prop), SCE_SNAP_MODE_FACE_RAYCAST); - } - /* use_snap_self is misnamed and should be use_snap_active */ if ((prop = RNA_struct_find_property(op->ptr, "use_snap_self")) && RNA_property_is_set(op->ptr, prop)) { - SET_FLAG_FROM_TEST(t->tsnap.target_operation, + SET_FLAG_FROM_TEST(t->tsnap.exclude_active, !RNA_property_boolean_get(op->ptr, prop), - SCE_SNAP_TARGET_NOT_ACTIVE); + SCE_SNAP_MODE_GEOM_ALL); } if ((prop = RNA_struct_find_property(op->ptr, "use_snap_edit")) && RNA_property_is_set(op->ptr, prop)) { - SET_FLAG_FROM_TEST(t->tsnap.target_operation, + SET_FLAG_FROM_TEST(t->tsnap.exclude_edited, !RNA_property_boolean_get(op->ptr, prop), - SCE_SNAP_TARGET_NOT_EDITED); + SCE_SNAP_MODE_GEOM_ALL); } if ((prop = RNA_struct_find_property(op->ptr, "use_snap_nonedit")) && RNA_property_is_set(op->ptr, prop)) { - SET_FLAG_FROM_TEST(t->tsnap.target_operation, + SET_FLAG_FROM_TEST(t->tsnap.exclude_nonedited, !RNA_property_boolean_get(op->ptr, prop), - SCE_SNAP_TARGET_NOT_NONEDITED); + SCE_SNAP_MODE_GEOM_ALL); } - if ((prop = RNA_struct_find_property(op->ptr, "use_snap_selectable")) && + if ((prop = RNA_struct_find_property(op->ptr, "use_snap_nonselectable")) && RNA_property_is_set(op->ptr, prop)) { - SET_FLAG_FROM_TEST(t->tsnap.target_operation, - RNA_property_boolean_get(op->ptr, prop), - SCE_SNAP_TARGET_ONLY_SELECTABLE); + SET_FLAG_FROM_TEST(t->tsnap.exclude_nonselectable, + !RNA_property_boolean_get(op->ptr, prop), + SCE_SNAP_MODE_GEOM_ALL); } } } @@ -881,19 +912,11 @@ void initSnapping(TransInfo *t, wmOperator *op) if (t->tsnap.flag & SCE_SNAP) { t->modifiers |= MOD_SNAP; } - - SET_FLAG_FROM_TEST(t->tsnap.target_operation, - (ts->snap_flag & SCE_SNAP_NOT_TO_ACTIVE), - SCE_SNAP_TARGET_NOT_ACTIVE); - SET_FLAG_FROM_TEST(t->tsnap.target_operation, - !(ts->snap_flag & SCE_SNAP_TO_INCLUDE_EDITED), - SCE_SNAP_TARGET_NOT_EDITED); - SET_FLAG_FROM_TEST(t->tsnap.target_operation, - !(ts->snap_flag & SCE_SNAP_TO_INCLUDE_NONEDITED), - SCE_SNAP_TARGET_NOT_NONEDITED); - SET_FLAG_FROM_TEST(t->tsnap.target_operation, - (ts->snap_flag & SCE_SNAP_TO_ONLY_SELECTABLE), - SCE_SNAP_TARGET_ONLY_SELECTABLE); + t->tsnap.exclude_active |= SCE_SNAP_MODE_GEOM_ALL & ~eSnapMode(ts->snap_filter_active); + t->tsnap.exclude_edited |= SCE_SNAP_MODE_GEOM_ALL & ~eSnapMode(ts->snap_filter_edit); + t->tsnap.exclude_nonedited |= SCE_SNAP_MODE_GEOM_ALL & ~eSnapMode(ts->snap_filter_nonedit); + t->tsnap.exclude_nonselectable |= SCE_SNAP_MODE_GEOM_ALL & + ~eSnapMode(ts->snap_filter_nonselectable); } t->tsnap.source_operation = snap_source; @@ -1138,7 +1161,7 @@ static void snap_target_uv_fn(TransInfo *t, float * /*vec*/) objects, objects_len, t->mval, - t->tsnap.target_operation & SCE_SNAP_TARGET_NOT_SELECTED, + t->tsnap.exclude_selected != SCE_SNAP_MODE_NONE, &dist_sq, t->tsnap.snap_target)) { @@ -1385,8 +1408,12 @@ eSnapMode snapObjectsTransform( TransInfo *t, const float mval[2], float *dist_px, float r_loc[3], float r_no[3]) { 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.exclude_active = t->tsnap.exclude_active; + snap_object_params.exclude_selected = t->tsnap.exclude_selected; + snap_object_params.exclude_edited = t->tsnap.exclude_edited; + snap_object_params.exclude_nonedited = t->tsnap.exclude_nonedited; + snap_object_params.exclude_nonselectable = t->tsnap.exclude_nonselectable; snap_object_params.use_occlusion_test = true; snap_object_params.use_backface_culling = (t->tsnap.flag & SCE_SNAP_BACKFACE_CULLING) != 0; @@ -1395,7 +1422,7 @@ eSnapMode snapObjectsTransform( t->depsgraph, t->region, static_cast(t->view), - t->tsnap.mode, + t->tsnap.mode & SCE_SNAP_MODE_GEOM, &snap_object_params, nullptr, mval, @@ -1420,8 +1447,12 @@ bool peelObjectsTransform(TransInfo *t, float *r_thickness) { 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.exclude_active = t->tsnap.exclude_active; + snap_object_params.exclude_selected = t->tsnap.exclude_selected; + snap_object_params.exclude_edited = t->tsnap.exclude_edited; + snap_object_params.exclude_nonedited = t->tsnap.exclude_nonedited; + snap_object_params.exclude_nonselectable = t->tsnap.exclude_nonselectable; ListBase depths_peel = {nullptr}; ED_transform_snap_object_project_all_view3d_ex(t->tsnap.object_context, @@ -1498,11 +1529,11 @@ bool peelObjectsTransform(TransInfo *t, /** \name snap Nodes * \{ */ -static bool snapNodeTest(View2D *v2d, bNode *node, eSnapTargetOP snap_target_select) +static bool snapNodeTest(View2D *v2d, bNode *node, bool exclude_selected) { /* node is use for snapping only if a) snap mode matches and b) node is inside the view */ - return (((snap_target_select & SCE_SNAP_TARGET_NOT_SELECTED) && !(node->flag & NODE_SELECT)) || - (snap_target_select == SCE_SNAP_TARGET_ALL && !(node->flag & NODE_ACTIVE))) && + return ((exclude_selected && !(node->flag & NODE_SELECT)) || + (!exclude_selected && !(node->flag & NODE_ACTIVE))) && (node->runtime->totr.xmin < v2d->cur.xmax && node->runtime->totr.xmax > v2d->cur.xmin && node->runtime->totr.ymin < v2d->cur.ymax && node->runtime->totr.ymax > v2d->cur.ymin); } @@ -1583,7 +1614,7 @@ static bool snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *region, const int mval[2], - eSnapTargetOP snap_target_select, + bool exclude_selected, float r_loc[2], float *r_dist_px, char *r_node_border) @@ -1595,7 +1626,7 @@ static bool snapNodes(ToolSettings *ts, *r_node_border = 0; for (node = static_cast(ntree->nodes.first); node; node = node->next) { - if (snapNodeTest(®ion->v2d, node, snap_target_select)) { + if (snapNodeTest(®ion->v2d, node, exclude_selected)) { retval |= snapNode(ts, snode, region, node, mval, r_loc, r_dist_px, r_node_border); } } @@ -1610,7 +1641,7 @@ bool snapNodesTransform( static_cast(t->area->spacedata.first), t->region, mval, - t->tsnap.target_operation, + t->tsnap.exclude_selected != SCE_SNAP_MODE_NONE, r_loc, r_dist_px, r_node_border); diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index 8bc50ceca1b..ecdc46b1765 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -410,23 +410,22 @@ using IterSnapObjsCallback = eSnapMode (*)(SnapObjectContext *sctx, bool use_hide, void *data); -static bool snap_object_is_snappable(const SnapObjectContext *sctx, - const eSnapTargetOP snap_target_select, - const Base *base_act, - const Base *base) +static eSnapMode snap_object_mode_filter(const SnapObjectContext *sctx, + const SnapObjectParams *params, + eSnapMode snap_mode, + const Base *base_act, + const Base *base) { if (!BASE_VISIBLE(sctx->runtime.v3d, base)) { - return false; - } - - if ((snap_target_select == SCE_SNAP_TARGET_ALL) || - (base->flag_legacy & BA_TRANSFORM_LOCKED_IN_PLACE)) - { - return true; + return SCE_SNAP_MODE_NONE; } if (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) { - return false; + return SCE_SNAP_MODE_NONE; + } + + if (base->flag_legacy & BA_TRANSFORM_LOCKED_IN_PLACE) { + return snap_mode; } /* Get attributes of potential target. */ @@ -440,30 +439,30 @@ static bool snap_object_is_snappable(const SnapObjectContext *sctx, if (is_in_object_mode) { /* Handle target selection options that make sense for object mode. */ - if ((snap_target_select & SCE_SNAP_TARGET_NOT_SELECTED) && is_selected) { + if (is_selected) { /* What is selectable or not is part of the object and depends on the mode. */ - return false; + return snap_mode & ~params->exclude_selected; } } else { /* Handle target selection options that make sense for edit/pose mode. */ - if ((snap_target_select & SCE_SNAP_TARGET_NOT_ACTIVE) && is_active) { - return false; + if (is_active) { + return snap_mode & ~params->exclude_active; } - if ((snap_target_select & SCE_SNAP_TARGET_NOT_EDITED) && is_edited && !is_active) { + if (is_edited && !is_active) { /* Base is edited, but not active. */ - return false; + return snap_mode & ~params->exclude_edited; } - if ((snap_target_select & SCE_SNAP_TARGET_NOT_NONEDITED) && !is_edited) { - return false; + if (!is_edited) { + return snap_mode & ~params->exclude_nonedited; } } - if ((snap_target_select & SCE_SNAP_TARGET_ONLY_SELECTABLE) && !is_selectable) { - return false; + if (!is_selectable) { + return snap_mode & ~params->exclude_nonselectable; } - return true; + return snap_mode; } /** @@ -476,18 +475,23 @@ static eSnapMode iter_snap_objects(SnapObjectContext *sctx, { eSnapMode ret = SCE_SNAP_MODE_NONE; eSnapMode tmp; + eSnapMode snap_to_flag = sctx->runtime.snap_to_flag; Scene *scene = DEG_get_input_scene(sctx->runtime.depsgraph); ViewLayer *view_layer = DEG_get_input_view_layer(sctx->runtime.depsgraph); - const eSnapTargetOP snap_target_select = params->snap_target_select; BKE_view_layer_synced_ensure(scene, view_layer); Base *base_act = BKE_view_layer_active_base_get(view_layer); LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { - if (!snap_object_is_snappable(sctx, snap_target_select, base_act, base)) { + eSnapMode snap_mode_filtered = snap_object_mode_filter( + sctx, params, snap_to_flag, base_act, base); + + if (snap_mode_filtered == SCE_SNAP_MODE_NONE) { continue; } + sctx->runtime.snap_to_flag = snap_mode_filtered; + const bool is_object_active = (base == base_act); Object *obj_eval = DEG_get_evaluated_object(sctx->runtime.depsgraph, base->object); if (obj_eval->transflag & OB_DUPLI || BKE_object_has_geometry_set_instances(obj_eval)) { @@ -2101,7 +2105,8 @@ static eSnapMode snapArmature(SnapObjectContext *sctx, const bool is_posemode = is_object_active && (ob_eval->mode & OB_MODE_POSE); const bool skip_selected = (is_editmode || is_posemode) && - (params->snap_target_select & SCE_SNAP_TARGET_NOT_SELECTED); + (params->exclude_selected & + (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE)); const bool is_persp = sctx->runtime.view_proj == VIEW_PROJ_PERSP; if (arm->edbo) { @@ -2280,7 +2285,7 @@ static eSnapMode snapCurve(SnapObjectContext *sctx, } bool is_persp = sctx->runtime.view_proj == VIEW_PROJ_PERSP; - bool skip_selected = params->snap_target_select & SCE_SNAP_TARGET_NOT_SELECTED; + bool skip_selected = params->exclude_selected & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE); LISTBASE_FOREACH (Nurb *, nu, (use_obedit ? &cu->editnurb->nurbs : &cu->nurb)) { for (int u = 0; u < nu->pntsu; u++) { @@ -3276,8 +3281,6 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont sctx->ret.dist_sq = FLT_MAX; sctx->ret.is_edit = false; - BLI_assert(snap_to_flag & (SCE_SNAP_MODE_GEOM | SCE_SNAP_MODE_FACE_NEAREST)); - eSnapMode retval = SCE_SNAP_MODE_NONE; bool has_hit = false; @@ -3301,6 +3304,9 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont snap_to_flag &= ~SCE_SNAP_MODE_FACE_NEAREST; } + BLI_assert(snap_to_flag & (SCE_SNAP_MODE_GEOM | SCE_SNAP_MODE_FACE_NEAREST)); + sctx->runtime.snap_to_flag = snap_to_flag; + /* NOTE: if both face ray-cast and face nearest are enabled, first find result of nearest, then * override with ray-cast. */ if ((snap_to_flag & SCE_SNAP_MODE_FACE_NEAREST) && !has_hit) { diff --git a/source/blender/makesdna/DNA_scene_defaults.h b/source/blender/makesdna/DNA_scene_defaults.h index 7d32b304401..f3d47e38db0 100644 --- a/source/blender/makesdna/DNA_scene_defaults.h +++ b/source/blender/makesdna/DNA_scene_defaults.h @@ -336,10 +336,14 @@ .autokey_mode = AUTOKEY_MODE_NORMAL, \ \ .transform_pivot_point = V3D_AROUND_CENTER_MEDIAN, \ - .snap_mode = SCE_SNAP_MODE_INCREMENT, \ + .snap_mode = SCE_SNAP_MODE_GEOM, \ + .snap_filter_active = SCE_SNAP_MODE_GEOM_ALL, \ + .snap_filter_edit = SCE_SNAP_MODE_GEOM_ALL, \ + .snap_filter_nonedit = SCE_SNAP_MODE_GEOM_ALL, \ + .snap_filter_nonselectable = SCE_SNAP_MODE_GEOM_ALL, \ .snap_node_mode = SCE_SNAP_MODE_GRID, \ .snap_uv_mode = SCE_SNAP_MODE_INCREMENT, \ - .snap_flag = SCE_SNAP_TO_INCLUDE_EDITED | SCE_SNAP_TO_INCLUDE_NONEDITED, \ + .snap_flag = SCE_SNAP_INCLUDE_ACTIVE, \ .snap_transform_mode_flag = SCE_SNAP_TRANSFORM_MODE_TRANSLATE, \ .snap_face_nearest_steps = 1, \ \ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 3559612f36a..89fb0241a6b 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1617,6 +1617,10 @@ typedef struct ToolSettings { /** Snap elements (per space-type), #eSnapMode. */ char _pad1[1]; short snap_mode; + short snap_filter_active; + short snap_filter_edit; + short snap_filter_nonedit; + short snap_filter_nonselectable; char snap_node_mode; char snap_uv_mode; /** Generic flags (per space-type), #eSnapFlag. */ @@ -2254,16 +2258,15 @@ typedef enum eSnapFlag { SCE_SNAP = (1 << 0), SCE_SNAP_ROTATE = (1 << 1), SCE_SNAP_PEEL_OBJECT = (1 << 2), - // SCE_SNAP_PROJECT = (1 << 3), /* DEPRECATED, see #SCE_SNAP_MODE_FACE_RAYCAST. */ - /** Was `SCE_SNAP_NO_SELF`, but self should be active. */ - SCE_SNAP_NOT_TO_ACTIVE = (1 << 4), + SCE_SNAP_KEEP_ON_SAME_OBJECT = (1 << 3), + // SCE_SNAP_NOT_TO_ACTIVE = (1 << 4), /* DEPRECATED */ SCE_SNAP_ABS_GRID = (1 << 5), SCE_SNAP_BACKFACE_CULLING = (1 << 6), - SCE_SNAP_KEEP_ON_SAME_OBJECT = (1 << 7), /** see #eSnapTargetOP */ - SCE_SNAP_TO_INCLUDE_EDITED = (1 << 8), - SCE_SNAP_TO_INCLUDE_NONEDITED = (1 << 9), - SCE_SNAP_TO_ONLY_SELECTABLE = (1 << 10), + SCE_SNAP_INCLUDE_ACTIVE = (1 << 7), + SCE_SNAP_INCLUDE_EDITED = (1 << 8), + SCE_SNAP_INCLUDE_NONEDITED = (1 << 9), + SCE_SNAP_INCLUDE_NONSELECTABLE = (1 << 10), } eSnapFlag; /* Due to dependency conflicts with Cycles, header cannot directly include `BLI_utildefines.h`. */ /* TODO: move this macro to a more general place. */ @@ -2281,21 +2284,6 @@ typedef enum eSnapSourceOP { ENUM_OPERATORS(eSnapSourceOP, SCE_SNAP_SOURCE_ACTIVE) -/** - * #TransSnap.target_operation and #ToolSettings.snap_flag - * (#SCE_SNAP_NOT_TO_ACTIVE, #SCE_SNAP_TO_INCLUDE_EDITED, #SCE_SNAP_TO_INCLUDE_NONEDITED, - * #SCE_SNAP_TO_ONLY_SELECTABLE). - */ -typedef enum eSnapTargetOP { - SCE_SNAP_TARGET_ALL = 0, - SCE_SNAP_TARGET_NOT_SELECTED = (1 << 0), - SCE_SNAP_TARGET_NOT_ACTIVE = (1 << 1), - SCE_SNAP_TARGET_NOT_EDITED = (1 << 2), - SCE_SNAP_TARGET_ONLY_SELECTABLE = (1 << 3), - SCE_SNAP_TARGET_NOT_NONEDITED = (1 << 4), -} eSnapTargetOP; -ENUM_OPERATORS(eSnapTargetOP, SCE_SNAP_TARGET_NOT_NONEDITED) - /** #ToolSettings.snap_mode */ typedef enum eSnapMode { SCE_SNAP_MODE_NONE = 0, @@ -2330,6 +2318,10 @@ ENUM_OPERATORS(eSnapMode, SCE_SNAP_MODE_FACE_RAYCAST) (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | \ SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT) +#define SCE_SNAP_MODE_GEOM_ALL \ + (SCE_SNAP_MODE_GEOM | SCE_SNAP_MODE_VOLUME | SCE_SNAP_MODE_FACE_NEAREST | \ + SCE_SNAP_MODE_FACE_RAYCAST) + /** #SequencerToolSettings.snap_mode */ #define SEQ_SNAP_TO_STRIPS (1 << 0) #define SEQ_SNAP_TO_CURRENT_FRAME (1 << 1) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index c8b324b61ae..28aa95a959e 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -157,9 +157,9 @@ const EnumPropertyItem rna_enum_mesh_select_mode_uv_items[] = { {SCE_SNAP_MODE_VERTEX, "VERTEX", ICON_SNAP_VERTEX, "Vertex", "Snap to vertices"}, \ {SCE_SNAP_MODE_EDGE, "EDGE", ICON_SNAP_EDGE, "Edge", "Snap to edges"}, \ {SCE_SNAP_MODE_FACE, "FACE", ICON_SNAP_FACE, "Face", "Snap by projecting onto faces"}, \ - {SCE_SNAP_MODE_VOLUME, "VOLUME", ICON_SNAP_VOLUME, "Volume", "Snap to volume"}, \ {SCE_SNAP_MODE_EDGE_MIDPOINT, "EDGE_MIDPOINT", ICON_SNAP_MIDPOINT, "Edge Center", "Snap to the middle of edges"}, \ - {SCE_SNAP_MODE_EDGE_PERPENDICULAR, "EDGE_PERPENDICULAR", ICON_SNAP_PERPENDICULAR, "Edge Perpendicular", "Snap to the nearest point on an edge"} + {SCE_SNAP_MODE_EDGE_PERPENDICULAR, "EDGE_PERPENDICULAR", ICON_SNAP_PERPENDICULAR, "Edge Perpendicular", "Snap to the nearest point on an edge"}, \ + {SCE_SNAP_MODE_VOLUME, "VOLUME", ICON_SNAP_VOLUME, "Volume", "Snap to volume"} /* clang-format on */ const EnumPropertyItem rna_enum_snap_element_items[] = { @@ -186,6 +186,18 @@ const EnumPropertyItem rna_enum_snap_element_base_items[] = { const EnumPropertyItem *rna_enum_snap_element_individual_items = &rna_enum_snap_element_items[ARRAY_SIZE(rna_enum_snap_element_items) - 3]; +const EnumPropertyItem rna_enum_snap_select_filter_items[] = { + {SCE_SNAP_INCLUDE_ACTIVE, "ACTIVE", ICON_EDITMODE_HLT, "Active", ""}, + {SCE_SNAP_INCLUDE_EDITED, "EDITED", ICON_OUTLINER_DATA_MESH, "Edited", ""}, + {SCE_SNAP_INCLUDE_NONEDITED, "NONEDITED", ICON_OUTLINER_OB_MESH, "Non-edited", ""}, + {SCE_SNAP_INCLUDE_NONSELECTABLE, + "NONSELECTABLE", + ICON_RESTRICT_SELECT_ON, + "Non-selectable", + ""}, + {0, NULL, 0, NULL, NULL}, +}; + const EnumPropertyItem rna_enum_snap_node_element_items[] = { {SCE_SNAP_MODE_GRID, "GRID", ICON_SNAP_GRID, "Grid", "Snap to grid"}, {SCE_SNAP_MODE_NODE_X, "NODE_X", ICON_NODE_SIDE, "Node X", "Snap to left/right node border"}, @@ -755,6 +767,12 @@ static void rna_ToolSettings_snap_mode_set(struct PointerRNA *ptr, int value) } } +static int rna_ToolSettings_snap_flag_get(PointerRNA *ptr) +{ + ToolSettings *ts = (ToolSettings *)(ptr->data); + return ts->snap_flag; +} + /* Grease Pencil update cache */ static void rna_GPencil_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) { @@ -3411,6 +3429,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_enum_funcs( prop, "rna_ToolSettings_snap_mode_get", "rna_ToolSettings_snap_mode_set", NULL); RNA_def_property_flag(prop, PROP_ENUM_FLAG); + RNA_def_property_enum_default(prop, SCE_SNAP_MODE_GEOM); RNA_def_property_ui_text(prop, "Snap Element", "Type of element to snap to"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ @@ -3433,6 +3452,48 @@ static void rna_def_tool_settings(BlenderRNA *brna) prop, "Project Mode", "Type of element for individual transformed elements to snap to"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + prop = RNA_def_property(srna, "snap_filter_active", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_filter_active"); + RNA_def_property_enum_items(prop, rna_enum_snap_element_items); + RNA_def_property_flag(prop, PROP_ENUM_FLAG); + RNA_def_property_enum_default(prop, SCE_SNAP_MODE_GEOM_ALL); + RNA_def_property_ui_text(prop, "Snap onto Active", "Snap onto itself if in Edit Mode"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + + prop = RNA_def_property(srna, "snap_filter_edit", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_filter_edit"); + RNA_def_property_enum_items(prop, rna_enum_snap_element_items); + RNA_def_property_flag(prop, PROP_ENUM_FLAG); + RNA_def_property_enum_default(prop, SCE_SNAP_MODE_GEOM_ALL); + RNA_def_property_ui_text(prop, "Snap onto Edited", "Snap onto non-active objects in Edit Mode"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + + prop = RNA_def_property(srna, "snap_filter_nonedit", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_filter_nonedit"); + RNA_def_property_enum_items(prop, rna_enum_snap_element_items); + RNA_def_property_flag(prop, PROP_ENUM_FLAG); + RNA_def_property_enum_default(prop, SCE_SNAP_MODE_GEOM_ALL); + RNA_def_property_ui_text(prop, "Snap onto Non-edited", "Snap onto objects not in Edit Mode"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + + prop = RNA_def_property(srna, "snap_filter_nonselectable", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_filter_nonselectable"); + RNA_def_property_enum_items(prop, rna_enum_snap_element_items); + RNA_def_property_flag(prop, PROP_ENUM_FLAG); + RNA_def_property_enum_default(prop, SCE_SNAP_MODE_GEOM_ALL); + RNA_def_property_ui_text( + prop, "Snap onto Non-selectable", "Snap onto objects that are non-selectable"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + + prop = RNA_def_property(srna, "show_snap_filter", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "snap_flag"); + RNA_def_property_enum_items(prop, rna_enum_snap_select_filter_items); + RNA_def_property_enum_funcs(prop, "rna_ToolSettings_snap_flag_get", NULL, NULL); + RNA_def_property_flag(prop, PROP_ENUM_FLAG); + RNA_def_property_enum_default(prop, SCE_SNAP_INCLUDE_ACTIVE); + RNA_def_property_ui_text(prop, "Show Snap Filter", ""); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + prop = RNA_def_property(srna, "snap_face_nearest_steps", PROP_INT, PROP_FACTOR); RNA_def_property_int_sdna(prop, NULL, "snap_face_nearest_steps"); RNA_def_property_range(prop, 1, 100); @@ -3476,6 +3537,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "snap_target", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "snap_target"); RNA_def_property_enum_items(prop, rna_enum_snap_source_items); + RNA_def_property_enum_default(prop, SCE_SNAP_SOURCE_CLOSEST); RNA_def_property_ui_text(prop, "Snap Target", "Which part to snap onto the target"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ @@ -3490,32 +3552,6 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Backface Culling", "Exclude back facing geometry from snapping"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - /* TODO(@gfxcoder): Rename `use_snap_self` to `use_snap_active`, because active is correct but - * self is not (breaks API). This only makes a difference when more than one mesh is edited. */ - prop = RNA_def_property(srna, "use_snap_self", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "snap_flag", SCE_SNAP_NOT_TO_ACTIVE); - RNA_def_property_ui_text( - prop, "Snap onto Active", "Snap onto itself only if enabled (Edit Mode Only)"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - - prop = RNA_def_property(srna, "use_snap_edit", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_TO_INCLUDE_EDITED); - RNA_def_property_ui_text( - prop, "Snap onto Edited", "Snap onto non-active objects in Edit Mode (Edit Mode Only)"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - - prop = RNA_def_property(srna, "use_snap_nonedit", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_TO_INCLUDE_NONEDITED); - RNA_def_property_ui_text( - prop, "Snap onto Non-edited", "Snap onto objects not in Edit Mode (Edit Mode Only)"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - - prop = RNA_def_property(srna, "use_snap_selectable", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_TO_ONLY_SELECTABLE); - RNA_def_property_ui_text( - prop, "Snap onto Selectable Only", "Snap only onto objects that are selectable"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - prop = RNA_def_property(srna, "use_snap_translate", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna( prop, NULL, "snap_transform_mode_flag", SCE_SNAP_TRANSFORM_MODE_TRANSLATE); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index d2ca87df491..111c5cfdd3b 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -141,9 +141,7 @@ static void rna_Scene_ray_cast(Scene *scene, bool ret = ED_transform_snap_object_project_ray_ex(sctx, depsgraph, NULL, - &(const struct SnapObjectParams){ - .snap_target_select = SCE_SNAP_TARGET_ALL, - }, + &(const struct SnapObjectParams){0}, origin, direction, &ray_dist, diff --git a/source/blender/windowmanager/xr/intern/wm_xr_operators.c b/source/blender/windowmanager/xr/intern/wm_xr_operators.c index 2350d592640..59dc8e1a07c 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_operators.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_operators.c @@ -733,9 +733,9 @@ static void wm_xr_raycast(Scene *scene, sctx, depsgraph, NULL, - &(const struct SnapObjectParams){.snap_target_select = (selectable_only ? - SCE_SNAP_TARGET_ONLY_SELECTABLE : - SCE_SNAP_TARGET_ALL)}, + &(const struct SnapObjectParams){.exclude_nonselectable = (selectable_only ? + SCE_SNAP_MODE_GEOM_ALL : + SCE_SNAP_MODE_NONE)}, origin, direction, ray_dist, -- 2.30.2 From 3fec2b2dd9c2273b48ada5158f983d7976a2873a Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 9 Jun 2023 13:25:48 -0300 Subject: [PATCH 2/4] Fix occlusion test failing --- .../transform/transform_snap_object.cc | 92 ++++++++++--------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index ecdc46b1765..b2452fc745f 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -117,8 +117,10 @@ struct SnapObjectContext { struct { Depsgraph *depsgraph; + ViewLayer *view_layer; const ARegion *region; const View3D *v3d; + const Base *base_act; float mval[2]; float pmat[4][4]; /* perspective matrix */ @@ -143,6 +145,7 @@ struct SnapObjectContext { /* List of #SnapObjectHitDepth (caller must free). */ ListBase *hit_list; /* Snapped object. */ + Base *base; Object *ob; /* Snapped data. */ ID *data; @@ -476,18 +479,19 @@ static eSnapMode iter_snap_objects(SnapObjectContext *sctx, eSnapMode ret = SCE_SNAP_MODE_NONE; eSnapMode tmp; eSnapMode snap_to_flag = sctx->runtime.snap_to_flag; + const Base *base_act = sctx->runtime.base_act; - Scene *scene = DEG_get_input_scene(sctx->runtime.depsgraph); - ViewLayer *view_layer = DEG_get_input_view_layer(sctx->runtime.depsgraph); - BKE_view_layer_synced_ensure(scene, view_layer); - Base *base_act = BKE_view_layer_active_base_get(view_layer); + const bool use_occlusion_test = params->use_occlusion_test; - LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(sctx->runtime.view_layer)) { eSnapMode snap_mode_filtered = snap_object_mode_filter( sctx, params, snap_to_flag, base_act, base); if (snap_mode_filtered == SCE_SNAP_MODE_NONE) { - continue; + if (!use_occlusion_test || !(snap_to_flag & SCE_SNAP_MODE_FACE)) { + continue; + } + snap_mode_filtered = SCE_SNAP_MODE_FACE; } sctx->runtime.snap_to_flag = snap_mode_filtered; @@ -507,6 +511,7 @@ static eSnapMode iter_snap_objects(SnapObjectContext *sctx, false, data)) != SCE_SNAP_MODE_NONE) { + sctx->ret.base = base; ret = tmp; } } @@ -524,6 +529,7 @@ static eSnapMode iter_snap_objects(SnapObjectContext *sctx, use_hide, data)) != SCE_SNAP_MODE_NONE) { + sctx->ret.base = base; ret = tmp; } } @@ -1100,6 +1106,7 @@ static bool raycastObjects(SnapObjectContext *sctx, data.use_occlusion_test = use_occlusion_test; data.use_occlusion_test_edit = use_occlusion_test_edit; + sctx->runtime.snap_to_flag = SCE_SNAP_MODE_FACE; return iter_snap_objects(sctx, params, raycast_obj_fn, &data) != SCE_SNAP_MODE_NONE; } @@ -1771,6 +1778,12 @@ static eSnapMode snap_mesh_polygon(SnapObjectContext *sctx, float *dist_px) { eSnapMode elem = SCE_SNAP_MODE_NONE; + eSnapMode snap_mode_filtered = snap_object_mode_filter( + sctx, params, sctx->runtime.snap_to_flag, sctx->runtime.base_act, sctx->ret.base); + + if (snap_mode_filtered == SCE_SNAP_MODE_NONE) { + return elem; + } float lpmat[4][4]; mul_m4_m4m4(lpmat, sctx->runtime.pmat, sctx->ret.obmat); @@ -3039,6 +3052,32 @@ static eSnapMode snapObjectsRay(SnapObjectContext *sctx, return iter_snap_objects(sctx, params, snap_obj_fn, &data); } +static void snap_object_context_runtime_init(SnapObjectContext *sctx, + Depsgraph *depsgraph, + const ARegion *region, + const View3D *v3d, + ListBase *r_hit_list) +{ + sctx->runtime.depsgraph = depsgraph; + sctx->runtime.region = region; + sctx->runtime.v3d = v3d; + + Scene *scene = DEG_get_input_scene(depsgraph); + sctx->runtime.view_layer = DEG_get_input_view_layer(depsgraph); + BKE_view_layer_synced_ensure(scene, sctx->runtime.view_layer); + sctx->runtime.base_act = BKE_view_layer_active_base_get(sctx->runtime.view_layer); + + zero_v3(sctx->ret.loc); + zero_v3(sctx->ret.no); + sctx->ret.index = -1; + zero_m4(sctx->ret.obmat); + sctx->ret.hit_list = r_hit_list; + sctx->ret.ob = nullptr; + sctx->ret.data = nullptr; + sctx->ret.dist_sq = FLT_MAX; + sctx->ret.is_edit = false; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -3104,18 +3143,7 @@ bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx, Object **r_ob, float r_obmat[4][4]) { - sctx->runtime.depsgraph = depsgraph; - sctx->runtime.v3d = v3d; - - zero_v3(sctx->ret.loc); - zero_v3(sctx->ret.no); - sctx->ret.index = -1; - zero_m4(sctx->ret.obmat); - sctx->ret.hit_list = nullptr; - sctx->ret.ob = nullptr; - sctx->ret.data = nullptr; - sctx->ret.dist_sq = FLT_MAX; - sctx->ret.is_edit = false; + snap_object_context_runtime_init(sctx, depsgraph, nullptr, v3d, nullptr); if (raycastObjects(sctx, params, @@ -3153,18 +3181,7 @@ bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx, bool sort, ListBase *r_hit_list) { - sctx->runtime.depsgraph = depsgraph; - sctx->runtime.v3d = v3d; - - zero_v3(sctx->ret.loc); - zero_v3(sctx->ret.no); - sctx->ret.index = -1; - zero_m4(sctx->ret.obmat); - sctx->ret.hit_list = r_hit_list; - sctx->ret.ob = nullptr; - sctx->ret.data = nullptr; - sctx->ret.dist_sq = FLT_MAX; - sctx->ret.is_edit = false; + snap_object_context_runtime_init(sctx, depsgraph, nullptr, v3d, r_hit_list); if (ray_depth == -1.0f) { ray_depth = BVH_RAYCAST_DIST_MAX; @@ -3267,19 +3284,7 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont float r_obmat[4][4], float r_face_nor[3]) { - sctx->runtime.depsgraph = depsgraph; - sctx->runtime.region = region; - sctx->runtime.v3d = v3d; - - zero_v3(sctx->ret.loc); - zero_v3(sctx->ret.no); - sctx->ret.index = -1; - zero_m4(sctx->ret.obmat); - sctx->ret.hit_list = nullptr; - sctx->ret.ob = nullptr; - sctx->ret.data = nullptr; - sctx->ret.dist_sq = FLT_MAX; - sctx->ret.is_edit = false; + snap_object_context_runtime_init(sctx, depsgraph, region, v3d, nullptr); eSnapMode retval = SCE_SNAP_MODE_NONE; @@ -3305,7 +3310,6 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont } BLI_assert(snap_to_flag & (SCE_SNAP_MODE_GEOM | SCE_SNAP_MODE_FACE_NEAREST)); - sctx->runtime.snap_to_flag = snap_to_flag; /* NOTE: if both face ray-cast and face nearest are enabled, first find result of nearest, then * override with ray-cast. */ -- 2.30.2 From 2b178b272d2b629b02cb1ebdaafdf853a9218079 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 9 Jun 2023 14:24:45 -0300 Subject: [PATCH 3/4] Fixes: Snap to Face, Snap Nearest Mixed --- .../editors/transform/transform_snap_object.cc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index b2452fc745f..7236e4149ba 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -446,6 +446,7 @@ static eSnapMode snap_object_mode_filter(const SnapObjectContext *sctx, /* What is selectable or not is part of the object and depends on the mode. */ return snap_mode & ~params->exclude_selected; } + return snap_mode & ~params->exclude_nonedited; } else { /* Handle target selection options that make sense for edit/pose mode. */ @@ -481,17 +482,15 @@ static eSnapMode iter_snap_objects(SnapObjectContext *sctx, eSnapMode snap_to_flag = sctx->runtime.snap_to_flag; const Base *base_act = sctx->runtime.base_act; - const bool use_occlusion_test = params->use_occlusion_test; + const bool is_occlusion_test = params->use_occlusion_test && snap_to_flag == SCE_SNAP_MODE_NONE; LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(sctx->runtime.view_layer)) { - eSnapMode snap_mode_filtered = snap_object_mode_filter( - sctx, params, snap_to_flag, base_act, base); - - if (snap_mode_filtered == SCE_SNAP_MODE_NONE) { - if (!use_occlusion_test || !(snap_to_flag & SCE_SNAP_MODE_FACE)) { + eSnapMode snap_mode_filtered = snap_to_flag; + if (!is_occlusion_test) { + snap_mode_filtered = snap_object_mode_filter(sctx, params, snap_to_flag, base_act, base); + if (snap_mode_filtered == SCE_SNAP_MODE_NONE) { continue; } - snap_mode_filtered = SCE_SNAP_MODE_FACE; } sctx->runtime.snap_to_flag = snap_mode_filtered; @@ -1106,7 +1105,6 @@ static bool raycastObjects(SnapObjectContext *sctx, data.use_occlusion_test = use_occlusion_test; data.use_occlusion_test_edit = use_occlusion_test_edit; - sctx->runtime.snap_to_flag = SCE_SNAP_MODE_FACE; return iter_snap_objects(sctx, params, raycast_obj_fn, &data) != SCE_SNAP_MODE_NONE; } @@ -3145,6 +3143,7 @@ bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx, { snap_object_context_runtime_init(sctx, depsgraph, nullptr, v3d, nullptr); + sctx->runtime.snap_to_flag = SCE_SNAP_MODE_FACE; if (raycastObjects(sctx, params, ray_start, @@ -3191,6 +3190,7 @@ bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx, float ray_depth_prev = ray_depth; #endif + sctx->runtime.snap_to_flag = SCE_SNAP_MODE_FACE; if (raycastObjects(sctx, params, ray_start, @@ -3314,6 +3314,7 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont /* NOTE: if both face ray-cast and face nearest are enabled, first find result of nearest, then * override with ray-cast. */ if ((snap_to_flag & SCE_SNAP_MODE_FACE_NEAREST) && !has_hit) { + sctx->runtime.snap_to_flag = (snap_to_flag & SCE_SNAP_MODE_FACE_NEAREST); has_hit = nearestWorldObjects(sctx, params, init_co, prev_co); if (has_hit) { @@ -3345,6 +3346,7 @@ static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectCont float dummy_ray_depth = BVH_RAYCAST_DIST_MAX; + sctx->runtime.snap_to_flag = (snap_to_flag & SCE_SNAP_MODE_FACE); has_hit = raycastObjects(sctx, params, ray_start, -- 2.30.2 From 4d2cbba5a69dc1c790fa9e6a70fca74c2cccb5f7 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 9 Jun 2023 15:41:34 -0300 Subject: [PATCH 4/4] Fix Set Snap Base not including active object --- .../ED_transform_snap_object_context.h | 6 +++-- .../transform/transform_mode_snapsource.c | 4 ++++ .../editors/transform/transform_snap.cc | 4 ++++ .../transform/transform_snap_object.cc | 23 ++++++++++++------- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h index 3c1e0f77030..572304520d9 100644 --- a/source/blender/editors/include/ED_transform_snap_object_context.h +++ b/source/blender/editors/include/ED_transform_snap_object_context.h @@ -64,14 +64,16 @@ struct SnapObjectParams { eSnapMode exclude_nonedited; eSnapMode exclude_nonselectable; + /* snap to the closest element, use when using more than one snap type */ + bool exclude_moving : 1; /* 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; - /* Break nearest face snapping into steps to improve transformations across U-shaped targets. */ - short face_nearest_steps; /* Enable to force nearest face snapping to snap to target the source was initially near. */ bool keep_on_same_target : 1; + /* Break nearest face snapping into steps to improve transformations across U-shaped targets. */ + short face_nearest_steps; }; typedef struct SnapObjectContext SnapObjectContext; diff --git a/source/blender/editors/transform/transform_mode_snapsource.c b/source/blender/editors/transform/transform_mode_snapsource.c index 41509dd1697..7f0d76b9ea1 100644 --- a/source/blender/editors/transform/transform_mode_snapsource.c +++ b/source/blender/editors/transform/transform_mode_snapsource.c @@ -37,6 +37,7 @@ struct SnapSouceCustomData { TransModeInfo *mode_info_prev; void *customdata_mode_prev; + eSnapMode exclude_active_prev; eSnapMode exclude_selected_prev; struct { @@ -55,6 +56,7 @@ static void snapsource_end(TransInfo *t) t->mode_info = customdata->mode_info_prev; t->custom.mode.data = customdata->customdata_mode_prev; + t->tsnap.exclude_active = customdata->exclude_active_prev; t->tsnap.exclude_selected = customdata->exclude_selected_prev; t->mouse.apply = customdata->mouse_prev.apply; @@ -165,6 +167,7 @@ void transform_mode_snap_source_init(TransInfo *t, wmOperator *UNUSED(op)) struct SnapSouceCustomData *customdata = MEM_callocN(sizeof(*customdata), __func__); customdata->mode_info_prev = t->mode_info; + customdata->exclude_active_prev = t->tsnap.exclude_active; customdata->exclude_selected_prev = t->tsnap.exclude_selected; customdata->mouse_prev.apply = t->mouse.apply; @@ -179,6 +182,7 @@ void transform_mode_snap_source_init(TransInfo *t, wmOperator *UNUSED(op)) } t->mode_info = &TransMode_snapsource; + t->tsnap.exclude_active = SCE_SNAP_MODE_NONE; t->tsnap.exclude_selected = SCE_SNAP_MODE_NONE; t->tsnap.status &= ~SNAP_SOURCE_FOUND; diff --git a/source/blender/editors/transform/transform_snap.cc b/source/blender/editors/transform/transform_snap.cc index 446e5dfeb85..230483bc8cb 100644 --- a/source/blender/editors/transform/transform_snap.cc +++ b/source/blender/editors/transform/transform_snap.cc @@ -367,6 +367,7 @@ static bool applyFaceProject(TransInfo *t, TransDataContainer *tc, TransData *td snap_object_params.exclude_edited = t->tsnap.exclude_edited & ~SCE_SNAP_MODE_FACE; snap_object_params.exclude_nonedited = t->tsnap.exclude_nonedited & ~SCE_SNAP_MODE_FACE; snap_object_params.exclude_nonselectable = t->tsnap.exclude_nonselectable & ~SCE_SNAP_MODE_FACE; + snap_object_params.exclude_moving = !(t->modifiers & MOD_EDIT_SNAP_SOURCE); snap_object_params.use_occlusion_test = false; snap_object_params.use_backface_culling = (t->tsnap.flag & SCE_SNAP_BACKFACE_CULLING) != 0; @@ -450,6 +451,7 @@ static void applyFaceNearest(TransInfo *t, TransDataContainer *tc, TransData *td snap_object_params.exclude_edited = t->tsnap.exclude_edited; snap_object_params.exclude_nonedited = t->tsnap.exclude_nonedited; snap_object_params.exclude_nonselectable = t->tsnap.exclude_nonselectable; + snap_object_params.exclude_moving = !(t->modifiers & MOD_EDIT_SNAP_SOURCE); snap_object_params.use_occlusion_test = false; snap_object_params.use_backface_culling = false; snap_object_params.face_nearest_steps = t->tsnap.face_nearest_steps; @@ -1414,6 +1416,7 @@ eSnapMode snapObjectsTransform( snap_object_params.exclude_edited = t->tsnap.exclude_edited; snap_object_params.exclude_nonedited = t->tsnap.exclude_nonedited; snap_object_params.exclude_nonselectable = t->tsnap.exclude_nonselectable; + snap_object_params.exclude_moving = !(t->modifiers & MOD_EDIT_SNAP_SOURCE); snap_object_params.use_occlusion_test = true; snap_object_params.use_backface_culling = (t->tsnap.flag & SCE_SNAP_BACKFACE_CULLING) != 0; @@ -1453,6 +1456,7 @@ bool peelObjectsTransform(TransInfo *t, snap_object_params.exclude_edited = t->tsnap.exclude_edited; snap_object_params.exclude_nonedited = t->tsnap.exclude_nonedited; snap_object_params.exclude_nonselectable = t->tsnap.exclude_nonselectable; + snap_object_params.exclude_moving = !(t->modifiers & MOD_EDIT_SNAP_SOURCE); ListBase depths_peel = {nullptr}; ED_transform_snap_object_project_all_view3d_ex(t->tsnap.object_context, diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index 7236e4149ba..6bcf92f11e2 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -415,21 +415,28 @@ using IterSnapObjsCallback = eSnapMode (*)(SnapObjectContext *sctx, static eSnapMode snap_object_mode_filter(const SnapObjectContext *sctx, const SnapObjectParams *params, - eSnapMode snap_mode, - const Base *base_act, + const eSnapMode snap_mode, const Base *base) { if (!BASE_VISIBLE(sctx->runtime.v3d, base)) { return SCE_SNAP_MODE_NONE; } - if (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) { + if (base->flag_legacy & BA_TRANSFORM_LOCKED_IN_PLACE || + (params->exclude_active == SCE_SNAP_MODE_NONE && + params->exclude_selected == SCE_SNAP_MODE_NONE && + params->exclude_edited == SCE_SNAP_MODE_NONE && + params->exclude_nonedited == SCE_SNAP_MODE_NONE && + params->exclude_nonselectable == SCE_SNAP_MODE_NONE)) + { + return snap_mode; + } + + if (params->exclude_moving && base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) { return SCE_SNAP_MODE_NONE; } - if (base->flag_legacy & BA_TRANSFORM_LOCKED_IN_PLACE) { - return snap_mode; - } + const Base *base_act = sctx->runtime.base_act; /* Get attributes of potential target. */ const bool is_active = (base_act == base); @@ -487,7 +494,7 @@ static eSnapMode iter_snap_objects(SnapObjectContext *sctx, LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(sctx->runtime.view_layer)) { eSnapMode snap_mode_filtered = snap_to_flag; if (!is_occlusion_test) { - snap_mode_filtered = snap_object_mode_filter(sctx, params, snap_to_flag, base_act, base); + snap_mode_filtered = snap_object_mode_filter(sctx, params, snap_to_flag, base); if (snap_mode_filtered == SCE_SNAP_MODE_NONE) { continue; } @@ -1777,7 +1784,7 @@ static eSnapMode snap_mesh_polygon(SnapObjectContext *sctx, { eSnapMode elem = SCE_SNAP_MODE_NONE; eSnapMode snap_mode_filtered = snap_object_mode_filter( - sctx, params, sctx->runtime.snap_to_flag, sctx->runtime.base_act, sctx->ret.base); + sctx, params, sctx->runtime.snap_to_flag, sctx->ret.base); if (snap_mode_filtered == SCE_SNAP_MODE_NONE) { return elem; -- 2.30.2