diff options
Diffstat (limited to 'source/blender/editors/space_view3d/view3d_walk.c')
-rw-r--r-- | source/blender/editors/space_view3d/view3d_walk.c | 2067 |
1 files changed, 1037 insertions, 1030 deletions
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index a015b7f9945..a0613d3b76f 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -52,7 +52,7 @@ #include "DEG_depsgraph.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ #ifdef WITH_INPUT_NDOF //# define NDOF_WALK_DEBUG @@ -71,330 +71,344 @@ static float getVelocityZeroTime(const float gravity, const float velocity); /* NOTE: these defines are saved in keymap files, * do not change values but just add new ones */ enum { - WALK_MODAL_CANCEL = 1, - WALK_MODAL_CONFIRM, - WALK_MODAL_DIR_FORWARD, - WALK_MODAL_DIR_FORWARD_STOP, - WALK_MODAL_DIR_BACKWARD, - WALK_MODAL_DIR_BACKWARD_STOP, - WALK_MODAL_DIR_LEFT, - WALK_MODAL_DIR_LEFT_STOP, - WALK_MODAL_DIR_RIGHT, - WALK_MODAL_DIR_RIGHT_STOP, - WALK_MODAL_DIR_UP, - WALK_MODAL_DIR_UP_STOP, - WALK_MODAL_DIR_DOWN, - WALK_MODAL_DIR_DOWN_STOP, - WALK_MODAL_FAST_ENABLE, - WALK_MODAL_FAST_DISABLE, - WALK_MODAL_SLOW_ENABLE, - WALK_MODAL_SLOW_DISABLE, - WALK_MODAL_JUMP, - WALK_MODAL_JUMP_STOP, - WALK_MODAL_TELEPORT, - WALK_MODAL_TOGGLE, - WALK_MODAL_ACCELERATE, - WALK_MODAL_DECELERATE, + WALK_MODAL_CANCEL = 1, + WALK_MODAL_CONFIRM, + WALK_MODAL_DIR_FORWARD, + WALK_MODAL_DIR_FORWARD_STOP, + WALK_MODAL_DIR_BACKWARD, + WALK_MODAL_DIR_BACKWARD_STOP, + WALK_MODAL_DIR_LEFT, + WALK_MODAL_DIR_LEFT_STOP, + WALK_MODAL_DIR_RIGHT, + WALK_MODAL_DIR_RIGHT_STOP, + WALK_MODAL_DIR_UP, + WALK_MODAL_DIR_UP_STOP, + WALK_MODAL_DIR_DOWN, + WALK_MODAL_DIR_DOWN_STOP, + WALK_MODAL_FAST_ENABLE, + WALK_MODAL_FAST_DISABLE, + WALK_MODAL_SLOW_ENABLE, + WALK_MODAL_SLOW_DISABLE, + WALK_MODAL_JUMP, + WALK_MODAL_JUMP_STOP, + WALK_MODAL_TELEPORT, + WALK_MODAL_TOGGLE, + WALK_MODAL_ACCELERATE, + WALK_MODAL_DECELERATE, }; enum { - WALK_BIT_FORWARD = 1 << 0, - WALK_BIT_BACKWARD = 1 << 1, - WALK_BIT_LEFT = 1 << 2, - WALK_BIT_RIGHT = 1 << 3, - WALK_BIT_UP = 1 << 4, - WALK_BIT_DOWN = 1 << 5, + WALK_BIT_FORWARD = 1 << 0, + WALK_BIT_BACKWARD = 1 << 1, + WALK_BIT_LEFT = 1 << 2, + WALK_BIT_RIGHT = 1 << 3, + WALK_BIT_UP = 1 << 4, + WALK_BIT_DOWN = 1 << 5, }; typedef enum eWalkTeleportState { - WALK_TELEPORT_STATE_OFF = 0, - WALK_TELEPORT_STATE_ON, + WALK_TELEPORT_STATE_OFF = 0, + WALK_TELEPORT_STATE_ON, } eWalkTeleportState; typedef enum eWalkMethod { - WALK_MODE_FREE = 0, - WALK_MODE_GRAVITY, + WALK_MODE_FREE = 0, + WALK_MODE_GRAVITY, } eWalkMethod; typedef enum eWalkGravityState { - WALK_GRAVITY_STATE_OFF = 0, - WALK_GRAVITY_STATE_JUMP, - WALK_GRAVITY_STATE_START, - WALK_GRAVITY_STATE_ON, + WALK_GRAVITY_STATE_OFF = 0, + WALK_GRAVITY_STATE_JUMP, + WALK_GRAVITY_STATE_START, + WALK_GRAVITY_STATE_ON, } eWalkGravityState; /* called in transform_ops.c, on each regeneration of keymaps */ void walk_modal_keymap(wmKeyConfig *keyconf) { - static const EnumPropertyItem modal_items[] = { - {WALK_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, - {WALK_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, + static const EnumPropertyItem modal_items[] = { + {WALK_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, + {WALK_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, - {WALK_MODAL_DIR_FORWARD, "FORWARD", 0, "Forward", ""}, - {WALK_MODAL_DIR_BACKWARD, "BACKWARD", 0, "Backward", ""}, - {WALK_MODAL_DIR_LEFT, "LEFT", 0, "Left (Strafe)", ""}, - {WALK_MODAL_DIR_RIGHT, "RIGHT", 0, "Right (Strafe)", ""}, - {WALK_MODAL_DIR_UP, "UP", 0, "Up", ""}, - {WALK_MODAL_DIR_DOWN, "DOWN", 0, "Down", ""}, + {WALK_MODAL_DIR_FORWARD, "FORWARD", 0, "Forward", ""}, + {WALK_MODAL_DIR_BACKWARD, "BACKWARD", 0, "Backward", ""}, + {WALK_MODAL_DIR_LEFT, "LEFT", 0, "Left (Strafe)", ""}, + {WALK_MODAL_DIR_RIGHT, "RIGHT", 0, "Right (Strafe)", ""}, + {WALK_MODAL_DIR_UP, "UP", 0, "Up", ""}, + {WALK_MODAL_DIR_DOWN, "DOWN", 0, "Down", ""}, - {WALK_MODAL_DIR_FORWARD_STOP, "FORWARD_STOP", 0, "Stop Move Forward", ""}, - {WALK_MODAL_DIR_BACKWARD_STOP, "BACKWARD_STOP", 0, "Stop Mode Backward", ""}, - {WALK_MODAL_DIR_LEFT_STOP, "LEFT_STOP", 0, "Stop Move Left", ""}, - {WALK_MODAL_DIR_RIGHT_STOP, "RIGHT_STOP", 0, "Stop Mode Right", ""}, - {WALK_MODAL_DIR_UP_STOP, "UP_STOP", 0, "Stop Move Up", ""}, - {WALK_MODAL_DIR_DOWN_STOP, "DOWN_STOP", 0, "Stop Mode Down", ""}, + {WALK_MODAL_DIR_FORWARD_STOP, "FORWARD_STOP", 0, "Stop Move Forward", ""}, + {WALK_MODAL_DIR_BACKWARD_STOP, "BACKWARD_STOP", 0, "Stop Mode Backward", ""}, + {WALK_MODAL_DIR_LEFT_STOP, "LEFT_STOP", 0, "Stop Move Left", ""}, + {WALK_MODAL_DIR_RIGHT_STOP, "RIGHT_STOP", 0, "Stop Mode Right", ""}, + {WALK_MODAL_DIR_UP_STOP, "UP_STOP", 0, "Stop Move Up", ""}, + {WALK_MODAL_DIR_DOWN_STOP, "DOWN_STOP", 0, "Stop Mode Down", ""}, - {WALK_MODAL_TELEPORT, "TELEPORT", 0, "Teleport", "Move forward a few units at once"}, + {WALK_MODAL_TELEPORT, "TELEPORT", 0, "Teleport", "Move forward a few units at once"}, - {WALK_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""}, - {WALK_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""}, + {WALK_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""}, + {WALK_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""}, - {WALK_MODAL_FAST_ENABLE, "FAST_ENABLE", 0, "Fast", "Move faster (walk or fly)"}, - {WALK_MODAL_FAST_DISABLE, "FAST_DISABLE", 0, "Fast (Off)", "Resume regular speed"}, + {WALK_MODAL_FAST_ENABLE, "FAST_ENABLE", 0, "Fast", "Move faster (walk or fly)"}, + {WALK_MODAL_FAST_DISABLE, "FAST_DISABLE", 0, "Fast (Off)", "Resume regular speed"}, - {WALK_MODAL_SLOW_ENABLE, "SLOW_ENABLE", 0, "Slow", "Move slower (walk or fly)"}, - {WALK_MODAL_SLOW_DISABLE, "SLOW_DISABLE", 0, "Slow (Off)", "Resume regular speed"}, + {WALK_MODAL_SLOW_ENABLE, "SLOW_ENABLE", 0, "Slow", "Move slower (walk or fly)"}, + {WALK_MODAL_SLOW_DISABLE, "SLOW_DISABLE", 0, "Slow (Off)", "Resume regular speed"}, - {WALK_MODAL_JUMP, "JUMP", 0, "Jump", "Jump when in walk mode"}, - {WALK_MODAL_JUMP_STOP, "JUMP_STOP", 0, "Jump (Off)", "Stop pushing jump"}, + {WALK_MODAL_JUMP, "JUMP", 0, "Jump", "Jump when in walk mode"}, + {WALK_MODAL_JUMP_STOP, "JUMP_STOP", 0, "Jump (Off)", "Stop pushing jump"}, - {WALK_MODAL_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"}, + {WALK_MODAL_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"}, - {0, NULL, 0, NULL, NULL}, - }; + {0, NULL, 0, NULL, NULL}, + }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Walk Modal"); + wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Walk Modal"); - /* this function is called for each spacetype, only needs to add map once */ - if (keymap && keymap->modal_items) { - return; - } + /* this function is called for each spacetype, only needs to add map once */ + if (keymap && keymap->modal_items) { + return; + } - keymap = WM_modalkeymap_add(keyconf, "View3D Walk Modal", modal_items); + keymap = WM_modalkeymap_add(keyconf, "View3D Walk Modal", modal_items); - /* assign map to operators */ - WM_modalkeymap_assign(keymap, "VIEW3D_OT_walk"); + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW3D_OT_walk"); } - typedef struct WalkTeleport { - eWalkTeleportState state; - float duration; /* from user preferences */ - float origin[3]; - float direction[3]; - double initial_time; - eWalkMethod navigation_mode; /* teleport always set FREE mode on */ + eWalkTeleportState state; + float duration; /* from user preferences */ + float origin[3]; + float direction[3]; + double initial_time; + eWalkMethod navigation_mode; /* teleport always set FREE mode on */ } WalkTeleport; typedef struct WalkInfo { - /* context stuff */ - RegionView3D *rv3d; - View3D *v3d; - ARegion *ar; - struct Depsgraph *depsgraph; - Scene *scene; + /* context stuff */ + RegionView3D *rv3d; + View3D *v3d; + ARegion *ar; + struct Depsgraph *depsgraph; + Scene *scene; - wmTimer *timer; /* needed for redraws */ + wmTimer *timer; /* needed for redraws */ - short state; - bool redraw; + short state; + bool redraw; - int prev_mval[2]; /* previous 2D mouse values */ - int center_mval[2]; /* center mouse values */ - int moffset[2]; + int prev_mval[2]; /* previous 2D mouse values */ + int center_mval[2]; /* center mouse values */ + int moffset[2]; #ifdef WITH_INPUT_NDOF - wmNDOFMotionData *ndof; /* latest 3D mouse values */ + wmNDOFMotionData *ndof; /* latest 3D mouse values */ #endif - /* walk state state */ - float base_speed; /* the base speed without run/slow down modifications */ - float speed; /* the speed the view is moving per redraw */ - float grid; /* world scale 1.0 default */ + /* walk state state */ + float base_speed; /* the base speed without run/slow down modifications */ + float speed; /* the speed the view is moving per redraw */ + float grid; /* world scale 1.0 default */ - /* compare between last state */ - double time_lastdraw; /* time between draws */ + /* compare between last state */ + double time_lastdraw; /* time between draws */ - void *draw_handle_pixel; + void *draw_handle_pixel; - /* use for some lag */ - float dvec_prev[3]; /* old for some lag */ + /* use for some lag */ + float dvec_prev[3]; /* old for some lag */ - /* walk/fly */ - eWalkMethod navigation_mode; + /* walk/fly */ + eWalkMethod navigation_mode; - /* teleport */ - WalkTeleport teleport; + /* teleport */ + WalkTeleport teleport; - /* look speed factor - user preferences */ - float mouse_speed; + /* look speed factor - user preferences */ + float mouse_speed; - /* speed adjustments */ - bool is_fast; - bool is_slow; + /* speed adjustments */ + bool is_fast; + bool is_slow; - /* mouse reverse */ - bool is_reversed; + /* mouse reverse */ + bool is_reversed; #ifdef USE_TABLET_SUPPORT - /* check if we had a cursor event before */ - bool is_cursor_first; + /* check if we had a cursor event before */ + bool is_cursor_first; - /* tablet devices (we can't relocate the cursor) */ - bool is_cursor_absolute; + /* tablet devices (we can't relocate the cursor) */ + bool is_cursor_absolute; #endif - /* gravity system */ - eWalkGravityState gravity_state; - float gravity; + /* gravity system */ + eWalkGravityState gravity_state; + float gravity; - /* height to use in walk mode */ - float view_height; + /* height to use in walk mode */ + float view_height; - /* counting system to allow movement to continue if a direction (WASD) key is still pressed */ - int active_directions; + /* counting system to allow movement to continue if a direction (WASD) key is still pressed */ + int active_directions; - float speed_jump; - float jump_height; /* maximum jump height */ - float speed_factor; /* to use for fast/slow speeds */ + float speed_jump; + float jump_height; /* maximum jump height */ + float speed_factor; /* to use for fast/slow speeds */ - struct SnapObjectContext *snap_context; + struct SnapObjectContext *snap_context; - struct View3DCameraControl *v3d_camera_control; + struct View3DCameraControl *v3d_camera_control; } WalkInfo; static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *arg) { - /* draws an aim/cross in the center */ - WalkInfo *walk = arg; + /* draws an aim/cross in the center */ + WalkInfo *walk = arg; - const int outter_length = 24; - const int inner_length = 14; - int xoff, yoff; - rctf viewborder; + const int outter_length = 24; + const int inner_length = 14; + int xoff, yoff; + rctf viewborder; - if (ED_view3d_cameracontrol_object_get(walk->v3d_camera_control)) { - ED_view3d_calc_camera_border(walk->scene, walk->depsgraph, ar, walk->v3d, walk->rv3d, &viewborder, false); - xoff = viewborder.xmin + BLI_rctf_size_x(&viewborder) * 0.5f; - yoff = viewborder.ymin + BLI_rctf_size_y(&viewborder) * 0.5f; - } - else { - xoff = walk->ar->winx / 2; - yoff = walk->ar->winy / 2; - } + if (ED_view3d_cameracontrol_object_get(walk->v3d_camera_control)) { + ED_view3d_calc_camera_border( + walk->scene, walk->depsgraph, ar, walk->v3d, walk->rv3d, &viewborder, false); + xoff = viewborder.xmin + BLI_rctf_size_x(&viewborder) * 0.5f; + yoff = viewborder.ymin + BLI_rctf_size_y(&viewborder) * 0.5f; + } + else { + xoff = walk->ar->winx / 2; + yoff = walk->ar->winy / 2; + } - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformThemeColor(TH_VIEW_OVERLAY); + immUniformThemeColor(TH_VIEW_OVERLAY); - immBegin(GPU_PRIM_LINES, 8); + immBegin(GPU_PRIM_LINES, 8); - /* North */ - immVertex2i(pos, xoff, yoff + inner_length); - immVertex2i(pos, xoff, yoff + outter_length); + /* North */ + immVertex2i(pos, xoff, yoff + inner_length); + immVertex2i(pos, xoff, yoff + outter_length); - /* East */ - immVertex2i(pos, xoff + inner_length, yoff); - immVertex2i(pos, xoff + outter_length, yoff); + /* East */ + immVertex2i(pos, xoff + inner_length, yoff); + immVertex2i(pos, xoff + outter_length, yoff); - /* South */ - immVertex2i(pos, xoff, yoff - inner_length); - immVertex2i(pos, xoff, yoff - outter_length); + /* South */ + immVertex2i(pos, xoff, yoff - inner_length); + immVertex2i(pos, xoff, yoff - outter_length); - /* West */ - immVertex2i(pos, xoff - inner_length, yoff); - immVertex2i(pos, xoff - outter_length, yoff); + /* West */ + immVertex2i(pos, xoff - inner_length, yoff); + immVertex2i(pos, xoff - outter_length, yoff); - immEnd(); - immUnbindProgram(); + immEnd(); + immUnbindProgram(); } static void walk_update_header(bContext *C, wmOperator *op, WalkInfo *walk) { - const bool gravity = (walk->navigation_mode == WALK_MODE_GRAVITY) || - ((walk->teleport.state == WALK_TELEPORT_STATE_ON) && - (walk->teleport.navigation_mode == WALK_MODE_GRAVITY)); - char header[UI_MAX_DRAW_STR]; - char buf[UI_MAX_DRAW_STR]; + const bool gravity = (walk->navigation_mode == WALK_MODE_GRAVITY) || + ((walk->teleport.state == WALK_TELEPORT_STATE_ON) && + (walk->teleport.navigation_mode == WALK_MODE_GRAVITY)); + char header[UI_MAX_DRAW_STR]; + char buf[UI_MAX_DRAW_STR]; - char *p = buf; - int available_len = sizeof(buf); + char *p = buf; + int available_len = sizeof(buf); #define WM_MODALKEY(_id) \ - WM_modalkeymap_operator_items_to_string_buf(op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p) - - BLI_snprintf(header, sizeof(header), IFACE_("%s: confirm, %s: cancel, " - "%s: gravity (%s), " - "%s|%s|%s|%s: move around, " - "%s: fast, %s: slow, " - "%s|%s: up and down, " - "%s: teleport, %s: jump, " - "%s: increase speed, %s: decrease speed"), - WM_MODALKEY(WALK_MODAL_CONFIRM), WM_MODALKEY(WALK_MODAL_CANCEL), - WM_MODALKEY(WALK_MODAL_TOGGLE), WM_bool_as_string(gravity), - WM_MODALKEY(WALK_MODAL_DIR_FORWARD), WM_MODALKEY(WALK_MODAL_DIR_LEFT), - WM_MODALKEY(WALK_MODAL_DIR_BACKWARD), WM_MODALKEY(WALK_MODAL_DIR_RIGHT), - WM_MODALKEY(WALK_MODAL_FAST_ENABLE), WM_MODALKEY(WALK_MODAL_SLOW_ENABLE), - WM_MODALKEY(WALK_MODAL_DIR_UP), WM_MODALKEY(WALK_MODAL_DIR_DOWN), - WM_MODALKEY(WALK_MODAL_TELEPORT), WM_MODALKEY(WALK_MODAL_JUMP), - WM_MODALKEY(WALK_MODAL_ACCELERATE), WM_MODALKEY(WALK_MODAL_DECELERATE)); + WM_modalkeymap_operator_items_to_string_buf( \ + op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p) + + BLI_snprintf(header, + sizeof(header), + IFACE_("%s: confirm, %s: cancel, " + "%s: gravity (%s), " + "%s|%s|%s|%s: move around, " + "%s: fast, %s: slow, " + "%s|%s: up and down, " + "%s: teleport, %s: jump, " + "%s: increase speed, %s: decrease speed"), + WM_MODALKEY(WALK_MODAL_CONFIRM), + WM_MODALKEY(WALK_MODAL_CANCEL), + WM_MODALKEY(WALK_MODAL_TOGGLE), + WM_bool_as_string(gravity), + WM_MODALKEY(WALK_MODAL_DIR_FORWARD), + WM_MODALKEY(WALK_MODAL_DIR_LEFT), + WM_MODALKEY(WALK_MODAL_DIR_BACKWARD), + WM_MODALKEY(WALK_MODAL_DIR_RIGHT), + WM_MODALKEY(WALK_MODAL_FAST_ENABLE), + WM_MODALKEY(WALK_MODAL_SLOW_ENABLE), + WM_MODALKEY(WALK_MODAL_DIR_UP), + WM_MODALKEY(WALK_MODAL_DIR_DOWN), + WM_MODALKEY(WALK_MODAL_TELEPORT), + WM_MODALKEY(WALK_MODAL_JUMP), + WM_MODALKEY(WALK_MODAL_ACCELERATE), + WM_MODALKEY(WALK_MODAL_DECELERATE)); #undef WM_MODALKEY - ED_workspace_status_text(C, header); + ED_workspace_status_text(C, header); } static void walk_navigation_mode_set(bContext *C, wmOperator *op, WalkInfo *walk, eWalkMethod mode) { - if (mode == WALK_MODE_FREE) { - walk->navigation_mode = WALK_MODE_FREE; - walk->gravity_state = WALK_GRAVITY_STATE_OFF; - } - else { /* WALK_MODE_GRAVITY */ - walk->navigation_mode = WALK_MODE_GRAVITY; - walk->gravity_state = WALK_GRAVITY_STATE_START; - } - - walk_update_header(C, op, walk); + if (mode == WALK_MODE_FREE) { + walk->navigation_mode = WALK_MODE_FREE; + walk->gravity_state = WALK_GRAVITY_STATE_OFF; + } + else { /* WALK_MODE_GRAVITY */ + walk->navigation_mode = WALK_MODE_GRAVITY; + walk->gravity_state = WALK_GRAVITY_STATE_START; + } + + walk_update_header(C, op, walk); } /** * \param r_distance: Distance to the hit point */ -static bool walk_floor_distance_get( - RegionView3D *rv3d, WalkInfo *walk, const float dvec[3], - float *r_distance) +static bool walk_floor_distance_get(RegionView3D *rv3d, + WalkInfo *walk, + const float dvec[3], + float *r_distance) { - float ray_normal[3] = {0, 0, -1}; /* down */ - float ray_start[3]; - float r_location[3]; - float r_normal_dummy[3]; - float dvec_tmp[3]; - bool ret; - - *r_distance = BVH_RAYCAST_DIST_MAX; - - copy_v3_v3(ray_start, rv3d->viewinv[3]); - - mul_v3_v3fl(dvec_tmp, dvec, walk->grid); - add_v3_v3(ray_start, dvec_tmp); - - ret = ED_transform_snap_object_project_ray( - walk->snap_context, - &(const struct SnapObjectParams){ - .snap_select = SNAP_ALL, - }, - ray_start, ray_normal, r_distance, - r_location, r_normal_dummy); - - /* artificially scale the distance to the scene size */ - *r_distance /= walk->grid; - return ret; + float ray_normal[3] = {0, 0, -1}; /* down */ + float ray_start[3]; + float r_location[3]; + float r_normal_dummy[3]; + float dvec_tmp[3]; + bool ret; + + *r_distance = BVH_RAYCAST_DIST_MAX; + + copy_v3_v3(ray_start, rv3d->viewinv[3]); + + mul_v3_v3fl(dvec_tmp, dvec, walk->grid); + add_v3_v3(ray_start, dvec_tmp); + + ret = ED_transform_snap_object_project_ray(walk->snap_context, + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + }, + ray_start, + ray_normal, + r_distance, + r_location, + r_normal_dummy); + + /* artificially scale the distance to the scene size */ + *r_distance /= walk->grid; + return ret; } /** @@ -402,46 +416,50 @@ static bool walk_floor_distance_get( * \param r_location: Location of the hit point * \param r_normal: Normal of the hit surface, transformed to always face the camera */ -static bool walk_ray_cast( - RegionView3D *rv3d, WalkInfo *walk, - float r_location[3], float r_normal[3], float *ray_distance) +static bool walk_ray_cast(RegionView3D *rv3d, + WalkInfo *walk, + float r_location[3], + float r_normal[3], + float *ray_distance) { - float ray_normal[3] = {0, 0, -1}; /* forward */ - float ray_start[3]; - bool ret; + float ray_normal[3] = {0, 0, -1}; /* forward */ + float ray_start[3]; + bool ret; - *ray_distance = BVH_RAYCAST_DIST_MAX; + *ray_distance = BVH_RAYCAST_DIST_MAX; - copy_v3_v3(ray_start, rv3d->viewinv[3]); + copy_v3_v3(ray_start, rv3d->viewinv[3]); - mul_mat3_m4_v3(rv3d->viewinv, ray_normal); + mul_mat3_m4_v3(rv3d->viewinv, ray_normal); - normalize_v3(ray_normal); + normalize_v3(ray_normal); - ret = ED_transform_snap_object_project_ray( - walk->snap_context, - &(const struct SnapObjectParams){ - .snap_select = SNAP_ALL, - }, - ray_start, ray_normal, NULL, - r_location, r_normal); + ret = ED_transform_snap_object_project_ray(walk->snap_context, + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + }, + ray_start, + ray_normal, + NULL, + r_location, + r_normal); - /* dot is positive if both rays are facing the same direction */ - if (dot_v3v3(ray_normal, r_normal) > 0) { - negate_v3(r_normal); - } + /* dot is positive if both rays are facing the same direction */ + if (dot_v3v3(ray_normal, r_normal) > 0) { + negate_v3(r_normal); + } - /* artificially scale the distance to the scene size */ - *ray_distance /= walk->grid; + /* artificially scale the distance to the scene size */ + *ray_distance /= walk->grid; - return ret; + return ret; } /* WalkInfo->state */ enum { - WALK_RUNNING = 0, - WALK_CANCEL = 1, - WALK_CONFIRM = 2, + WALK_RUNNING = 0, + WALK_CANCEL = 1, + WALK_CONFIRM = 2, }; /* keep the previous speed until user changes userpreferences */ @@ -450,484 +468,484 @@ static float userdef_speed = -1.f; static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) { - Main *bmain = CTX_data_main(C); - wmWindow *win = CTX_wm_window(C); + Main *bmain = CTX_data_main(C); + wmWindow *win = CTX_wm_window(C); - walk->rv3d = CTX_wm_region_view3d(C); - walk->v3d = CTX_wm_view3d(C); - walk->ar = CTX_wm_region(C); - walk->depsgraph = CTX_data_depsgraph(C); - walk->scene = CTX_data_scene(C); + walk->rv3d = CTX_wm_region_view3d(C); + walk->v3d = CTX_wm_view3d(C); + walk->ar = CTX_wm_region(C); + walk->depsgraph = CTX_data_depsgraph(C); + walk->scene = CTX_data_scene(C); #ifdef NDOF_WALK_DEBUG - puts("\n-- walk begin --"); + puts("\n-- walk begin --"); #endif - /* sanity check: for rare but possible case (if lib-linking the camera fails) */ - if ((walk->rv3d->persp == RV3D_CAMOB) && (walk->v3d->camera == NULL)) { - walk->rv3d->persp = RV3D_PERSP; - } - - if (walk->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(walk->v3d->camera)) { - BKE_report(op->reports, RPT_ERROR, "Cannot navigate a camera from an external library"); - return false; - } - - if (ED_view3d_offset_lock_check(walk->v3d, walk->rv3d)) { - BKE_report(op->reports, RPT_ERROR, "Cannot navigate when the view offset is locked"); - return false; - } - - if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->constraints.first) { - BKE_report(op->reports, RPT_ERROR, "Cannot navigate an object with constraints"); - return false; - } - - walk->state = WALK_RUNNING; - - if (fabsf(U.walk_navigation.walk_speed - userdef_speed) > 0.1f) { - base_speed = U.walk_navigation.walk_speed; - userdef_speed = U.walk_navigation.walk_speed; - } - - walk->speed = 0.0f; - walk->is_fast = false; - walk->is_slow = false; - walk->grid = (walk->scene->unit.system == USER_UNIT_NONE) ? 1.f : 1.f / walk->scene->unit.scale_length; - - /* user preference settings */ - walk->teleport.duration = U.walk_navigation.teleport_time; - walk->mouse_speed = U.walk_navigation.mouse_speed; - - if ((U.walk_navigation.flag & USER_WALK_GRAVITY)) { - walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY); - } - else { - walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); - } - - walk->view_height = U.walk_navigation.view_height; - walk->jump_height = U.walk_navigation.jump_height; - walk->speed = U.walk_navigation.walk_speed; - walk->speed_factor = U.walk_navigation.walk_speed_factor; - - walk->gravity_state = WALK_GRAVITY_STATE_OFF; - - if ((walk->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY)) { - walk->gravity = fabsf(walk->scene->physics_settings.gravity[2]); - } - else { - walk->gravity = 9.80668f; /* m/s2 */ - } - - walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0); + /* sanity check: for rare but possible case (if lib-linking the camera fails) */ + if ((walk->rv3d->persp == RV3D_CAMOB) && (walk->v3d->camera == NULL)) { + walk->rv3d->persp = RV3D_PERSP; + } + + if (walk->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(walk->v3d->camera)) { + BKE_report(op->reports, RPT_ERROR, "Cannot navigate a camera from an external library"); + return false; + } + + if (ED_view3d_offset_lock_check(walk->v3d, walk->rv3d)) { + BKE_report(op->reports, RPT_ERROR, "Cannot navigate when the view offset is locked"); + return false; + } + + if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->constraints.first) { + BKE_report(op->reports, RPT_ERROR, "Cannot navigate an object with constraints"); + return false; + } + + walk->state = WALK_RUNNING; + + if (fabsf(U.walk_navigation.walk_speed - userdef_speed) > 0.1f) { + base_speed = U.walk_navigation.walk_speed; + userdef_speed = U.walk_navigation.walk_speed; + } + + walk->speed = 0.0f; + walk->is_fast = false; + walk->is_slow = false; + walk->grid = (walk->scene->unit.system == USER_UNIT_NONE) ? 1.f : + 1.f / walk->scene->unit.scale_length; + + /* user preference settings */ + walk->teleport.duration = U.walk_navigation.teleport_time; + walk->mouse_speed = U.walk_navigation.mouse_speed; + + if ((U.walk_navigation.flag & USER_WALK_GRAVITY)) { + walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY); + } + else { + walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); + } + + walk->view_height = U.walk_navigation.view_height; + walk->jump_height = U.walk_navigation.jump_height; + walk->speed = U.walk_navigation.walk_speed; + walk->speed_factor = U.walk_navigation.walk_speed_factor; + + walk->gravity_state = WALK_GRAVITY_STATE_OFF; + + if ((walk->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY)) { + walk->gravity = fabsf(walk->scene->physics_settings.gravity[2]); + } + else { + walk->gravity = 9.80668f; /* m/s2 */ + } + + walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0); #ifdef USE_TABLET_SUPPORT - walk->is_cursor_first = true; + walk->is_cursor_first = true; - walk->is_cursor_absolute = false; + walk->is_cursor_absolute = false; #endif - walk->active_directions = 0; + walk->active_directions = 0; #ifdef NDOF_WALK_DRAW_TOOMUCH - walk->redraw = 1; + walk->redraw = 1; #endif - zero_v3(walk->dvec_prev); + zero_v3(walk->dvec_prev); - walk->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f); + walk->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f); #ifdef WITH_INPUT_NDOF - walk->ndof = NULL; + walk->ndof = NULL; #endif - walk->time_lastdraw = PIL_check_seconds_timer(); + walk->time_lastdraw = PIL_check_seconds_timer(); - walk->draw_handle_pixel = ED_region_draw_cb_activate(walk->ar->type, drawWalkPixel, walk, REGION_DRAW_POST_PIXEL); + walk->draw_handle_pixel = ED_region_draw_cb_activate( + walk->ar->type, drawWalkPixel, walk, REGION_DRAW_POST_PIXEL); - walk->rv3d->rflag |= RV3D_NAVIGATING; + walk->rv3d->rflag |= RV3D_NAVIGATING; - walk->snap_context = ED_transform_snap_object_context_create_view3d( - bmain, walk->scene, CTX_data_depsgraph(C), 0, - walk->ar, walk->v3d); + walk->snap_context = ED_transform_snap_object_context_create_view3d( + bmain, walk->scene, CTX_data_depsgraph(C), 0, walk->ar, walk->v3d); - walk->v3d_camera_control = ED_view3d_cameracontrol_acquire( - walk->depsgraph, walk->scene, walk->v3d, walk->rv3d, - (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0); + walk->v3d_camera_control = ED_view3d_cameracontrol_acquire( + walk->depsgraph, + walk->scene, + walk->v3d, + walk->rv3d, + (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0); - /* center the mouse */ - walk->center_mval[0] = walk->ar->winx * 0.5f; - walk->center_mval[1] = walk->ar->winy * 0.5f; + /* center the mouse */ + walk->center_mval[0] = walk->ar->winx * 0.5f; + walk->center_mval[1] = walk->ar->winy * 0.5f; #ifdef USE_PIXELSIZE_NATIVE_SUPPORT - walk->center_mval[0] += walk->ar->winrct.xmin; - walk->center_mval[1] += walk->ar->winrct.ymin; + walk->center_mval[0] += walk->ar->winrct.xmin; + walk->center_mval[1] += walk->ar->winrct.ymin; - WM_cursor_compatible_xy(win, &walk->center_mval[0], &walk->center_mval[1]); + WM_cursor_compatible_xy(win, &walk->center_mval[0], &walk->center_mval[1]); - walk->center_mval[0] -= walk->ar->winrct.xmin; - walk->center_mval[1] -= walk->ar->winrct.ymin; + walk->center_mval[0] -= walk->ar->winrct.xmin; + walk->center_mval[1] -= walk->ar->winrct.ymin; #endif - copy_v2_v2_int(walk->prev_mval, walk->center_mval); + copy_v2_v2_int(walk->prev_mval, walk->center_mval); - WM_cursor_warp(win, - walk->ar->winrct.xmin + walk->center_mval[0], - walk->ar->winrct.ymin + walk->center_mval[1]); + WM_cursor_warp(win, + walk->ar->winrct.xmin + walk->center_mval[0], + walk->ar->winrct.ymin + walk->center_mval[1]); - /* remove the mouse cursor temporarily */ - WM_cursor_modal_set(win, CURSOR_NONE); + /* remove the mouse cursor temporarily */ + WM_cursor_modal_set(win, CURSOR_NONE); - return 1; + return 1; } static int walkEnd(bContext *C, WalkInfo *walk) { - wmWindow *win; - RegionView3D *rv3d; + wmWindow *win; + RegionView3D *rv3d; - if (walk->state == WALK_RUNNING) { - return OPERATOR_RUNNING_MODAL; - } + if (walk->state == WALK_RUNNING) { + return OPERATOR_RUNNING_MODAL; + } #ifdef NDOF_WALK_DEBUG - puts("\n-- walk end --"); + puts("\n-- walk end --"); #endif - win = CTX_wm_window(C); - rv3d = walk->rv3d; + win = CTX_wm_window(C); + rv3d = walk->rv3d; - WM_event_remove_timer(CTX_wm_manager(C), win, walk->timer); + WM_event_remove_timer(CTX_wm_manager(C), win, walk->timer); - ED_region_draw_cb_exit(walk->ar->type, walk->draw_handle_pixel); + ED_region_draw_cb_exit(walk->ar->type, walk->draw_handle_pixel); - ED_transform_snap_object_context_destroy(walk->snap_context); + ED_transform_snap_object_context_destroy(walk->snap_context); - ED_view3d_cameracontrol_release(walk->v3d_camera_control, walk->state == WALK_CANCEL); + ED_view3d_cameracontrol_release(walk->v3d_camera_control, walk->state == WALK_CANCEL); - rv3d->rflag &= ~RV3D_NAVIGATING; + rv3d->rflag &= ~RV3D_NAVIGATING; #ifdef WITH_INPUT_NDOF - if (walk->ndof) { - MEM_freeN(walk->ndof); - } + if (walk->ndof) { + MEM_freeN(walk->ndof); + } #endif - /* restore the cursor */ - WM_cursor_modal_restore(win); + /* restore the cursor */ + WM_cursor_modal_restore(win); #ifdef USE_TABLET_SUPPORT - if (walk->is_cursor_absolute == false) + if (walk->is_cursor_absolute == false) #endif - { - /* center the mouse */ - WM_cursor_warp( - win, - walk->ar->winrct.xmin + walk->center_mval[0], - walk->ar->winrct.ymin + walk->center_mval[1]); - } - - if (walk->state == WALK_CONFIRM) { - MEM_freeN(walk); - return OPERATOR_FINISHED; - } - - MEM_freeN(walk); - return OPERATOR_CANCELLED; + { + /* center the mouse */ + WM_cursor_warp(win, + walk->ar->winrct.xmin + walk->center_mval[0], + walk->ar->winrct.ymin + walk->center_mval[1]); + } + + if (walk->state == WALK_CONFIRM) { + MEM_freeN(walk); + return OPERATOR_FINISHED; + } + + MEM_freeN(walk); + return OPERATOR_CANCELLED; } static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent *event) { - if (event->type == TIMER && event->customdata == walk->timer) { - walk->redraw = true; - } - else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { + if (event->type == TIMER && event->customdata == walk->timer) { + walk->redraw = true; + } + else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { #ifdef USE_TABLET_SUPPORT - if (walk->is_cursor_first) { - /* wait until we get the 'warp' event */ - if ((walk->center_mval[0] == event->mval[0]) && - (walk->center_mval[1] == event->mval[1])) - { - walk->is_cursor_first = false; - } - else { - /* note, its possible the system isn't giving us the warp event - * ideally we shouldn't have to worry about this, see: T45361 */ - wmWindow *win = CTX_wm_window(C); - WM_cursor_warp(win, - walk->ar->winrct.xmin + walk->center_mval[0], - walk->ar->winrct.ymin + walk->center_mval[1]); - } - return; - } - - if ((walk->is_cursor_absolute == false) && event->is_motion_absolute) { - walk->is_cursor_absolute = true; - copy_v2_v2_int(walk->prev_mval, event->mval); - copy_v2_v2_int(walk->center_mval, event->mval); - /* without this we can't turn 180d */ - CLAMP_MIN(walk->mouse_speed, 4.0f); - } -#endif /* USE_TABLET_SUPPORT */ - - - walk->moffset[0] += event->mval[0] - walk->prev_mval[0]; - walk->moffset[1] += event->mval[1] - walk->prev_mval[1]; - - copy_v2_v2_int(walk->prev_mval, event->mval); - - if ((walk->center_mval[0] != event->mval[0]) || - (walk->center_mval[1] != event->mval[1])) - { - walk->redraw = true; + if (walk->is_cursor_first) { + /* wait until we get the 'warp' event */ + if ((walk->center_mval[0] == event->mval[0]) && (walk->center_mval[1] == event->mval[1])) { + walk->is_cursor_first = false; + } + else { + /* note, its possible the system isn't giving us the warp event + * ideally we shouldn't have to worry about this, see: T45361 */ + wmWindow *win = CTX_wm_window(C); + WM_cursor_warp(win, + walk->ar->winrct.xmin + walk->center_mval[0], + walk->ar->winrct.ymin + walk->center_mval[1]); + } + return; + } + + if ((walk->is_cursor_absolute == false) && event->is_motion_absolute) { + walk->is_cursor_absolute = true; + copy_v2_v2_int(walk->prev_mval, event->mval); + copy_v2_v2_int(walk->center_mval, event->mval); + /* without this we can't turn 180d */ + CLAMP_MIN(walk->mouse_speed, 4.0f); + } +#endif /* USE_TABLET_SUPPORT */ + + walk->moffset[0] += event->mval[0] - walk->prev_mval[0]; + walk->moffset[1] += event->mval[1] - walk->prev_mval[1]; + + copy_v2_v2_int(walk->prev_mval, event->mval); + + if ((walk->center_mval[0] != event->mval[0]) || (walk->center_mval[1] != event->mval[1])) { + walk->redraw = true; #ifdef USE_TABLET_SUPPORT - if (walk->is_cursor_absolute) { - /* pass */ - } - else + if (walk->is_cursor_absolute) { + /* pass */ + } + else #endif - if (WM_event_is_last_mousemove(event)) { - wmWindow *win = CTX_wm_window(C); + if (WM_event_is_last_mousemove(event)) { + wmWindow *win = CTX_wm_window(C); #ifdef __APPLE__ - if ((abs(walk->prev_mval[0] - walk->center_mval[0]) > walk->center_mval[0] / 2) || - (abs(walk->prev_mval[1] - walk->center_mval[1]) > walk->center_mval[1] / 2)) + if ((abs(walk->prev_mval[0] - walk->center_mval[0]) > walk->center_mval[0] / 2) || + (abs(walk->prev_mval[1] - walk->center_mval[1]) > walk->center_mval[1] / 2)) #endif - { - WM_cursor_warp(win, - walk->ar->winrct.xmin + walk->center_mval[0], - walk->ar->winrct.ymin + walk->center_mval[1]); - copy_v2_v2_int(walk->prev_mval, walk->center_mval); - } - } - } - } + { + WM_cursor_warp(win, + walk->ar->winrct.xmin + walk->center_mval[0], + walk->ar->winrct.ymin + walk->center_mval[1]); + copy_v2_v2_int(walk->prev_mval, walk->center_mval); + } + } + } + } #ifdef WITH_INPUT_NDOF - else if (event->type == NDOF_MOTION) { - /* do these automagically get delivered? yes. */ - // puts("ndof motion detected in walk mode!"); - // static const char *tag_name = "3D mouse position"; - - const wmNDOFMotionData *incoming_ndof = event->customdata; - switch (incoming_ndof->progress) { - case P_STARTING: - /* start keeping track of 3D mouse position */ + else if (event->type == NDOF_MOTION) { + /* do these automagically get delivered? yes. */ + // puts("ndof motion detected in walk mode!"); + // static const char *tag_name = "3D mouse position"; + + const wmNDOFMotionData *incoming_ndof = event->customdata; + switch (incoming_ndof->progress) { + case P_STARTING: + /* start keeping track of 3D mouse position */ # ifdef NDOF_WALK_DEBUG - puts("start keeping track of 3D mouse position"); + puts("start keeping track of 3D mouse position"); # endif - /* fall-through */ - case P_IN_PROGRESS: - /* update 3D mouse position */ + /* fall-through */ + case P_IN_PROGRESS: + /* update 3D mouse position */ # ifdef NDOF_WALK_DEBUG - putchar('.'); fflush(stdout); + putchar('.'); + fflush(stdout); # endif - if (walk->ndof == NULL) { - // walk->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); - walk->ndof = MEM_dupallocN(incoming_ndof); - // walk->ndof = malloc(sizeof(wmNDOFMotionData)); - } - else { - memcpy(walk->ndof, incoming_ndof, sizeof(wmNDOFMotionData)); - } - break; - case P_FINISHING: - /* stop keeping track of 3D mouse position */ + if (walk->ndof == NULL) { + // walk->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); + walk->ndof = MEM_dupallocN(incoming_ndof); + // walk->ndof = malloc(sizeof(wmNDOFMotionData)); + } + else { + memcpy(walk->ndof, incoming_ndof, sizeof(wmNDOFMotionData)); + } + break; + case P_FINISHING: + /* stop keeping track of 3D mouse position */ # ifdef NDOF_WALK_DEBUG - puts("stop keeping track of 3D mouse position"); + puts("stop keeping track of 3D mouse position"); # endif - if (walk->ndof) { - MEM_freeN(walk->ndof); - // free(walk->ndof); - walk->ndof = NULL; - } - - /* update the time else the view will jump when 2D mouse/timer resume */ - walk->time_lastdraw = PIL_check_seconds_timer(); - - break; - default: - break; /* should always be one of the above 3 */ - } - } + if (walk->ndof) { + MEM_freeN(walk->ndof); + // free(walk->ndof); + walk->ndof = NULL; + } + + /* update the time else the view will jump when 2D mouse/timer resume */ + walk->time_lastdraw = PIL_check_seconds_timer(); + + break; + default: + break; /* should always be one of the above 3 */ + } + } #endif /* WITH_INPUT_NDOF */ - /* handle modal keymap first */ - else if (event->type == EVT_MODAL_MAP) { - switch (event->val) { - case WALK_MODAL_CANCEL: - walk->state = WALK_CANCEL; - break; - case WALK_MODAL_CONFIRM: - walk->state = WALK_CONFIRM; - break; - - case WALK_MODAL_ACCELERATE: - base_speed *= 1.0f + (walk->is_slow ? 0.01f : 0.1f); - break; - case WALK_MODAL_DECELERATE: - base_speed /= 1.0f + (walk->is_slow ? 0.01f : 0.1f); - break; - - /* implement WASD keys */ - case WALK_MODAL_DIR_FORWARD: - walk->active_directions |= WALK_BIT_FORWARD; - break; - case WALK_MODAL_DIR_BACKWARD: - walk->active_directions |= WALK_BIT_BACKWARD; - break; - case WALK_MODAL_DIR_LEFT: - walk->active_directions |= WALK_BIT_LEFT; - break; - case WALK_MODAL_DIR_RIGHT: - walk->active_directions |= WALK_BIT_RIGHT; - break; - case WALK_MODAL_DIR_UP: - walk->active_directions |= WALK_BIT_UP; - break; - case WALK_MODAL_DIR_DOWN: - walk->active_directions |= WALK_BIT_DOWN; - break; - - case WALK_MODAL_DIR_FORWARD_STOP: - walk->active_directions &= ~WALK_BIT_FORWARD; - break; - case WALK_MODAL_DIR_BACKWARD_STOP: - walk->active_directions &= ~WALK_BIT_BACKWARD; - break; - case WALK_MODAL_DIR_LEFT_STOP: - walk->active_directions &= ~WALK_BIT_LEFT; - break; - case WALK_MODAL_DIR_RIGHT_STOP: - walk->active_directions &= ~WALK_BIT_RIGHT; - break; - case WALK_MODAL_DIR_UP_STOP: - walk->active_directions &= ~WALK_BIT_UP; - break; - case WALK_MODAL_DIR_DOWN_STOP: - walk->active_directions &= ~WALK_BIT_DOWN; - break; - - case WALK_MODAL_FAST_ENABLE: - walk->is_fast = true; - break; - case WALK_MODAL_FAST_DISABLE: - walk->is_fast = false; - break; - case WALK_MODAL_SLOW_ENABLE: - walk->is_slow = true; - break; - case WALK_MODAL_SLOW_DISABLE: - walk->is_slow = false; - break; + /* handle modal keymap first */ + else if (event->type == EVT_MODAL_MAP) { + switch (event->val) { + case WALK_MODAL_CANCEL: + walk->state = WALK_CANCEL; + break; + case WALK_MODAL_CONFIRM: + walk->state = WALK_CONFIRM; + break; + + case WALK_MODAL_ACCELERATE: + base_speed *= 1.0f + (walk->is_slow ? 0.01f : 0.1f); + break; + case WALK_MODAL_DECELERATE: + base_speed /= 1.0f + (walk->is_slow ? 0.01f : 0.1f); + break; + + /* implement WASD keys */ + case WALK_MODAL_DIR_FORWARD: + walk->active_directions |= WALK_BIT_FORWARD; + break; + case WALK_MODAL_DIR_BACKWARD: + walk->active_directions |= WALK_BIT_BACKWARD; + break; + case WALK_MODAL_DIR_LEFT: + walk->active_directions |= WALK_BIT_LEFT; + break; + case WALK_MODAL_DIR_RIGHT: + walk->active_directions |= WALK_BIT_RIGHT; + break; + case WALK_MODAL_DIR_UP: + walk->active_directions |= WALK_BIT_UP; + break; + case WALK_MODAL_DIR_DOWN: + walk->active_directions |= WALK_BIT_DOWN; + break; + + case WALK_MODAL_DIR_FORWARD_STOP: + walk->active_directions &= ~WALK_BIT_FORWARD; + break; + case WALK_MODAL_DIR_BACKWARD_STOP: + walk->active_directions &= ~WALK_BIT_BACKWARD; + break; + case WALK_MODAL_DIR_LEFT_STOP: + walk->active_directions &= ~WALK_BIT_LEFT; + break; + case WALK_MODAL_DIR_RIGHT_STOP: + walk->active_directions &= ~WALK_BIT_RIGHT; + break; + case WALK_MODAL_DIR_UP_STOP: + walk->active_directions &= ~WALK_BIT_UP; + break; + case WALK_MODAL_DIR_DOWN_STOP: + walk->active_directions &= ~WALK_BIT_DOWN; + break; + + case WALK_MODAL_FAST_ENABLE: + walk->is_fast = true; + break; + case WALK_MODAL_FAST_DISABLE: + walk->is_fast = false; + break; + case WALK_MODAL_SLOW_ENABLE: + walk->is_slow = true; + break; + case WALK_MODAL_SLOW_DISABLE: + walk->is_slow = false; + break; #define JUMP_SPEED_MIN 1.0f #define JUMP_TIME_MAX 0.2f /* s */ #define JUMP_SPEED_MAX sqrtf(2.0f * walk->gravity * walk->jump_height) - case WALK_MODAL_JUMP_STOP: - if (walk->gravity_state == WALK_GRAVITY_STATE_JUMP) { - float t; - - /* delta time */ - t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); - - /* reduce the veolocity, if JUMP wasn't hold for long enough */ - t = min_ff(t, JUMP_TIME_MAX); - walk->speed_jump = JUMP_SPEED_MIN + t * (JUMP_SPEED_MAX - JUMP_SPEED_MIN) / JUMP_TIME_MAX; - - /* when jumping, duration is how long it takes before we start going down */ - walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump); - - /* no more increase of jump speed */ - walk->gravity_state = WALK_GRAVITY_STATE_ON; - } - break; - case WALK_MODAL_JUMP: - if ((walk->navigation_mode == WALK_MODE_GRAVITY) && - (walk->gravity_state == WALK_GRAVITY_STATE_OFF) && - (walk->teleport.state == WALK_TELEPORT_STATE_OFF)) - { - /* no need to check for ground, - * walk->gravity wouldn't be off - * if we were over a hole */ - walk->gravity_state = WALK_GRAVITY_STATE_JUMP; - walk->speed_jump = JUMP_SPEED_MAX; - - walk->teleport.initial_time = PIL_check_seconds_timer(); - copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]); - - /* using previous vec because WASD keys are not called when SPACE is */ - copy_v2_v2(walk->teleport.direction, walk->dvec_prev); - - /* when jumping, duration is how long it takes before we start going down */ - walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump); - } - - break; - - case WALK_MODAL_TELEPORT: - { - float loc[3], nor[3]; - float distance; - bool ret = walk_ray_cast(walk->rv3d, walk, loc, nor, &distance); - - /* in case we are teleporting middle way from a jump */ - walk->speed_jump = 0.0f; - - if (ret) { - WalkTeleport *teleport = &walk->teleport; - teleport->state = WALK_TELEPORT_STATE_ON; - teleport->initial_time = PIL_check_seconds_timer(); - teleport->duration = U.walk_navigation.teleport_time; - - teleport->navigation_mode = walk->navigation_mode; - walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); - - copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]); - - /* stop the camera from a distance (camera height) */ - normalize_v3_length(nor, walk->view_height); - add_v3_v3(loc, nor); - - sub_v3_v3v3(teleport->direction, loc, teleport->origin); - } - else { - walk->teleport.state = WALK_TELEPORT_STATE_OFF; - } - break; - } + case WALK_MODAL_JUMP_STOP: + if (walk->gravity_state == WALK_GRAVITY_STATE_JUMP) { + float t; + + /* delta time */ + t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); + + /* reduce the veolocity, if JUMP wasn't hold for long enough */ + t = min_ff(t, JUMP_TIME_MAX); + walk->speed_jump = JUMP_SPEED_MIN + + t * (JUMP_SPEED_MAX - JUMP_SPEED_MIN) / JUMP_TIME_MAX; + + /* when jumping, duration is how long it takes before we start going down */ + walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump); + + /* no more increase of jump speed */ + walk->gravity_state = WALK_GRAVITY_STATE_ON; + } + break; + case WALK_MODAL_JUMP: + if ((walk->navigation_mode == WALK_MODE_GRAVITY) && + (walk->gravity_state == WALK_GRAVITY_STATE_OFF) && + (walk->teleport.state == WALK_TELEPORT_STATE_OFF)) { + /* no need to check for ground, + * walk->gravity wouldn't be off + * if we were over a hole */ + walk->gravity_state = WALK_GRAVITY_STATE_JUMP; + walk->speed_jump = JUMP_SPEED_MAX; + + walk->teleport.initial_time = PIL_check_seconds_timer(); + copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]); + + /* using previous vec because WASD keys are not called when SPACE is */ + copy_v2_v2(walk->teleport.direction, walk->dvec_prev); + + /* when jumping, duration is how long it takes before we start going down */ + walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump); + } + + break; + + case WALK_MODAL_TELEPORT: { + float loc[3], nor[3]; + float distance; + bool ret = walk_ray_cast(walk->rv3d, walk, loc, nor, &distance); + + /* in case we are teleporting middle way from a jump */ + walk->speed_jump = 0.0f; + + if (ret) { + WalkTeleport *teleport = &walk->teleport; + teleport->state = WALK_TELEPORT_STATE_ON; + teleport->initial_time = PIL_check_seconds_timer(); + teleport->duration = U.walk_navigation.teleport_time; + + teleport->navigation_mode = walk->navigation_mode; + walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); + + copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]); + + /* stop the camera from a distance (camera height) */ + normalize_v3_length(nor, walk->view_height); + add_v3_v3(loc, nor); + + sub_v3_v3v3(teleport->direction, loc, teleport->origin); + } + else { + walk->teleport.state = WALK_TELEPORT_STATE_OFF; + } + break; + } #undef JUMP_SPEED_MAX #undef JUMP_TIME_MAX #undef JUMP_SPEED_MIN - case WALK_MODAL_TOGGLE: - if (walk->navigation_mode == WALK_MODE_GRAVITY) { - walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); - } - else { /* WALK_MODE_FREE */ - walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY); - } - break; - } - } + case WALK_MODAL_TOGGLE: + if (walk->navigation_mode == WALK_MODE_GRAVITY) { + walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); + } + else { /* WALK_MODE_FREE */ + walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY); + } + break; + } + } } -static void walkMoveCamera(bContext *C, WalkInfo *walk, - const bool do_rotate, const bool do_translate) +static void walkMoveCamera(bContext *C, + WalkInfo *walk, + const bool do_rotate, + const bool do_translate) { - ED_view3d_cameracontrol_update(walk->v3d_camera_control, true, C, do_rotate, do_translate); + ED_view3d_cameracontrol_update(walk->v3d_camera_control, true, C, do_rotate, do_translate); } static float getFreeFallDistance(const float gravity, const float time) { - return gravity * (time * time) * 0.5f; + return gravity * (time * time) * 0.5f; } static float getVelocityZeroTime(const float gravity, const float velocity) { - return velocity / gravity; + return velocity / gravity; } static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk) @@ -938,361 +956,347 @@ static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk) #define WALK_MOVE_SPEED base_speed #define WALK_BOOST_FACTOR ((void)0, walk->speed_factor) - /* walk mode - Ctrl+Shift+F - * a walk loop where the user can move move the view as if they are in a walk game - */ - RegionView3D *rv3d = walk->rv3d; - ARegion *ar = walk->ar; + /* walk mode - Ctrl+Shift+F + * a walk loop where the user can move move the view as if they are in a walk game + */ + RegionView3D *rv3d = walk->rv3d; + ARegion *ar = walk->ar; - /* 3x3 copy of the view matrix so we can move along the view axis */ - float mat[3][3]; - /* this is the direction that's added to the view offset per redraw */ - float dvec[3] = {0.0f, 0.0f, 0.0f}; + /* 3x3 copy of the view matrix so we can move along the view axis */ + float mat[3][3]; + /* this is the direction that's added to the view offset per redraw */ + float dvec[3] = {0.0f, 0.0f, 0.0f}; - int moffset[2]; /* mouse offset from the views center */ - float tmp_quat[4]; /* used for rotating the view */ + int moffset[2]; /* mouse offset from the views center */ + float tmp_quat[4]; /* used for rotating the view */ #ifdef NDOF_WALK_DEBUG - { - static uint iteration = 1; - printf("walk timer %d\n", iteration++); - } + { + static uint iteration = 1; + printf("walk timer %d\n", iteration++); + } #endif - { - /* mouse offset from the center */ - copy_v2_v2_int(moffset, walk->moffset); - - /* apply moffset so we can re-accumulate */ - walk->moffset[0] = 0; - walk->moffset[1] = 0; - - /* revert mouse */ - if (walk->is_reversed) { - moffset[1] = -moffset[1]; - } - - /* Should we redraw? */ - if ((walk->active_directions) || - moffset[0] || moffset[1] || - walk->teleport.state == WALK_TELEPORT_STATE_ON || - walk->gravity_state != WALK_GRAVITY_STATE_OFF) - { - float dvec_tmp[3]; - - /* time how fast it takes for us to redraw, - * this is so simple scenes don't walk too fast */ - double time_current; - float time_redraw; + { + /* mouse offset from the center */ + copy_v2_v2_int(moffset, walk->moffset); + + /* apply moffset so we can re-accumulate */ + walk->moffset[0] = 0; + walk->moffset[1] = 0; + + /* revert mouse */ + if (walk->is_reversed) { + moffset[1] = -moffset[1]; + } + + /* Should we redraw? */ + if ((walk->active_directions) || moffset[0] || moffset[1] || + walk->teleport.state == WALK_TELEPORT_STATE_ON || + walk->gravity_state != WALK_GRAVITY_STATE_OFF) { + float dvec_tmp[3]; + + /* time how fast it takes for us to redraw, + * this is so simple scenes don't walk too fast */ + double time_current; + float time_redraw; #ifdef NDOF_WALK_DRAW_TOOMUCH - walk->redraw = 1; + walk->redraw = 1; #endif - time_current = PIL_check_seconds_timer(); - time_redraw = (float)(time_current - walk->time_lastdraw); - - walk->time_lastdraw = time_current; - - /* base speed in m/s */ - walk->speed = WALK_MOVE_SPEED; - - if (walk->is_fast) { - walk->speed *= WALK_BOOST_FACTOR; - } - else if (walk->is_slow) { - walk->speed *= 1.0f / WALK_BOOST_FACTOR; - } - - copy_m3_m4(mat, rv3d->viewinv); + time_current = PIL_check_seconds_timer(); + time_redraw = (float)(time_current - walk->time_lastdraw); - { - /* rotate about the X axis- look up/down */ - if (moffset[1]) { - float upvec[3]; - float angle; - float y; + walk->time_lastdraw = time_current; - /* relative offset */ - y = (float) moffset[1] / ar->winy; + /* base speed in m/s */ + walk->speed = WALK_MOVE_SPEED; - /* speed factor */ - y *= WALK_ROTATE_FAC; + if (walk->is_fast) { + walk->speed *= WALK_BOOST_FACTOR; + } + else if (walk->is_slow) { + walk->speed *= 1.0f / WALK_BOOST_FACTOR; + } - /* user adjustment factor */ - y *= walk->mouse_speed; + copy_m3_m4(mat, rv3d->viewinv); - /* clamp the angle limits */ - /* it ranges from 90.0f to -90.0f */ - angle = -asinf(rv3d->viewmat[2][2]); + { + /* rotate about the X axis- look up/down */ + if (moffset[1]) { + float upvec[3]; + float angle; + float y; - if (angle > WALK_TOP_LIMIT && y > 0.0f) { - y = 0.0f; - } - else if (angle < WALK_BOTTOM_LIMIT && y < 0.0f) { - y = 0.0f; - } + /* relative offset */ + y = (float)moffset[1] / ar->winy; - copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); - mul_m3_v3(mat, upvec); - /* Rotate about the relative up vec */ - axis_angle_to_quat(tmp_quat, upvec, -y); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); - } + /* speed factor */ + y *= WALK_ROTATE_FAC; - /* rotate about the Y axis- look left/right */ - if (moffset[0]) { - float upvec[3]; - float x; + /* user adjustment factor */ + y *= walk->mouse_speed; - /* if we're upside down invert the moffset */ - copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f); - mul_m3_v3(mat, upvec); + /* clamp the angle limits */ + /* it ranges from 90.0f to -90.0f */ + angle = -asinf(rv3d->viewmat[2][2]); - if (upvec[2] < 0.0f) { - moffset[0] = -moffset[0]; - } + if (angle > WALK_TOP_LIMIT && y > 0.0f) { + y = 0.0f; + } + else if (angle < WALK_BOTTOM_LIMIT && y < 0.0f) { + y = 0.0f; + } - /* relative offset */ - x = (float) moffset[0] / ar->winx; + copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); + mul_m3_v3(mat, upvec); + /* Rotate about the relative up vec */ + axis_angle_to_quat(tmp_quat, upvec, -y); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); + } - /* speed factor */ - x *= WALK_ROTATE_FAC; + /* rotate about the Y axis- look left/right */ + if (moffset[0]) { + float upvec[3]; + float x; - /* user adjustment factor */ - x *= walk->mouse_speed; + /* if we're upside down invert the moffset */ + copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f); + mul_m3_v3(mat, upvec); - /* Rotate about the relative up vec */ - axis_angle_to_quat_single(tmp_quat, 'Z', x); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); - } - } + if (upvec[2] < 0.0f) { + moffset[0] = -moffset[0]; + } - /* WASD - 'move' translation code */ - if ((walk->active_directions) && - (walk->gravity_state == WALK_GRAVITY_STATE_OFF)) - { + /* relative offset */ + x = (float)moffset[0] / ar->winx; - short direction; - zero_v3(dvec); + /* speed factor */ + x *= WALK_ROTATE_FAC; - if ((walk->active_directions & WALK_BIT_FORWARD) || - (walk->active_directions & WALK_BIT_BACKWARD)) - { + /* user adjustment factor */ + x *= walk->mouse_speed; - direction = 0; + /* Rotate about the relative up vec */ + axis_angle_to_quat_single(tmp_quat, 'Z', x); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); + } + } - if ((walk->active_directions & WALK_BIT_FORWARD)) { - direction += 1; - } + /* WASD - 'move' translation code */ + if ((walk->active_directions) && (walk->gravity_state == WALK_GRAVITY_STATE_OFF)) { - if ((walk->active_directions & WALK_BIT_BACKWARD)) { - direction -= 1; - } + short direction; + zero_v3(dvec); - copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction); - mul_m3_v3(mat, dvec_tmp); + if ((walk->active_directions & WALK_BIT_FORWARD) || + (walk->active_directions & WALK_BIT_BACKWARD)) { - if (walk->navigation_mode == WALK_MODE_GRAVITY) { - dvec_tmp[2] = 0.0f; - } + direction = 0; - normalize_v3(dvec_tmp); - add_v3_v3(dvec, dvec_tmp); + if ((walk->active_directions & WALK_BIT_FORWARD)) { + direction += 1; + } - } + if ((walk->active_directions & WALK_BIT_BACKWARD)) { + direction -= 1; + } - if ((walk->active_directions & WALK_BIT_LEFT) || - (walk->active_directions & WALK_BIT_RIGHT)) - { + copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction); + mul_m3_v3(mat, dvec_tmp); - direction = 0; + if (walk->navigation_mode == WALK_MODE_GRAVITY) { + dvec_tmp[2] = 0.0f; + } - if ((walk->active_directions & WALK_BIT_LEFT)) { - direction += 1; - } + normalize_v3(dvec_tmp); + add_v3_v3(dvec, dvec_tmp); + } - if ((walk->active_directions & WALK_BIT_RIGHT)) { - direction -= 1; - } + if ((walk->active_directions & WALK_BIT_LEFT) || + (walk->active_directions & WALK_BIT_RIGHT)) { - dvec_tmp[0] = direction * rv3d->viewinv[0][0]; - dvec_tmp[1] = direction * rv3d->viewinv[0][1]; - dvec_tmp[2] = 0.0f; + direction = 0; - normalize_v3(dvec_tmp); - add_v3_v3(dvec, dvec_tmp); + if ((walk->active_directions & WALK_BIT_LEFT)) { + direction += 1; + } - } + if ((walk->active_directions & WALK_BIT_RIGHT)) { + direction -= 1; + } - if ((walk->active_directions & WALK_BIT_UP) || - (walk->active_directions & WALK_BIT_DOWN)) - { + dvec_tmp[0] = direction * rv3d->viewinv[0][0]; + dvec_tmp[1] = direction * rv3d->viewinv[0][1]; + dvec_tmp[2] = 0.0f; - if (walk->navigation_mode == WALK_MODE_FREE) { + normalize_v3(dvec_tmp); + add_v3_v3(dvec, dvec_tmp); + } - direction = 0; - - if ((walk->active_directions & WALK_BIT_UP)) { - direction -= 1; - } - - if ((walk->active_directions & WALK_BIT_DOWN)) { - direction = 1; - } - - copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction); - add_v3_v3(dvec, dvec_tmp); - } - } - - /* apply movement */ - mul_v3_fl(dvec, walk->speed * time_redraw); - } - - /* stick to the floor */ - if (walk->navigation_mode == WALK_MODE_GRAVITY && - ELEM(walk->gravity_state, - WALK_GRAVITY_STATE_OFF, - WALK_GRAVITY_STATE_START)) - { - - bool ret; - float ray_distance; - float difference = -100.0f; - float fall_distance; - - ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance); - - if (ret) { - difference = walk->view_height - ray_distance; - } - - /* the distance we would fall naturally smoothly enough that we - * can manually drop the object without activating gravity */ - fall_distance = time_redraw * walk->speed * WALK_BOOST_FACTOR; - - if (fabsf(difference) < fall_distance) { - /* slope/stairs */ - dvec[2] -= difference; - - /* in case we switched from FREE to GRAVITY too close to the ground */ - if (walk->gravity_state == WALK_GRAVITY_STATE_START) { - walk->gravity_state = WALK_GRAVITY_STATE_OFF; - } - } - else { - /* hijack the teleport variables */ - walk->teleport.initial_time = PIL_check_seconds_timer(); - walk->gravity_state = WALK_GRAVITY_STATE_ON; - walk->teleport.duration = 0.0f; - - copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]); - copy_v2_v2(walk->teleport.direction, dvec); - - } - } - - /* Falling or jumping) */ - if (ELEM(walk->gravity_state, WALK_GRAVITY_STATE_ON, WALK_GRAVITY_STATE_JUMP)) { - float t; - float z_cur, z_new; - bool ret; - float ray_distance, difference = -100.0f; - - /* delta time */ - t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); - - /* keep moving if we were moving */ - copy_v2_v2(dvec, walk->teleport.direction); - - z_cur = walk->rv3d->viewinv[3][2]; - z_new = walk->teleport.origin[2] - getFreeFallDistance(walk->gravity, t) * walk->grid; - - /* jump */ - z_new += t * walk->speed_jump * walk->grid; - - /* duration is the jump duration */ - if (t > walk->teleport.duration) { - - /* check to see if we are landing */ - ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance); - - if (ret) { - difference = walk->view_height - ray_distance; - } - - if (difference > 0.0f) { - /* quit falling, lands at "view_height" from the floor */ - dvec[2] -= difference; - walk->gravity_state = WALK_GRAVITY_STATE_OFF; - walk->speed_jump = 0.0f; - } - else { - /* keep falling */ - dvec[2] = z_cur - z_new; - } - } - else { - /* keep going up (jump) */ - dvec[2] = z_cur - z_new; - } - } - - /* Teleport */ - else if (walk->teleport.state == WALK_TELEPORT_STATE_ON) { - float t; /* factor */ - float new_loc[3]; - float cur_loc[3]; - - /* linear interpolation */ - t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); - t /= walk->teleport.duration; - - /* clamp so we don't go past our limit */ - if (t >= 1.0f) { - t = 1.0f; - walk->teleport.state = WALK_TELEPORT_STATE_OFF; - walk_navigation_mode_set(C, op, walk, walk->teleport.navigation_mode); - } - - mul_v3_v3fl(new_loc, walk->teleport.direction, t); - add_v3_v3(new_loc, walk->teleport.origin); - - copy_v3_v3(cur_loc, walk->rv3d->viewinv[3]); - sub_v3_v3v3(dvec, cur_loc, new_loc); - } - - if (rv3d->persp == RV3D_CAMOB) { - Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); - if (lock_ob->protectflag & OB_LOCK_LOCX) { - dvec[0] = 0.0f; - } - if (lock_ob->protectflag & OB_LOCK_LOCY) { - dvec[1] = 0.0f; - } - if (lock_ob->protectflag & OB_LOCK_LOCZ) { - dvec[2] = 0.0f; - } - } - - /* scale the movement to the scene size */ - mul_v3_v3fl(dvec_tmp, dvec, walk->grid); - add_v3_v3(rv3d->ofs, dvec_tmp); - - if (rv3d->persp == RV3D_CAMOB) { - const bool do_rotate = (moffset[0] || moffset[1]); - const bool do_translate = (walk->speed != 0.0f); - walkMoveCamera(C, walk, do_rotate, do_translate); - } - } - else { - /* we're not redrawing but we need to update the time else the view will jump */ - walk->time_lastdraw = PIL_check_seconds_timer(); - } - /* end drawing */ - copy_v3_v3(walk->dvec_prev, dvec); - } - - return OPERATOR_FINISHED; + if ((walk->active_directions & WALK_BIT_UP) || (walk->active_directions & WALK_BIT_DOWN)) { + + if (walk->navigation_mode == WALK_MODE_FREE) { + + direction = 0; + + if ((walk->active_directions & WALK_BIT_UP)) { + direction -= 1; + } + + if ((walk->active_directions & WALK_BIT_DOWN)) { + direction = 1; + } + + copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction); + add_v3_v3(dvec, dvec_tmp); + } + } + + /* apply movement */ + mul_v3_fl(dvec, walk->speed * time_redraw); + } + + /* stick to the floor */ + if (walk->navigation_mode == WALK_MODE_GRAVITY && + ELEM(walk->gravity_state, WALK_GRAVITY_STATE_OFF, WALK_GRAVITY_STATE_START)) { + + bool ret; + float ray_distance; + float difference = -100.0f; + float fall_distance; + + ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance); + + if (ret) { + difference = walk->view_height - ray_distance; + } + + /* the distance we would fall naturally smoothly enough that we + * can manually drop the object without activating gravity */ + fall_distance = time_redraw * walk->speed * WALK_BOOST_FACTOR; + + if (fabsf(difference) < fall_distance) { + /* slope/stairs */ + dvec[2] -= difference; + + /* in case we switched from FREE to GRAVITY too close to the ground */ + if (walk->gravity_state == WALK_GRAVITY_STATE_START) { + walk->gravity_state = WALK_GRAVITY_STATE_OFF; + } + } + else { + /* hijack the teleport variables */ + walk->teleport.initial_time = PIL_check_seconds_timer(); + walk->gravity_state = WALK_GRAVITY_STATE_ON; + walk->teleport.duration = 0.0f; + + copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]); + copy_v2_v2(walk->teleport.direction, dvec); + } + } + + /* Falling or jumping) */ + if (ELEM(walk->gravity_state, WALK_GRAVITY_STATE_ON, WALK_GRAVITY_STATE_JUMP)) { + float t; + float z_cur, z_new; + bool ret; + float ray_distance, difference = -100.0f; + + /* delta time */ + t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); + + /* keep moving if we were moving */ + copy_v2_v2(dvec, walk->teleport.direction); + + z_cur = walk->rv3d->viewinv[3][2]; + z_new = walk->teleport.origin[2] - getFreeFallDistance(walk->gravity, t) * walk->grid; + + /* jump */ + z_new += t * walk->speed_jump * walk->grid; + + /* duration is the jump duration */ + if (t > walk->teleport.duration) { + + /* check to see if we are landing */ + ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance); + + if (ret) { + difference = walk->view_height - ray_distance; + } + + if (difference > 0.0f) { + /* quit falling, lands at "view_height" from the floor */ + dvec[2] -= difference; + walk->gravity_state = WALK_GRAVITY_STATE_OFF; + walk->speed_jump = 0.0f; + } + else { + /* keep falling */ + dvec[2] = z_cur - z_new; + } + } + else { + /* keep going up (jump) */ + dvec[2] = z_cur - z_new; + } + } + + /* Teleport */ + else if (walk->teleport.state == WALK_TELEPORT_STATE_ON) { + float t; /* factor */ + float new_loc[3]; + float cur_loc[3]; + + /* linear interpolation */ + t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); + t /= walk->teleport.duration; + + /* clamp so we don't go past our limit */ + if (t >= 1.0f) { + t = 1.0f; + walk->teleport.state = WALK_TELEPORT_STATE_OFF; + walk_navigation_mode_set(C, op, walk, walk->teleport.navigation_mode); + } + + mul_v3_v3fl(new_loc, walk->teleport.direction, t); + add_v3_v3(new_loc, walk->teleport.origin); + + copy_v3_v3(cur_loc, walk->rv3d->viewinv[3]); + sub_v3_v3v3(dvec, cur_loc, new_loc); + } + + if (rv3d->persp == RV3D_CAMOB) { + Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); + if (lock_ob->protectflag & OB_LOCK_LOCX) { + dvec[0] = 0.0f; + } + if (lock_ob->protectflag & OB_LOCK_LOCY) { + dvec[1] = 0.0f; + } + if (lock_ob->protectflag & OB_LOCK_LOCZ) { + dvec[2] = 0.0f; + } + } + + /* scale the movement to the scene size */ + mul_v3_v3fl(dvec_tmp, dvec, walk->grid); + add_v3_v3(rv3d->ofs, dvec_tmp); + + if (rv3d->persp == RV3D_CAMOB) { + const bool do_rotate = (moffset[0] || moffset[1]); + const bool do_translate = (walk->speed != 0.0f); + walkMoveCamera(C, walk, do_rotate, do_translate); + } + } + else { + /* we're not redrawing but we need to update the time else the view will jump */ + walk->time_lastdraw = PIL_check_seconds_timer(); + } + /* end drawing */ + copy_v3_v3(walk->dvec_prev, dvec); + } + + return OPERATOR_FINISHED; #undef WALK_ROTATE_FAC #undef WALK_ZUP_CORRECT_FAC #undef WALK_ZUP_CORRECT_ACCEL @@ -1306,121 +1310,124 @@ static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk) #ifdef WITH_INPUT_NDOF static void walkApply_ndof(bContext *C, WalkInfo *walk) { - Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); - bool has_translate, has_rotate; - - view3d_ndof_fly(walk->ndof, - walk->v3d, walk->rv3d, - walk->is_slow, lock_ob ? lock_ob->protectflag : 0, - &has_translate, &has_rotate); - - if (has_translate || has_rotate) { - walk->redraw = true; - - if (walk->rv3d->persp == RV3D_CAMOB) { - walkMoveCamera(C, walk, has_rotate, has_translate); - } - } + Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); + bool has_translate, has_rotate; + + view3d_ndof_fly(walk->ndof, + walk->v3d, + walk->rv3d, + walk->is_slow, + lock_ob ? lock_ob->protectflag : 0, + &has_translate, + &has_rotate); + + if (has_translate || has_rotate) { + walk->redraw = true; + + if (walk->rv3d->persp == RV3D_CAMOB) { + walkMoveCamera(C, walk, has_rotate, has_translate); + } + } } #endif /* WITH_INPUT_NDOF */ /****** walk operator ******/ static int walk_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); - WalkInfo *walk; + RegionView3D *rv3d = CTX_wm_region_view3d(C); + WalkInfo *walk; - if (rv3d->viewlock & RV3D_LOCKED) { - return OPERATOR_CANCELLED; - } + if (rv3d->viewlock & RV3D_LOCKED) { + return OPERATOR_CANCELLED; + } - walk = MEM_callocN(sizeof(WalkInfo), "NavigationWalkOperation"); + walk = MEM_callocN(sizeof(WalkInfo), "NavigationWalkOperation"); - op->customdata = walk; + op->customdata = walk; - if (initWalkInfo(C, walk, op) == false) { - MEM_freeN(op->customdata); - return OPERATOR_CANCELLED; - } + if (initWalkInfo(C, walk, op) == false) { + MEM_freeN(op->customdata); + return OPERATOR_CANCELLED; + } - walkEvent(C, op, walk, event); + walkEvent(C, op, walk, event); - WM_event_add_modal_handler(C, op); + WM_event_add_modal_handler(C, op); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } static void walk_cancel(bContext *C, wmOperator *op) { - WalkInfo *walk = op->customdata; + WalkInfo *walk = op->customdata; - walk->state = WALK_CANCEL; - walkEnd(C, walk); - op->customdata = NULL; + walk->state = WALK_CANCEL; + walkEnd(C, walk); + op->customdata = NULL; } static int walk_modal(bContext *C, wmOperator *op, const wmEvent *event) { - int exit_code; - bool do_draw = false; - WalkInfo *walk = op->customdata; - RegionView3D *rv3d = walk->rv3d; - Object *walk_object = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); + int exit_code; + bool do_draw = false; + WalkInfo *walk = op->customdata; + RegionView3D *rv3d = walk->rv3d; + Object *walk_object = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); - walk->redraw = false; + walk->redraw = false; - walkEvent(C, op, walk, event); + walkEvent(C, op, walk, event); #ifdef WITH_INPUT_NDOF - if (walk->ndof) { /* 3D mouse overrules [2D mouse + timer] */ - if (event->type == NDOF_MOTION) { - walkApply_ndof(C, walk); - } - } - else + if (walk->ndof) { /* 3D mouse overrules [2D mouse + timer] */ + if (event->type == NDOF_MOTION) { + walkApply_ndof(C, walk); + } + } + else #endif /* WITH_INPUT_NDOF */ - if (event->type == TIMER && event->customdata == walk->timer) { - walkApply(C, op, walk); - } + if (event->type == TIMER && event->customdata == walk->timer) { + walkApply(C, op, walk); + } - do_draw |= walk->redraw; + do_draw |= walk->redraw; - exit_code = walkEnd(C, walk); + exit_code = walkEnd(C, walk); - if (exit_code != OPERATOR_RUNNING_MODAL) { - do_draw = true; - } + if (exit_code != OPERATOR_RUNNING_MODAL) { + do_draw = true; + } - if (do_draw) { - if (rv3d->persp == RV3D_CAMOB) { - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, walk_object); - } + if (do_draw) { + if (rv3d->persp == RV3D_CAMOB) { + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, walk_object); + } - // too frequent, commented with NDOF_WALK_DRAW_TOOMUCH for now - // puts("redraw!"); - ED_region_tag_redraw(CTX_wm_region(C)); - } + // too frequent, commented with NDOF_WALK_DRAW_TOOMUCH for now + // puts("redraw!"); + ED_region_tag_redraw(CTX_wm_region(C)); + } - if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) { - ED_workspace_status_text(C, NULL); - } + if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) { + ED_workspace_status_text(C, NULL); + } - return exit_code; + return exit_code; } void VIEW3D_OT_walk(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Walk Navigation"; - ot->description = "Interactively walk around the scene"; - ot->idname = "VIEW3D_OT_walk"; - - /* api callbacks */ - ot->invoke = walk_invoke; - ot->cancel = walk_cancel; - ot->modal = walk_modal; - ot->poll = ED_operator_region_view3d_active; - - /* flags */ - ot->flag = OPTYPE_BLOCKING; + /* identifiers */ + ot->name = "Walk Navigation"; + ot->description = "Interactively walk around the scene"; + ot->idname = "VIEW3D_OT_walk"; + + /* api callbacks */ + ot->invoke = walk_invoke; + ot->cancel = walk_cancel; + ot->modal = walk_modal; + ot->poll = ED_operator_region_view3d_active; + + /* flags */ + ot->flag = OPTYPE_BLOCKING; } |