Blender  V3.3
view3d_navigate_roll.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "BLI_blenlib.h"
8 #include "BLI_dial_2d.h"
9 #include "BLI_math.h"
10 
11 #include "BKE_context.h"
12 
13 #include "WM_api.h"
14 
15 #include "RNA_access.h"
16 #include "RNA_define.h"
17 
18 #include "DEG_depsgraph_query.h"
19 
20 #include "ED_screen.h"
21 
22 #include "view3d_intern.h"
23 #include "view3d_navigate.h" /* own include */
24 
25 /* -------------------------------------------------------------------- */
34 static void view_roll_angle(ARegion *region,
35  float quat[4],
36  const float orig_quat[4],
37  const float dvec[3],
38  float angle,
39  bool use_axis_view)
40 {
41  RegionView3D *rv3d = region->regiondata;
42  float quat_mul[4];
43 
44  /* camera axis */
45  axis_angle_normalized_to_quat(quat_mul, dvec, angle);
46 
47  mul_qt_qtqt(quat, orig_quat, quat_mul);
48 
49  /* avoid precision loss over time */
50  normalize_qt(quat);
51 
52  if (use_axis_view && RV3D_VIEW_IS_AXIS(rv3d->view) && (fabsf(angle) == (float)M_PI_2)) {
54  }
55  else {
56  rv3d->view = RV3D_VIEW_USER;
57  }
58 }
59 
60 static void viewroll_apply(ViewOpsData *vod, int x, int y)
61 {
62  float angle = BLI_dial_angle(vod->init.dial, (const float[2]){x, y});
63 
64  if (angle != 0.0f) {
66  vod->region, vod->rv3d->viewquat, vod->init.quat, vod->init.mousevec, angle, false);
67  }
68 
69  if (vod->use_dyn_ofs) {
71  vod->rv3d->ofs, vod->init.ofs, vod->init.quat, vod->rv3d->viewquat, vod->dyn_ofs);
72  }
73 
74  if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
75  view3d_boxview_sync(vod->area, vod->region);
76  }
77 
78  ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
79 
81 }
82 
83 static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
84 {
85  ViewOpsData *vod = op->customdata;
86  short event_code = VIEW_PASS;
87  bool use_autokey = false;
89 
90  /* execute the events */
91  if (event->type == MOUSEMOVE) {
92  event_code = VIEW_APPLY;
93  }
94  else if (event->type == EVT_MODAL_MAP) {
95  switch (event->val) {
96  case VIEW_MODAL_CONFIRM:
97  event_code = VIEW_CONFIRM;
98  break;
100  WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL, event);
101  event_code = VIEW_CONFIRM;
102  break;
104  WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL, event);
105  event_code = VIEW_CONFIRM;
106  break;
107  }
108  }
109  else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
110  /* Note this does not remove auto-keys on locked cameras. */
111  copy_qt_qt(vod->rv3d->viewquat, vod->init.quat);
112  ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
114  op->customdata = NULL;
115  return OPERATOR_CANCELLED;
116  }
117  else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
118  event_code = VIEW_CONFIRM;
119  }
120 
121  if (event_code == VIEW_APPLY) {
122  viewroll_apply(vod, event->xy[0], event->xy[1]);
124  use_autokey = true;
125  }
126  }
127  else if (event_code == VIEW_CONFIRM) {
128  use_autokey = true;
130  }
131 
132  if (use_autokey) {
133  ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, false);
134  }
135 
136  if (ret & OPERATOR_FINISHED) {
138  op->customdata = NULL;
139  }
140 
141  return ret;
142 }
143 
144 enum {
147 };
148 
150  {0, "ANGLE", 0, "Roll Angle", "Roll the view using an angle value"},
151  {V3D_VIEW_STEPLEFT, "LEFT", 0, "Roll Left", "Roll the view around to the left"},
152  {V3D_VIEW_STEPRIGHT, "RIGHT", 0, "Roll Right", "Roll the view around to the right"},
153  {0, NULL, 0, NULL, NULL},
154 };
155 
157 {
158  View3D *v3d;
159  RegionView3D *rv3d;
160  ARegion *region;
161 
162  if (op->customdata) {
163  ViewOpsData *vod = op->customdata;
164  region = vod->region;
165  v3d = vod->v3d;
166  }
167  else {
168  ED_view3d_context_user_region(C, &v3d, &region);
169  }
170 
171  rv3d = region->regiondata;
172 
173  const bool is_camera_lock = ED_view3d_camera_lock_check(v3d, rv3d);
174  if ((rv3d->persp != RV3D_CAMOB) || is_camera_lock) {
175  if (is_camera_lock) {
178  }
179 
181 
182  int type = RNA_enum_get(op->ptr, "type");
183  float angle = (type == 0) ? RNA_float_get(op->ptr, "angle") : DEG2RADF(U.pad_rot_angle);
184  float mousevec[3];
185  float quat_new[4];
186 
187  const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
188 
189  if (type == V3D_VIEW_STEPLEFT) {
190  angle = -angle;
191  }
192 
193  normalize_v3_v3(mousevec, rv3d->viewinv[2]);
194  negate_v3(mousevec);
195  view_roll_angle(region, quat_new, rv3d->viewquat, mousevec, angle, true);
196 
197  const float *dyn_ofs_pt = NULL;
198  float dyn_ofs[3];
199  if (U.uiflag & USER_ORBIT_SELECTION) {
200  if (view3d_orbit_calc_center(C, dyn_ofs)) {
201  negate_v3(dyn_ofs);
202  dyn_ofs_pt = dyn_ofs;
203  }
204  }
205 
207  v3d,
208  region,
209  smooth_viewtx,
210  &(const V3D_SmoothParams){
211  .quat = quat_new,
212  .dyn_ofs = dyn_ofs_pt,
213  /* Group as successive roll may run by holding a key. */
214  .undo_str = op->type->name,
215  .undo_grouped = true,
216  });
217 
219  op->customdata = NULL;
220  return OPERATOR_FINISHED;
221  }
222 
224  op->customdata = NULL;
225  return OPERATOR_CANCELLED;
226 }
227 
228 static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
229 {
230  ViewOpsData *vod;
231 
232  bool use_angle = RNA_enum_get(op->ptr, "type") != 0;
233 
234  if (use_angle || RNA_struct_property_is_set(op->ptr, "angle")) {
235  viewroll_exec(C, op);
236  }
237  else {
238  /* makes op->customdata */
240  vod->init.dial = BLI_dial_init((const float[2]){BLI_rcti_cent_x(&vod->region->winrct),
241  BLI_rcti_cent_y(&vod->region->winrct)},
242  FLT_EPSILON);
243 
245 
246  /* overwrite the mouse vector with the view direction */
247  normalize_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
248  negate_v3(vod->init.mousevec);
249 
250  if (event->type == MOUSEROTATE) {
251  vod->init.event_xy[0] = vod->prev.event_xy[0] = event->xy[0];
252  viewroll_apply(vod, event->prev_xy[0], event->prev_xy[1]);
253 
255  op->customdata = NULL;
256  return OPERATOR_FINISHED;
257  }
258 
259  /* add temp handler */
261  return OPERATOR_RUNNING_MODAL;
262  }
263  return OPERATOR_FINISHED;
264 }
265 
267 {
269  op->customdata = NULL;
270 }
271 
273 {
274  PropertyRNA *prop;
275 
276  /* identifiers */
277  ot->name = "View Roll";
278  ot->description = "Roll the view";
279  ot->idname = "VIEW3D_OT_view_roll";
280 
281  /* api callbacks */
283  ot->exec = viewroll_exec;
287 
288  /* flags */
289  ot->flag = 0;
290 
291  /* properties */
292  ot->prop = prop = RNA_def_float(
293  ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
295  prop = RNA_def_enum(ot->srna,
296  "type",
298  0,
299  "Roll Angle Source",
300  "How roll angle is calculated");
302 }
303 
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
Dial * BLI_dial_init(const float start_position[2], float threshold)
Definition: BLI_dial_2d.c:34
float BLI_dial_angle(Dial *dial, const float current_position[2])
Definition: BLI_dial_2d.c:44
#define M_PI_2
Definition: BLI_math_base.h:23
float normalize_qt(float q[4])
#define DEG2RADF(_deg)
void axis_angle_normalized_to_quat(float r[4], const float axis[3], float angle)
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
Definition: math_rotation.c:46
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:33
MINLINE void negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
BLI_INLINE int BLI_rcti_cent_y(const struct rcti *rct)
Definition: BLI_rect.h:173
BLI_INLINE int BLI_rcti_cent_x(const struct rcti *rct)
Definition: BLI_rect.h:169
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ USER_ORBIT_SELECTION
#define RV3D_VIEW_IS_AXIS(view)
#define RV3D_LOCK_FLAGS(rv3d)
#define RV3D_CAMOB
@ RV3D_BOXVIEW
#define RV3D_VIEW_USER
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
bScreen * ED_screen_animation_playing(const struct wmWindowManager *wm)
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:655
bool ED_view3d_camera_lock_sync(const struct Depsgraph *depsgraph, struct View3D *v3d, struct RegionView3D *rv3d)
bool ED_view3d_camera_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d)
bool ED_operator_rv3d_user_region_poll(struct bContext *C)
Definition: view3d_view.c:277
bool ED_view3d_quat_to_axis_view_and_reset_quat(float viewquat[4], float epsilon, char *r_view, char *r_view_axis_rotation)
bool ED_view3d_camera_lock_autokey(struct View3D *v3d, struct RegionView3D *rv3d, struct bContext *C, bool do_rotate, bool do_translate)
Definition: view3d_utils.c:665
void ED_view3d_camera_lock_init(const struct Depsgraph *depsgraph, struct View3D *v3d, struct RegionView3D *rv3d)
bool ED_view3d_context_user_region(struct bContext *C, struct View3D **r_v3d, struct ARegion **r_region)
Definition: space_view3d.c:98
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
#define C
Definition: RandGen.cpp:25
@ KM_RELEASE
Definition: WM_types.h:268
@ WM_OP_INVOKE_DEFAULT
Definition: WM_types.h:201
unsigned int U
Definition: btGjkEpa3.h:78
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
const Depsgraph * depsgraph
@ VIEW_CONFIRM
Definition: image_ops.c:583
@ VIEW_PASS
Definition: image_ops.c:581
@ VIEW_APPLY
Definition: image_ops.c:582
#define fabsf(x)
Definition: metal/compat.h:219
return ret
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4957
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:5301
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3836
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3783
void * regiondata
float viewquat[4]
float viewinv[4][4]
struct Dial * dial
struct RegionView3D * rv3d
float dyn_ofs[3]
struct ViewOpsData::@577 prev
struct Depsgraph * depsgraph
struct ARegion * region
struct ViewOpsData::@576 init
float quat[4]
struct ScrArea * area
float mousevec[3]
struct View3D * v3d
float ofs[3]
short val
Definition: WM_types.h:680
int xy[2]
Definition: WM_types.h:682
int prev_xy[2]
Definition: WM_types.h:728
short type
Definition: WM_types.h:678
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct wmOperatorType * type
struct PointerRNA * ptr
void view3d_boxview_sync(struct ScrArea *area, struct ARegion *region)
Definition: view3d_utils.c:890
void viewops_data_free(bContext *C, ViewOpsData *vod)
ViewOpsData * viewops_data_create(bContext *C, const wmEvent *event, enum eViewOpsFlag viewops_flag)
void view3d_orbit_apply_dyn_ofs(float r_ofs[3], const float ofs_old[3], const float viewquat_old[4], const float viewquat_new[4], const float dyn_ofs[3])
enum eViewOpsFlag viewops_flag_from_prefs(void)
bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
@ VIEWROT_MODAL_SWITCH_ROTATE
@ VIEWROT_MODAL_SWITCH_MOVE
@ VIEW_MODAL_CONFIRM
void ED_view3d_smooth_view(struct bContext *C, struct View3D *v3d, struct ARegion *region, int smooth_viewtx, const V3D_SmoothParams *sview)
void ED_view3d_smooth_view_force_finish(struct bContext *C, struct View3D *v3d, struct ARegion *region)
void VIEW3D_OT_view_roll(wmOperatorType *ot)
@ V3D_VIEW_STEPRIGHT
@ V3D_VIEW_STEPLEFT
static void viewroll_cancel(bContext *C, wmOperator *op)
static const EnumPropertyItem prop_view_roll_items[]
static void view_roll_angle(ARegion *region, float quat[4], const float orig_quat[4], const float dvec[3], float angle, bool use_axis_view)
static void viewroll_apply(ViewOpsData *vod, int x, int y)
static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int viewroll_exec(bContext *C, wmOperator *op)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
int WM_operator_name_call(bContext *C, const char *opstring, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
@ RIGHTMOUSE
@ EVT_MODAL_MAP
@ MOUSEROTATE
@ MOUSEMOVE
@ EVT_ESCKEY
wmOperatorType * ot
Definition: wm_files.c:3479
int WM_operator_smooth_viewtx_get(const wmOperator *op)