Blender  V3.3
view3d_navigate_fly.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
11 /* defines VIEW3D_OT_fly modal operator */
12 
13 #ifdef WITH_INPUT_NDOF
14 //# define NDOF_FLY_DEBUG
15 /* is this needed for ndof? - commented so redraw doesn't thrash - campbell */
16 //# define NDOF_FLY_DRAW_TOOMUCH
17 #endif /* WITH_INPUT_NDOF */
18 
19 #include "DNA_object_types.h"
20 
21 #include "MEM_guardedalloc.h"
22 
23 #include "BLI_blenlib.h"
24 #include "BLI_math.h"
25 
26 #include "BKE_context.h"
27 #include "BKE_lib_id.h"
28 #include "BKE_report.h"
29 
30 #include "BLT_translation.h"
31 
32 #include "WM_api.h"
33 #include "WM_types.h"
34 
35 #include "ED_screen.h"
36 #include "ED_space_api.h"
37 
38 #include "PIL_time.h" /* Smooth-view. */
39 
40 #include "UI_interface.h"
41 #include "UI_resources.h"
42 
43 #include "GPU_immediate.h"
44 
45 #include "DEG_depsgraph.h"
46 
47 #include "view3d_intern.h" /* own include */
48 #include "view3d_navigate.h"
49 
50 /* -------------------------------------------------------------------- */
54 /* NOTE: these defines are saved in keymap files,
55  * do not change values but just add new ones */
56 enum {
75  FLY_MODAL_SPEED, /* mouse-pan typically. */
76 };
77 
78 /* relative view axis locking - xlock, zlock */
79 typedef enum eFlyPanState {
80  /* disabled */
82 
83  /* enabled but not checking because mouse hasn't moved outside the margin since locking was
84  * checked an not needed when the mouse moves, locking is set to 2 so checks are done. */
86 
87  /* mouse moved and checking needed,
88  * if no view altering is done its changed back to #FLY_AXISLOCK_STATE_IDLE */
91 
93 {
94  static const EnumPropertyItem modal_items[] = {
95  {FLY_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
96  {FLY_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
97 
98  {FLY_MODAL_DIR_FORWARD, "FORWARD", 0, "Forward", ""},
99  {FLY_MODAL_DIR_BACKWARD, "BACKWARD", 0, "Backward", ""},
100  {FLY_MODAL_DIR_LEFT, "LEFT", 0, "Left", ""},
101  {FLY_MODAL_DIR_RIGHT, "RIGHT", 0, "Right", ""},
102  {FLY_MODAL_DIR_UP, "UP", 0, "Up", ""},
103  {FLY_MODAL_DIR_DOWN, "DOWN", 0, "Down", ""},
104 
105  {FLY_MODAL_PAN_ENABLE, "PAN_ENABLE", 0, "Pan", ""},
106  {FLY_MODAL_PAN_DISABLE, "PAN_DISABLE", 0, "Pan (Off)", ""},
107 
108  {FLY_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""},
109  {FLY_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""},
110 
111  {FLY_MODAL_AXIS_LOCK_X, "AXIS_LOCK_X", 0, "X Axis Correction", "X axis correction (toggle)"},
112  {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "Z Axis Correction", "Z axis correction (toggle)"},
113 
114  {FLY_MODAL_PRECISION_ENABLE, "PRECISION_ENABLE", 0, "Precision", ""},
115  {FLY_MODAL_PRECISION_DISABLE, "PRECISION_DISABLE", 0, "Precision (Off)", ""},
116 
117  {FLY_MODAL_FREELOOK_ENABLE, "FREELOOK_ENABLE", 0, "Rotation", ""},
118  {FLY_MODAL_FREELOOK_DISABLE, "FREELOOK_DISABLE", 0, "Rotation (Off)", ""},
119 
120  {0, NULL, 0, NULL, NULL},
121  };
122 
123  wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Fly Modal");
124 
125  /* this function is called for each spacetype, only needs to add map once */
126  if (keymap && keymap->modal_items) {
127  return;
128  }
129 
130  keymap = WM_modalkeymap_ensure(keyconf, "View3D Fly Modal", modal_items);
131 
132  /* assign map to operators */
133  WM_modalkeymap_assign(keymap, "VIEW3D_OT_fly");
134 }
135 
138 /* -------------------------------------------------------------------- */
142 typedef struct FlyInfo {
143  /* context stuff */
149 
152 
153  short state;
154  bool redraw;
158 
166 
168  int mval[2];
170  int center_mval[2];
172  float width, height;
173 
174 #ifdef WITH_INPUT_NDOF
176  wmNDOFMotionData *ndof;
177 #endif
178 
179  /* Fly state. */
181  float speed;
183  short axis;
185  bool pan_view;
186 
191  float grid;
192 
193  /* compare between last state */
198 
200 
201  /* use for some lag */
203  float dvec_prev[3];
204 
206 
208 
211 /* -------------------------------------------------------------------- */
215 /* prototypes */
216 #ifdef WITH_INPUT_NDOF
217 static void flyApply_ndof(bContext *C, FlyInfo *fly, bool is_confirm);
218 #endif /* WITH_INPUT_NDOF */
219 static int flyApply(bContext *C, struct FlyInfo *fly, bool is_confirm);
220 
221 static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(region), void *arg)
222 {
223  FlyInfo *fly = arg;
224  rctf viewborder;
225  int xoff, yoff;
226  float x1, x2, y1, y2;
227 
230  fly->scene, fly->depsgraph, fly->region, fly->v3d, fly->rv3d, &viewborder, false);
231  xoff = viewborder.xmin;
232  yoff = viewborder.ymin;
233  }
234  else {
235  xoff = 0;
236  yoff = 0;
237  }
238 
239  /* draws 4 edge brackets that frame the safe area where the
240  * mouse can move during fly mode without spinning the view */
241 
242  x1 = xoff + 0.45f * fly->width;
243  y1 = yoff + 0.45f * fly->height;
244  x2 = xoff + 0.55f * fly->width;
245  y2 = yoff + 0.55f * fly->height;
246 
249 
251 
253 
255 
256  /* bottom left */
257  immVertex2f(pos, x1, y1);
258  immVertex2f(pos, x1, y1 + 5);
259 
260  immVertex2f(pos, x1, y1);
261  immVertex2f(pos, x1 + 5, y1);
262 
263  /* top right */
264  immVertex2f(pos, x2, y2);
265  immVertex2f(pos, x2, y2 - 5);
266 
267  immVertex2f(pos, x2, y2);
268  immVertex2f(pos, x2 - 5, y2);
269 
270  /* top left */
271  immVertex2f(pos, x1, y2);
272  immVertex2f(pos, x1, y2 - 5);
273 
274  immVertex2f(pos, x1, y2);
275  immVertex2f(pos, x1 + 5, y2);
276 
277  /* bottom right */
278  immVertex2f(pos, x2, y1);
279  immVertex2f(pos, x2, y1 + 5);
280 
281  immVertex2f(pos, x2, y1);
282  immVertex2f(pos, x2 - 5, y1);
283 
284  immEnd();
286 }
287 
290 /* -------------------------------------------------------------------- */
294 /* FlyInfo->state */
295 enum {
299 };
300 
301 static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event)
302 {
304  wmWindow *win = CTX_wm_window(C);
305  rctf viewborder;
306 
307  float upvec[3]; /* tmp */
308  float mat[3][3];
309 
310  fly->rv3d = CTX_wm_region_view3d(C);
311  fly->v3d = CTX_wm_view3d(C);
312  fly->region = CTX_wm_region(C);
314  fly->scene = CTX_data_scene(C);
315 
316 #ifdef NDOF_FLY_DEBUG
317  puts("\n-- fly begin --");
318 #endif
319 
320  /* sanity check: for rare but possible case (if lib-linking the camera fails) */
321  if ((fly->rv3d->persp == RV3D_CAMOB) && (fly->v3d->camera == NULL)) {
322  fly->rv3d->persp = RV3D_PERSP;
323  }
324 
325  if (fly->rv3d->persp == RV3D_CAMOB &&
327  BKE_report(op->reports,
328  RPT_ERROR,
329  "Cannot navigate a camera from an external library or non-editable override");
330 
331  return false;
332  }
333 
334  if (ED_view3d_offset_lock_check(fly->v3d, fly->rv3d)) {
335  BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view offset is locked");
336  return false;
337  }
338 
339  if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->constraints.first) {
340  BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints");
341  return false;
342  }
343 
344  fly->state = FLY_RUNNING;
345  fly->speed = 0.0f;
346  fly->axis = 2;
347  fly->pan_view = false;
350  fly->xlock_momentum = 0.0f;
351  fly->zlock_momentum = 0.0f;
352  fly->grid = 1.0f;
353  fly->use_precision = false;
354  fly->use_freelook = false;
356 
357 #ifdef NDOF_FLY_DRAW_TOOMUCH
358  fly->redraw = 1;
359 #endif
360  zero_v3(fly->dvec_prev);
361 
362  fly->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f);
363 
364  copy_v2_v2_int(fly->mval, event->mval);
365 
366 #ifdef WITH_INPUT_NDOF
367  fly->ndof = NULL;
368 #endif
369 
371 
374 
375  fly->rv3d->rflag |= RV3D_NAVIGATING;
376 
377  /* detect whether to start with Z locking */
378  copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
379  copy_m3_m4(mat, fly->rv3d->viewinv);
380  mul_m3_v3(mat, upvec);
381  if (fabsf(upvec[2]) < 0.1f) {
383  }
384 
386  fly->depsgraph, fly->scene, fly->v3d, fly->rv3d);
387 
388  /* calculate center */
391  fly->scene, fly->depsgraph, fly->region, fly->v3d, fly->rv3d, &viewborder, false);
392 
393  fly->width = BLI_rctf_size_x(&viewborder);
394  fly->height = BLI_rctf_size_y(&viewborder);
395 
396  fly->center_mval[0] = viewborder.xmin + fly->width / 2;
397  fly->center_mval[1] = viewborder.ymin + fly->height / 2;
398  }
399  else {
400  fly->width = fly->region->winx;
401  fly->height = fly->region->winy;
402 
403  fly->center_mval[0] = fly->width / 2;
404  fly->center_mval[1] = fly->height / 2;
405  }
406 
407  /* center the mouse, probably the UI mafia are against this but without its quite annoying */
408  WM_cursor_warp(win,
409  fly->region->winrct.xmin + fly->center_mval[0],
410  fly->region->winrct.ymin + fly->center_mval[1]);
411 
412  return 1;
413 }
414 
415 static int flyEnd(bContext *C, FlyInfo *fly)
416 {
417  wmWindow *win;
418  RegionView3D *rv3d;
419 
420  if (fly->state == FLY_RUNNING) {
421  return OPERATOR_RUNNING_MODAL;
422  }
423  if (fly->state == FLY_CONFIRM) {
424  /* Needed for auto_keyframe. */
425 #ifdef WITH_INPUT_NDOF
426  if (fly->ndof) {
427  flyApply_ndof(C, fly, true);
428  }
429  else
430 #endif /* WITH_INPUT_NDOF */
431  {
432  flyApply(C, fly, true);
433  }
434  }
435 
436 #ifdef NDOF_FLY_DEBUG
437  puts("\n-- fly end --");
438 #endif
439 
440  win = CTX_wm_window(C);
441  rv3d = fly->rv3d;
442 
444 
446 
448 
449  rv3d->rflag &= ~RV3D_NAVIGATING;
450 
451 #ifdef WITH_INPUT_NDOF
452  if (fly->ndof) {
453  MEM_freeN(fly->ndof);
454  }
455 #endif
456 
457  if (fly->state == FLY_CONFIRM) {
458  MEM_freeN(fly);
459  return OPERATOR_FINISHED;
460  }
461 
462  MEM_freeN(fly);
463  return OPERATOR_CANCELLED;
464 }
465 
466 static void flyEvent(FlyInfo *fly, const wmEvent *event)
467 {
468  if (event->type == TIMER && event->customdata == fly->timer) {
469  fly->redraw = 1;
470  }
471  else if (event->type == MOUSEMOVE) {
472  copy_v2_v2_int(fly->mval, event->mval);
473  }
474 #ifdef WITH_INPUT_NDOF
475  else if (event->type == NDOF_MOTION) {
476  /* do these automagically get delivered? yes. */
477  // puts("ndof motion detected in fly mode!");
478  // static const char *tag_name = "3D mouse position";
479 
480  const wmNDOFMotionData *incoming_ndof = event->customdata;
481  switch (incoming_ndof->progress) {
482  case P_STARTING:
483  /* start keeping track of 3D mouse position */
484 # ifdef NDOF_FLY_DEBUG
485  puts("start keeping track of 3D mouse position");
486 # endif
487  /* fall-through */
488  case P_IN_PROGRESS:
489  /* update 3D mouse position */
490 # ifdef NDOF_FLY_DEBUG
491  putchar('.');
492  fflush(stdout);
493 # endif
494  if (fly->ndof == NULL) {
495  // fly->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name);
496  fly->ndof = MEM_dupallocN(incoming_ndof);
497  // fly->ndof = malloc(sizeof(wmNDOFMotionData));
498  }
499  else {
500  memcpy(fly->ndof, incoming_ndof, sizeof(wmNDOFMotionData));
501  }
502  break;
503  case P_FINISHING:
504  /* stop keeping track of 3D mouse position */
505 # ifdef NDOF_FLY_DEBUG
506  puts("stop keeping track of 3D mouse position");
507 # endif
508  if (fly->ndof) {
509  MEM_freeN(fly->ndof);
510  // free(fly->ndof);
511  fly->ndof = NULL;
512  }
513  /* update the time else the view will jump when 2D mouse/timer resume */
515  break;
516  default:
517  break; /* should always be one of the above 3 */
518  }
519  }
520 #endif /* WITH_INPUT_NDOF */
521  /* handle modal keymap first */
522  else if (event->type == EVT_MODAL_MAP) {
523  switch (event->val) {
524  case FLY_MODAL_CANCEL:
525  fly->state = FLY_CANCEL;
526  break;
527  case FLY_MODAL_CONFIRM:
528  fly->state = FLY_CONFIRM;
529  break;
530 
531  /* Speed adjusting with mouse-pan (track-pad). */
532  case FLY_MODAL_SPEED: {
533  float fac = 0.02f * (event->prev_xy[1] - event->xy[1]);
534 
535  /* allowing to brake immediate */
536  if (fac > 0.0f && fly->speed < 0.0f) {
537  fly->speed = 0.0f;
538  }
539  else if (fac < 0.0f && fly->speed > 0.0f) {
540  fly->speed = 0.0f;
541  }
542  else {
543  fly->speed += fly->grid * fac;
544  }
545 
546  break;
547  }
548  case FLY_MODAL_ACCELERATE: {
549  double time_currwheel;
550  float time_wheel;
551 
552  /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */
553  if (fly->axis == -1) {
554  fly->axis = 2;
555  fly->speed = fabsf(fly->speed);
556  }
557 
558  time_currwheel = PIL_check_seconds_timer();
559  time_wheel = (float)(time_currwheel - fly->time_lastwheel);
560  fly->time_lastwheel = time_currwheel;
561  /* Mouse wheel delays range from (0.5 == slow) to (0.01 == fast) */
562  /* 0-0.5 -> 0-5.0 */
563  time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f)));
564 
565  if (fly->speed < 0.0f) {
566  fly->speed = 0.0f;
567  }
568  else {
569  fly->speed += fly->grid * time_wheel * (fly->use_precision ? 0.1f : 1.0f);
570  }
571  break;
572  }
573  case FLY_MODAL_DECELERATE: {
574  double time_currwheel;
575  float time_wheel;
576 
577  /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */
578  if (fly->axis == -1) {
579  fly->axis = 2;
580  fly->speed = -fabsf(fly->speed);
581  }
582 
583  time_currwheel = PIL_check_seconds_timer();
584  time_wheel = (float)(time_currwheel - fly->time_lastwheel);
585  fly->time_lastwheel = time_currwheel;
586  /* 0-0.5 -> 0-5.0 */
587  time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f)));
588 
589  if (fly->speed > 0.0f) {
590  fly->speed = 0;
591  }
592  else {
593  fly->speed -= fly->grid * time_wheel * (fly->use_precision ? 0.1f : 1.0f);
594  }
595  break;
596  }
598  fly->pan_view = true;
599  break;
601  fly->pan_view = false;
602  break;
603 
604  /* Implement WASD keys, comments only for 'forward'. */
606  if (fly->axis == 2 && fly->speed < 0.0f) {
607  /* reverse direction stops, tap again to continue */
608  fly->axis = -1;
609  }
610  else {
611  /* Flip speed rather than stopping, game like motion,
612  * else increase like mouse-wheel if we're already moving in that direction. */
613  if (fly->speed < 0.0f) {
614  fly->speed = -fly->speed;
615  }
616  else if (fly->axis == 2) {
617  fly->speed += fly->grid;
618  }
619  fly->axis = 2;
620  }
621  break;
623  if (fly->axis == 2 && fly->speed > 0.0f) {
624  fly->axis = -1;
625  }
626  else {
627  if (fly->speed > 0.0f) {
628  fly->speed = -fly->speed;
629  }
630  else if (fly->axis == 2) {
631  fly->speed -= fly->grid;
632  }
633 
634  fly->axis = 2;
635  }
636  break;
637  case FLY_MODAL_DIR_LEFT:
638  if (fly->axis == 0 && fly->speed < 0.0f) {
639  fly->axis = -1;
640  }
641  else {
642  if (fly->speed < 0.0f) {
643  fly->speed = -fly->speed;
644  }
645  else if (fly->axis == 0) {
646  fly->speed += fly->grid;
647  }
648 
649  fly->axis = 0;
650  }
651  break;
652  case FLY_MODAL_DIR_RIGHT:
653  if (fly->axis == 0 && fly->speed > 0.0f) {
654  fly->axis = -1;
655  }
656  else {
657  if (fly->speed > 0.0f) {
658  fly->speed = -fly->speed;
659  }
660  else if (fly->axis == 0) {
661  fly->speed -= fly->grid;
662  }
663 
664  fly->axis = 0;
665  }
666  break;
667  case FLY_MODAL_DIR_DOWN:
668  if (fly->axis == 1 && fly->speed < 0.0f) {
669  fly->axis = -1;
670  }
671  else {
672  if (fly->speed < 0.0f) {
673  fly->speed = -fly->speed;
674  }
675  else if (fly->axis == 1) {
676  fly->speed += fly->grid;
677  }
678  fly->axis = 1;
679  }
680  break;
681  case FLY_MODAL_DIR_UP:
682  if (fly->axis == 1 && fly->speed > 0.0f) {
683  fly->axis = -1;
684  }
685  else {
686  if (fly->speed > 0.0f) {
687  fly->speed = -fly->speed;
688  }
689  else if (fly->axis == 1) {
690  fly->speed -= fly->grid;
691  }
692  fly->axis = 1;
693  }
694  break;
695 
697  if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
699  }
700  else {
702  fly->xlock_momentum = 0.0;
703  }
704  break;
706  if (fly->zlock != FLY_AXISLOCK_STATE_OFF) {
708  }
709  else {
711  fly->zlock_momentum = 0.0;
712  }
713  break;
714 
716  fly->use_precision = true;
717  break;
719  fly->use_precision = false;
720  break;
721 
723  fly->use_freelook = true;
724  break;
726  fly->use_freelook = false;
727  break;
728  }
729  }
730 }
731 
732 static void flyMoveCamera(bContext *C,
733  FlyInfo *fly,
734  const bool do_rotate,
735  const bool do_translate,
736  const bool is_confirm)
737 {
738  /* we only consider autokeying on playback or if user confirmed fly on the same frame
739  * otherwise we get a keyframe even if the user cancels. */
740  const bool use_autokey = is_confirm || fly->anim_playing;
741  ED_view3d_cameracontrol_update(fly->v3d_camera_control, use_autokey, C, do_rotate, do_translate);
742 }
743 
744 static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm)
745 {
746 #define FLY_ROTATE_FAC 10.0f /* more is faster */
747 #define FLY_ZUP_CORRECT_FAC 0.1f /* amount to correct per step */
748 #define FLY_ZUP_CORRECT_ACCEL 0.05f /* increase upright momentum each step */
749 #define FLY_SMOOTH_FAC 20.0f /* higher value less lag */
750 
751  RegionView3D *rv3d = fly->rv3d;
752 
753  /* 3x3 copy of the view matrix so we can move along the view axis */
754  float mat[3][3];
755  /* this is the direction that's added to the view offset per redraw */
756  float dvec[3] = {0, 0, 0};
757 
758  /* Camera Up-righting variables. */
759  float moffset[2]; /* mouse offset from the views center */
760  float tmp_quat[4]; /* used for rotating the view */
761 
762  /* x and y margin defining the safe area where the mouse's movement won't rotate the view */
763  int xmargin, ymargin;
764 
765 #ifdef NDOF_FLY_DEBUG
766  {
767  static uint iteration = 1;
768  printf("fly timer %d\n", iteration++);
769  }
770 #endif
771 
772  xmargin = fly->width / 20.0f;
773  ymargin = fly->height / 20.0f;
774 
775  {
776 
777  /* mouse offset from the center */
778  moffset[0] = fly->mval[0] - fly->center_mval[0];
779  moffset[1] = fly->mval[1] - fly->center_mval[1];
780 
781  /* enforce a view margin */
782  if (moffset[0] > xmargin) {
783  moffset[0] -= xmargin;
784  }
785  else if (moffset[0] < -xmargin) {
786  moffset[0] += xmargin;
787  }
788  else {
789  moffset[0] = 0;
790  }
791 
792  if (moffset[1] > ymargin) {
793  moffset[1] -= ymargin;
794  }
795  else if (moffset[1] < -ymargin) {
796  moffset[1] += ymargin;
797  }
798  else {
799  moffset[1] = 0;
800  }
801 
802  /* Scale the mouse movement by this value - scales mouse movement to the view size
803  * `moffset[0] / (region->winx-xmargin * 2)` - window size minus margin (same for y)
804  *
805  * the mouse moves isn't linear. */
806 
807  if (moffset[0]) {
808  moffset[0] /= fly->width - (xmargin * 2);
809  moffset[0] *= fabsf(moffset[0]);
810  }
811 
812  if (moffset[1]) {
813  moffset[1] /= fly->height - (ymargin * 2);
814  moffset[1] *= fabsf(moffset[1]);
815  }
816 
817  /* Should we redraw? */
818  if ((fly->speed != 0.0f) || moffset[0] || moffset[1] ||
819  (fly->zlock != FLY_AXISLOCK_STATE_OFF) || (fly->xlock != FLY_AXISLOCK_STATE_OFF) ||
820  dvec[0] || dvec[1] || dvec[2]) {
821  float dvec_tmp[3];
822 
823  /* time how fast it takes for us to redraw,
824  * this is so simple scenes don't fly too fast */
825  double time_current;
826  float time_redraw;
827  float time_redraw_clamped;
828 #ifdef NDOF_FLY_DRAW_TOOMUCH
829  fly->redraw = 1;
830 #endif
831  time_current = PIL_check_seconds_timer();
832  time_redraw = (float)(time_current - fly->time_lastdraw);
833 
834  /* clamp redraw time to avoid jitter in roll correction */
835  time_redraw_clamped = min_ff(0.05f, time_redraw);
836 
837  fly->time_lastdraw = time_current;
838 
839  /* Scale the time to use shift to scale the speed down- just like
840  * shift slows many other areas of blender down */
841  if (fly->use_precision) {
842  fly->speed = fly->speed * (1.0f - time_redraw_clamped);
843  }
844 
845  copy_m3_m4(mat, rv3d->viewinv);
846 
847  if (fly->pan_view == true) {
848  /* pan only */
849  copy_v3_fl3(dvec_tmp, -moffset[0], -moffset[1], 0.0f);
850 
851  if (fly->use_precision) {
852  dvec_tmp[0] *= 0.1f;
853  dvec_tmp[1] *= 0.1f;
854  }
855 
856  mul_m3_v3(mat, dvec_tmp);
857  mul_v3_fl(dvec_tmp, time_redraw * 200.0f * fly->grid);
858  }
859  else {
860  float roll; /* similar to the angle between the camera's up and the Z-up,
861  * but its very rough so just roll */
862 
863  /* rotate about the X axis- look up/down */
864  if (moffset[1]) {
865  float upvec[3];
866  copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
867  mul_m3_v3(mat, upvec);
868  /* Rotate about the relative up vec */
869  axis_angle_to_quat(tmp_quat, upvec, moffset[1] * time_redraw * -FLY_ROTATE_FAC);
870  mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
871 
872  if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
873  fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; /* check for rotation */
874  }
875  if (fly->zlock != FLY_AXISLOCK_STATE_OFF) {
877  }
878  fly->xlock_momentum = 0.0f;
879  }
880 
881  /* rotate about the Y axis- look left/right */
882  if (moffset[0]) {
883  float upvec[3];
884  /* if we're upside down invert the moffset */
885  copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
886  mul_m3_v3(mat, upvec);
887 
888  if (upvec[2] < 0.0f) {
889  moffset[0] = -moffset[0];
890  }
891 
892  /* make the lock vectors */
893  if (fly->zlock) {
894  copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
895  }
896  else {
897  copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
898  mul_m3_v3(mat, upvec);
899  }
900 
901  /* Rotate about the relative up vec */
902  axis_angle_to_quat(tmp_quat, upvec, moffset[0] * time_redraw * FLY_ROTATE_FAC);
903  mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
904 
905  if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
906  fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; /* check for rotation */
907  }
908  if (fly->zlock != FLY_AXISLOCK_STATE_OFF) {
910  }
911  }
912 
913  if (fly->zlock == FLY_AXISLOCK_STATE_ACTIVE) {
914  float upvec[3];
915  copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
916  mul_m3_v3(mat, upvec);
917 
918  /* make sure we have some z rolling */
919  if (fabsf(upvec[2]) > 0.00001f) {
920  roll = upvec[2] * 5.0f;
921  /* rotate the view about this axis */
922  copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
923  mul_m3_v3(mat, upvec);
924  /* Rotate about the relative up vec */
925  axis_angle_to_quat(tmp_quat,
926  upvec,
927  roll * time_redraw_clamped * fly->zlock_momentum *
929  mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
930 
932  }
933  else {
934  /* don't check until the view rotates again */
936  fly->zlock_momentum = 0.0f;
937  }
938  }
939 
940  /* Only apply X-axis correction when mouse isn't applying x rotation. */
941  if (fly->xlock == FLY_AXISLOCK_STATE_ACTIVE && moffset[1] == 0) {
942  float upvec[3];
943  copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
944  mul_m3_v3(mat, upvec);
945  /* make sure we have some z rolling */
946  if (fabsf(upvec[2]) > 0.00001f) {
947  roll = upvec[2] * -5.0f;
948  /* rotate the view about this axis */
949  copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
950  mul_m3_v3(mat, upvec);
951 
952  /* Rotate about the relative up vec */
954  tmp_quat, upvec, roll * time_redraw_clamped * fly->xlock_momentum * 0.1f);
955  mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
956 
957  fly->xlock_momentum += 0.05f;
958  }
959  else {
960  fly->xlock = FLY_AXISLOCK_STATE_IDLE; /* see above */
961  fly->xlock_momentum = 0.0f;
962  }
963  }
964 
965  if (fly->axis == -1) {
966  /* pause */
967  zero_v3(dvec_tmp);
968  }
969  else if (!fly->use_freelook) {
970  /* Normal operation */
971  /* define dvec, view direction vector */
972  zero_v3(dvec_tmp);
973  /* move along the current axis */
974  dvec_tmp[fly->axis] = 1.0f;
975 
976  mul_m3_v3(mat, dvec_tmp);
977  }
978  else {
979  normalize_v3_v3(dvec_tmp, fly->dvec_prev);
980  if (fly->speed < 0.0f) {
981  negate_v3(dvec_tmp);
982  }
983  }
984 
985  mul_v3_fl(dvec_tmp, fly->speed * time_redraw * 0.25f);
986  }
987 
988  /* impose a directional lag */
990  dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * FLY_SMOOTH_FAC))));
991 
992  add_v3_v3(rv3d->ofs, dvec);
993 
994  if (rv3d->persp == RV3D_CAMOB) {
995  const bool do_rotate = ((fly->xlock != FLY_AXISLOCK_STATE_OFF) ||
996  (fly->zlock != FLY_AXISLOCK_STATE_OFF) ||
997  ((moffset[0] || moffset[1]) && !fly->pan_view));
998  const bool do_translate = (fly->speed != 0.0f || fly->pan_view);
999  flyMoveCamera(C, fly, do_rotate, do_translate, is_confirm);
1000  }
1001  }
1002  else {
1003  /* we're not redrawing but we need to update the time else the view will jump */
1005  }
1006  /* end drawing */
1007  copy_v3_v3(fly->dvec_prev, dvec);
1008  }
1009 
1010  return OPERATOR_FINISHED;
1011 }
1012 
1013 #ifdef WITH_INPUT_NDOF
1014 static void flyApply_ndof(bContext *C, FlyInfo *fly, bool is_confirm)
1015 {
1017  bool has_translate, has_rotate;
1018 
1019  view3d_ndof_fly(fly->ndof,
1020  fly->v3d,
1021  fly->rv3d,
1022  fly->use_precision,
1023  lock_ob ? lock_ob->protectflag : 0,
1024  &has_translate,
1025  &has_rotate);
1026 
1027  if (has_translate || has_rotate) {
1028  fly->redraw = true;
1029 
1030  if (fly->rv3d->persp == RV3D_CAMOB) {
1031  flyMoveCamera(C, fly, has_rotate, has_translate, is_confirm);
1032  }
1033  }
1034 }
1035 #endif /* WITH_INPUT_NDOF */
1036 
1039 /* -------------------------------------------------------------------- */
1043 static int fly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1044 {
1046  FlyInfo *fly;
1047 
1049  return OPERATOR_CANCELLED;
1050  }
1051 
1052  fly = MEM_callocN(sizeof(FlyInfo), "FlyOperation");
1053 
1054  op->customdata = fly;
1055 
1056  if (initFlyInfo(C, fly, op, event) == false) {
1057  MEM_freeN(op->customdata);
1058  return OPERATOR_CANCELLED;
1059  }
1060 
1061  flyEvent(fly, event);
1062 
1064 
1065  return OPERATOR_RUNNING_MODAL;
1066 }
1067 
1068 static void fly_cancel(bContext *C, wmOperator *op)
1069 {
1070  FlyInfo *fly = op->customdata;
1071 
1072  fly->state = FLY_CANCEL;
1073  flyEnd(C, fly);
1074  op->customdata = NULL;
1075 }
1076 
1077 static int fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
1078 {
1079  int exit_code;
1080  bool do_draw = false;
1081  FlyInfo *fly = op->customdata;
1082  View3D *v3d = fly->v3d;
1083  RegionView3D *rv3d = fly->rv3d;
1085 
1086  fly->redraw = 0;
1087 
1088  flyEvent(fly, event);
1089 
1090 #ifdef WITH_INPUT_NDOF
1091  if (fly->ndof) { /* 3D mouse overrules [2D mouse + timer] */
1092  if (event->type == NDOF_MOTION) {
1093  flyApply_ndof(C, fly, false);
1094  }
1095  }
1096  else
1097 #endif /* WITH_INPUT_NDOF */
1098  if (event->type == TIMER && event->customdata == fly->timer) {
1099  flyApply(C, fly, false);
1100  }
1101 
1102  do_draw |= fly->redraw;
1103 
1104  exit_code = flyEnd(C, fly);
1105 
1106  if (exit_code == OPERATOR_FINISHED) {
1107  ED_view3d_camera_lock_undo_push(op->type->name, v3d, rv3d, C);
1108  }
1109  if (exit_code != OPERATOR_RUNNING_MODAL) {
1110  do_draw = true;
1111  }
1112 
1113  if (do_draw) {
1114  if (rv3d->persp == RV3D_CAMOB) {
1116  }
1117 
1118  // puts("redraw!"); // too frequent, commented with NDOF_FLY_DRAW_TOOMUCH for now
1120  }
1121 
1122  return exit_code;
1123 }
1124 
1126 {
1127  /* identifiers */
1128  ot->name = "Fly Navigation";
1129  ot->description = "Interactively fly around the scene";
1130  ot->idname = "VIEW3D_OT_fly";
1131 
1132  /* api callbacks */
1133  ot->invoke = fly_invoke;
1134  ot->cancel = fly_cancel;
1135  ot->modal = fly_modal;
1137 
1138  /* flags */
1139  ot->flag = OPTYPE_BLOCKING;
1140 }
1141 
typedef float(TangentPoint)[2]
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
struct Depsgraph * CTX_data_expect_evaluated_depsgraph(const bContext *C)
Definition: context.c:1519
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct RegionView3D * CTX_wm_region_view3d(const bContext *C)
Definition: context.c:793
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
bool BKE_id_is_editable(const struct Main *bmain, const struct ID *id)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
MINLINE float min_ff(float a, float b)
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:926
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
void axis_angle_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
MINLINE void mul_v3_fl(float r[3], float f)
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 void copy_v3_fl3(float v[3], float x, float y, float z)
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
MINLINE void negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:194
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition: BLI_rect.h:198
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
Object is a sort of wrapper for general info.
#define RV3D_LOCK_FLAGS(rv3d)
#define RV3D_CAMOB
@ RV3D_LOCK_ANY_TRANSFORM
#define RV3D_PERSP
#define RV3D_NAVIGATING
@ 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_operator_region_view3d_active(struct bContext *C)
Definition: screen_ops.c:230
void * ED_region_draw_cb_activate(struct ARegionType *art, void(*draw)(const struct bContext *, struct ARegion *, void *), void *customdata, int type)
Definition: spacetypes.c:226
#define REGION_DRAW_POST_PIXEL
Definition: ED_space_api.h:63
bool ED_region_draw_cb_exit(struct ARegionType *art, void *handle)
Definition: spacetypes.c:241
bool ED_view3d_offset_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d)
bool ED_view3d_camera_lock_undo_push(const char *str, View3D *v3d, struct RegionView3D *rv3d, struct bContext *C)
Definition: view3d_utils.c:726
void ED_view3d_calc_camera_border(const struct Scene *scene, struct Depsgraph *depsgraph, const struct ARegion *region, const struct View3D *v3d, const struct RegionView3D *rv3d, struct rctf *r_viewborder, bool no_shift)
void immUnbindProgram(void)
void immVertex2f(uint attr_id, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immUniformThemeColor3(int color_id)
GPUVertFormat * immVertexFormat(void)
void immBegin(GPUPrimType, uint vertex_len)
void immEnd(void)
_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 GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble y1
_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 GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble x2
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:20
@ GPU_SHADER_2D_UNIFORM_COLOR
Definition: GPU_shader.h:201
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Read Guarded memory(de)allocation.
Platform independent time functions.
#define C
Definition: RandGen.cpp:25
@ TH_VIEW_OVERLAY
Definition: UI_resources.h:327
@ OPTYPE_BLOCKING
Definition: WM_types.h:150
#define ND_TRANSFORM
Definition: WM_types.h:405
#define NC_OBJECT
Definition: WM_types.h:329
@ P_IN_PROGRESS
Definition: WM_types.h:763
@ P_STARTING
Definition: WM_types.h:762
@ P_FINISHING
Definition: WM_types.h:764
uint pos
format
Definition: logImageCore.h:38
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define fabsf(x)
Definition: metal/compat.h:219
struct ARegionType * type
double time_lastdraw
eFlyPanState xlock
wmTimer * timer
RegionView3D * rv3d
float dvec_prev[3]
struct View3DCameraControl * v3d_camera_control
double time_lastwheel
eFlyPanState zlock
float zlock_momentum
ARegion * region
int center_mval[2]
struct Depsgraph * depsgraph
float xlock_momentum
void * draw_handle_pixel
void * first
Definition: DNA_listBase.h:31
ListBase constraints
short protectflag
float viewquat[4]
float viewinv[4][4]
struct Object * camera
float xmin
Definition: DNA_vec_types.h:69
float ymin
Definition: DNA_vec_types.h:70
int ymin
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
short val
Definition: WM_types.h:680
int mval[2]
Definition: WM_types.h:684
short type
Definition: WM_types.h:678
void * customdata
Definition: WM_types.h:715
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 ReportList * reports
struct wmOperatorType * type
double PIL_check_seconds_timer(void)
Definition: time.c:64
void ED_view3d_cameracontrol_update(View3DCameraControl *vctrl, const bool use_autokey, struct bContext *C, const bool do_rotate, const bool do_translate)
Object * ED_view3d_cameracontrol_object_get(View3DCameraControl *vctrl)
struct View3DCameraControl * ED_view3d_cameracontrol_acquire(Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d)
void ED_view3d_cameracontrol_release(View3DCameraControl *vctrl, const bool restore)
#define FLY_ZUP_CORRECT_ACCEL
#define FLY_SMOOTH_FAC
static void flyEvent(FlyInfo *fly, const wmEvent *event)
eFlyPanState
@ FLY_AXISLOCK_STATE_OFF
@ FLY_AXISLOCK_STATE_ACTIVE
@ FLY_AXISLOCK_STATE_IDLE
static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(region), void *arg)
static int flyEnd(bContext *C, FlyInfo *fly)
void fly_modal_keymap(wmKeyConfig *keyconf)
@ FLY_CONFIRM
@ FLY_CANCEL
@ FLY_RUNNING
#define FLY_ZUP_CORRECT_FAC
static void fly_cancel(bContext *C, wmOperator *op)
static int flyApply(bContext *C, struct FlyInfo *fly, bool is_confirm)
#define FLY_ROTATE_FAC
struct FlyInfo FlyInfo
static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event)
@ FLY_MODAL_CANCEL
@ FLY_MODAL_ACCELERATE
@ FLY_MODAL_SPEED
@ FLY_MODAL_DIR_DOWN
@ FLY_MODAL_PRECISION_ENABLE
@ FLY_MODAL_AXIS_LOCK_Z
@ FLY_MODAL_PAN_DISABLE
@ FLY_MODAL_DIR_RIGHT
@ FLY_MODAL_DIR_UP
@ FLY_MODAL_FREELOOK_DISABLE
@ FLY_MODAL_FREELOOK_ENABLE
@ FLY_MODAL_DIR_FORWARD
@ FLY_MODAL_PRECISION_DISABLE
@ FLY_MODAL_AXIS_LOCK_X
@ FLY_MODAL_DIR_LEFT
@ FLY_MODAL_DIR_BACKWARD
@ FLY_MODAL_DECELERATE
@ FLY_MODAL_PAN_ENABLE
@ FLY_MODAL_CONFIRM
void VIEW3D_OT_fly(wmOperatorType *ot)
static int fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int fly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void flyMoveCamera(bContext *C, FlyInfo *fly, const bool do_rotate, const bool do_translate, const bool is_confirm)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ TIMER
@ EVT_MODAL_MAP
@ MOUSEMOVE
@ NDOF_MOTION
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
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition: wm_keymap.c:888
void WM_event_remove_timer(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *timer)
Definition: wm_window.c:1682
void WM_cursor_warp(wmWindow *win, int x, int y)
Definition: wm_window.c:2054
wmTimer * WM_event_add_timer(wmWindowManager *wm, wmWindow *win, int event_type, double timestep)
Definition: wm_window.c:1630