Blender V4.5
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
15
16#include "DNA_object_types.h"
17#include "DNA_scene_types.h"
18
19#include "MEM_guardedalloc.h"
20
21#include "BLI_kdopbvh.hh"
22#include "BLI_math_matrix.h"
23#include "BLI_math_rotation.h"
24#include "BLI_math_vector.h"
25#include "BLI_rect.h"
26#include "BLI_time.h" /* Smooth-view. */
27#include "BLI_utildefines.h"
28
29#include "BKE_context.hh"
30#include "BKE_lib_id.hh"
31#include "BKE_report.hh"
32#include "BKE_screen.hh"
33
34#include "BLT_translation.hh"
35
36#include "WM_api.hh"
37#include "WM_types.hh"
38
39#include "ED_screen.hh"
40#include "ED_space_api.hh"
42#include "ED_undo.hh"
43
44#include "UI_resources.hh"
45
46#include "GPU_immediate.hh"
47
48#include "view3d_intern.hh" /* own include */
49#include "view3d_navigate.hh"
50
51#include <fmt/format.h>
52
53#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
54
55#ifdef WITH_INPUT_NDOF
56// # define NDOF_WALK_DEBUG
57/* NOTE(@ideasman42): Is this needed for NDOF? commented so redraw doesn't thrash. */
58// # define NDOF_WALK_DRAW_TOOMUCH
59#endif
60
61#define USE_TABLET_SUPPORT
62
63/* -------------------------------------------------------------------- */
66
67/* NOTE: these defines are saved in key-map files,
68 * do not change values but just add new ones. */
69enum {
101};
102
114
119
124
131
143
145{
146 static const EnumPropertyItem modal_items[] = {
147 {WALK_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
148 {WALK_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
149
150 {WALK_MODAL_DIR_FORWARD, "FORWARD", 0, "Forward", ""},
151 {WALK_MODAL_DIR_BACKWARD, "BACKWARD", 0, "Backward", ""},
152 {WALK_MODAL_DIR_LEFT, "LEFT", 0, "Left", ""},
153 {WALK_MODAL_DIR_RIGHT, "RIGHT", 0, "Right", ""},
154 {WALK_MODAL_DIR_UP, "UP", 0, "Up", ""},
155 {WALK_MODAL_DIR_DOWN, "DOWN", 0, "Down", ""},
156 {WALK_MODAL_DIR_LOCAL_UP, "LOCAL_UP", 0, "Local Up", ""},
157 {WALK_MODAL_DIR_LOCAL_DOWN, "LOCAL_DOWN", 0, "Local Down", ""},
158
159 {WALK_MODAL_DIR_FORWARD_STOP, "FORWARD_STOP", 0, "Stop Move Forward", ""},
160 {WALK_MODAL_DIR_BACKWARD_STOP, "BACKWARD_STOP", 0, "Stop Move Backward", ""},
161 {WALK_MODAL_DIR_LEFT_STOP, "LEFT_STOP", 0, "Stop Move Left", ""},
162 {WALK_MODAL_DIR_RIGHT_STOP, "RIGHT_STOP", 0, "Stop Move Right", ""},
163 {WALK_MODAL_DIR_UP_STOP, "UP_STOP", 0, "Stop Move Global Up", ""},
164 {WALK_MODAL_DIR_DOWN_STOP, "DOWN_STOP", 0, "Stop Move Global Down", ""},
165 {WALK_MODAL_DIR_LOCAL_UP_STOP, "LOCAL_UP_STOP", 0, "Stop Move Local Up", ""},
166 {WALK_MODAL_DIR_LOCAL_DOWN_STOP, "LOCAL_DOWN_STOP", 0, "Stop Move Local Down", ""},
167
168 {WALK_MODAL_TELEPORT, "TELEPORT", 0, "Teleport", "Move forward a few units at once"},
169
170 {WALK_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""},
171 {WALK_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""},
172
173 {WALK_MODAL_FAST_ENABLE, "FAST_ENABLE", 0, "Fast", "Move faster (walk or fly)"},
174 {WALK_MODAL_FAST_DISABLE, "FAST_DISABLE", 0, "Fast (Off)", "Resume regular speed"},
175
176 {WALK_MODAL_SLOW_ENABLE, "SLOW_ENABLE", 0, "Slow", "Move slower (walk or fly)"},
177 {WALK_MODAL_SLOW_DISABLE, "SLOW_DISABLE", 0, "Slow (Off)", "Resume regular speed"},
178
179 {WALK_MODAL_JUMP, "JUMP", 0, "Jump", "Jump when in walk mode"},
180 {WALK_MODAL_JUMP_STOP, "JUMP_STOP", 0, "Jump (Off)", "Stop pushing jump"},
181
182 {WALK_MODAL_GRAVITY_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"},
183
184 {WALK_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "Z Axis Correction", "Z axis correction"},
185
187 "INCREASE_JUMP",
188 0,
189 "Increase Jump Height",
190 "Increase jump height"},
192 "DECREASE_JUMP",
193 0,
194 "Decrease Jump Height",
195 "Decrease jump height"},
196
197 {0, nullptr, 0, nullptr, nullptr},
198 };
199
200 wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Walk Modal");
201
202 /* This function is called for each space-type, only needs to add map once. */
203 if (keymap && keymap->modal_items) {
204 return;
205 }
206
207 keymap = WM_modalkeymap_ensure(keyconf, "View3D Walk Modal", modal_items);
208
209 /* Assign map to operators. */
210 WM_modalkeymap_assign(keymap, "VIEW3D_OT_walk");
211}
212
214
215/* -------------------------------------------------------------------- */
218
229
236
237struct WalkInfo {
238 /* context stuff */
242 Depsgraph *depsgraph;
244
247
249 bool redraw;
250
260
262 int prev_mval[2];
264 int init_mval[2];
265
266 int moffset[2];
267
268#ifdef WITH_INPUT_NDOF
270 wmNDOFMotionData *ndof;
271#endif
272
273 /* Walk state. */
277 float speed;
279 float grid;
280
281 /* Compare between last state. */
284
286
288 float dvec_prev[3];
289
292
295
298
302
305
306#ifdef USE_TABLET_SUPPORT
309#endif
310
313 float gravity;
314
317
320
324
327
331
333
335};
336
338
339/* -------------------------------------------------------------------- */
342
343/* Prototypes. */
344#ifdef WITH_INPUT_NDOF
345static void walkApply_ndof(bContext *C, WalkInfo *walk, bool is_confirm);
346#endif /* WITH_INPUT_NDOF */
347static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm);
348static float walk_calc_velocity_zero_time(const float gravity, const float velocity);
349
350static void drawWalkPixel(const bContext * /*C*/, ARegion *region, void *arg)
351{
352 /* Draws an aim/cross in the center. */
353 WalkInfo *walk = static_cast<WalkInfo *>(arg);
354
355 const float outer_length = 24.0f;
356 const float inner_length = 14.0f;
357 float xoff, yoff;
358 rctf viewborder;
359
362 walk->scene, walk->depsgraph, region, walk->v3d, walk->rv3d, false, &viewborder);
363 xoff = viewborder.xmin + BLI_rctf_size_x(&viewborder) * 0.5f;
364 yoff = viewborder.ymin + BLI_rctf_size_y(&viewborder) * 0.5f;
365 }
366 else {
367 xoff = float(walk->region->winx) / 2.0f;
368 yoff = float(walk->region->winy) / 2.0f;
369 }
370
373
375
377
379
380 /* North. */
381 immVertex2f(pos, xoff, yoff + inner_length);
382 immVertex2f(pos, xoff, yoff + outer_length);
383
384 /* East. */
385 immVertex2f(pos, xoff + inner_length, yoff);
386 immVertex2f(pos, xoff + outer_length, yoff);
387
388 /* South. */
389 immVertex2f(pos, xoff, yoff - inner_length);
390 immVertex2f(pos, xoff, yoff - outer_length);
391
392 /* West. */
393 immVertex2f(pos, xoff - inner_length, yoff);
394 immVertex2f(pos, xoff - outer_length, yoff);
395
396 immEnd();
398}
399
401
402/* -------------------------------------------------------------------- */
405
407{
408 if (mode == WALK_MODE_FREE) {
411 }
412 else { /* WALK_MODE_GRAVITY */
415 }
416}
417
422 WalkInfo *walk,
423 const float dvec[3],
424 float *r_distance)
425{
426 const float ray_normal[3] = {0, 0, -1}; /* down */
427 float ray_start[3];
428 float location_dummy[3];
429 float normal_dummy[3];
430 float dvec_tmp[3];
431
432 *r_distance = BVH_RAYCAST_DIST_MAX;
433
434 copy_v3_v3(ray_start, rv3d->viewinv[3]);
435
436 mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
437 add_v3_v3(ray_start, dvec_tmp);
438
441 /* Avoid having to convert the edit-mesh to a regular mesh. */
443
445 walk->depsgraph,
446 walk->v3d,
447 &snap_params,
448 ray_start,
449 ray_normal,
450 r_distance,
451 location_dummy,
452 normal_dummy);
453
454 /* Artificially scale the distance to the scene size. */
455 *r_distance /= walk->grid;
456 return ret;
457}
458
464static bool walk_ray_cast(RegionView3D *rv3d,
465 WalkInfo *walk,
466 float r_location[3],
467 float r_normal[3],
468 float *r_ray_distance)
469{
470 float ray_normal[3] = {0, 0, -1}; /* Forward axis. */
471 float ray_start[3];
472
473 *r_ray_distance = BVH_RAYCAST_DIST_MAX;
474
475 copy_v3_v3(ray_start, rv3d->viewinv[3]);
476
477 mul_mat3_m4_v3(rv3d->viewinv, ray_normal);
478
479 normalize_v3(ray_normal);
480
483
485 walk->depsgraph,
486 walk->v3d,
487 &snap_params,
488 ray_start,
489 ray_normal,
490 nullptr,
491 r_location,
492 r_normal);
493
494 /* Dot is positive if both rays are facing the same direction. */
495 if (dot_v3v3(ray_normal, r_normal) > 0) {
496 negate_v3(r_normal);
497 }
498
499 /* Artificially scale the distance to the scene size. */
500 *r_ray_distance /= walk->grid;
501
502 return ret;
503}
504
506static struct {
511} g_walk = {
512 /*base_speed*/ -1.0f,
513 /*userdef_speed*/ -1.0f,
514 /*jump_height*/ -1.0f,
515 /*userdef_jump_height*/ -1.0f,
517
518static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op, const int mval[2])
519{
521 wmWindow *win = CTX_wm_window(C);
522
523 walk->rv3d = CTX_wm_region_view3d(C);
524 walk->v3d = CTX_wm_view3d(C);
525 walk->region = CTX_wm_region(C);
527 walk->scene = CTX_data_scene(C);
528
529#ifdef NDOF_WALK_DEBUG
530 puts("\n-- walk begin --");
531#endif
532
533 /* Sanity check: for rare but possible case (if lib-linking the camera fails). */
534 if ((walk->rv3d->persp == RV3D_CAMOB) && (walk->v3d->camera == nullptr)) {
535 walk->rv3d->persp = RV3D_PERSP;
536 }
537
538 if (walk->rv3d->persp == RV3D_CAMOB &&
540 {
542 RPT_ERROR,
543 "Cannot navigate a camera from an external library or non-editable override");
544 return false;
545 }
546
547 if (ED_view3d_offset_lock_check(walk->v3d, walk->rv3d)) {
548 BKE_report(op->reports, RPT_ERROR, "Cannot navigate when the view offset is locked");
549 return false;
550 }
551
552 if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->constraints.first) {
553 BKE_report(op->reports, RPT_ERROR, "Cannot navigate an object with constraints");
554 return false;
555 }
556
557 walk->state = WALK_RUNNING;
558
559 if (fabsf(U.walk_navigation.walk_speed - g_walk.userdef_speed) > 0.1f) {
560 g_walk.base_speed = U.walk_navigation.walk_speed;
561 g_walk.userdef_speed = U.walk_navigation.walk_speed;
562 }
563
564 if (fabsf(U.walk_navigation.jump_height - g_walk.userdef_jump_height) > 0.1f) {
565 g_walk.jump_height = U.walk_navigation.jump_height;
566 g_walk.userdef_jump_height = U.walk_navigation.jump_height;
567 }
568
569 walk->jump_height = 0.0f;
570
571 walk->speed = 0.0f;
572 walk->is_fast = false;
573 walk->is_slow = false;
574 walk->grid = (walk->scene->unit.system == USER_UNIT_NONE) ?
575 1.0f :
576 1.0f / walk->scene->unit.scale_length;
577
578 /* User preference settings. */
579 walk->teleport.duration = U.walk_navigation.teleport_time;
580 walk->mouse_speed = U.walk_navigation.mouse_speed;
581
582 if (U.walk_navigation.flag & USER_WALK_GRAVITY) {
584 }
585 else {
587 }
588
589 walk->view_height = U.walk_navigation.view_height;
590 walk->jump_height = U.walk_navigation.jump_height;
591 walk->speed = U.walk_navigation.walk_speed;
592 walk->speed_factor = U.walk_navigation.walk_speed_factor;
594
596
598 walk->gravity = fabsf(walk->scene->physics_settings.gravity[2]);
599 }
600 else {
601 walk->gravity = 9.80668f; /* m/s2 */
602 }
603
604 walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0);
605
606#ifdef USE_TABLET_SUPPORT
607 walk->is_cursor_absolute = false;
608#endif
609
611
612#ifdef NDOF_WALK_DRAW_TOOMUCH
613 walk->redraw = true;
614#endif
615 zero_v3(walk->dvec_prev);
616
617 walk->timer = WM_event_timer_add(CTX_wm_manager(C), win, TIMER, 0.01f);
618
619#ifdef WITH_INPUT_NDOF
620 walk->ndof = nullptr;
621#endif
622
624 walk->need_rotation_keyframe = false;
625 walk->need_translation_keyframe = false;
626
628
631
632 walk->rv3d->rflag |= RV3D_NAVIGATING;
633
635
637 walk->depsgraph, walk->scene, walk->v3d, walk->rv3d);
638
639 copy_v2_v2_int(walk->init_mval, mval);
640 copy_v2_v2_int(walk->prev_mval, mval);
641
643
644 return true;
645}
646
648{
649 wmWindow *win;
650 RegionView3D *rv3d;
651
652 if (walk->state == WALK_RUNNING) {
654 }
655 if (walk->state == WALK_CONFIRM) {
656 /* Needed for auto_keyframe. */
657#ifdef WITH_INPUT_NDOF
658 if (walk->ndof) {
659 walkApply_ndof(C, walk, true);
660 }
661 else
662#endif /* WITH_INPUT_NDOF */
663 {
664 walkApply(C, walk, true);
665 }
666 }
667
668#ifdef NDOF_WALK_DEBUG
669 puts("\n-- walk end --");
670#endif
671
672 win = CTX_wm_window(C);
673 rv3d = walk->rv3d;
674
675 ED_workspace_status_text(C, nullptr);
676
678
680
682
684
685 rv3d->rflag &= ~RV3D_NAVIGATING;
686
687#ifdef WITH_INPUT_NDOF
688 if (walk->ndof) {
689 MEM_freeN(walk->ndof);
690 }
691#endif
692
693 WM_cursor_grab_disable(win, nullptr);
694
695 if (walk->state == WALK_CONFIRM) {
696 MEM_freeN(walk);
697 return OPERATOR_FINISHED;
698 }
699
700 MEM_freeN(walk);
701 return OPERATOR_CANCELLED;
702}
703
704static void walkEvent(WalkInfo *walk, const wmEvent *event)
705{
706 if (event->type == TIMER && event->customdata == walk->timer) {
707 walk->redraw = true;
708 }
709 else if (ISMOUSE_MOTION(event->type)) {
710
711#ifdef USE_TABLET_SUPPORT
712 if ((walk->is_cursor_absolute == false) && event->tablet.is_motion_absolute) {
713 walk->is_cursor_absolute = true;
714 }
715#endif /* USE_TABLET_SUPPORT */
716
717 walk->moffset[0] += event->mval[0] - walk->prev_mval[0];
718 walk->moffset[1] += event->mval[1] - walk->prev_mval[1];
719
720 copy_v2_v2_int(walk->prev_mval, event->mval);
721
722 if (walk->moffset[0] || walk->moffset[1]) {
723 walk->redraw = true;
724 }
725 }
726#ifdef WITH_INPUT_NDOF
727 else if (event->type == NDOF_MOTION) {
728 /* Do these auto-magically get delivered? yes. */
729 // puts("ndof motion detected in walk mode!");
730 // static const char *tag_name = "3D mouse position";
731
732 const wmNDOFMotionData *incoming_ndof = static_cast<const wmNDOFMotionData *>(
733 event->customdata);
734 switch (incoming_ndof->progress) {
735 case P_STARTING: {
736 /* Start keeping track of 3D mouse position. */
737# ifdef NDOF_WALK_DEBUG
738 puts("start keeping track of 3D mouse position");
739# endif
740 /* Fall-through. */
741 }
742 case P_IN_PROGRESS: {
743 /* Update 3D mouse position. */
744# ifdef NDOF_WALK_DEBUG
745 putchar('.');
746 fflush(stdout);
747# endif
748 if (walk->ndof == nullptr) {
749 // walk->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name);
750 walk->ndof = static_cast<wmNDOFMotionData *>(MEM_dupallocN(incoming_ndof));
751 // walk->ndof = malloc(sizeof(wmNDOFMotionData));
752 }
753 else {
754 memcpy(walk->ndof, incoming_ndof, sizeof(wmNDOFMotionData));
755 }
756 break;
757 }
758 case P_FINISHING: {
759 /* Stop keeping track of 3D mouse position. */
760# ifdef NDOF_WALK_DEBUG
761 puts("stop keeping track of 3D mouse position");
762# endif
763 if (walk->ndof) {
764 MEM_freeN(walk->ndof);
765 // free(walk->ndof);
766 walk->ndof = nullptr;
767 }
768
769 /* Update the time else the view will jump when 2D mouse/timer resume. */
771
772 break;
773 }
774 default: {
775 /* Should always be one of the above 3. */
776 break;
777 }
778 }
779 }
780#endif /* WITH_INPUT_NDOF */
781 /* Handle modal key-map first. */
782 else if (event->type == EVT_MODAL_MAP) {
783 switch (event->val) {
784 case WALK_MODAL_CANCEL: {
785 walk->state = WALK_CANCEL;
786 break;
787 }
788 case WALK_MODAL_CONFIRM: {
789 walk->state = WALK_CONFIRM;
790 break;
791 }
793 g_walk.base_speed *= 1.0f + (walk->is_slow ? 0.01f : 0.1f);
794 break;
795 }
797 g_walk.base_speed /= 1.0f + (walk->is_slow ? 0.01f : 0.1f);
798 break;
799 }
800 /* Implement WASD keys. */
803 break;
804 }
807 break;
808 }
809 case WALK_MODAL_DIR_LEFT: {
811 break;
812 }
815 break;
816 }
817 case WALK_MODAL_DIR_UP: {
819 break;
820 }
821 case WALK_MODAL_DIR_DOWN: {
823 break;
824 }
827 break;
828 }
831 break;
832 }
835 break;
836 }
839 break;
840 }
843 break;
844 }
847 break;
848 }
851 break;
852 }
855 break;
856 }
859 break;
860 }
863 break;
864 }
866 walk->is_fast = true;
867 break;
868 }
870 walk->is_fast = false;
871 break;
872 }
874 walk->is_slow = true;
875 break;
876 }
878 walk->is_slow = false;
879 break;
880 }
881
882#define JUMP_SPEED_MIN 1.0f
883#define JUMP_TIME_MAX 0.2f /* s */
884#define JUMP_SPEED_MAX sqrtf(2.0f * walk->gravity * walk->jump_height)
885
888 float t;
889
890 /* Delta time. */
891 t = float(BLI_time_now_seconds() - walk->teleport.initial_time);
892
893 /* Reduce the velocity, if JUMP wasn't hold for long enough. */
894 t = min_ff(t, JUMP_TIME_MAX);
895 walk->speed_jump = JUMP_SPEED_MIN +
897
898 /* When jumping, duration is how long it takes before we start going down. */
900
901 /* No more increase of jump speed. */
903 }
904 break;
905 }
906 case WALK_MODAL_JUMP: {
907 if ((walk->navigation_mode == WALK_MODE_GRAVITY) &&
910 {
911 /* No need to check for ground, `walk->gravity`
912 * wouldn't be off if we were over a hole. */
915
917 copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);
918
919 /* Using previous vector because WASD keys are not called when SPACE is. */
921
922 /* When jumping, duration is how long it takes before we start going down. */
924 }
925 break;
926 }
927
928 case WALK_MODAL_TELEPORT: {
929 float loc[3], nor[3];
930 float distance;
931 const bool ret = walk_ray_cast(walk->rv3d, walk, loc, nor, &distance);
932
933 /* In case we are teleporting middle way from a jump. */
934 walk->speed_jump = 0.0f;
935
936 if (ret) {
937 WalkTeleport *teleport = &walk->teleport;
938
939 /* Store the current navigation mode if we are not already teleporting. */
940 if (teleport->state == WALK_TELEPORT_STATE_OFF) {
941 teleport->navigation_mode = walk->navigation_mode;
942 }
943 teleport->state = WALK_TELEPORT_STATE_ON;
945 teleport->duration = U.walk_navigation.teleport_time;
946
948
949 copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]);
950
951 /* Stop the camera from a distance (camera height). */
953 add_v3_v3(loc, nor);
954
955 sub_v3_v3v3(teleport->direction, loc, teleport->origin);
956 }
957 break;
958 }
959
960#undef JUMP_SPEED_MAX
961#undef JUMP_TIME_MAX
962#undef JUMP_SPEED_MIN
963
965 if (walk->navigation_mode == WALK_MODE_GRAVITY) {
967 }
968 else { /* WALK_MODE_FREE */
970 }
971 break;
972 }
973
975 if (walk->zlock != WALK_AXISLOCK_STATE_DONE) {
977 walk->zlock_momentum = 0.0f;
978 }
979 break;
980 }
981
982#define JUMP_HEIGHT_FACTOR 1.5f
983#define JUMP_HEIGHT_MIN 0.1f
984#define JUMP_HEIGHT_MAX 10.0f
985
987 g_walk.jump_height = min_ff(g_walk.jump_height * JUMP_HEIGHT_FACTOR, JUMP_HEIGHT_MAX);
988 break;
989 }
991 g_walk.jump_height = max_ff(g_walk.jump_height / JUMP_HEIGHT_FACTOR, JUMP_HEIGHT_MIN);
992 break;
993 }
994
995#undef JUMP_HEIGHT_FACTOR
996#undef JUMP_HEIGHT_MIN
997#undef JUMP_HEIGHT_MAX
998 }
999 }
1000}
1001
1003 WalkInfo *walk,
1004 const bool do_rotate,
1005 const bool do_translate,
1006 const bool is_confirm)
1007{
1008 /* We only consider auto-keying on playback or if user confirmed walk on the same frame
1009 * otherwise we get a keyframe even if the user cancels. */
1010 const bool use_autokey = is_confirm || walk->anim_playing;
1012 walk->v3d_camera_control, use_autokey, C, do_rotate, do_translate);
1013 if (use_autokey) {
1014 walk->need_rotation_keyframe = false;
1015 walk->need_translation_keyframe = false;
1016 }
1017}
1018
1019static float walk_calc_free_fall_distance(const float gravity, const float time)
1020{
1021 return gravity * (time * time) * 0.5f;
1022}
1023
1024static float walk_calc_velocity_zero_time(const float gravity, const float velocity)
1025{
1026 return velocity / gravity;
1027}
1028
1029static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
1030{
1031#define WALK_ROTATE_TABLET_FAC 8.8f /* Higher is faster, relative to region size. */
1032#define WALK_ROTATE_CONSTANT_FAC DEG2RADF(0.15f) /* Higher is faster, radians per-pixel. */
1033#define WALK_TOP_LIMIT DEG2RADF(85.0f)
1034#define WALK_BOTTOM_LIMIT DEG2RADF(-80.0f)
1035#define WALK_MOVE_SPEED (0 ? 0.0f : g_walk.base_speed)
1036#define WALK_JUMP_HEIGHT (0 ? 0.0f : g_walk.jump_height)
1037#define WALK_BOOST_FACTOR ((void)0, walk->speed_factor)
1038#define WALK_ZUP_CORRECT_FAC 0.1f /* Amount to correct per step. */
1039#define WALK_ZUP_CORRECT_ACCEL 0.05f /* Increase upright momentum each step. */
1040
1041 RegionView3D *rv3d = walk->rv3d;
1042 ARegion *region = walk->region;
1043
1044 /* 3x3 copy of the view matrix so we can move along the view axis. */
1045 float mat[3][3];
1046 /* This is the direction that's added to the view offset per redraw. */
1047 float dvec[3] = {0.0f, 0.0f, 0.0f};
1048
1049 int moffset[2]; /* Mouse offset from the views center. */
1050 float tmp_quat[4]; /* Used for rotating the view. */
1051
1052#ifdef NDOF_WALK_DEBUG
1053 {
1054 static uint iteration = 1;
1055 printf("walk timer %d\n", iteration++);
1056 }
1057#endif
1058
1059 {
1060 /* Mouse offset from the center. */
1061 copy_v2_v2_int(moffset, walk->moffset);
1062
1063 /* Apply `moffset` so we can re-accumulate. */
1064 walk->moffset[0] = 0;
1065 walk->moffset[1] = 0;
1066
1067 /* Revert mouse. */
1068 if (walk->is_reversed) {
1069 moffset[1] = -moffset[1];
1070 }
1071
1072 /* Update jump height. */
1075 }
1076
1077 /* Should we redraw? */
1078 if ((walk->active_directions) || moffset[0] || moffset[1] ||
1081 walk->teleport.state == WALK_TELEPORT_STATE_ON || is_confirm)
1082 {
1083 float dvec_tmp[3];
1084
1085 /* Time how fast it takes for us to redraw,
1086 * this is so simple scenes don't walk too fast. */
1087 double time_current;
1088 float time_redraw;
1089 float time_redraw_clamped;
1090#ifdef NDOF_WALK_DRAW_TOOMUCH
1091 walk->redraw = true;
1092#endif
1093 time_current = BLI_time_now_seconds();
1094 time_redraw = float(time_current - walk->time_lastdraw);
1095
1096 /* Clamp redraw time to avoid jitter in roll correction. */
1097 time_redraw_clamped = min_ff(0.05f, time_redraw);
1098
1099 walk->time_lastdraw = time_current;
1100
1101 /* Base speed in m/s. */
1102 walk->speed = WALK_MOVE_SPEED;
1103
1104 if (walk->is_fast) {
1105 walk->speed *= WALK_BOOST_FACTOR;
1106 }
1107 else if (walk->is_slow) {
1108 walk->speed *= 1.0f / WALK_BOOST_FACTOR;
1109 }
1110
1111 copy_m3_m4(mat, rv3d->viewinv);
1112
1113 {
1114 /* Rotate about the X axis- look up/down. */
1115 if (moffset[1]) {
1116 float upvec[3];
1117 float angle;
1118 float y;
1119
1120 /* Relative offset. */
1121 y = float(moffset[1]);
1122
1123 /* Speed factor. */
1124#ifdef USE_TABLET_SUPPORT
1125 if (walk->is_cursor_absolute) {
1126 y /= region->winy;
1128 }
1129 else
1130#endif
1131 {
1133 }
1134
1135 /* User adjustment factor. */
1136 y *= walk->mouse_speed;
1137
1138 /* Clamp the angle limits: it ranges from 90.0f to -90.0f. */
1139 angle = -asinf(rv3d->viewmat[2][2]);
1140
1141 if (angle > WALK_TOP_LIMIT && y > 0.0f) {
1142 y = 0.0f;
1143 }
1144 else if (angle < WALK_BOTTOM_LIMIT && y < 0.0f) {
1145 y = 0.0f;
1146 }
1147
1148 copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
1149 mul_m3_v3(mat, upvec);
1150 /* Rotate about the relative up vector. */
1151 axis_angle_to_quat(tmp_quat, upvec, -y);
1152 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
1153 }
1154
1155 /* Rotate about the Y axis- look left/right. */
1156 if (moffset[0]) {
1157 float upvec[3];
1158 float x;
1159
1160 /* If we're upside down invert the `moffset`. */
1161 copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
1162 mul_m3_v3(mat, upvec);
1163
1164 if (upvec[2] < 0.0f) {
1165 moffset[0] = -moffset[0];
1166 }
1167
1168 /* Relative offset. */
1169 x = float(moffset[0]);
1170
1171 /* Speed factor. */
1172#ifdef USE_TABLET_SUPPORT
1173 if (walk->is_cursor_absolute) {
1174 x /= region->winx;
1176 }
1177 else
1178#endif
1179 {
1181 }
1182
1183 /* User adjustment factor. */
1184 x *= walk->mouse_speed;
1185
1186 /* Rotate about the relative up vector */
1187 axis_angle_to_quat_single(tmp_quat, 'Z', x);
1188 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
1189 }
1190
1191 if (walk->zlock == WALK_AXISLOCK_STATE_ACTIVE) {
1192 float upvec[3];
1193 copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
1194 mul_m3_v3(mat, upvec);
1195
1196 /* Make sure we have some Z rolling. */
1197 if (fabsf(upvec[2]) > 0.00001f) {
1198 float roll = upvec[2] * 5.0f;
1199 /* Rotate the view about this axis. */
1200 copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
1201 mul_m3_v3(mat, upvec);
1202 /* Rotate about the relative up vector. */
1203 axis_angle_to_quat(tmp_quat,
1204 upvec,
1205 roll * time_redraw_clamped * walk->zlock_momentum *
1207 mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
1208
1210 }
1211 else {
1212 /* Lock fixed, don't need to check it ever again. */
1214 }
1215 }
1216 }
1217
1218 /* WASD - 'move' translation code. */
1219 if ((walk->active_directions) && (walk->gravity_state == WALK_GRAVITY_STATE_OFF)) {
1220
1221 short direction;
1222 zero_v3(dvec);
1223
1226 {
1227
1228 direction = 0;
1229
1231 direction += 1;
1232 }
1233
1235 direction -= 1;
1236 }
1237
1238 copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
1239 mul_m3_v3(mat, dvec_tmp);
1240
1241 if (walk->navigation_mode == WALK_MODE_GRAVITY) {
1242 dvec_tmp[2] = 0.0f;
1243 }
1244
1245 add_v3_v3(dvec, dvec_tmp);
1246 }
1247
1248 if ((walk->active_directions & WALK_BIT_LOCAL_LEFT) ||
1250 {
1251
1252 direction = 0;
1253
1255 direction += 1;
1256 }
1257
1259 direction -= 1;
1260 }
1261
1262 dvec_tmp[0] = direction * rv3d->viewinv[0][0];
1263 dvec_tmp[1] = direction * rv3d->viewinv[0][1];
1264 dvec_tmp[2] = 0.0f;
1265
1266 add_v3_v3(dvec, dvec_tmp);
1267 }
1268
1269 /* Up and down movement is only available in free mode, not gravity mode. */
1270 if (walk->navigation_mode == WALK_MODE_FREE) {
1271
1273
1274 direction = 0;
1275
1277 direction -= 1;
1278 }
1279
1281 direction += 1;
1282 }
1283
1284 copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
1285 add_v3_v3(dvec, dvec_tmp);
1286 }
1287
1289
1290 direction = 0;
1291
1293 direction -= 1;
1294 }
1295
1297 direction += 1;
1298 }
1299
1300 madd_v3_v3fl(dvec, rv3d->viewinv[1], direction);
1301 }
1302 }
1303
1304 normalize_v3(dvec);
1305
1306 /* Apply movement. */
1307 mul_v3_fl(dvec, walk->speed * time_redraw);
1308 }
1309
1310 /* Stick to the floor. */
1311 if (walk->navigation_mode == WALK_MODE_GRAVITY &&
1313 {
1314 float ray_distance;
1315 float difference = -100.0f;
1316
1317 if (walk_floor_distance_get(rv3d, walk, dvec, &ray_distance)) {
1318 difference = walk->view_height - ray_distance;
1319 }
1320
1321 /* The distance we would fall naturally smoothly enough that we
1322 * can manually drop the object without activating gravity. */
1323 const float fall_distance = time_redraw * walk->speed * WALK_BOOST_FACTOR;
1324
1325 if (fabsf(difference) < fall_distance) {
1326 /* slope/stairs */
1327 dvec[2] -= difference;
1328
1329 /* In case we switched from FREE to GRAVITY too close to the ground. */
1332 }
1333 }
1334 else {
1335 /* Hijack the teleport variables. */
1338 walk->teleport.duration = 0.0f;
1339
1340 copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);
1341 copy_v2_v2(walk->teleport.direction, dvec);
1342 }
1343 }
1344
1345 /* Falling or jumping). */
1347 float ray_distance, difference = -100.0f;
1348 /* Delta time. */
1349 const float t = float(BLI_time_now_seconds() - walk->teleport.initial_time);
1350
1351 /* Keep moving if we were moving. */
1352 copy_v2_v2(dvec, walk->teleport.direction);
1353
1354 const float z_cur = walk->rv3d->viewinv[3][2] / walk->grid;
1355 const float z_new = ((walk->teleport.origin[2] / walk->grid) -
1357 /* Jump. */
1358 (t * walk->speed_jump);
1359
1360 /* Duration is the jump duration. */
1361 if (t > walk->teleport.duration) {
1362
1363 /* Check to see if we are landing. */
1364 if (walk_floor_distance_get(rv3d, walk, dvec, &ray_distance)) {
1365 difference = walk->view_height - ray_distance;
1366 }
1367
1368 if (difference > 0.0f) {
1369 /* Quit falling, lands at "view_height" from the floor. */
1370 dvec[2] -= difference;
1372 walk->speed_jump = 0.0f;
1373 }
1374 else {
1375 /* Keep falling. */
1376 dvec[2] = z_cur - z_new;
1377 }
1378 }
1379 else {
1380 /* Keep going up (jump). */
1381 dvec[2] = z_cur - z_new;
1382 }
1383 }
1384
1385 /* Teleport. */
1386 else if (walk->teleport.state == WALK_TELEPORT_STATE_ON) {
1387 float t; /* factor */
1388 float new_loc[3];
1389 float cur_loc[3];
1390
1391 /* Linear interpolation. */
1392 t = float(BLI_time_now_seconds() - walk->teleport.initial_time);
1393 t /= walk->teleport.duration;
1394
1395 /* Clamp so we don't go past our limit. */
1396 if (t >= 1.0f) {
1397 t = 1.0f;
1400 }
1401
1402 mul_v3_v3fl(new_loc, walk->teleport.direction, t);
1403 add_v3_v3(new_loc, walk->teleport.origin);
1404
1405 copy_v3_v3(cur_loc, walk->rv3d->viewinv[3]);
1406 sub_v3_v3v3(dvec, cur_loc, new_loc);
1407 }
1408
1409 /* Scale the movement to the scene size. */
1410 mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
1411 add_v3_v3(rv3d->ofs, dvec_tmp);
1412
1413 if (rv3d->persp == RV3D_CAMOB) {
1414 walk->need_rotation_keyframe |= (moffset[0] || moffset[1] ||
1416 walk->need_translation_keyframe |= (len_squared_v3(dvec_tmp) > FLT_EPSILON);
1418 C, walk, walk->need_rotation_keyframe, walk->need_translation_keyframe, is_confirm);
1419 }
1420 }
1421 else {
1422 /* We're not redrawing but we need to update the time else the view will jump. */
1424 }
1425 /* End drawing. */
1426 copy_v3_v3(walk->dvec_prev, dvec);
1427 }
1428
1429 return OPERATOR_FINISHED;
1430#undef WALK_ROTATE_TABLET_FAC
1431#undef WALK_TOP_LIMIT
1432#undef WALK_BOTTOM_LIMIT
1433#undef WALK_MOVE_SPEED
1434#undef WALK_JUMP_HEIGHT
1435#undef WALK_BOOST_FACTOR
1436}
1437
1438#ifdef WITH_INPUT_NDOF
1439static void walkApply_ndof(bContext *C, WalkInfo *walk, bool is_confirm)
1440{
1442 bool has_translate, has_rotate;
1443
1444 view3d_ndof_fly(*walk->ndof,
1445 walk->v3d,
1446 walk->rv3d,
1447 walk->is_slow,
1448 lock_ob ? lock_ob->protectflag : 0,
1449 &has_translate,
1450 &has_rotate);
1451
1452 if (has_translate || has_rotate) {
1453 walk->redraw = true;
1454
1455 if (walk->rv3d->persp == RV3D_CAMOB) {
1456 walk->need_rotation_keyframe |= has_rotate;
1457 walk->need_translation_keyframe |= has_translate;
1459 C, walk, walk->need_rotation_keyframe, walk->need_translation_keyframe, is_confirm);
1460 }
1461 }
1462}
1463#endif /* WITH_INPUT_NDOF */
1464
1466
1467/* -------------------------------------------------------------------- */
1470
1472{
1473 WalkInfo *walk = static_cast<WalkInfo *>(op->customdata);
1474
1475 WorkspaceStatus status(C);
1476
1477 status.opmodal(IFACE_("Confirm"), op->type, WALK_MODAL_CONFIRM);
1478 status.opmodal(IFACE_("Cancel"), op->type, WALK_MODAL_CANCEL);
1479
1480 status.opmodal(
1483 status.opmodal(
1485 status.opmodal(
1487 status.item(IFACE_("Move"), ICON_NONE);
1488
1490 status.opmodal(
1492 status.item(IFACE_("Up/Down"), ICON_NONE);
1493
1494 status.opmodal(
1496 status.opmodal(
1498 status.item(IFACE_("Local Up/Down"), ICON_NONE);
1499
1500 status.opmodal(
1502
1503 status.opmodal(IFACE_("Teleport"),
1504 op->type,
1507
1508 status.opmodal(IFACE_("Fast"), op->type, WALK_MODAL_FAST_ENABLE, walk->is_fast);
1509 status.opmodal(IFACE_("Slow"), op->type, WALK_MODAL_SLOW_ENABLE, walk->is_slow);
1510
1511 status.opmodal(IFACE_("Gravity"),
1512 op->type,
1515
1516 status.opmodal("", op->type, WALK_MODAL_ACCELERATE);
1517 status.opmodal("", op->type, WALK_MODAL_DECELERATE);
1518 status.item(fmt::format("{} ({:.2f})", IFACE_("Acceleration"), g_walk.base_speed), ICON_NONE);
1519
1520 status.opmodal("", op->type, WALK_MODAL_INCREASE_JUMP);
1521 status.opmodal("", op->type, WALK_MODAL_DECREASE_JUMP);
1522 status.item(fmt::format("{} ({:.2f})", IFACE_("Jump Height"), g_walk.jump_height), ICON_NONE);
1523
1524 status.opmodal(IFACE_("Z Axis Correction"),
1525 op->type,
1528}
1529
1531{
1534 return OPERATOR_CANCELLED;
1535 }
1536
1537 WalkInfo *walk = MEM_callocN<WalkInfo>("NavigationWalkOperation");
1538
1539 op->customdata = walk;
1540
1541 if (initWalkInfo(C, walk, op, event->mval) == false) {
1542 MEM_freeN(walk);
1543 return OPERATOR_CANCELLED;
1544 }
1545
1546 walkEvent(walk, event);
1547
1548 walk_draw_status(C, op);
1549
1551
1553}
1554
1556{
1557 WalkInfo *walk = static_cast<WalkInfo *>(op->customdata);
1558
1559 walk->state = WALK_CANCEL;
1560 walkEnd(C, walk);
1561 op->customdata = nullptr;
1562}
1563
1565{
1566 bool do_draw = false;
1567 WalkInfo *walk = static_cast<WalkInfo *>(op->customdata);
1568 ARegion *region = walk->region;
1569 View3D *v3d = walk->v3d;
1570 RegionView3D *rv3d = walk->rv3d;
1572
1573 walk->redraw = false;
1574
1575 walkEvent(walk, event);
1576
1577 walk_draw_status(C, op);
1578
1579#ifdef WITH_INPUT_NDOF
1580 if (walk->ndof) { /* 3D mouse overrules [2D mouse + timer]. */
1581 if (event->type == NDOF_MOTION) {
1582 walkApply_ndof(C, walk, false);
1583 }
1584 }
1585 else
1586#endif /* WITH_INPUT_NDOF */
1587 {
1588 if (event->type == TIMER && event->customdata == walk->timer) {
1589 walkApply(C, walk, false);
1590 }
1591 }
1592
1593 do_draw |= walk->redraw;
1594
1595 const wmOperatorStatus exit_code = walkEnd(C, walk);
1596
1597 if (exit_code != OPERATOR_RUNNING_MODAL) {
1598 do_draw = true;
1599 }
1600 if (exit_code == OPERATOR_FINISHED) {
1601 const bool is_undo_pushed = ED_view3d_camera_lock_undo_push(op->type->name, v3d, rv3d, C);
1602 /* If generic 'locked camera' code did not push an undo, but there is a valid 'walking
1603 * object', an undo push is still needed, since that object transform was modified. */
1604 if (!is_undo_pushed && walk_object && ED_undo_is_memfile_compatible(C)) {
1605 ED_undo_push(C, op->type->name);
1606 }
1607 }
1608
1609 if (do_draw) {
1610 if (rv3d->persp == RV3D_CAMOB) {
1612 }
1613
1614 /* Too frequent, commented with `NDOF_WALK_DRAW_TOOMUCH` for now. */
1615 // puts("redraw!");
1616 ED_region_tag_redraw(region);
1617 }
1618 return exit_code;
1619}
1620
1622{
1623 /* Identifiers. */
1624 ot->name = "Walk Navigation";
1625 ot->description = "Interactively walk around the scene";
1626 ot->idname = "VIEW3D_OT_walk";
1627
1628 /* API callbacks. */
1629 ot->invoke = walk_invoke;
1630 ot->cancel = walk_cancel;
1631 ot->modal = walk_modal;
1633
1634 /* flags */
1635 /* NOTE: #OPTYPE_BLOCKING isn't used because this needs to grab & hide the cursor.
1636 * where as blocking confines the cursor to the window bounds, even when hidden. */
1637 ot->flag = 0;
1638}
1639
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:2503
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
#define BVH_RAYCAST_DIST_MAX
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:202
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition BLI_rect.h:206
unsigned int uint
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.cc:65
#define ENUM_OPERATORS(_type, _max)
#define ELEM(...)
#define IFACE_(msgid)
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
@ RV3D_LOCK_ANY_TRANSFORM
#define RV3D_LOCK_FLAGS(rv3d)
@ RV3D_CAMOB
@ RV3D_PERSP
@ RV3D_NAVIGATING
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
bool ED_operator_region_view3d_active(bContext *C)
bScreen * ED_screen_animation_playing(const wmWindowManager *wm)
void ED_workspace_status_text(bContext *C, const char *str)
Definition area.cc:1040
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:639
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
void ED_undo_push(bContext *C, const char *str)
Definition ed_undo.cc:99
bool ED_undo_is_memfile_compatible(const bContext *C)
Definition ed_undo.cc:386
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 immVertex2f(uint attr_id, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
GPUVertFormat * immVertexFormat()
void immBegin(GPUPrimType, uint vertex_len)
@ GPU_PRIM_LINES
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, blender::StringRef name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
@ TH_VIEW_OVERLAY
#define ND_TRANSFORM
Definition WM_types.hh:453
#define NC_OBJECT
Definition WM_types.hh:376
@ P_IN_PROGRESS
Definition WM_types.hh:850
@ P_STARTING
Definition WM_types.hh:849
@ P_FINISHING
Definition WM_types.hh:851
@ WM_CURSOR_WRAP_NONE
Definition WM_types.hh:226
#define U
void item(std::string text, int icon1, int icon2=0)
Definition area.cc:979
void opmodal(std::string text, const wmOperatorType *ot, int propvalue, bool inverted=false)
Definition area.cc:1005
#define asinf(x)
#define fabsf(x)
uint pos
uint nor
#define printf(...)
float distance(VecOp< float, D >, VecOp< float, D >) RET
format
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
void snap_object_context_destroy(SnapObjectContext *sctx)
SnapObjectContext * snap_object_context_create(Scene *scene, int flag)
bool 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])
return ret
ARegionRuntimeHandle * runtime
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
blender::ed::transform::SnapObjectContext * snap_context
RegionView3D * rv3d
eWalkMethod navigation_mode
eWalkTeleportState state
float xmin
float ymin
wmEventType type
Definition WM_types.hh:754
short val
Definition WM_types.hh:756
int mval[2]
Definition WM_types.hh:760
wmTabletData tablet
Definition WM_types.hh:783
void * customdata
Definition WM_types.hh:804
const void * modal_items
const char * name
Definition WM_types.hh:1030
struct ReportList * reports
struct wmOperatorType * type
char is_motion_absolute
Definition WM_types.hh:709
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 walk_draw_status(bContext *C, wmOperator *op)
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
@ 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
static bool walk_floor_distance_get(RegionView3D *rv3d, WalkInfo *walk, const float dvec[3], float *r_distance)
#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 wmOperatorStatus 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
@ WALK_MODE_GRAVITY
static wmOperatorStatus walkEnd(bContext *C, WalkInfo *walk)
#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 wmOperatorStatus walk_modal(bContext *C, wmOperator *op, const wmEvent *event)
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
static struct @203073062103026360241211311015220011237232374374 g_walk
#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:4226
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition wm_keymap.cc:929
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition wm_keymap.cc:956
wmTimer * WM_event_timer_add(wmWindowManager *wm, wmWindow *win, const wmEventType event_type, const double time_step)
void WM_event_timer_remove(wmWindowManager *wm, wmWindow *, wmTimer *timer)