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]: 63bae864f4
This commit is contained in:
@@ -1317,18 +1317,41 @@ 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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user