Blender V4.3
view3d_navigate_walk.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
16#include "DNA_object_types.h"
17#include "DNA_scene_types.h"
18
19#include "MEM_guardedalloc.h"
20
21#include "BLI_kdopbvh.h"
22#include "BLI_math_matrix.h"
23#include "BLI_math_rotation.h"
24#include "BLI_rect.h"
25#include "BLI_time.h" /* Smooth-view. */
26#include "BLI_utildefines.h"
27
28#include "BKE_context.hh"
29#include "BKE_lib_id.hh"
30#include "BKE_report.hh"
31
32#include "WM_api.hh"
33#include "WM_types.hh"
34
35#include "ED_screen.hh"
36#include "ED_space_api.hh"
38#include "ED_undo.hh"
39
40#include "UI_resources.hh"
41
42#include "GPU_immediate.hh"
43
44#include "view3d_intern.hh" /* own include */
45#include "view3d_navigate.hh"
46
47#include "BLI_strict_flags.h" /* Keep last. */
48
49#ifdef WITH_INPUT_NDOF
50// # define NDOF_WALK_DEBUG
51/* NOTE(@ideasman42): Is this needed for NDOF? commented so redraw doesn't thrash. */
52// # define NDOF_WALK_DRAW_TOOMUCH
53#endif
54
55#define USE_TABLET_SUPPORT
56
57/* -------------------------------------------------------------------- */
61/* NOTE: these defines are saved in key-map files,
62 * do not change values but just add new ones. */
63enum {
95};
96
108
113
118
125
137
139{
140 static const EnumPropertyItem modal_items[] = {
141 {WALK_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
142 {WALK_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
143
144 {WALK_MODAL_DIR_FORWARD, "FORWARD", 0, "Forward", ""},
145 {WALK_MODAL_DIR_BACKWARD, "BACKWARD", 0, "Backward", ""},
146 {WALK_MODAL_DIR_LEFT, "LEFT", 0, "Left", ""},
147 {WALK_MODAL_DIR_RIGHT, "RIGHT", 0, "Right", ""},
148 {WALK_MODAL_DIR_UP, "UP", 0, "Up", ""},
149 {WALK_MODAL_DIR_DOWN, "DOWN", 0, "Down", ""},
150 {WALK_MODAL_DIR_LOCAL_UP, "LOCAL_UP", 0, "Local Up", ""},
151 {WALK_MODAL_DIR_LOCAL_DOWN, "LOCAL_DOWN", 0, "Local Down", ""},
152
153 {WALK_MODAL_DIR_FORWARD_STOP, "FORWARD_STOP", 0, "Stop Move Forward", ""},
154 {WALK_MODAL_DIR_BACKWARD_STOP, "BACKWARD_STOP", 0, "Stop Move Backward", ""},
155 {WALK_MODAL_DIR_LEFT_STOP, "LEFT_STOP", 0, "Stop Move Left", ""},
156 {WALK_MODAL_DIR_RIGHT_STOP, "RIGHT_STOP", 0, "Stop Move Right", ""},
157 {WALK_MODAL_DIR_UP_STOP, "UP_STOP", 0, "Stop Move Global Up", ""},
158 {WALK_MODAL_DIR_DOWN_STOP, "DOWN_STOP", 0, "Stop Move Global Down", ""},
159 {WALK_MODAL_DIR_LOCAL_UP_STOP, "LOCAL_UP_STOP", 0, "Stop Move Local Up", ""},
160 {WALK_MODAL_DIR_LOCAL_DOWN_STOP, "LOCAL_DOWN_STOP", 0, "Stop Move Local Down", ""},
161
162 {WALK_MODAL_TELEPORT, "TELEPORT", 0, "Teleport", "Move forward a few units at once"},
163
164 {WALK_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""},
165 {WALK_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""},
166
167 {WALK_MODAL_FAST_ENABLE, "FAST_ENABLE", 0, "Fast", "Move faster (walk or fly)"},
168 {WALK_MODAL_FAST_DISABLE, "FAST_DISABLE", 0, "Fast (Off)", "Resume regular speed"},
169
170 {WALK_MODAL_SLOW_ENABLE, "SLOW_ENABLE", 0, "Slow", "Move slower (walk or fly)"},
171 {WALK_MODAL_SLOW_DISABLE, "SLOW_DISABLE", 0, "Slow (Off)", "Resume regular speed"},
172
173 {WALK_MODAL_JUMP, "JUMP", 0, "Jump", "Jump when in walk mode"},
174 {WALK_MODAL_JUMP_STOP, "JUMP_STOP", 0, "Jump (Off)", "Stop pushing jump"},
175
176 {WALK_MODAL_GRAVITY_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"},
177
178 {WALK_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "Z Axis Correction", "Z axis correction"},
179
181 "INCREASE_JUMP",
182 0,
183 "Increase Jump Height",
184 "Increase jump height"},
186 "DECREASE_JUMP",
187 0,
188 "Decrease Jump Height",
189 "Decrease jump height"},
190
191 {0, nullptr, 0, nullptr, nullptr},
192 };
193
194 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Walk Modal");
195
196 /* This function is called for each space-type, only needs to add map once. */
197 if (keymap && keymap->modal_items) {
198 return;
199 }
200
201 keymap = WM_modalkeymap_ensure(keyconf, "View3D Walk Modal", modal_items);
202
203 /* Assign map to operators. */
204 WM_modalkeymap_assign(keymap, "VIEW3D_OT_walk");
205}
206
209/* -------------------------------------------------------------------- */
223
230
231struct WalkInfo {
232 /* context stuff */
236 Depsgraph *depsgraph;
238
241
243 bool redraw;
244
254
256 int prev_mval[2];
258 int init_mval[2];
259
260 int moffset[2];
261
262#ifdef WITH_INPUT_NDOF
264 wmNDOFMotionData *ndof;
265#endif
266
267 /* Walk state. */
271 float speed;
273 float grid;
274
275 /* Compare between last state. */
278
280
282 float dvec_prev[3];
283
286
289
292
296
299
300#ifdef USE_TABLET_SUPPORT
303#endif
304
307 float gravity;
308
311
314
318
321
325
327
329};
330
333/* -------------------------------------------------------------------- */
337/* Prototypes. */
338#ifdef WITH_INPUT_NDOF
339static void walkApply_ndof(bContext *C, WalkInfo *walk, bool is_confirm);
340#endif /* WITH_INPUT_NDOF */
341static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm);
342static float walk_calc_velocity_zero_time(const float gravity, const float velocity);
343
344static void drawWalkPixel(const bContext * /*C*/, ARegion *region, void *arg)
345{
346 /* Draws an aim/cross in the center. */
347 WalkInfo *walk = static_cast<WalkInfo *>(arg);
348
349 const int outter_length = 24;
350 const int inner_length = 14;
351 int xoff, yoff;
352 rctf viewborder;
353
356 walk->scene, walk->depsgraph, region, walk->v3d, walk->rv3d, false, &viewborder);
357 xoff = int(viewborder.xmin + BLI_rctf_size_x(&viewborder) * 0.5f);
358 yoff = int(viewborder.ymin + BLI_rctf_size_y(&viewborder) * 0.5f);
359 }
360 else {
361 xoff = walk->region->winx / 2;
362 yoff = walk->region->winy / 2;
363 }
364
367
369
371
373
374 /* North. */
375 immVertex2i(pos, xoff, yoff + inner_length);
376 immVertex2i(pos, xoff, yoff + outter_length);
377
378 /* East. */
379 immVertex2i(pos, xoff + inner_length, yoff);
380 immVertex2i(pos, xoff + outter_length, yoff);
381
382 /* South. */
383 immVertex2i(pos, xoff, yoff - inner_length);
384 immVertex2i(pos, xoff, yoff - outter_length);
385
386 /* West. */
387 immVertex2i(pos, xoff - inner_length, yoff);
388 immVertex2i(pos, xoff - outter_length, yoff);
389
390 immEnd();
392}
393
396/* -------------------------------------------------------------------- */
401{
402 if (mode == WALK_MODE_FREE) {
405 }
406 else { /* WALK_MODE_GRAVITY */
409 }
410}
411
416 WalkInfo *walk,
417 const float dvec[3],
418 float *r_distance)
419{
420 const float ray_normal[3] = {0, 0, -1}; /* down */
421 float ray_start[3];
422 float location_dummy[3];
423 float normal_dummy[3];
424 float dvec_tmp[3];
425
426 *r_distance = BVH_RAYCAST_DIST_MAX;
427
428 copy_v3_v3(ray_start, rv3d->viewinv[3]);
429
430 mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
431 add_v3_v3(ray_start, dvec_tmp);
432
433 SnapObjectParams snap_params = {};
435 /* Avoid having to convert the edit-mesh to a regular mesh. */
436 snap_params.edit_mode_type = SNAP_GEOM_EDIT;
437
439 walk->depsgraph,
440 walk->v3d,
441 &snap_params,
442 ray_start,
443 ray_normal,
444 r_distance,
445 location_dummy,
446 normal_dummy);
447
448 /* Artificially scale the distance to the scene size. */
449 *r_distance /= walk->grid;
450 return ret;
451}
452
458static bool walk_ray_cast(RegionView3D *rv3d,
459 WalkInfo *walk,
460 float r_location[3],
461 float r_normal[3],
462 float *r_ray_distance)
463{
464 float ray_normal[3] = {0, 0, -1}; /* Forward axis. */
465 float ray_start[3];
466
467 *r_ray_distance = BVH_RAYCAST_DIST_MAX;
468
469 copy_v3_v3(ray_start, rv3d->viewinv[3]);
470
471 mul_mat3_m4_v3(rv3d->viewinv, ray_normal);
472
473 normalize_v3(ray_normal);
474
475 SnapObjectParams snap_params = {};
477
479 walk->depsgraph,
480 walk->v3d,
481 &snap_params,
482 ray_start,
483 ray_normal,
484 nullptr,
485 r_location,
486 r_normal);
487
488 /* Dot is positive if both rays are facing the same direction. */
489 if (dot_v3v3(ray_normal, r_normal) > 0) {
490 negate_v3(r_normal);
491 }
492
493 /* Artificially scale the distance to the scene size. */
494 *r_ray_distance /= walk->grid;
495
496 return ret;
497}
498
500static struct {
505} g_walk = {
506 /*base_speed*/ -1.0f,
507 /*userdef_speed*/ -1.0f,
508 /*jump_height*/ -1.0f,
509 /*userdef_jump_height*/ -1.0f,
511
512static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op, const int mval[2])
513{
515 wmWindow *win = CTX_wm_window(C);
516
517 walk->rv3d = CTX_wm_region_view3d(C);
518 walk->v3d = CTX_wm_view3d(C);
519 walk->region = CTX_wm_region(C);
521 walk->scene = CTX_data_scene(C);
522
523#ifdef NDOF_WALK_DEBUG
524 puts("\n-- walk begin --");
525#endif
526
527 /* Sanity check: for rare but possible case (if lib-linking the camera fails). */
528 if ((walk->rv3d->persp == RV3D_CAMOB) && (walk->v3d->camera == nullptr)) {
529 walk->rv3d->persp = RV3D_PERSP;
530 }
531
532 if (walk->rv3d->persp == RV3D_CAMOB &&
534 {
536 RPT_ERROR,
537 "Cannot navigate a camera from an external library or non-editable override");
538 return false;
539 }
540
541 if (ED_view3d_offset_lock_check(walk->v3d, walk->rv3d)) {
542 BKE_report(op->reports, RPT_ERROR, "Cannot navigate when the view offset is locked");
543 return false;
544 }
545
546 if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->constraints.first) {
547 BKE_report(op->reports, RPT_ERROR, "Cannot navigate an object with constraints");
548 return false;
549 }
550
551 walk->state = WALK_RUNNING;
552
553 if (fabsf(U.walk_navigation.walk_speed - g_walk.userdef_speed) > 0.1f) {
554 g_walk.base_speed = U.walk_navigation.walk_speed;
555 g_walk.userdef_speed = U.walk_navigation.walk_speed;
556 }
557
558 if (fabsf(U.walk_navigation.jump_height - g_walk.userdef_jump_height) > 0.1f) {
559 g_walk.jump_height = U.walk_navigation.jump_height;
560 g_walk.userdef_jump_height = U.walk_navigation.jump_height;
561 }
562
563 walk->jump_height = 0.0f;
564
565 walk->speed = 0.0f;
566 walk->is_fast = false;
567 walk->is_slow = false;
568 walk->grid = (walk->scene->unit.system == USER_UNIT_NONE) ?
569 1.0f :
570 1.0f / walk->scene->unit.scale_length;
571
572 /* User preference settings. */
573 walk->teleport.duration = U.walk_navigation.teleport_time;
574 walk->mouse_speed = U.walk_navigation.mouse_speed;
575
576 if (U.walk_navigation.flag & USER_WALK_GRAVITY) {
578 }
579 else {
581 }
582
583 walk->view_height = U.walk_navigation.view_height;
584 walk->jump_height = U.walk_navigation.jump_height;
585 walk->speed = U.walk_navigation.walk_speed;
586 walk->speed_factor = U.walk_navigation.walk_speed_factor;
588
590
592 walk->gravity = fabsf(walk->scene->physics_settings.gravity[2]);
593 }
594 else {
595 walk->gravity = 9.80668f; /* m/s2 */
596 }
597
598 walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0);
599
600#ifdef USE_TABLET_SUPPORT
601 walk->is_cursor_absolute = false;
602#endif
603
605
606#ifdef NDOF_WALK_DRAW_TOOMUCH
607 walk->redraw = true;
608#endif
609 zero_v3(walk->dvec_prev);
610
611 walk->timer = WM_event_timer_add(CTX_wm_manager(C), win, TIMER, 0.01f);
612
613#ifdef WITH_INPUT_NDOF
614 walk->ndof = nullptr;
615#endif
616
618 walk->need_rotation_keyframe = false;
619 walk->need_translation_keyframe = false;
620
622
625
626 walk->rv3d->rflag |= RV3D_NAVIGATING;
627
629
631 walk->depsgraph, walk->scene, walk->v3d, walk->rv3d);
632
633 copy_v2_v2_int(walk->init_mval, mval);
634 copy_v2_v2_int(walk->prev_mval, mval);
635
637
638 return true;
639}
640
641static int walkEnd(bContext *C, WalkInfo *walk)
642{
643 wmWindow *win;
644 RegionView3D *rv3d;
645
646 if (walk->state == WALK_RUNNING) {
648 }
649 if (walk->state == WALK_CONFIRM) {
650 /* Needed for auto_keyframe. */
651#ifdef WITH_INPUT_NDOF
652 if (walk->ndof) {
653 walkApply_ndof(C, walk, true);
654 }
655 else
656#endif /* WITH_INPUT_NDOF */
657 {
658 walkApply(C, walk, true);
659 }
660 }
661
662#ifdef NDOF_WALK_DEBUG
663 puts("\n-- walk end --");
664#endif
665
666 win = CTX_wm_window(C);
667 rv3d = walk->rv3d;
668
670
672
674
676
677 rv3d->rflag &= ~RV3D_NAVIGATING;
678
679#ifdef WITH_INPUT_NDOF
680 if (walk->ndof) {
681 MEM_freeN(walk->ndof);
682 }
683#endif
684
685 WM_cursor_grab_disable(win, nullptr);
686
687 if (walk->state == WALK_CONFIRM) {
688 MEM_freeN(walk);
689 return OPERATOR_FINISHED;
690 }
691
692 MEM_freeN(walk);
693 return OPERATOR_CANCELLED;
694}
695
696static void walkEvent(WalkInfo *walk, const wmEvent *event)
697{
698 if (event->type == TIMER && event->customdata == walk->timer) {
699 walk->redraw = true;
700 }
701 else if (ISMOUSE_MOTION(event->type)) {
702
703#ifdef USE_TABLET_SUPPORT
704 if ((walk->is_cursor_absolute == false) && event->tablet.is_motion_absolute) {
705 walk->is_cursor_absolute = true;
706 }
707#endif /* USE_TABLET_SUPPORT */
708
709 walk->moffset[0] += event->mval[0] - walk->prev_mval[0];
710 walk->moffset[1] += event->mval[1] - walk->prev_mval[1];
711
712 copy_v2_v2_int(walk->prev_mval, event->mval);
713
714 if (walk->moffset[0] || walk->moffset[1]) {
715 walk->redraw = true;
716 }
717 }
718#ifdef WITH_INPUT_NDOF
719 else if (event->type == NDOF_MOTION) {
720 /* Do these auto-magically get delivered? yes. */
721 // puts("ndof motion detected in walk mode!");
722 // static const char *tag_name = "3D mouse position";
723
724 const wmNDOFMotionData *incoming_ndof = static_cast<const wmNDOFMotionData *>(
725 event->customdata);
726 switch (incoming_ndof->progress) {
727 case P_STARTING: {
728 /* Start keeping track of 3D mouse position. */
729# ifdef NDOF_WALK_DEBUG
730 puts("start keeping track of 3D mouse position");
731# endif
732 /* Fall-through. */
733 }
734 case P_IN_PROGRESS: {
735 /* Update 3D mouse position. */
736# ifdef NDOF_WALK_DEBUG
737 putchar('.');
738 fflush(stdout);
739# endif
740 if (walk->ndof == nullptr) {
741 // walk->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name);
742 walk->ndof = static_cast<wmNDOFMotionData *>(MEM_dupallocN(incoming_ndof));
743 // walk->ndof = malloc(sizeof(wmNDOFMotionData));
744 }
745 else {
746 memcpy(walk->ndof, incoming_ndof, sizeof(wmNDOFMotionData));
747 }
748 break;
749 }
750 case P_FINISHING: {
751 /* Stop keeping track of 3D mouse position. */
752# ifdef NDOF_WALK_DEBUG
753 puts("stop keeping track of 3D mouse position");
754# endif
755 if (walk->ndof) {
756 MEM_freeN(walk->ndof);
757 // free(walk->ndof);
758 walk->ndof = nullptr;
759 }
760
761 /* Update the time else the view will jump when 2D mouse/timer resume. */
763
764 break;
765 }
766 default: {
767 /* Should always be one of the above 3. */
768 break;
769 }
770 }
771 }
772#endif /* WITH_INPUT_NDOF */
773 /* Handle modal key-map first. */
774 else if (event->type == EVT_MODAL_MAP) {
775 switch (event->val) {
776 case WALK_MODAL_CANCEL: {
777 walk->state = WALK_CANCEL;
778 break;
779 }
780 case WALK_MODAL_CONFIRM: {
781 walk->state = WALK_CONFIRM;
782 break;
783 }
785 g_walk.base_speed *= 1.0f + (walk->is_slow ? 0.01f : 0.1f);
786 break;
787 }
789 g_walk.base_speed /= 1.0f + (walk->is_slow ? 0.01f : 0.1f);
790 break;
791 }
792 /* Implement WASD keys. */
795 break;
796 }
799 break;
800 }
801 case WALK_MODAL_DIR_LEFT: {
803 break;
804 }
807 break;
808 }
809 case WALK_MODAL_DIR_UP: {
811 break;
812 }
813 case WALK_MODAL_DIR_DOWN: {
815 break;
816 }
819 break;
820 }
823 break;
824 }
826 walk->active_directions &= ~WALK_BIT_LOCAL_FORWARD;
827 break;
828 }
830 walk->active_directions &= ~WALK_BIT_LOCAL_BACKWARD;
831 break;
832 }
834 walk->active_directions &= ~WALK_BIT_LOCAL_LEFT;
835 break;
836 }
838 walk->active_directions &= ~WALK_BIT_LOCAL_RIGHT;
839 break;
840 }
842 walk->active_directions &= ~WALK_BIT_GLOBAL_UP;
843 break;
844 }
846 walk->active_directions &= ~WALK_BIT_GLOBAL_DOWN;
847 break;
848 }
850 walk->active_directions &= ~WALK_BIT_LOCAL_UP;
851 break;
852 }
854 walk->active_directions &= ~WALK_BIT_LOCAL_DOWN;
855 break;
856 }
858 walk->is_fast = true;
859 break;
860 }
862 walk->is_fast = false;
863 break;
864 }
866 walk->is_slow = true;
867 break;
868 }
870 walk->is_slow = false;
871 break;
872 }
873
874#define JUMP_SPEED_MIN 1.0f
875#define JUMP_TIME_MAX 0.2f /* s */
876#define JUMP_SPEED_MAX sqrtf(2.0f * walk->gravity * walk->jump_height)
877
880 float t;
881
882 /* Delta time. */
884
885 /* Reduce the velocity, if JUMP wasn't hold for long enough. */
886 t = min_ff(t, JUMP_TIME_MAX);
887 walk->speed_jump = JUMP_SPEED_MIN +
889
890 /* When jumping, duration is how long it takes before we start going down. */
892
893 /* No more increase of jump speed. */
895 }
896 break;
897 }
898 case WALK_MODAL_JUMP: {
899 if ((walk->navigation_mode == WALK_MODE_GRAVITY) &&
902 {
903 /* No need to check for ground, `walk->gravity`
904 * wouldn't be off if we were over a hole. */
907
909 copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);
910
911 /* Using previous vector because WASD keys are not called when SPACE is. */
913
914 /* When jumping, duration is how long it takes before we start going down. */
916 }
917 break;
918 }
919
920 case WALK_MODAL_TELEPORT: {
921 float loc[3], nor[3];
922 float distance;
923 const bool ret = walk_ray_cast(walk->rv3d, walk, loc, nor, &distance);
924
925 /* In case we are teleporting middle way from a jump. */
926 walk->speed_jump = 0.0f;
927
928 if (ret) {
929 WalkTeleport *teleport = &walk->teleport;
930
931 /* Store the current navigation mode if we are not already teleporting. */
932 if (teleport->state == WALK_TELEPORT_STATE_OFF) {
933 teleport->navigation_mode = walk->navigation_mode;
934 }
935 teleport->state = WALK_TELEPORT_STATE_ON;
937 teleport->duration = U.walk_navigation.teleport_time;
938
940
941 copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]);
942
943 /* Stop the camera from a distance (camera height). */
945 add_v3_v3(loc, nor);
946
947 sub_v3_v3v3(teleport->direction, loc, teleport->origin);
948 }
949 break;
950 }
951
952#undef JUMP_SPEED_MAX
953#undef JUMP_TIME_MAX
954#undef JUMP_SPEED_MIN
955
957 if (walk->navigation_mode == WALK_MODE_GRAVITY) {
959 }
960 else { /* WALK_MODE_FREE */
962 }
963 break;
964 }
965
967 if (walk->zlock != WALK_AXISLOCK_STATE_DONE) {
969 walk->zlock_momentum = 0.0f;
970 }
971 break;
972 }
973
974#define JUMP_HEIGHT_FACTOR 1.5f
975#define JUMP_HEIGHT_MIN 0.1f
976#define JUMP_HEIGHT_MAX 10.0f
977
979 g_walk.jump_height = min_ff(g_walk.jump_height * JUMP_HEIGHT_FACTOR, JUMP_HEIGHT_MAX);
980 break;
981 }
983 g_walk.jump_height = max_ff(g_walk.jump_height / JUMP_HEIGHT_FACTOR, JUMP_HEIGHT_MIN);
984 break;
985 }
986
987#undef JUMP_HEIGHT_FACTOR
988#undef JUMP_HEIGHT_MIN
989#undef JUMP_HEIGHT_MAX
990 }
991 }
992}
993
995 WalkInfo *walk,
996 const bool do_rotate,
997 const bool do_translate,
998 const bool is_confirm)
999{
1000 /* We only consider auto-keying on playback or if user confirmed walk on the same frame
1001 * otherwise we get a keyframe even if the user cancels. */
1002 const bool use_autokey = is_confirm || walk->anim_playing;
1004 walk->v3d_camera_control, use_autokey, C, do_rotate, do_translate);
1005 if (use_autokey) {
1006 walk->need_rotation_keyframe = false;
1007 walk->need_translation_keyframe = false;
1008 }
1009}
1010
1011static float walk_calc_free_fall_distance(const float gravity, const float time)
1012{
1013 return gravity * (time * time) * 0.5f;
1014}
1015
1016static float walk_calc_velocity_zero_time(const float gravity, const float velocity)
1017{
1018 return velocity / gravity;
1019}
1020
1021static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
1022{
1023#define WALK_ROTATE_TABLET_FAC 8.8f /* Higher is faster, relative to region size. */
1024#define WALK_ROTATE_CONSTANT_FAC DEG2RADF(0.15f) /* Higher is faster, radians per-pixel. */
1025#define WALK_TOP_LIMIT DEG2RADF(85.0f)
1026#define WALK_BOTTOM_LIMIT DEG2RADF(-80.0f)
1027#define WALK_MOVE_SPEED (0 ? 0.0f : g_walk.base_speed)
1028#define WALK_JUMP_HEIGHT (0 ? 0.0f : g_walk.jump_height)
1029#define WALK_BOOST_FACTOR ((void)0, walk->speed_factor)
1030#define WALK_ZUP_CORRECT_FAC 0.1f /* Amount to correct per step. */
1031#define WALK_ZUP_CORRECT_ACCEL 0.05f /* Increase upright momentum each step. */
1032
1033 RegionView3D *rv3d = walk->rv3d;
1034 ARegion *region = walk->region;
1035
1036 /* 3x3 copy of the view matrix so we can move along the view axis. */
1037 float mat[3][3];
1038 /* This is the direction that's added to the view offset per redraw. */
1039 float dvec[3] = {0.0f, 0.0f, 0.0f};
1040
1041 int moffset[2]; /* Mouse offset from the views center. */
1042 float tmp_quat[4]; /* Used for rotating the view. */
1043
1044#ifdef NDOF_WALK_DEBUG
1045 {
1046 static uint iteration = 1;
1047 printf("walk timer %d\n", iteration++);
1048 }
1049#endif
1050
1051 {
1052 /* Mouse offset from the center. */
1053 copy_v2_v2_int(moffset, walk->moffset);
1054
1055 /* Apply `moffset` so we can re-accumulate. */
1056 walk->moffset[0] = 0;
1057 walk->moffset[1] = 0;
1058
1059 /* Revert mouse. */
1060 if (walk->is_reversed) {
1061 moffset[1] = -moffset[1];
1062 }
1063
1064 /* Update jump height. */
1067 }
1068
1069 /* Should we redraw? */
1070 if ((walk->active_directions) || moffset[0] || moffset[1] ||
1073 walk->teleport.state == WALK_TELEPORT_STATE_ON || is_confirm)
1074 {
1075 float dvec_tmp[3];
1076
1077 /* Time how fast it takes for us to redraw,
1078 * this is so simple scenes don't walk too fast. */
1079 double time_current;
1080 float time_redraw;
1081 float time_redraw_clamped;
1082#ifdef NDOF_WALK_DRAW_TOOMUCH
1083 walk->redraw = true;
1084#endif
1085 time_current = BLI_time_now_seconds();
1086 time_redraw = float(time_current - walk->time_lastdraw);
1087
1088 /* Clamp redraw time to avoid jitter in roll correction. */
1089 time_redraw_clamped = min_ff(0.05f, time_redraw);
1090
1091 walk->time_lastdraw = time_current;
1092
1093 /* Base speed in m/s. */
1094 walk->speed = WALK_MOVE_SPEED;
1095
1096 if (walk->is_fast) {
1097 walk->speed *= WALK_BOOST_FACTOR;
1098 }
1099 else if (walk->is_slow) {
1100 walk->speed *= 1.0f / WALK_BOOST_FACTOR;
1101 }
1102
1103 copy_m3_m4(mat, rv3d->viewinv);
1104
1105 {
1106 /* Rotate about the X axis- look up/down. */
1107 if (moffset[1]) {
1108 float upvec[3];
1109 float angle;
1110 float y;
1111
1112 /* Relative offset. */
1113 y = float(moffset[1]);
1114
1115 /* Speed factor. */
1116#ifdef USE_TABLET_SUPPORT
1117 if (walk->is_cursor_absolute) {
1118 y /= region->winy;
1120 }
1121 else
1122#endif
1123 {
1125 }
1126
1127 /* User adjustment factor. */
1128 y *= walk->mouse_speed;
1129
1130 /* Clamp the angle limits: it ranges from 90.0f to -90.0f. */
1131 angle = -asinf(rv3d->viewmat[2][2]);
1132
1133 if (angle > WALK_TOP_LIMIT && y > 0.0f) {
1134 y = 0.0f;
1135 }
1136 else if (angle < WALK_BOTTOM_LIMIT && y < 0.0f) {
1137 y = 0.0f;
1138 }
1139
1140 copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
1141 mul_m3_v3(mat, upvec);
1142 /* Rotate about the relative up vector. */
1143 axis_angle_to_quat(tmp_quat, upvec, -y);
1144 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
1145 }
1146
1147 /* Rotate about the Y axis- look left/right. */
1148 if (moffset[0]) {
1149 float upvec[3];
1150 float x;
1151
1152 /* If we're upside down invert the `moffset`. */
1153 copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
1154 mul_m3_v3(mat, upvec);
1155
1156 if (upvec[2] < 0.0f) {
1157 moffset[0] = -moffset[0];
1158 }
1159
1160 /* Relative offset. */
1161 x = float(moffset[0]);
1162
1163 /* Speed factor. */
1164#ifdef USE_TABLET_SUPPORT
1165 if (walk->is_cursor_absolute) {
1166 x /= region->winx;
1168 }
1169 else
1170#endif
1171 {
1173 }
1174
1175 /* User adjustment factor. */
1176 x *= walk->mouse_speed;
1177
1178 /* Rotate about the relative up vector */
1179 axis_angle_to_quat_single(tmp_quat, 'Z', x);
1180 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
1181 }
1182
1183 if (walk->zlock == WALK_AXISLOCK_STATE_ACTIVE) {
1184 float upvec[3];
1185 copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
1186 mul_m3_v3(mat, upvec);
1187
1188 /* Make sure we have some Z rolling. */
1189 if (fabsf(upvec[2]) > 0.00001f) {
1190 float roll = upvec[2] * 5.0f;
1191 /* Rotate the view about this axis. */
1192 copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
1193 mul_m3_v3(mat, upvec);
1194 /* Rotate about the relative up vector. */
1195 axis_angle_to_quat(tmp_quat,
1196 upvec,
1197 roll * time_redraw_clamped * walk->zlock_momentum *
1199 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
1200
1202 }
1203 else {
1204 /* Lock fixed, don't need to check it ever again. */
1206 }
1207 }
1208 }
1209
1210 /* WASD - 'move' translation code. */
1211 if ((walk->active_directions) && (walk->gravity_state == WALK_GRAVITY_STATE_OFF)) {
1212
1213 short direction;
1214 zero_v3(dvec);
1215
1218 {
1219
1220 direction = 0;
1221
1223 direction += 1;
1224 }
1225
1227 direction -= 1;
1228 }
1229
1230 copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
1231 mul_m3_v3(mat, dvec_tmp);
1232
1233 if (walk->navigation_mode == WALK_MODE_GRAVITY) {
1234 dvec_tmp[2] = 0.0f;
1235 }
1236
1237 add_v3_v3(dvec, dvec_tmp);
1238 }
1239
1240 if ((walk->active_directions & WALK_BIT_LOCAL_LEFT) ||
1242 {
1243
1244 direction = 0;
1245
1247 direction += 1;
1248 }
1249
1251 direction -= 1;
1252 }
1253
1254 dvec_tmp[0] = direction * rv3d->viewinv[0][0];
1255 dvec_tmp[1] = direction * rv3d->viewinv[0][1];
1256 dvec_tmp[2] = 0.0f;
1257
1258 add_v3_v3(dvec, dvec_tmp);
1259 }
1260
1261 /* Up and down movement is only available in free mode, not gravity mode. */
1262 if (walk->navigation_mode == WALK_MODE_FREE) {
1263
1265
1266 direction = 0;
1267
1269 direction -= 1;
1270 }
1271
1273 direction += 1;
1274 }
1275
1276 copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
1277 add_v3_v3(dvec, dvec_tmp);
1278 }
1279
1281
1282 direction = 0;
1283
1285 direction -= 1;
1286 }
1287
1289 direction += 1;
1290 }
1291
1292 madd_v3_v3fl(dvec, rv3d->viewinv[1], direction);
1293 }
1294 }
1295
1296 normalize_v3(dvec);
1297
1298 /* Apply movement. */
1299 mul_v3_fl(dvec, walk->speed * time_redraw);
1300 }
1301
1302 /* Stick to the floor. */
1303 if (walk->navigation_mode == WALK_MODE_GRAVITY &&
1305 {
1306 float ray_distance;
1307 float difference = -100.0f;
1308
1309 if (walk_floor_distance_get(rv3d, walk, dvec, &ray_distance)) {
1310 difference = walk->view_height - ray_distance;
1311 }
1312
1313 /* The distance we would fall naturally smoothly enough that we
1314 * can manually drop the object without activating gravity. */
1315 const float fall_distance = time_redraw * walk->speed * WALK_BOOST_FACTOR;
1316
1317 if (fabsf(difference) < fall_distance) {
1318 /* slope/stairs */
1319 dvec[2] -= difference;
1320
1321 /* In case we switched from FREE to GRAVITY too close to the ground. */
1324 }
1325 }
1326 else {
1327 /* Hijack the teleport variables. */
1330 walk->teleport.duration = 0.0f;
1331
1332 copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);
1333 copy_v2_v2(walk->teleport.direction, dvec);
1334 }
1335 }
1336
1337 /* Falling or jumping). */
1339 float ray_distance, difference = -100.0f;
1340 /* Delta time. */
1341 const float t = float(BLI_time_now_seconds() - walk->teleport.initial_time);
1342
1343 /* Keep moving if we were moving. */
1344 copy_v2_v2(dvec, walk->teleport.direction);
1345
1346 const float z_cur = walk->rv3d->viewinv[3][2] / walk->grid;
1347 const float z_new = ((walk->teleport.origin[2] / walk->grid) -
1349 /* Jump. */
1350 (t * walk->speed_jump);
1351
1352 /* Duration is the jump duration. */
1353 if (t > walk->teleport.duration) {
1354
1355 /* Check to see if we are landing. */
1356 if (walk_floor_distance_get(rv3d, walk, dvec, &ray_distance)) {
1357 difference = walk->view_height - ray_distance;
1358 }
1359
1360 if (difference > 0.0f) {
1361 /* Quit falling, lands at "view_height" from the floor. */
1362 dvec[2] -= difference;
1364 walk->speed_jump = 0.0f;
1365 }
1366 else {
1367 /* Keep falling. */
1368 dvec[2] = z_cur - z_new;
1369 }
1370 }
1371 else {
1372 /* Keep going up (jump). */
1373 dvec[2] = z_cur - z_new;
1374 }
1375 }
1376
1377 /* Teleport. */
1378 else if (walk->teleport.state == WALK_TELEPORT_STATE_ON) {
1379 float t; /* factor */
1380 float new_loc[3];
1381 float cur_loc[3];
1382
1383 /* Linear interpolation. */
1385 t /= walk->teleport.duration;
1386
1387 /* Clamp so we don't go past our limit. */
1388 if (t >= 1.0f) {
1389 t = 1.0f;
1392 }
1393
1394 mul_v3_v3fl(new_loc, walk->teleport.direction, t);
1395 add_v3_v3(new_loc, walk->teleport.origin);
1396
1397 copy_v3_v3(cur_loc, walk->rv3d->viewinv[3]);
1398 sub_v3_v3v3(dvec, cur_loc, new_loc);
1399 }
1400
1401 /* Scale the movement to the scene size. */
1402 mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
1403 add_v3_v3(rv3d->ofs, dvec_tmp);
1404
1405 if (rv3d->persp == RV3D_CAMOB) {
1406 walk->need_rotation_keyframe |= (moffset[0] || moffset[1] ||
1408 walk->need_translation_keyframe |= (len_squared_v3(dvec_tmp) > FLT_EPSILON);
1410 C, walk, walk->need_rotation_keyframe, walk->need_translation_keyframe, is_confirm);
1411 }
1412 }
1413 else {
1414 /* We're not redrawing but we need to update the time else the view will jump. */
1416 }
1417 /* End drawing. */
1418 copy_v3_v3(walk->dvec_prev, dvec);
1419 }
1420
1421 return OPERATOR_FINISHED;
1422#undef WALK_ROTATE_TABLET_FAC
1423#undef WALK_TOP_LIMIT
1424#undef WALK_BOTTOM_LIMIT
1425#undef WALK_MOVE_SPEED
1426#undef WALK_JUMP_HEIGHT
1427#undef WALK_BOOST_FACTOR
1428}
1429
1430#ifdef WITH_INPUT_NDOF
1431static void walkApply_ndof(bContext *C, WalkInfo *walk, bool is_confirm)
1432{
1434 bool has_translate, has_rotate;
1435
1436 view3d_ndof_fly(walk->ndof,
1437 walk->v3d,
1438 walk->rv3d,
1439 walk->is_slow,
1440 lock_ob ? lock_ob->protectflag : 0,
1441 &has_translate,
1442 &has_rotate);
1443
1444 if (has_translate || has_rotate) {
1445 walk->redraw = true;
1446
1447 if (walk->rv3d->persp == RV3D_CAMOB) {
1448 walk->need_rotation_keyframe |= has_rotate;
1449 walk->need_translation_keyframe |= has_translate;
1451 C, walk, walk->need_rotation_keyframe, walk->need_translation_keyframe, is_confirm);
1452 }
1453 }
1454}
1455#endif /* WITH_INPUT_NDOF */
1456
1459/* -------------------------------------------------------------------- */
1463static int walk_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1464{
1467 return OPERATOR_CANCELLED;
1468 }
1469
1470 WalkInfo *walk = MEM_cnew<WalkInfo>("NavigationWalkOperation");
1471
1472 op->customdata = walk;
1473
1474 if (initWalkInfo(C, walk, op, event->mval) == false) {
1475 MEM_freeN(op->customdata);
1476 return OPERATOR_CANCELLED;
1477 }
1478
1479 walkEvent(walk, event);
1480
1482
1484}
1485
1486static void walk_cancel(bContext *C, wmOperator *op)
1487{
1488 WalkInfo *walk = static_cast<WalkInfo *>(op->customdata);
1489
1490 walk->state = WALK_CANCEL;
1491 walkEnd(C, walk);
1492 op->customdata = nullptr;
1493}
1494
1495static int walk_modal(bContext *C, wmOperator *op, const wmEvent *event)
1496{
1497 bool do_draw = false;
1498 WalkInfo *walk = static_cast<WalkInfo *>(op->customdata);
1499 View3D *v3d = walk->v3d;
1500 RegionView3D *rv3d = walk->rv3d;
1502
1503 walk->redraw = false;
1504
1505 walkEvent(walk, event);
1506
1507#ifdef WITH_INPUT_NDOF
1508 if (walk->ndof) { /* 3D mouse overrules [2D mouse + timer]. */
1509 if (event->type == NDOF_MOTION) {
1510 walkApply_ndof(C, walk, false);
1511 }
1512 }
1513 else
1514#endif /* WITH_INPUT_NDOF */
1515 if (event->type == TIMER && event->customdata == walk->timer) {
1516 walkApply(C, walk, false);
1517 }
1518
1519 do_draw |= walk->redraw;
1520
1521 const int exit_code = walkEnd(C, walk);
1522
1523 if (exit_code != OPERATOR_RUNNING_MODAL) {
1524 do_draw = true;
1525 }
1526 if (exit_code == OPERATOR_FINISHED) {
1527 const bool is_undo_pushed = ED_view3d_camera_lock_undo_push(op->type->name, v3d, rv3d, C);
1528 /* If generic 'locked camera' code did not push an undo, but there is a valid 'walking
1529 * object', an undo push is still needed, since that object transform was modified. */
1530 if (!is_undo_pushed && walk_object && ED_undo_is_memfile_compatible(C)) {
1531 ED_undo_push(C, op->type->name);
1532 }
1533 }
1534
1535 if (do_draw) {
1536 if (rv3d->persp == RV3D_CAMOB) {
1537 WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, walk_object);
1538 }
1539
1540 /* Too frequent, commented with `NDOF_WALK_DRAW_TOOMUCH` for now. */
1541 // puts("redraw!");
1543 }
1544 return exit_code;
1545}
1546
1548{
1549 /* Identifiers. */
1550 ot->name = "Walk Navigation";
1551 ot->description = "Interactively walk around the scene";
1552 ot->idname = "VIEW3D_OT_walk";
1553
1554 /* API callbacks. */
1557 ot->modal = walk_modal;
1559
1560 /* flags */
1561 /* NOTE: #OPTYPE_BLOCKING isn't used because this needs to grab & hide the cursor.
1562 * where as blocking confines the cursor to the window bounds, even when hidden. */
1563 ot->flag = 0;
1564}
1565
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
RegionView3D * CTX_wm_region_view3d(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
bool BKE_id_is_editable(const Main *bmain, const ID *id)
Definition lib_id.cc:2456
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
#define BVH_RAYCAST_DIST_MAX
Definition BLI_kdopbvh.h:92
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
void mul_m3_v3(const float M[3][3], float r[3])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
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 mul_qt_qtqt(float q[4], const float a[4], const float b[4])
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
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)
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void negate_v3(float r[3])
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3_length(float n[3], float unit_length)
MINLINE float normalize_v3(float n[3])
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition BLI_rect.h:197
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition BLI_rect.h:201
unsigned int uint
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.c:65
#define ENUM_OPERATORS(_type, _max)
#define ELEM(...)
Object is a sort of wrapper for general info.
@ USER_UNIT_NONE
@ PHYS_GLOBAL_GRAVITY
@ SCE_SNAP_TARGET_ALL
@ USER_WALK_MOUSE_REVERSE
@ USER_WALK_GRAVITY
#define RV3D_LOCK_FLAGS(rv3d)
@ RV3D_NAVIGATING
@ RV3D_CAMOB
@ RV3D_PERSP
@ RV3D_LOCK_ANY_TRANSFORM
@ OPERATOR_RUNNING_MODAL
bool ED_operator_region_view3d_active(bContext *C)
bScreen * ED_screen_animation_playing(const wmWindowManager *wm)
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:634
void * ED_region_draw_cb_activate(ARegionType *art, void(*draw)(const bContext *, ARegion *, void *), void *customdata, int type)
bool ED_region_draw_cb_exit(ARegionType *art, void *handle)
#define REGION_DRAW_POST_PIXEL
SnapObjectContext * ED_transform_snap_object_context_create(Scene *scene, int flag)
bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx, Depsgraph *depsgraph, const View3D *v3d, const SnapObjectParams *params, const float ray_start[3], const float ray_normal[3], float *ray_depth, float r_co[3], float r_no[3])
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
void ED_undo_push(bContext *C, const char *str)
Definition ed_undo.cc:104
bool ED_undo_is_memfile_compatible(const bContext *C)
Definition ed_undo.cc:409
bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d)
bool ED_view3d_camera_lock_undo_push(const char *str, const View3D *v3d, const RegionView3D *rv3d, bContext *C)
void ED_view3d_calc_camera_border(const Scene *scene, const Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const RegionView3D *rv3d, bool no_shift, rctf *r_viewborder)
void immUniformThemeColorAlpha(int color_id, float a)
void immEnd()
void immUnbindProgram()
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immVertex2i(uint attr_id, int x, int y)
GPUVertFormat * immVertexFormat()
void immBegin(GPUPrimType, uint vertex_len)
@ GPU_PRIM_LINES
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_FETCH_INT_TO_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_I32
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
Read Guarded memory(de)allocation.
@ TH_VIEW_OVERLAY
#define ND_TRANSFORM
Definition WM_types.hh:423
#define NC_OBJECT
Definition WM_types.hh:346
@ P_IN_PROGRESS
Definition WM_types.hh:815
@ P_STARTING
Definition WM_types.hh:814
@ P_FINISHING
Definition WM_types.hh:816
@ WM_CURSOR_WRAP_NONE
Definition WM_types.hh:206
unsigned int U
Definition btGjkEpa3.h:78
#define printf
double time
#define asinf(x)
#define fabsf(x)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
format
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
float distance(float a, float b)
Frequency::GEOMETRY nor[]
return ret
struct ARegionType * type
void * first
ListBase constraints
short protectflag
float viewmat[4][4]
float viewinv[4][4]
struct PhysicsSettings physics_settings
struct UnitSettings unit
struct Object * camera
Depsgraph * depsgraph
eWalkMethod navigation_mode
WalkTeleport teleport
eWalkDirectionFlag active_directions
eWalkGravityState gravity_state
View3DCameraControl * v3d_camera_control
eWalkLockState zlock
SnapObjectContext * snap_context
RegionView3D * rv3d
eWalkMethod navigation_mode
eWalkTeleportState state
float xmin
float ymin
short val
Definition WM_types.hh:724
int mval[2]
Definition WM_types.hh:728
wmTabletData tablet
Definition WM_types.hh:751
short type
Definition WM_types.hh:722
void * customdata
Definition WM_types.hh:772
const void * modal_items
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(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1036
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
const char * description
Definition WM_types.hh:996
void(* cancel)(bContext *C, wmOperator *op)
Definition WM_types.hh:1028
struct ReportList * reports
struct wmOperatorType * type
char is_motion_absolute
Definition WM_types.hh:677
View3DCameraControl * ED_view3d_cameracontrol_acquire(Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d)
Object * ED_view3d_cameracontrol_object_get(View3DCameraControl *vctrl)
void ED_view3d_cameracontrol_update(View3DCameraControl *vctrl, const bool use_autokey, bContext *C, const bool do_rotate, const bool do_translate)
void ED_view3d_cameracontrol_release(View3DCameraControl *vctrl, const bool restore)
static void walkMoveCamera(bContext *C, WalkInfo *walk, const bool do_rotate, const bool do_translate, const bool is_confirm)
static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op, const int mval[2])
float userdef_jump_height
#define WALK_JUMP_HEIGHT
static bool walk_floor_distance_get(RegionView3D *rv3d, WalkInfo *walk, const float dvec[3], float *r_distance)
@ WALK_MODAL_DECELERATE
@ WALK_MODAL_DIR_LOCAL_DOWN
@ WALK_MODAL_JUMP
@ WALK_MODAL_DIR_LEFT_STOP
@ WALK_MODAL_SLOW_DISABLE
@ WALK_MODAL_DIR_RIGHT
@ WALK_MODAL_SLOW_ENABLE
@ WALK_MODAL_DIR_LOCAL_UP
@ WALK_MODAL_DIR_DOWN_STOP
@ WALK_MODAL_DECREASE_JUMP
@ WALK_MODAL_INCREASE_JUMP
@ WALK_MODAL_CONFIRM
@ WALK_MODAL_DIR_LEFT
@ WALK_MODAL_FAST_ENABLE
@ WALK_MODAL_DIR_BACKWARD
@ WALK_MODAL_TELEPORT
@ WALK_MODAL_DIR_FORWARD_STOP
@ WALK_MODAL_DIR_UP
@ WALK_MODAL_JUMP_STOP
@ WALK_MODAL_DIR_DOWN
@ WALK_MODAL_GRAVITY_TOGGLE
@ WALK_MODAL_DIR_FORWARD
@ WALK_MODAL_DIR_BACKWARD_STOP
@ WALK_MODAL_DIR_RIGHT_STOP
@ WALK_MODAL_CANCEL
@ WALK_MODAL_ACCELERATE
@ WALK_MODAL_DIR_UP_STOP
@ WALK_MODAL_DIR_LOCAL_DOWN_STOP
@ WALK_MODAL_DIR_LOCAL_UP_STOP
@ WALK_MODAL_AXIS_LOCK_Z
@ WALK_MODAL_FAST_DISABLE
#define WALK_ROTATE_TABLET_FAC
#define JUMP_SPEED_MAX
#define WALK_MOVE_SPEED
static void walkEvent(WalkInfo *walk, const wmEvent *event)
float jump_height
#define WALK_ROTATE_CONSTANT_FAC
@ WALK_TELEPORT_STATE_ON
@ WALK_TELEPORT_STATE_OFF
static int walk_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int walkEnd(bContext *C, WalkInfo *walk)
static int walk_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void VIEW3D_OT_walk(wmOperatorType *ot)
float userdef_speed
@ WALK_GRAVITY_STATE_START
@ WALK_GRAVITY_STATE_JUMP
@ WALK_GRAVITY_STATE_OFF
@ WALK_GRAVITY_STATE_ON
#define JUMP_TIME_MAX
static struct @552 g_walk
@ WALK_MODE_GRAVITY
#define JUMP_HEIGHT_MAX
static void walk_cancel(bContext *C, wmOperator *op)
#define WALK_TOP_LIMIT
static float walk_calc_free_fall_distance(const float gravity, const float time)
static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
#define WALK_ZUP_CORRECT_ACCEL
static float walk_calc_velocity_zero_time(const float gravity, const float velocity)
static void drawWalkPixel(const bContext *, ARegion *region, void *arg)
#define WALK_ZUP_CORRECT_FAC
@ WALK_AXISLOCK_STATE_DONE
@ WALK_AXISLOCK_STATE_OFF
@ WALK_AXISLOCK_STATE_ACTIVE
@ WALK_BIT_LOCAL_LEFT
@ WALK_BIT_GLOBAL_DOWN
@ WALK_BIT_LOCAL_RIGHT
@ WALK_BIT_GLOBAL_UP
@ WALK_BIT_LOCAL_FORWARD
@ WALK_BIT_LOCAL_DOWN
@ WALK_BIT_LOCAL_UP
@ WALK_BIT_LOCAL_BACKWARD
#define WALK_BOOST_FACTOR
#define JUMP_HEIGHT_FACTOR
void walk_modal_keymap(wmKeyConfig *keyconf)
static bool walk_ray_cast(RegionView3D *rv3d, WalkInfo *walk, float r_location[3], float r_normal[3], float *r_ray_distance)
#define JUMP_HEIGHT_MIN
#define JUMP_SPEED_MIN
float base_speed
static void walk_navigation_mode_set(WalkInfo *walk, eWalkMethod mode)
#define WALK_BOTTOM_LIMIT
void WM_cursor_grab_enable(wmWindow *win, const eWM_CursorWrapAxis wrap, const rcti *wrap_region, const bool hide)
void WM_cursor_grab_disable(wmWindow *win, const int mouse_ungrab_xy[2])
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
#define ISMOUSE_MOTION(event_type)
@ TIMER
@ EVT_MODAL_MAP
@ NDOF_MOTION
wmOperatorType * ot
Definition wm_files.cc:4125
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition wm_keymap.cc:933
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition wm_keymap.cc:960
void WM_event_timer_remove(wmWindowManager *wm, wmWindow *, wmTimer *timer)
wmTimer * WM_event_timer_add(wmWindowManager *wm, wmWindow *win, const int event_type, const double time_step)