Blender V4.3
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
9#include "MEM_guardedalloc.h"
10
11#include "BLI_math_rotation.h"
12
13#include "BLT_translation.hh"
14
15#include "BKE_context.hh"
16
17#include "ED_transform.hh"
18
19#include "WM_api.hh"
20
21#include "RNA_access.hh"
22#include "RNA_define.hh"
23
24#include "UI_resources.hh"
25
26#include "view3d_intern.hh"
27
28#include "view3d_navigate.hh" /* own include */
29
30/* -------------------------------------------------------------------- */
35 {RV3D_VIEW_LEFT, "LEFT", ICON_TRIA_LEFT, "Left", "View from the left"},
36 {RV3D_VIEW_RIGHT, "RIGHT", ICON_TRIA_RIGHT, "Right", "View from the right"},
37 {RV3D_VIEW_BOTTOM, "BOTTOM", ICON_TRIA_DOWN, "Bottom", "View from the bottom"},
38 {RV3D_VIEW_TOP, "TOP", ICON_TRIA_UP, "Top", "View from the top"},
39 {RV3D_VIEW_FRONT, "FRONT", 0, "Front", "View from the front"},
40 {RV3D_VIEW_BACK, "BACK", 0, "Back", "View from the back"},
41 {0, nullptr, 0, nullptr, nullptr},
42};
43
45{
46 View3D *v3d;
47 ARegion *region;
48 RegionView3D *rv3d;
49 static int perspo = RV3D_PERSP;
50 int viewnum;
51 int view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
52 const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
53
54 /* no nullptr check is needed, poll checks */
55 ED_view3d_context_user_region(C, &v3d, &region);
56 rv3d = static_cast<RegionView3D *>(region->regiondata);
57
59
60 viewnum = RNA_enum_get(op->ptr, "type");
61
62 float align_quat_buf[4];
63 float *align_quat = nullptr;
64
65 if (RNA_boolean_get(op->ptr, "align_active")) {
66 /* align to active object */
68 if (obact != nullptr) {
69 float twmat[3][3];
70 const Scene *scene = CTX_data_scene(C);
71 ViewLayer *view_layer = CTX_data_view_layer(C);
72 Object *obedit = CTX_data_edit_object(C);
73 /* same as transform gizmo when normal is set */
75 scene, view_layer, v3d, obact, obedit, V3D_AROUND_ACTIVE, twmat);
76 align_quat = align_quat_buf;
77 mat3_to_quat(align_quat, twmat);
78 invert_qt_normalized(align_quat);
79 }
80 }
81
82 if (RNA_boolean_get(op->ptr, "relative")) {
83 float quat_rotate[4];
84 float quat_test[4];
85
86 if (viewnum == RV3D_VIEW_LEFT) {
87 axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], -M_PI_2);
88 }
89 else if (viewnum == RV3D_VIEW_RIGHT) {
90 axis_angle_to_quat(quat_rotate, rv3d->viewinv[1], M_PI_2);
91 }
92 else if (viewnum == RV3D_VIEW_TOP) {
93 axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], -M_PI_2);
94 }
95 else if (viewnum == RV3D_VIEW_BOTTOM) {
96 axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI_2);
97 }
98 else if (viewnum == RV3D_VIEW_FRONT) {
99 unit_qt(quat_rotate);
100 }
101 else if (viewnum == RV3D_VIEW_BACK) {
102 axis_angle_to_quat(quat_rotate, rv3d->viewinv[0], M_PI);
103 }
104 else {
105 BLI_assert(0);
106 }
107
108 mul_qt_qtqt(quat_test, rv3d->viewquat, quat_rotate);
109
110 float angle_best = FLT_MAX;
111 int view_best = -1;
112 int view_axis_roll_best = -1;
113 for (int i = RV3D_VIEW_FRONT; i <= RV3D_VIEW_BOTTOM; i++) {
114 for (int j = RV3D_VIEW_AXIS_ROLL_0; j <= RV3D_VIEW_AXIS_ROLL_270; j++) {
115 float quat_axis[4];
116 ED_view3d_quat_from_axis_view(i, j, quat_axis);
117 if (align_quat) {
118 mul_qt_qtqt(quat_axis, quat_axis, align_quat);
119 }
120 const float angle_test = fabsf(angle_signed_qtqt(quat_axis, quat_test));
121 if (angle_best > angle_test) {
122 angle_best = angle_test;
123 view_best = i;
124 view_axis_roll_best = j;
125 }
126 }
127 }
128 if (view_best == -1) {
129 view_best = RV3D_VIEW_FRONT;
130 view_axis_roll_best = RV3D_VIEW_AXIS_ROLL_0;
131 }
132
133 /* Disallow non-upright views in turn-table modes,
134 * it's too difficult to navigate out of them. */
135 if ((U.flag & USER_TRACKBALL) == 0) {
136 if (!ELEM(view_best, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
137 view_axis_roll_best = RV3D_VIEW_AXIS_ROLL_0;
138 }
139 }
140
141 viewnum = view_best;
142 view_axis_roll = view_axis_roll_best;
143 }
144
145 /* Use this to test if we started out with a camera */
146 const int nextperspo = (rv3d->persp == RV3D_CAMOB) ? rv3d->lpersp : perspo;
147 float quat[4];
148 ED_view3d_quat_from_axis_view(viewnum, view_axis_roll, quat);
150 C, v3d, region, quat, viewnum, view_axis_roll, nextperspo, align_quat, smooth_viewtx);
151
152 perspo = rv3d->persp;
153
154 return OPERATOR_FINISHED;
155}
156
158{
159 PropertyRNA *prop;
160
161 /* identifiers */
162 ot->name = "View Axis";
163 ot->description = "Use a preset viewpoint";
164 ot->idname = "VIEW3D_OT_view_axis";
165
166 /* api callbacks */
169
170 /* flags */
171 ot->flag = 0;
172
173 ot->prop = RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "Preset viewpoint to use");
176
177 prop = RNA_def_boolean(
178 ot->srna, "align_active", false, "Align Active", "Align to the active object's axis");
180 prop = RNA_def_boolean(
181 ot->srna, "relative", false, "Relative", "Rotate relative to the current orientation");
183}
184
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:50
#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
@ V3D_AROUND_ACTIVE
@ RV3D_VIEW_AXIS_ROLL_270
@ RV3D_VIEW_AXIS_ROLL_0
@ RV3D_CAMOB
@ RV3D_PERSP
@ RV3D_VIEW_FRONT
@ RV3D_VIEW_BOTTOM
@ RV3D_VIEW_LEFT
@ RV3D_VIEW_RIGHT
@ RV3D_VIEW_TOP
@ RV3D_VIEW_BACK
void ED_getTransformOrientationMatrix(const Scene *scene, ViewLayer *view_layer, const View3D *v3d, Object *ob, Object *obedit, short around, float r_orientation_mat[3][3])
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)
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition RNA_types.hh:245
unsigned int U
Definition btGjkEpa3.h:78
#define fabsf(x)
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
float viewinv[4][4]
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
PropertyRNA * prop
Definition WM_types.hh:1092
StructRNA * srna
Definition WM_types.hh:1080
struct PointerRNA * ptr
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 int view_axis_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem prop_view_items[]
wmOperatorType * ot
Definition wm_files.cc:4125
int WM_operator_smooth_viewtx_get(const wmOperator *op)