Blender  V3.3
view3d_navigate_rotate.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "BLI_math.h"
8 
9 #include "BKE_context.h"
10 
11 #include "WM_api.h"
12 
13 #include "RNA_access.h"
14 
15 #include "ED_screen.h"
16 
17 #include "view3d_intern.h"
18 #include "view3d_navigate.h" /* own include */
19 
20 /* -------------------------------------------------------------------- */
25 {
26  static const EnumPropertyItem modal_items[] = {
27  {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
28 
29  {VIEWROT_MODAL_AXIS_SNAP_ENABLE, "AXIS_SNAP_ENABLE", 0, "Axis Snap", ""},
30  {VIEWROT_MODAL_AXIS_SNAP_DISABLE, "AXIS_SNAP_DISABLE", 0, "Axis Snap (Off)", ""},
31 
32  {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"},
33  {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
34 
35  {0, NULL, 0, NULL, NULL},
36  };
37 
38  wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Rotate Modal");
39 
40  /* this function is called for each spacetype, only needs to add map once */
41  if (keymap && keymap->modal_items) {
42  return;
43  }
44 
45  keymap = WM_modalkeymap_ensure(keyconf, "View3D Rotate Modal", modal_items);
46 
47  /* disabled mode switching for now, can re-implement better, later on */
48 #if 0
50  &(const KeyMapItem_Params){
51  .type = LEFTMOUSE,
52  .value = KM_PRESS,
53  .modifier = KM_ANY,
54  .direction = KM_ANY,
55  },
58  &(const KeyMapItem_Params){
59  .type = EVT_LEFTCTRLKEY,
60  .value = KM_PRESS,
61  .modifier = KM_ANY,
62  .direction = KM_ANY,
63  },
66  &(const KeyMapItem_Params){
67  .type = EVT_LEFTSHIFTKEY,
68  .value = KM_PRESS,
69  .modifier = KM_ANY,
70  .direction = KM_ANY,
71  },
73 #endif
74 
75  /* assign map to operators */
76  WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate");
77 }
78 
80 {
81  const float axis_limit = DEG2RADF(45 / 3);
82 
83  RegionView3D *rv3d = vod->rv3d;
84 
85  float viewquat_inv[4];
86  float zaxis[3] = {0, 0, 1};
87  float zaxis_best[3];
88  int x, y, z;
89  bool found = false;
90 
91  invert_qt_qt_normalized(viewquat_inv, vod->curr.viewquat);
92 
93  mul_qt_v3(viewquat_inv, zaxis);
94  normalize_v3(zaxis);
95 
96  for (x = -1; x < 2; x++) {
97  for (y = -1; y < 2; y++) {
98  for (z = -1; z < 2; z++) {
99  if (x || y || z) {
100  float zaxis_test[3] = {x, y, z};
101 
102  normalize_v3(zaxis_test);
103 
104  if (angle_normalized_v3v3(zaxis_test, zaxis) < axis_limit) {
105  copy_v3_v3(zaxis_best, zaxis_test);
106  found = true;
107  }
108  }
109  }
110  }
111  }
112 
113  if (found) {
114 
115  /* find the best roll */
116  float quat_roll[4], quat_final[4], quat_best[4], quat_snap[4];
117  float viewquat_align[4]; /* viewquat aligned to zaxis_best */
118  float viewquat_align_inv[4]; /* viewquat aligned to zaxis_best */
119  float best_angle = axis_limit;
120  int j;
121 
122  /* viewquat_align is the original viewquat aligned to the snapped axis
123  * for testing roll */
124  rotation_between_vecs_to_quat(viewquat_align, zaxis_best, zaxis);
125  normalize_qt(viewquat_align);
126  mul_qt_qtqt(viewquat_align, vod->curr.viewquat, viewquat_align);
127  normalize_qt(viewquat_align);
128  invert_qt_qt_normalized(viewquat_align_inv, viewquat_align);
129 
130  vec_to_quat(quat_snap, zaxis_best, OB_NEGZ, OB_POSY);
131  normalize_qt(quat_snap);
132  invert_qt_normalized(quat_snap);
133 
134  /* check if we can find the roll */
135  found = false;
136 
137  /* find best roll */
138  for (j = 0; j < 8; j++) {
139  float angle;
140  float xaxis1[3] = {1, 0, 0};
141  float xaxis2[3] = {1, 0, 0};
142  float quat_final_inv[4];
143 
144  axis_angle_to_quat(quat_roll, zaxis_best, (float)j * DEG2RADF(45.0f));
145  normalize_qt(quat_roll);
146 
147  mul_qt_qtqt(quat_final, quat_snap, quat_roll);
148  normalize_qt(quat_final);
149 
150  /* compare 2 vector angles to find the least roll */
151  invert_qt_qt_normalized(quat_final_inv, quat_final);
152  mul_qt_v3(viewquat_align_inv, xaxis1);
153  mul_qt_v3(quat_final_inv, xaxis2);
154  angle = angle_v3v3(xaxis1, xaxis2);
155 
156  if (angle <= best_angle) {
157  found = true;
158  best_angle = angle;
159  copy_qt_qt(quat_best, quat_final);
160  }
161  }
162 
163  if (found) {
164  /* lock 'quat_best' to an axis view if we can */
166  quat_best, 0.01f, &rv3d->view, &rv3d->view_axis_roll);
167  }
168  else {
169  copy_qt_qt(quat_best, viewquat_align);
170  }
171 
172  copy_qt_qt(rv3d->viewquat, quat_best);
173 
175 
176  if (U.uiflag & USER_AUTOPERSP) {
177  if (RV3D_VIEW_IS_AXIS(rv3d->view)) {
178  if (rv3d->persp == RV3D_PERSP) {
179  rv3d->persp = RV3D_ORTHO;
180  }
181  }
182  }
183  }
184  else if (U.uiflag & USER_AUTOPERSP) {
185  rv3d->persp = vod->init.persp;
186  }
187 }
188 
189 static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2])
190 {
191  RegionView3D *rv3d = vod->rv3d;
192 
193  rv3d->view = RV3D_VIEW_USER; /* need to reset every time because of view snapping */
194 
195  if (U.flag & USER_TRACKBALL) {
196  float axis[3], q1[4], dvec[3], newvec[3];
197  float angle;
198 
199  {
200  const int event_xy_offset[2] = {
201  event_xy[0] + vod->init.event_xy_offset[0],
202  event_xy[1] + vod->init.event_xy_offset[1],
203  };
204  calctrackballvec(&vod->region->winrct, event_xy_offset, newvec);
205  }
206 
207  sub_v3_v3v3(dvec, newvec, vod->init.trackvec);
208 
209  angle = (len_v3(dvec) / (2.0f * V3D_OP_TRACKBALLSIZE)) * (float)M_PI;
210 
211  /* Before applying the sensitivity this is rotating 1:1,
212  * where the cursor would match the surface of a sphere in the view. */
213  angle *= U.view_rotate_sensitivity_trackball;
214 
215  /* Allow for rotation beyond the interval [-pi, pi] */
217 
218  /* This relation is used instead of the actual angle between vectors
219  * so that the angle of rotation is linearly proportional to
220  * the distance that the mouse is dragged. */
221 
222  cross_v3_v3v3(axis, vod->init.trackvec, newvec);
223  axis_angle_to_quat(q1, axis, angle);
224 
225  mul_qt_qtqt(vod->curr.viewquat, q1, vod->init.quat);
226 
228  }
229  else {
230  float quat_local_x[4], quat_global_z[4];
231  float m[3][3];
232  float m_inv[3][3];
233  const float zvec_global[3] = {0.0f, 0.0f, 1.0f};
234  float xaxis[3];
235 
236  /* Radians per-pixel. */
237  const float sensitivity = U.view_rotate_sensitivity_turntable / U.dpi_fac;
238 
239  /* Get the 3x3 matrix and its inverse from the quaternion */
240  quat_to_mat3(m, vod->curr.viewquat);
241  invert_m3_m3(m_inv, m);
242 
243  /* Avoid Gimbal Lock
244  *
245  * Even though turn-table mode is in use, this can occur when the user exits the camera view
246  * or when aligning the view to a rotated object.
247  *
248  * We have gimbal lock when the user's view is rotated +/- 90 degrees along the view axis.
249  * In this case the vertical rotation is the same as the sideways turntable motion.
250  * Making it impossible to get out of the gimbal locked state without resetting the view.
251  *
252  * The logic below lets the user exit out of this state without any abrupt 'fix'
253  * which would be disorienting.
254  *
255  * This works by blending two horizons:
256  * - Rotated-horizon: `cross_v3_v3v3(xaxis, zvec_global, m_inv[2])`
257  * When only this is used, this turntable rotation works - but it's side-ways
258  * (as if the entire turn-table has been placed on its side)
259  * While there is no gimbal lock, it's also awkward to use.
260  * - Un-rotated-horizon: `m_inv[0]`
261  * When only this is used, the turntable rotation can have gimbal lock.
262  *
263  * The solution used here is to blend between these two values,
264  * so the severity of the gimbal lock is used to blend the rotated horizon.
265  * Blending isn't essential, it just makes the transition smoother.
266  *
267  * This allows sideways turn-table rotation on a Z axis that isn't world-space Z,
268  * While up-down turntable rotation eventually corrects gimbal lock. */
269 #if 1
270  if (len_squared_v3v3(zvec_global, m_inv[2]) > 0.001f) {
271  float fac;
272  cross_v3_v3v3(xaxis, zvec_global, m_inv[2]);
273  if (dot_v3v3(xaxis, m_inv[0]) < 0) {
274  negate_v3(xaxis);
275  }
276  fac = angle_normalized_v3v3(zvec_global, m_inv[2]) / (float)M_PI;
277  fac = fabsf(fac - 0.5f) * 2;
278  fac = fac * fac;
279  interp_v3_v3v3(xaxis, xaxis, m_inv[0], fac);
280  }
281  else {
282  copy_v3_v3(xaxis, m_inv[0]);
283  }
284 #else
285  copy_v3_v3(xaxis, m_inv[0]);
286 #endif
287 
288  /* Determine the direction of the x vector (for rotating up and down) */
289  /* This can likely be computed directly from the quaternion. */
290 
291  /* Perform the up/down rotation */
292  axis_angle_to_quat(quat_local_x, xaxis, sensitivity * -(event_xy[1] - vod->prev.event_xy[1]));
293  mul_qt_qtqt(quat_local_x, vod->curr.viewquat, quat_local_x);
294 
295  /* Perform the orbital rotation */
297  quat_global_z, 'Z', sensitivity * vod->reverse * (event_xy[0] - vod->prev.event_xy[0]));
298  mul_qt_qtqt(vod->curr.viewquat, quat_local_x, quat_global_z);
299 
301  }
302 
303  /* avoid precision loss over time */
304  normalize_qt(vod->curr.viewquat);
305 
306  /* use a working copy so view rotation locking doesn't overwrite the locked
307  * rotation back into the view we calculate with */
308  copy_qt_qt(rv3d->viewquat, vod->curr.viewquat);
309 
310  /* Check for view snap,
311  * NOTE: don't apply snap to `vod->viewquat` so the view won't jam up. */
312  if (vod->axis_snap) {
314  }
315  vod->prev.event_xy[0] = event_xy[0];
316  vod->prev.event_xy[1] = event_xy[1];
317 
318  ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, rv3d);
319 
321 }
322 
323 static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
324 {
325  ViewOpsData *vod = op->customdata;
326  short event_code = VIEW_PASS;
327  bool use_autokey = false;
329 
330  /* execute the events */
331  if (event->type == MOUSEMOVE) {
332  event_code = VIEW_APPLY;
333  }
334  else if (event->type == EVT_MODAL_MAP) {
335  switch (event->val) {
336  case VIEW_MODAL_CONFIRM:
337  event_code = VIEW_CONFIRM;
338  break;
340  vod->axis_snap = true;
341  event_code = VIEW_APPLY;
342  break;
344  vod->rv3d->persp = vod->init.persp;
345  vod->axis_snap = false;
346  event_code = VIEW_APPLY;
347  break;
349  WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL, event);
350  event_code = VIEW_CONFIRM;
351  break;
353  WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL, event);
354  event_code = VIEW_CONFIRM;
355  break;
356  }
357  }
358  else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
359  event_code = VIEW_CONFIRM;
360  }
361 
362  if (event_code == VIEW_APPLY) {
363  viewrotate_apply(vod, event->xy);
365  use_autokey = true;
366  }
367  }
368  else if (event_code == VIEW_CONFIRM) {
369  use_autokey = true;
371  }
372 
373  if (use_autokey) {
374  ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, true);
375  }
376 
377  if (ret & OPERATOR_FINISHED) {
378  ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
380  op->customdata = NULL;
381  }
382 
383  return ret;
384 }
385 
386 static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
387 {
388  ViewOpsData *vod;
389 
390  const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
391 
392  /* makes op->customdata */
393  vod = op->customdata = viewops_data_create(
394  C,
395  event,
397  (use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
398 
400 
401  if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) {
402  /* Rotate direction we keep always same */
403  int event_xy[2];
404 
405  if (event->type == MOUSEPAN) {
406  if (event->flag & WM_EVENT_SCROLL_INVERT) {
407  event_xy[0] = 2 * event->xy[0] - event->prev_xy[0];
408  event_xy[1] = 2 * event->xy[1] - event->prev_xy[1];
409  }
410  else {
411  copy_v2_v2_int(event_xy, event->prev_xy);
412  }
413  }
414  else {
415  /* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
416  copy_v2_v2_int(event_xy, event->prev_xy);
417  }
418 
419  viewrotate_apply(vod, event_xy);
420 
422  op->customdata = NULL;
423 
424  return OPERATOR_FINISHED;
425  }
426 
427  /* add temp handler */
429 
430  return OPERATOR_RUNNING_MODAL;
431 }
432 
434 {
436  op->customdata = NULL;
437 }
438 
440 {
441  /* identifiers */
442  ot->name = "Rotate View";
443  ot->description = "Rotate the view";
444  ot->idname = "VIEW3D_OT_rotate";
445 
446  /* api callbacks */
451 
452  /* flags */
454 
456 }
457 
typedef float(TangentPoint)[2]
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
#define M_PI
Definition: BLI_math_base.h:20
bool invert_m3_m3(float R[3][3], const float A[3][3])
Definition: math_matrix.c:1180
void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3])
void invert_qt_normalized(float q[4])
void axis_angle_to_quat(float r[4], const float axis[3], float angle)
void axis_angle_to_quat_single(float q[4], char axis, float angle)
void vec_to_quat(float q[4], const float vec[3], short axis, short upflag)
float normalize_qt(float q[4])
#define DEG2RADF(_deg)
void mul_qt_v3(const float q[4], float r[3])
Definition: math_rotation.c:59
void invert_qt_qt_normalized(float q1[4], const float q2[4])
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
float angle_wrap_rad(float angle)
void quat_to_mat3(float mat[3][3], const float q[4])
float angle_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:385
MINLINE float normalize_v3(float r[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v2_v2_int(int r[2], const int a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:445
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
#define ELEM(...)
@ OB_NEGZ
@ OB_POSY
@ USER_AUTOPERSP
@ USER_TRACKBALL
#define RV3D_VIEW_IS_AXIS(view)
#define RV3D_PERSP
#define RV3D_VIEW_USER
#define RV3D_ORTHO
@ 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_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
bool ED_view3d_camera_lock_undo_push(const char *str, View3D *v3d, struct RegionView3D *rv3d, struct bContext *C)
Definition: view3d_utils.c:726
_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 GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble z
_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
static void axis_limit(const int axis, const float limits[2], float co[3], float dcut[3])
#define C
Definition: RandGen.cpp:25
@ KM_ANY
Definition: WM_types.h:265
@ KM_PRESS
Definition: WM_types.h:267
@ KM_RELEASE
Definition: WM_types.h:268
@ OPTYPE_BLOCKING
Definition: WM_types.h:150
@ OPTYPE_GRAB_CURSOR_XY
Definition: WM_types.h:154
@ WM_EVENT_SCROLL_INVERT
Definition: WM_types.h:606
@ 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
@ 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
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
float viewquat[4]
struct ViewOpsData::@578 curr
float viewquat[4]
struct RegionView3D * rv3d
struct ViewOpsData::@577 prev
struct Depsgraph * depsgraph
struct ARegion * region
struct ViewOpsData::@576 init
float quat[4]
float trackvec[3]
int event_xy_offset[2]
struct View3D * v3d
short val
Definition: WM_types.h:680
int xy[2]
Definition: WM_types.h:682
int prev_xy[2]
Definition: WM_types.h:728
eWM_EventFlag flag
Definition: WM_types.h:707
short type
Definition: WM_types.h:678
const void * modal_items
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
const char * description
Definition: WM_types.h:893
struct wmOperatorType * type
struct PointerRNA * ptr
void view3d_operator_properties_common(wmOperatorType *ot, const enum eV3D_OpPropFlag flag)
void viewops_data_free(bContext *C, ViewOpsData *vod)
ViewOpsData * viewops_data_create(bContext *C, const wmEvent *event, enum eViewOpsFlag viewops_flag)
bool view3d_rotation_poll(bContext *C)
enum eViewOpsFlag viewops_flag_from_prefs(void)
void calctrackballvec(const rcti *rect, const int event_xy[2], float r_dir[3])
void viewrotate_apply_dyn_ofs(ViewOpsData *vod, const float viewquat_new[4])
@ VIEWROT_MODAL_AXIS_SNAP_ENABLE
@ VIEWROT_MODAL_SWITCH_MOVE
@ VIEW_MODAL_CONFIRM
@ VIEWROT_MODAL_SWITCH_ZOOM
@ VIEWROT_MODAL_AXIS_SNAP_DISABLE
@ VIEWOPS_FLAG_USE_MOUSE_INIT
@ VIEWOPS_FLAG_PERSP_ENSURE
void ED_view3d_smooth_view_force_finish(struct bContext *C, struct View3D *v3d, struct ARegion *region)
@ V3D_OP_PROP_USE_MOUSE_INIT
#define V3D_OP_TRACKBALLSIZE
static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2])
static void viewrotate_cancel(bContext *C, wmOperator *op)
static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void VIEW3D_OT_rotate(wmOperatorType *ot)
void viewrotate_modal_keymap(wmKeyConfig *keyconf)
static void viewrotate_apply_snap(ViewOpsData *vod)
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)
@ MOUSEPAN
@ EVT_MODAL_MAP
@ MOUSEROTATE
@ EVT_LEFTCTRLKEY
@ MOUSEMOVE
@ LEFTMOUSE
@ EVT_LEFTSHIFTKEY
wmOperatorType * ot
Definition: wm_files.c:3479
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition: wm_keymap.c:914
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
Definition: wm_keymap.c:985
wmKeyMapItem * WM_modalkeymap_add_item(wmKeyMap *km, const KeyMapItem_Params *params, int value)
Definition: wm_keymap.c:927
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition: wm_keymap.c:888