View Navigation: Walk and Fly modes

This is a addtion to the dynamic fly mode.
It behaves as the first person navigation system available in most 3d world  games nowadays.

You can alternate between the old mode (Fly) and the new mode (Walk) in User Preferences > Inputs

Manual:
-------
http://wiki.blender.org/index.php/Doc:2.6/Manual/3D_interaction/Navigating/3D_View#View_Navigation
http://wiki.blender.org/index.php/Doc:2.6/Manual/3D_interaction/Navigating/3D_View/Navigation_Modes

Shortcuts:
----------
WASD (hold)  - Move forward/backward and straft left/right
QE (hold)    - Move up and down
Tab          - Alternate between Walk and Fly modes
Shift (hold) - Speed up movement
Alt (hold)   - Slow down movement
Space or MMB - Teleport
V            - Jump
+/- or mouse wheel - speed increase/decrease speed for this Blender session

User Preferences Options:
-------------------------
Navigation Mode   - fly/walk navigation systems (fly is the old, walk is the new, next options are for walk mode only)
Gravity           - alternate between free navigation and walk with gravity modes
Mouse Sensitivity - sensitivity factor to mouse influence to look around
Teleport Duration - how long the teleport lasts
Camera Height     - camera height to use in gravity mode
Jump Height       - maximum jump speed in m/s
Move Speed        - base move speed in m/s
Boost Factor      - multiplication factor when running or going slow (1/boost)

Development Notes:
------------------
* The initial code was based on view3d_fly.c.
* The NDoF code was not touched, so it most likely is not working.

Pending Issues:
---------------
* Draw in the UI the shortcut options, and current values (e.g., Mode: Fly/Walk)
  (we need a proper API for that)
* OSX seems to present issues if we re-center the mouse every time. We implemented a workaround for that, but a real fix would be welcome.

Code reviewed and with collaborations from Campbell Barton - @campbellbarton
Differential Revision: http://developer.blender.org/D30
This commit is contained in:
Dalai Felinto 2013-12-03 03:14:09 -02:00
parent 2e4601c356
commit ab49437958
Notes: blender-bot 2023-02-14 11:42:38 +01:00
Referenced by issue #38321, Screen Layout Freezes Blender
Referenced by issue #37704, Influence Density with Hair error
Referenced by issue #37690, VSE: UI does not immediatelly reflect new length of effect strip
Referenced by issue #37143, Wrong Normal Dir with Arbitrary Obj Rot + Normal Transf. Orient. + Individual Origins + Only one vert selected.
12 changed files with 1586 additions and 4 deletions

View File

@ -1051,6 +1051,28 @@ class USERPREF_PT_input(Panel):
sub.label(text="Trackpad:")
sub.prop(inputs, "use_trackpad_natural")
col.separator()
sub = col.column()
sub.label(text="View Navigation:")
sub.row().prop(inputs, "navigation_mode", expand=True)
if inputs.navigation_mode == 'WALK':
walk = inputs.walk_navigation
sub.prop(walk, "use_mouse_reverse")
sub.prop(walk, "mouse_speed")
sub.prop(walk, "teleport_time")
sub = col.column(align=True)
sub.prop(walk, "walk_speed")
sub.prop(walk, "walk_speed_factor")
sub.separator()
sub.prop(walk, "use_gravity")
sub = col.column(align=True)
sub.active = walk.use_gravity
sub.prop(walk, "view_height")
sub.prop(walk, "jump_height")
col.separator()
sub = col.column()
sub.label(text="NDOF Device:")

View File

@ -435,6 +435,7 @@ class VIEW3D_MT_view_navigation(Menu):
layout.separator()
layout.operator("view3d.fly")
layout.operator("view3d.walk")
class VIEW3D_MT_view_align(Menu):

View File

