Blender V5.0
view3d_navigate_view_axis.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BLI_math_base.h"
10#include "BLI_math_rotation.h"
11
12#include "DNA_userdef_types.h"
13
14#include "BLT_translation.hh"
15
16#include "BKE_context.hh"
17
18#include "ED_transform.hh"
19
20#include "WM_api.hh"
21
22#include "RNA_access.hh"
23#include "RNA_define.hh"
24
25#include "UI_resources.hh"
26
27#include "view3d_intern.hh"
28
29#include "view3d_navigate.hh" /* own include */
30
31/* -------------------------------------------------------------------- */
34
36 {RV3D_VIEW_LEFT, "LEFT", ICON_TRIA_LEFT, "Left", "View from the left"},
37 {RV3D_VIEW_RIGHT, "RIGHT", ICON_TRIA_RIGHT, "Right", "View from the right"},
38 {RV3D_VIEW_BOTTOM, "BOTTOM", ICON_TRIA_DOWN, "Bottom", "View from the bottom"},
39 {RV3D_VIEW_TOP, "TOP", ICON_TRIA_UP, "Top", "View from the top"},
40 {RV3D_VIEW_FRONT, "FRONT", 0, "Front", "View from the front"},
41 {RV3D_VIEW_BACK, "BACK", 0, "Back", "View from the back"},
42 {0, nullptr, 0, nullptr, nullptr},
43};
44
46{
47 View3D *v3d;
48 ARegion *region;
49 RegionView3D *rv3d;
50 static int perspo = RV3D_PERSP;
51 int viewnum;
52 int view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
53 const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
54
55 /* no nullptr check is needed, poll checks */
56 ED_view3d_context_user_region(C, &v3d, &region);
57 rv3d = static_cast<RegionView3D *>(region->regiondata);
58
60
61 viewnum = RNA_enum_get(op->ptr, "type");
62
63 float align_quat_buf[4];
64 float *align_quat = nullptr;
65
66 if (RNA_boolean_get(op->ptr, "align_active")) {
67 /* align to active object */
69 if (obact != nullptr) {
70 float twmat[3][3];
71 const Scene *scene = CTX_data_scene(C);
72 ViewLayer *view_layer = CTX_data_view_layer(C);
73 Object *obedit = CTX_data_edit_object(C);
74 /* same as transform gizmo when normal is set */
76 scene, view_layer, v3d, obact, obedit, V3D_AROUND_ACTIVE, twmat);
77 align_quat = align_quat_buf;
78 mat3_to_quat(align_quat, twmat);
79 invert_qt_normalized(align_quat);
80 }
81 }
82
83 if (RNA_boolean_get(op->ptr, "relative")) {
84 float quat_rotate[4];
85 float quat_test[4];
86
87 if (viewnum == RV3D_VIEW_LEFT) {
88 axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], -M_PI_2);
89 }
90 else if (viewnum == RV3D_VIEW_RIGHT) {
91 axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], M_PI_2);
92 }
93 else if (viewnum == RV3D_VIEW_TOP) {
94 axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], -M_PI_2);
95 }
96 else if (viewnum == RV3D_VIEW_BOTTOM) {
97 axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI_2);
98 }
99 else if (viewnum == RV3D_VIEW_FRONT) {
100 unit_qt(quat_rotate);
101 }
102 else if (viewnum == RV3D_VIEW_BACK) {
103 axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI);
104 }
105 else {
106 BLI_assert(0);
107 }
108
109 mul_qt_qtqt(quat_test, rv3d->viewquat, quat_rotate);
110
111 float angle_best = FLT_MAX;
112 int view_best = -1;
113 int view_axis_roll_best = -1;
114 for (int i = RV3D_VIEW_FRONT; i <= RV3D_VIEW_BOTTOM; i++) {
115 for (int j = RV3D_VIEW_AXIS_ROLL_0; j <= RV3D_VIEW_AXIS_ROLL_270; j++) {
116 float quat_axis[4];
117 ED_view3d_quat_from_axis_view(i, j, quat_axis);
118 if (align_quat) {
119 mul_qt_qtqt(quat_axis, quat_axis, align_quat);
120 }
121 const float angle_test = fabsf(angle_signed_qtqt(quat_axis, quat_test));
122 if (angle_best > angle_test) {
123 angle_best = angle_test;
124 view_best = i;
125 view_axis_roll_best = j;
126 }
127 }
128 }
129 if (view_best == -1) {
130 view_best = RV3D_VIEW_FRONT;
131 view_axis_roll_best = RV3D_VIEW_AXIS_ROLL_0;
132 }
133
134 /* Disallow non-upright views in turn-table modes,
135 * it's too difficult to navigate out of them. */
136 if ((U.flag & USER_TRACKBALL) == 0) {
137 if (!ELEM(view_best, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
138 view_axis_roll_best = RV3D_VIEW_AXIS_ROLL_0;
139 }
140 }
141
142 viewnum = view_best;
143 view_axis_roll = view_axis_roll_best;
144 }
145
146 /* Use this to test if we started out with a camera */
147 const int nextperspo = (rv3d->persp == RV3D_CAMOB) ? rv3d->lpersp : perspo;
148 float quat[4];
149 ED_view3d_quat_from_axis_view(viewnum, view_axis_roll, quat);
151 C, v3d, region, quat, viewnum, view_axis_roll, nextperspo, align_quat, smooth_viewtx);
152
153 perspo = rv3d->persp;
154
155 return OPERATOR_FINISHED;
156}
157
159{
160 PropertyRNA *prop;
161
162 /* identifiers */
163 ot->name = "View Axis";
164 ot->description = "Use a preset viewpoint";
165 ot->idname = "VIEW3D_OT_view_axis";
166
167 /* API callbacks. */
168 ot->exec = view_axis_exec;
170
171 /* flags */
172 ot->flag = 0;
173
174 ot->prop = RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "Preset viewpoint to use");
177
178 prop = RNA_def_boolean(
179 ot->srna, "align_active", false, "Align Active", "Align to the active object's axis");
181 prop = RNA_def_boolean(
182 ot->srna, "relative", false, "Relative", "Rotate relative to the current orientation");
184}
185
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define M_PI_2
#define M_PI
void invert_qt_normalized(float q[4])
void axis_angle_to_quat(float r[4], const float axis[3], float angle)
void mat3_to_quat(float q[4], const float mat[3][3])
void unit_qt(float q[4])
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
float angle_signed_qtqt(const float q1[4], const float q2[4])
#define ELEM(...)
#define BLT_I18NCONTEXT_EDITOR_VIEW3D
@ USER_TRACKBALL
@ RV3D_VIEW_AXIS_ROLL_270
@ RV3D_VIEW_AXIS_ROLL_0
@ RV3D_VIEW_FRONT
@ RV3D_VIEW_BOTTOM
@ RV3D_VIEW_LEFT
@ RV3D_VIEW_RIGHT
@ RV3D_VIEW_TOP
@ RV3D_VIEW_BACK
@ V3D_AROUND_ACTIVE
@ RV3D_CAMOB
@ RV3D_PERSP
@ OPERATOR_FINISHED
bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_region)
bool ED_view3d_quat_from_axis_view(char view, char view_axis_roll, float r_quat[4])
bool ED_operator_rv3d_user_region_poll(bContext *C)
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
#define C
Definition RandGen.cpp:29
#define U
void ED_getTransformOrientationMatrix(const Scene *scene, ViewLayer *view_layer, const View3D *v3d, Object *ob, Object *obedit, short around, float r_orientation_mat[3][3])
#define fabsf
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
#define FLT_MAX
Definition stdcycles.h:14
void * regiondata
float viewinv[4][4]
struct PointerRNA * ptr
i
Definition text_draw.cc:230
void axis_set_view(bContext *C, View3D *v3d, ARegion *region, const float quat_[4], char view, char view_axis_roll, int perspo, const float *align_to_quat, const int smooth_viewtx)
void ED_view3d_smooth_view_force_finish(bContext *C, View3D *v3d, ARegion *region)
void VIEW3D_OT_view_axis(wmOperatorType *ot)
static wmOperatorStatus view_axis_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem prop_view_items[]
wmOperatorType * ot
Definition wm_files.cc:4237
int WM_operator_smooth_viewtx_get(const wmOperator *op)