diff options
author | Campbell Barton <campbell@blender.org> | 2022-05-19 06:44:36 +0300 |
---|---|---|
committer | Campbell Barton <campbell@blender.org> | 2022-05-19 07:31:22 +0300 |
commit | 3ecc03c3d6b7baeee900a7ffd97fc0c2701adbc5 (patch) | |
tree | a1e24b86780eb540814427d7aa5480754a558ebe /source/blender | |
parent | 76b674198123eb0c5d77270ae037ad9c6c32c321 (diff) |
Fix T93779: Python is unable to set axis aligned views
It wasn't possible to temporarily orbit the view, then set back to an
axis-aligned view.
Details:
- It was possible to change RegionView3D.view_rotation while the view
kept the axis alignment value (Top, Left, Front .. etc) which
displayed in the viewport overlay.
Now changing the view rotation directly or via "view_matrix" resets
the axis-alignment - clearing when the view is no longer axis-aligned
or assigning the newly aligned axis.
- RegionView3D.is_orthographic_side_view added in [0] could be assigned
but wasn't useful as it treated an enum as a boolean only setting the
RegionView3D.view to RV3D_VIEW_USER or RV3D_VIEW_FRONT.
Now enabling this aligns the viewport rotation to it's closest
axis-aligned orientation setting RegionView3D.view & view_axis_roll
accordingly. Note that the "orthographic" term is misleading as the
property only relates to axis-alignment, not to the
perspective/orthographic setting. We could consider deprecating the
current naming.
[0]: 63bae864f40302b0a303498d26f230caf4f24339
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/space_view3d/view3d_utils.c | 41 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_space.c | 58 |
2 files changed, 88 insertions, 11 deletions
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index dd0d5966a76..51f50633468 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -1317,17 +1317,40 @@ bool ED_view3d_quat_to_axis_view(const float quat[4], *r_view = RV3D_VIEW_USER; *r_view_axis_roll = RV3D_VIEW_AXIS_ROLL_0; - /* quat values are all unit length */ - for (int view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) { - for (int view_axis_roll = RV3D_VIEW_AXIS_ROLL_0; view_axis_roll <= RV3D_VIEW_AXIS_ROLL_270; - view_axis_roll++) { - if (fabsf(angle_signed_qtqt( - quat, view3d_quat_axis[view - RV3D_VIEW_FRONT][view_axis_roll])) < epsilon) { - *r_view = view; - *r_view_axis_roll = view_axis_roll; - return true; + /* Quaternion values are all unit length. */ + + if (epsilon < M_PI_4) { + /* Under 45 degrees, just pick the closest value. */ + for (int view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) { + for (int view_axis_roll = RV3D_VIEW_AXIS_ROLL_0; view_axis_roll <= RV3D_VIEW_AXIS_ROLL_270; + view_axis_roll++) { + if (fabsf(angle_signed_qtqt( + quat, view3d_quat_axis[view - RV3D_VIEW_FRONT][view_axis_roll])) < epsilon) { + *r_view = view; + *r_view_axis_roll = view_axis_roll; + return true; + } + } + } + } + else { + /* Epsilon over 45 degrees, check all & find use the closest. */ + float delta_best = FLT_MAX; + for (int view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) { + for (int view_axis_roll = RV3D_VIEW_AXIS_ROLL_0; view_axis_roll <= RV3D_VIEW_AXIS_ROLL_270; + view_axis_roll++) { + const float delta_test = fabsf( + angle_signed_qtqt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT][view_axis_roll])); + if (delta_best > delta_test) { + delta_best = delta_test; + *r_view = view; + *r_view_axis_roll = view_axis_roll; + } } } + if (*r_view != RV3D_VIEW_USER) { + return true; + } } return false; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 1a9e7f5aad8..fb3fa69139a 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -1040,6 +1040,24 @@ static void rna_RegionView3D_quadview_clip_update(Main *UNUSED(main), } } +/** + * After the rotation changes, either clear the view axis + * or update it not to be aligned to an axis, without this the viewport will show + * text that doesn't match the rotation. + */ +static void rna_RegionView3D_view_rotation_set_validate_view_axis(RegionView3D *rv3d) +{ + /* Never rotate from a "User" view into an axis aligned view, + * otherwise rotation could be aligned by accident - giving unexpected behavior. */ + if (!RV3D_VIEW_IS_AXIS(rv3d->view)) { + return; + } + /* Keep this small as script authors wont expect the assigned value to change. */ + const float eps_quat = 1e-6f; + ED_view3d_quat_to_axis_view_and_reset_quat( + rv3d->viewquat, eps_quat, &rv3d->view, &rv3d->view_axis_roll); +} + static void rna_RegionView3D_view_location_get(PointerRNA *ptr, float *values) { RegionView3D *rv3d = (RegionView3D *)(ptr->data); @@ -1062,6 +1080,7 @@ static void rna_RegionView3D_view_rotation_set(PointerRNA *ptr, const float *val { RegionView3D *rv3d = (RegionView3D *)(ptr->data); invert_qt_qt(rv3d->viewquat, values); + rna_RegionView3D_view_rotation_set_validate_view_axis(rv3d); } static void rna_RegionView3D_view_matrix_set(PointerRNA *ptr, const float *values) @@ -1070,14 +1089,41 @@ static void rna_RegionView3D_view_matrix_set(PointerRNA *ptr, const float *value float mat[4][4]; invert_m4_m4(mat, (float(*)[4])values); ED_view3d_from_m4(mat, rv3d->ofs, rv3d->viewquat, &rv3d->dist); + rna_RegionView3D_view_rotation_set_validate_view_axis(rv3d); } static bool rna_RegionView3D_is_orthographic_side_view_get(PointerRNA *ptr) { + /* NOTE: only checks axis alignment, not orthographic, + * we may deprecate the current name to reflect this. */ RegionView3D *rv3d = (RegionView3D *)(ptr->data); return RV3D_VIEW_IS_AXIS(rv3d->view); } +static void rna_RegionView3D_is_orthographic_side_view_set(PointerRNA *ptr, int value) +{ + RegionView3D *rv3d = (RegionView3D *)(ptr->data); + const bool was_axis_view = RV3D_VIEW_IS_AXIS(rv3d->view); + if (value) { + /* Already axis aligned, nothing to do. */ + if (was_axis_view) { + return; + } + /* Use a large value as we always want to set this to the closest axis. */ + const float eps_quat = FLT_MAX; + ED_view3d_quat_to_axis_view_and_reset_quat( + rv3d->viewquat, eps_quat, &rv3d->view, &rv3d->view_axis_roll); + } + else { + /* Only allow changing from axis-views to user view as camera view for e.g. + * doesn't make sense to update. */ + if (!was_axis_view) { + return; + } + rv3d->view = RV3D_VIEW_USER; + } +} + static IDProperty **rna_View3DShading_idprops(PointerRNA *ptr) { View3DShading *shading = ptr->data; @@ -5077,10 +5123,18 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Is Perspective", ""); RNA_def_property_flag(prop, PROP_EDITABLE); + /* WARNING: Using "orthographic" in this name isn't correct and could be changed. */ prop = RNA_def_property(srna, "is_orthographic_side_view", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "view", 0); - RNA_def_property_boolean_funcs(prop, "rna_RegionView3D_is_orthographic_side_view_get", NULL); - RNA_def_property_ui_text(prop, "Is Axis Aligned", "Is current view an orthographic side view"); + RNA_def_property_boolean_funcs(prop, + "rna_RegionView3D_is_orthographic_side_view_get", + "rna_RegionView3D_is_orthographic_side_view_set"); + RNA_def_property_ui_text( + prop, + "Is Axis Aligned", + "Is current view aligned to an axis " + "(does not check the view is orthographic use \"is_perspective\" for that). " + "Assignment sets the \"view_rotation\" to the closest axis aligned view"); /* This isn't directly accessible from the UI, only an operator. */ prop = RNA_def_property(srna, "use_clip_planes", PROP_BOOLEAN, PROP_NONE); |