From 060174cf149c2b05ce09a0dfed33005f1fe15c28 Mon Sep 17 00:00:00 2001 From: Kyler Kelly Date: Sat, 9 Mar 2024 16:50:06 +1100 Subject: [PATCH] Transform: customizable rotation snap increment values Add two snapping increment options: a regular value (activated with Ctrl) and a precise value (activated with Ctrl+Shift). These values are separate for 2D and 3D views. Ref !118760 --- scripts/startup/bl_ui/space_image.py | 4 +++ scripts/startup/bl_ui/space_view3d.py | 4 +++ .../blender/blenkernel/BKE_blender_version.h | 2 +- .../blenloader/intern/versioning_400.cc | 14 ++++++++ .../blenloader/intern/versioning_defaults.cc | 8 +++++ .../gizmo_library/gizmo_types/dial3d_gizmo.cc | 25 ++++++++++---- source/blender/editors/transform/transform.cc | 13 +++++-- .../editors/transform/transform_mode_bend.cc | 3 +- .../transform/transform_mode_boneroll.cc | 3 +- .../transform_mode_edge_rotate_normal.cc | 3 +- .../transform/transform_mode_rotate.cc | 3 +- .../editors/transform/transform_mode_tilt.cc | 3 +- .../editors/transform/transform_snap.cc | 12 +++++++ .../editors/transform/transform_snap.hh | 1 + source/blender/makesdna/DNA_scene_defaults.h | 4 +++ source/blender/makesdna/DNA_scene_types.h | 6 ++++ source/blender/makesrna/intern/rna_scene.cc | 34 +++++++++++++++++++ 17 files changed, 122 insertions(+), 20 deletions(-) diff --git a/scripts/startup/bl_ui/space_image.py b/scripts/startup/bl_ui/space_image.py index 05b0d6c3051..f0fcc4bd595 100644 --- a/scripts/startup/bl_ui/space_image.py +++ b/scripts/startup/bl_ui/space_image.py @@ -996,6 +996,10 @@ class IMAGE_PT_snapping(Panel): row.prop(tool_settings, "use_snap_translate", text="Move", toggle=True) row.prop(tool_settings, "use_snap_rotate", text="Rotate", toggle=True) row.prop(tool_settings, "use_snap_scale", text="Scale", toggle=True) + col.label(text="Rotation Increment") + row = col.row(align=True) + row.prop(tool_settings, "snap_angle_increment_2d", text="") + row.prop(tool_settings, "snap_angle_increment_2d_precision", text="") class IMAGE_PT_proportional_edit(Panel): diff --git a/scripts/startup/bl_ui/space_view3d.py b/scripts/startup/bl_ui/space_view3d.py index 61b50501dfa..d602c528dfc 100644 --- a/scripts/startup/bl_ui/space_view3d.py +++ b/scripts/startup/bl_ui/space_view3d.py @@ -7591,6 +7591,10 @@ class VIEW3D_PT_snapping(Panel): row.prop(tool_settings, "use_snap_translate", text="Move", toggle=True) row.prop(tool_settings, "use_snap_rotate", text="Rotate", toggle=True) row.prop(tool_settings, "use_snap_scale", text="Scale", toggle=True) + col.label(text="Rotation Increment") + row = col.row(align=True) + row.prop(tool_settings, "snap_angle_increment_3d", text="") + row.prop(tool_settings, "snap_angle_increment_3d_precision", text="") class VIEW3D_PT_proportional_edit(Panel): diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 7946438710f..dd074b2c94d 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -29,7 +29,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 8 +#define BLENDER_FILE_SUBVERSION 9 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index c7071224504..f37b229ec7d 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -38,6 +38,7 @@ #include "BLI_assert.h" #include "BLI_listbase.h" #include "BLI_map.hh" +#include "BLI_math_rotation.h" #include "BLI_math_vector.h" #include "BLI_set.hh" #include "BLI_string.h" @@ -2981,6 +2982,19 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain) } } + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 9)) { + const float default_snap_angle_increment = DEG2RADF(15.0f); + const float default_snap_angle_increment_precision = DEG2RADF(5.0f); + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + scene->toolsettings->snap_angle_increment_2d = default_snap_angle_increment; + scene->toolsettings->snap_angle_increment_3d = default_snap_angle_increment; + scene->toolsettings->snap_angle_increment_2d_precision = + default_snap_angle_increment_precision; + scene->toolsettings->snap_angle_increment_3d_precision = + default_snap_angle_increment_precision; + } + } + /** * Always bump subversion in BKE_blender_version.h when adding versioning * code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check. diff --git a/source/blender/blenloader/intern/versioning_defaults.cc b/source/blender/blenloader/intern/versioning_defaults.cc index 913b7688d73..846b2679a15 100644 --- a/source/blender/blenloader/intern/versioning_defaults.cc +++ b/source/blender/blenloader/intern/versioning_defaults.cc @@ -329,6 +329,14 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene) /* Enable Soft Shadows by default. */ scene->eevee.flag |= SCE_EEVEE_SHADOW_SOFT; + /* Default Rotate Increment*/ + const float default_snap_angle_increment = DEG2RADF(15.0f); + scene->toolsettings->snap_angle_increment_2d = default_snap_angle_increment; + scene->toolsettings->snap_angle_increment_3d = default_snap_angle_increment; + const float default_snap_angle_increment_precision = DEG2RADF(5.0f); + scene->toolsettings->snap_angle_increment_2d_precision = default_snap_angle_increment_precision; + scene->toolsettings->snap_angle_increment_3d_precision = default_snap_angle_increment_precision; + /* Be sure `curfalloff` and primitive are initialized. */ ToolSettings *ts = scene->toolsettings; if (ts->gp_sculpt.cur_falloff == nullptr) { diff --git a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.cc b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.cc index 09beb7cd5e9..4500f4c1785 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.cc +++ b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.cc @@ -214,9 +214,10 @@ static void dial_ghostarc_draw_helpline(const float angle, /** * Draws segments to indicate the position of each increment. */ -static void dial_ghostarc_draw_incremental_angle(const float incremental_angle, const float offset) +static void dial_ghostarc_draw_incremental_angle(const float incremental_angle, + const float offset, + const float angle_delta) { - const int tot_incr = (2 * M_PI) / incremental_angle; uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); @@ -228,12 +229,21 @@ static void dial_ghostarc_draw_incremental_angle(const float incremental_angle, immUniform2fv("viewportSize", &viewport[2]); immUniform1f("lineWidth", U.pixelsize); - immBegin(GPU_PRIM_LINES, tot_incr * 2); + const int current_increment = roundf(angle_delta / incremental_angle); + const int total_increment = roundf((M_PI * 2.0f) / incremental_angle); + + immBegin(GPU_PRIM_LINES, total_increment * 2); + + /* Chop off excess full circles, draw an arc of ticks centered at current increment; + * if there's no even division of circle by increment, + * ends of the arc will move with the rotation */ + const float start_offset = fmodf( + offset + incremental_angle * (current_increment - total_increment / 2), M_PI * 2.0f); float v[3] = {0}; - for (int i = 0; i < tot_incr; i++) { - v[0] = sinf(offset + incremental_angle * i); - v[1] = cosf(offset + incremental_angle * i); + for (int i = 0; i < total_increment; i++) { + v[0] = sinf(start_offset + incremental_angle * i); + v[1] = cosf(start_offset + incremental_angle * i); mul_v2_fl(v, DIAL_WIDTH * 1.1f); immVertex3fv(pos, v); @@ -639,7 +649,8 @@ static void dial_3d_draw_util(const float matrix_final[4][4], } if (params->angle_increment) { - dial_ghostarc_draw_incremental_angle(params->angle_increment, params->angle_ofs); + dial_ghostarc_draw_incremental_angle( + params->angle_increment, params->angle_ofs, params->angle_delta); } /* Draw actual dial gizmo. */ diff --git a/source/blender/editors/transform/transform.cc b/source/blender/editors/transform/transform.cc index 8d25f64c028..dbfb5e60b02 100644 --- a/source/blender/editors/transform/transform.cc +++ b/source/blender/editors/transform/transform.cc @@ -1311,8 +1311,17 @@ int transformEvent(TransInfo *t, const wmEvent *event) } else if (event->prev_val == KM_PRESS) { t->modifiers |= MOD_PRECISION; - /* Shift is modifier for higher precision transform. */ - t->mouse.precision = true; + /* If we are already in a snapping mode, + * we don't want to add mouse precision, it makes things like rotate snap really + * tedious*/ + if (t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) { + t->mouse.precision = false; + } + else { + /* Shift is modifier for higher precision transform. */ + t->mouse.precision = true; + } + t->redraw |= TREDRAW_HARD; } else if (event->prev_val == KM_RELEASE) { diff --git a/source/blender/editors/transform/transform_mode_bend.cc b/source/blender/editors/transform/transform_mode_bend.cc index 444620d1a4c..4fea54dbbc5 100644 --- a/source/blender/editors/transform/transform_mode_bend.cc +++ b/source/blender/editors/transform/transform_mode_bend.cc @@ -337,8 +337,7 @@ static void initBend(TransInfo *t, wmOperator * /*op*/) t->idx_max = 1; t->num.idx_max = 1; - t->snap[0] = SNAP_INCREMENTAL_ANGLE; - t->snap[1] = t->snap[0] * 0.2; + initSnapAngleIncrements(t); copy_v3_fl(t->num.val_inc, t->snap[0]); t->num.unit_sys = t->scene->unit.system; diff --git a/source/blender/editors/transform/transform_mode_boneroll.cc b/source/blender/editors/transform/transform_mode_boneroll.cc index ece49b7fff1..dc8819675d0 100644 --- a/source/blender/editors/transform/transform_mode_boneroll.cc +++ b/source/blender/editors/transform/transform_mode_boneroll.cc @@ -81,8 +81,7 @@ static void initBoneRoll(TransInfo *t, wmOperator * /*op*/) t->idx_max = 0; t->num.idx_max = 0; - t->snap[0] = DEG2RAD(5.0); - t->snap[1] = DEG2RAD(1.0); + initSnapAngleIncrements(t); copy_v3_fl(t->num.val_inc, t->snap[0]); t->num.unit_sys = t->scene->unit.system; diff --git a/source/blender/editors/transform/transform_mode_edge_rotate_normal.cc b/source/blender/editors/transform/transform_mode_edge_rotate_normal.cc index 19982f90f14..5fbc9b180a2 100644 --- a/source/blender/editors/transform/transform_mode_edge_rotate_normal.cc +++ b/source/blender/editors/transform/transform_mode_edge_rotate_normal.cc @@ -118,8 +118,7 @@ static void initNormalRotation(TransInfo *t, wmOperator * /*op*/) t->idx_max = 0; t->num.idx_max = 0; - t->snap[0] = DEG2RAD(5.0); - t->snap[1] = DEG2RAD(1.0); + initSnapAngleIncrements(t); copy_v3_fl(t->num.val_inc, t->snap[1]); t->num.unit_sys = t->scene->unit.system; diff --git a/source/blender/editors/transform/transform_mode_rotate.cc b/source/blender/editors/transform/transform_mode_rotate.cc index 70cd1e7db97..91108fb1020 100644 --- a/source/blender/editors/transform/transform_mode_rotate.cc +++ b/source/blender/editors/transform/transform_mode_rotate.cc @@ -412,8 +412,7 @@ static void initRotation(TransInfo *t, wmOperator * /*op*/) t->idx_max = 0; t->num.idx_max = 0; - t->snap[0] = DEG2RAD(5.0); - t->snap[1] = DEG2RAD(1.0); + initSnapAngleIncrements(t); copy_v3_fl(t->num.val_inc, t->snap[1]); t->num.unit_sys = t->scene->unit.system; diff --git a/source/blender/editors/transform/transform_mode_tilt.cc b/source/blender/editors/transform/transform_mode_tilt.cc index 8cb5817090f..57157118d3b 100644 --- a/source/blender/editors/transform/transform_mode_tilt.cc +++ b/source/blender/editors/transform/transform_mode_tilt.cc @@ -86,8 +86,7 @@ static void initTilt(TransInfo *t, wmOperator * /*op*/) t->idx_max = 0; t->num.idx_max = 0; - t->snap[0] = DEG2RAD(5.0); - t->snap[1] = DEG2RAD(1.0); + initSnapAngleIncrements(t); copy_v3_fl(t->num.val_inc, t->snap[1]); t->num.unit_sys = t->scene->unit.system; diff --git a/source/blender/editors/transform/transform_snap.cc b/source/blender/editors/transform/transform_snap.cc index 97abbd92aaa..892e03b8d3e 100644 --- a/source/blender/editors/transform/transform_snap.cc +++ b/source/blender/editors/transform/transform_snap.cc @@ -961,6 +961,18 @@ void freeSnapping(TransInfo *t) } } +void initSnapAngleIncrements(TransInfo *t) +{ + if (t->spacetype == SPACE_VIEW3D) { + t->snap[0] = t->settings->snap_angle_increment_3d; + t->snap[1] = t->settings->snap_angle_increment_3d_precision; + } + else { + t->snap[0] = t->settings->snap_angle_increment_2d; + t->snap[1] = t->settings->snap_angle_increment_2d_precision; + } +} + static void setSnappingCallback(TransInfo *t) { if (t->spacetype == SPACE_VIEW3D) { diff --git a/source/blender/editors/transform/transform_snap.hh b/source/blender/editors/transform/transform_snap.hh index 79a23f518b9..5a5a4cfb78a 100644 --- a/source/blender/editors/transform/transform_snap.hh +++ b/source/blender/editors/transform/transform_snap.hh @@ -51,6 +51,7 @@ bool validSnap(const TransInfo *t); void initSnapping(TransInfo *t, wmOperator *op); void freeSnapping(TransInfo *t); +void initSnapAngleIncrements(TransInfo *t); bool transform_snap_project_individual_is_active(const TransInfo *t); void transform_snap_project_individual_apply(TransInfo *t); void transform_snap_mixed_apply(TransInfo *t, float *vec); diff --git a/source/blender/makesdna/DNA_scene_defaults.h b/source/blender/makesdna/DNA_scene_defaults.h index 26ee78c4ed3..cbcb8f72d0d 100644 --- a/source/blender/makesdna/DNA_scene_defaults.h +++ b/source/blender/makesdna/DNA_scene_defaults.h @@ -377,6 +377,10 @@ .snap_flag_anim = SCE_SNAP, \ .snap_transform_mode_flag = SCE_SNAP_TRANSFORM_MODE_TRANSLATE, \ .snap_face_nearest_steps = 1, \ + .snap_angle_increment_3d = DEG2RADF(15.0f), \ + .snap_angle_increment_2d = DEG2RADF(15.0f), \ + .snap_angle_increment_3d_precision = DEG2RADF(5.0f), \ + .snap_angle_increment_2d_precision = DEG2RADF(5.0f), \ \ .curve_paint_settings = _DNA_DEFAULTS_CurvePaintSettings, \ \ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 464d359d752..631d6c9da98 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1749,6 +1749,12 @@ typedef struct ToolSettings { char use_plane_axis_auto; char _pad7[2]; + /** Rotation Angle snapping amount */ + float snap_angle_increment_2d; + float snap_angle_increment_2d_precision; + float snap_angle_increment_3d; + float snap_angle_increment_3d_precision; + } ToolSettings; /** \} */ diff --git a/source/blender/makesrna/intern/rna_scene.cc b/source/blender/makesrna/intern/rna_scene.cc index 7640f8c3a6d..4cfaa2189a7 100644 --- a/source/blender/makesrna/intern/rna_scene.cc +++ b/source/blender/makesrna/intern/rna_scene.cc @@ -3518,6 +3518,40 @@ static void rna_def_tool_settings(BlenderRNA *brna) "Absolute grid alignment while translating (based on the pivot center)"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); /* header redraw */ + prop = RNA_def_property(srna, "snap_angle_increment_2d", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, nullptr, "snap_angle_increment_2d"); + RNA_def_property_ui_text( + prop, "Rotation Increment", "Angle used for rotation increments in 2D editors"); + RNA_def_property_range(prop, 0, DEG2RADF(180.0f)); + RNA_def_property_ui_range(prop, DEG2RADF(1.0f), DEG2RADF(180.0f), 100.0f, 2); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); /* header redraw */ + + prop = RNA_def_property(srna, "snap_angle_increment_2d_precision", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, nullptr, "snap_angle_increment_2d_precision"); + RNA_def_property_ui_text(prop, + "Rotation Precision Increment", + "Precision Angle used for rotation increments in 2D editors"); + RNA_def_property_range(prop, 0, DEG2RADF(180.0f)); + RNA_def_property_ui_range(prop, DEG2RADF(0.1f), DEG2RADF(180.0f), 10.0f, 3); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); /* header redraw */ + + prop = RNA_def_property(srna, "snap_angle_increment_3d", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, nullptr, "snap_angle_increment_3d"); + RNA_def_property_ui_text( + prop, "Rotation Increment", "Angle used for rotation increments in 3D editors"); + RNA_def_property_range(prop, 0, DEG2RADF(180.0f)); + RNA_def_property_ui_range(prop, DEG2RADF(1.0f), DEG2RADF(180.0f), 100.0f, 2); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); /* header redraw */ + + prop = RNA_def_property(srna, "snap_angle_increment_3d_precision", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, nullptr, "snap_angle_increment_3d_precision"); + RNA_def_property_ui_text(prop, + "Rotation Precision Increment", + "Precision Angle used for rotation increments in 3D editors"); + RNA_def_property_range(prop, 0, DEG2RADF(180.0f)); + RNA_def_property_ui_range(prop, DEG2RADF(0.1f), DEG2RADF(180.0f), 10.0f, 3); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); /* header redraw */ + prop = RNA_def_property(srna, "snap_elements", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, nullptr, "snap_mode"); RNA_def_property_flag(prop, PROP_DEG_SYNC_ONLY);