@ -7385,7 +7385,7 @@ static void convert_tface_mt(FileData *fd, Main *main)
/* initialize userdef with non-UI dependency stuff */
/* other initializers (such as theme color defaults) go to resources.c */
static void do_versions_userdef(FileData *UNUSED(fd), BlendFileData *bfd)
static void do_versions_userdef(FileData *fd, BlendFileData *bfd)
{
Main *bmain = bfd->main;
UserDef *user = bfd->user;
@ -7401,6 +7401,16 @@ static void do_versions_userdef(FileData *UNUSED(fd), BlendFileData *bfd)
copy_v4_v4_char(btheme->tseq.grid, btheme->tseq.back);
}
}
if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "WalkNavigation", "walk_navigation")) {
user->walk_navigation.mouse_speed = 1.0f;
user->walk_navigation.walk_speed = 2.5f; /* m/s */
user->walk_navigation.walk_speed_factor = 5.0f;
user->walk_navigation.view_height = 1.6f; /* m */
user->walk_navigation.jump_height = 0.4f; /* m */
user->walk_navigation.teleport_time = 0.2f; /* s */
}
}
static void do_versions(FileData *fd, Library *lib, Main *main)

View File

@ -50,6 +50,7 @@ set(SRC
view3d_draw.c
view3d_edit.c
view3d_fly.c
view3d_walk.c
view3d_header.c
view3d_iterators.c
view3d_ops.c

View File

@ -3889,6 +3889,35 @@ void VIEW3D_OT_view_persportho(wmOperatorType *ot)
ot->flag = 0;
}
static int view3d_navigate_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
eViewNavigation_Method mode = U.navigation_mode;
switch (mode) {
case VIEW_NAVIGATION_FLY:
WM_operator_name_call(C, "VIEW3D_OT_fly", WM_OP_INVOKE_DEFAULT, NULL);
break;
case VIEW_NAVIGATION_WALK:
default:
WM_operator_name_call(C, "VIEW3D_OT_walk", WM_OP_INVOKE_DEFAULT, NULL);
break;
}
return OPERATOR_FINISHED;
}
void VIEW3D_OT_navigate(wmOperatorType *ot)
{
/* identifiers */
ot->name = "View Navigation";
ot->description = "Interactively navigate around the scene. It uses the mode (walk/fly) preference";
ot->idname = "VIEW3D_OT_navigate";
/* api callbacks */
ot->invoke = view3d_navigate_invoke;
ot->poll = ED_operator_view3d_active;
}
/* ******************** add background image operator **************** */

View File

@ -92,6 +92,7 @@ void VIEW3D_OT_view_center_camera(struct wmOperatorType *ot);
void VIEW3D_OT_view_center_lock(struct wmOperatorType *ot);
void VIEW3D_OT_view_pan(struct wmOperatorType *ot);
void VIEW3D_OT_view_persportho(struct wmOperatorType *ot);
void VIEW3D_OT_navigate(struct wmOperatorType *ot);
void VIEW3D_OT_background_image_add(struct wmOperatorType *ot);
void VIEW3D_OT_background_image_remove(struct wmOperatorType *ot);
void VIEW3D_OT_view_orbit(struct wmOperatorType *ot);
@ -112,6 +113,9 @@ float ndof_to_axis_angle(const struct wmNDOFMotionData *ndof, float axis[3]);
void view3d_keymap(struct wmKeyConfig *keyconf);
void VIEW3D_OT_fly(struct wmOperatorType *ot);
/* view3d_walk.c */
void VIEW3D_OT_walk(struct wmOperatorType *ot);
/* view3d_ruler.c */
void VIEW3D_OT_ruler(struct wmOperatorType *ot);
@ -195,6 +199,7 @@ void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect);
void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d);
void fly_modal_keymap(struct wmKeyConfig *keyconf);
void walk_modal_keymap(struct wmKeyConfig *keyconf);
void viewrotate_modal_keymap(struct wmKeyConfig *keyconf);
void viewmove_modal_keymap(struct wmKeyConfig *keyconf);
void viewzoom_modal_keymap(struct wmKeyConfig *keyconf);

View File

@ -172,6 +172,8 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_localview);
WM_operatortype_append(VIEW3D_OT_game_start);
WM_operatortype_append(VIEW3D_OT_fly);
WM_operatortype_append(VIEW3D_OT_walk);
WM_operatortype_append(VIEW3D_OT_navigate);
WM_operatortype_append(VIEW3D_OT_ruler);
WM_operatortype_append(VIEW3D_OT_layers);
WM_operatortype_append(VIEW3D_OT_copybuffer);
@ -224,7 +226,7 @@ void view3d_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "VIEW3D_OT_view_lock_to_active", PADPERIOD, KM_PRESS, KM_SHIFT, 0);
WM_keymap_verify_item(keymap, "VIEW3D_OT_view_lock_clear", PADPERIOD, KM_PRESS, KM_ALT, 0);
WM_keymap_verify_item(keymap, "VIEW3D_OT_fly", FKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_verify_item(keymap, "VIEW3D_OT_navigate", FKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_verify_item(keymap, "VIEW3D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0);
@ -504,6 +506,7 @@ void view3d_keymap(wmKeyConfig *keyconf)
transform_keymap_for_space(keyconf, keymap, SPACE_VIEW3D);
fly_modal_keymap(keyconf);
walk_modal_keymap(keyconf);
viewrotate_modal_keymap(keyconf);
viewmove_modal_keymap(keyconf);
viewzoom_modal_keymap(keyconf);

File diff suppressed because it is too large Load Diff

View File

@ -374,6 +374,17 @@ typedef struct SolidLight {
float col[4], spec[4], vec[4];
} SolidLight;
typedef struct WalkNavigation {
float mouse_speed; /* speed factor for look around */
float walk_speed;
float walk_speed_factor;
float view_height;
float jump_height;
float teleport_time; /* duration to use for teleporting */
short flag;
short pad[3];
} WalkNavigation;
typedef struct UserDef {
/* UserDef has separate do-version handling, and can be read from other files */
int versionfile, subversionfile;
@ -477,7 +488,7 @@ typedef struct UserDef {
float gpencil_new_layer_col[4]; /* default color for newly created Grease Pencil layers */
short tweak_threshold;
short pad3;
char navigation_mode, pad;
char author[80]; /* author name for file formats supporting it */
@ -486,6 +497,8 @@ typedef struct UserDef {
float fcu_inactive_alpha; /* opacity of inactive F-Curves in F-Curve Editor */
float pixelsize; /* private, set by GHOST, to multiply DPI with */
struct WalkNavigation walk_navigation;
} UserDef;
extern UserDef U; /* from blenkernel blender.c */
@ -552,6 +565,18 @@ typedef enum eViewZoom_Style {
USER_ZOOM_DOLLY = 2
} eViewZoom_Style;
/* navigation_mode */
typedef enum eViewNavigation_Method {
VIEW_NAVIGATION_WALK = 0,
VIEW_NAVIGATION_FLY = 1,
} eViewNavigation_Method;
/* flag */
typedef enum eWalkNavigation_Flag {
USER_WALK_GRAVITY = (1 << 0),
USER_WALK_MOUSE_REVERSE = (1 << 1),
} eWalkNavigation_Flag;
/* uiflag */
typedef enum eUserpref_UI_Flag {
/* flags 0 and 1 were old flags (for autokeying) that aren't used anymore */

View File

@ -641,6 +641,7 @@ extern StructRNA RNA_UserPreferencesFilePaths;
extern StructRNA RNA_UserPreferencesInput;
extern StructRNA RNA_UserPreferencesSystem;
extern StructRNA RNA_UserPreferencesView;
extern StructRNA RNA_UserPreferencesWalkNavigation;
extern StructRNA RNA_UserSolidLight;
extern StructRNA RNA_VectorFont;
extern StructRNA RNA_VertexGroup;

View File

@ -135,6 +135,8 @@ extern EnumPropertyItem gameproperty_type_items[];
extern EnumPropertyItem viewport_shade_items[];
extern EnumPropertyItem navigation_mode_items[];
int rna_node_tree_type_to_enum(struct bNodeTreeType *typeinfo);
int rna_node_tree_idname_to_enum(const char *idname);
struct bNodeTreeType *rna_node_tree_type_from_enum(int value);

View File

@ -72,6 +72,12 @@ static EnumPropertyItem audio_device_items[] = {
{0, NULL, 0, NULL, NULL}
};
EnumPropertyItem navigation_mode_items[] = {
{VIEW_NAVIGATION_WALK, "WALK", 0, "Walk", "Interactively walk or free navigate around the scene"},
{VIEW_NAVIGATION_FLY, "FLY", 0, "Fly", "Use fly dynamics to navigate the scene"},
{0, NULL, 0, NULL, NULL}
};
#ifdef RNA_RUNTIME
#include "DNA_object_types.h"
@ -2873,6 +2879,51 @@ static void rna_def_userdef_solidlight(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_UserDef_viewport_lights_update");
}
static void rna_def_userdef_walk_navigation(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "WalkNavigation", NULL);
RNA_def_struct_sdna(srna, "WalkNavigation");
RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
RNA_def_struct_ui_text(srna, "Walk Navigation", "Walk navigation settings");
prop = RNA_def_property(srna, "mouse_speed", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.01f, 10.0f);
RNA_def_property_ui_text(prop, "Mouse Sensitivity", "Speed factor for when looking around, high values mean faster mouse movement");
prop = RNA_def_property(srna, "walk_speed", PROP_FLOAT, PROP_VELOCITY);
RNA_def_property_range(prop, 0.01f, 100.f);
RNA_def_property_ui_text(prop, "Walk Speed", "Base speed for walking and flying");
prop = RNA_def_property(srna, "walk_speed_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.01f, 10.f);
RNA_def_property_ui_text(prop, "Speed Factor", "Multiplication factor when using the fast or slow modifiers");
prop = RNA_def_property(srna, "view_height", PROP_FLOAT, PROP_UNIT_LENGTH);
RNA_def_property_ui_range(prop, 0.1f, 10.f, 0.1, 2);
RNA_def_property_range(prop, 0.f, 1000.f);
RNA_def_property_ui_text(prop, "View Height", "View distance from the floor when walking");
prop = RNA_def_property(srna, "jump_height", PROP_FLOAT, PROP_UNIT_LENGTH);
RNA_def_property_ui_range(prop, 0.1f, 10.f, 0.1, 2);
RNA_def_property_range(prop, 0.1f, 100.f);
RNA_def_property_ui_text(prop, "Jump Height", "Maximum height of a jump");
prop = RNA_def_property(srna, "teleport_time", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.f, 10.f);
RNA_def_property_ui_text(prop, "Teleport Duration", "Interval of time warp when teleporting in navigation mode");
prop = RNA_def_property(srna, "use_gravity", PROP_BOOLEAN, PROP_BOOLEAN);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_WALK_GRAVITY);
RNA_def_property_ui_text(prop, "Gravity", "Walks with gravity, or free navigate");
prop = RNA_def_property(srna, "use_mouse_reverse", PROP_BOOLEAN, PROP_BOOLEAN);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_WALK_MOUSE_REVERSE);
RNA_def_property_ui_text(prop, "Reverse Mouse", "Reverse the mouse look");
}
static void rna_def_userdef_view(BlenderRNA *brna)
{
static EnumPropertyItem timecode_styles[] = {
@ -3793,7 +3844,19 @@ static void rna_def_userdef_input(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Continuous Grab",
"Allow moving the mouse outside the view on some manipulations "
"(transform, ui control drag)");
/* View Navigation */
prop = RNA_def_property(srna, "navigation_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "navigation_mode");
RNA_def_property_enum_items(prop, navigation_mode_items);
RNA_def_property_ui_text(prop, "View Navigation", "Which method to use for viewport navigation");
prop = RNA_def_property(srna, "walk_navigation", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "walk_navigation");
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "WalkNavigation");
RNA_def_property_ui_text(prop, "Walk Navigation", "Settings for walk navigation mode");
/* tweak tablet & mouse preset */
prop = RNA_def_property(srna, "drag_threshold", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "dragthreshold");
@ -4128,6 +4191,7 @@ void RNA_def_userdef(BlenderRNA *brna)
rna_def_userdef_dothemes(brna);
rna_def_userdef_solidlight(brna);
rna_def_userdef_walk_navigation(brna);
srna = RNA_def_struct(brna, "UserPreferences", NULL);
RNA_def_struct_sdna(srna, "UserDef");