From a094e5dcdfebcd9465d800d521e9b2e04f3e8b0d Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Mon, 25 Oct 2021 00:39:50 +0200 Subject: [PATCH] Implement Alt + Mouse wheel to adjust FOV in the 3D editor viewport This allows for quicker FOV adjustments compared to using the View menu. --- editor/plugins/spatial_editor_plugin.cpp | 60 ++++++++++++++++++++---- editor/plugins/spatial_editor_plugin.h | 7 ++- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 1f8d8fa4abd6..5b926386f555 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -253,6 +253,14 @@ void ViewportRotationControl::_bind_methods() { ClassDB::bind_method(D_METHOD("_on_mouse_exited"), &ViewportRotationControl::_on_mouse_exited); } +void SpatialEditorViewport::_view_settings_confirmed(real_t p_interp_delta) { + // Set FOV override multiplier back to the default, so that the FOV + // setting specified in the View menu is correctly applied. + cursor.fov_scale = 1.0; + + _update_camera(p_interp_delta); +} + void SpatialEditorViewport::_update_camera(float p_interp_delta) { bool is_orthogonal = camera->get_projection() == Camera::PROJECTION_ORTHOGONAL; @@ -317,6 +325,8 @@ void SpatialEditorViewport::_update_camera(float p_interp_delta) { equal = false; } else if (!Math::is_equal_approx(old_camera_cursor.distance, camera_cursor.distance, tolerance)) { equal = false; + } else if (!Math::is_equal_approx(old_camera_cursor.fov_scale, camera_cursor.fov_scale, tolerance)) { + equal = false; } if (!equal || p_interp_delta == 0 || is_orthogonal != orthogonal) { @@ -380,7 +390,7 @@ float SpatialEditorViewport::get_zfar() const { return CLAMP(spatial_editor->get_zfar(), MIN_Z, MAX_Z); } float SpatialEditorViewport::get_fov() const { - return CLAMP(spatial_editor->get_fov(), MIN_FOV, MAX_FOV); + return CLAMP(spatial_editor->get_fov() * cursor.fov_scale, MIN_FOV, MAX_FOV); } Transform SpatialEditorViewport::_get_camera_transform() const { @@ -1161,18 +1171,26 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { float zoom_factor = 1 + (ZOOM_FREELOOK_MULTIPLIER - 1) * b->get_factor(); switch (b->get_button_index()) { case BUTTON_WHEEL_UP: { - if (is_freelook_active()) { - scale_freelook_speed(zoom_factor); + if (b->get_alt()) { + scale_fov(-0.05); } else { - scale_cursor_distance(1.0 / zoom_factor); + if (is_freelook_active()) { + scale_freelook_speed(zoom_factor); + } else { + scale_cursor_distance(1.0 / zoom_factor); + } } } break; case BUTTON_WHEEL_DOWN: { - if (is_freelook_active()) { - scale_freelook_speed(1.0 / zoom_factor); + if (b->get_alt()) { + scale_fov(0.05); } else { - scale_cursor_distance(zoom_factor); + if (is_freelook_active()) { + scale_freelook_speed(1.0 / zoom_factor); + } else { + scale_cursor_distance(zoom_factor); + } } } break; @@ -2120,6 +2138,18 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { emit_signal("toggle_maximize_view", this); } } + + if (ED_IS_SHORTCUT("spatial_editor/decrease_fov", p_event)) { + scale_fov(-0.05); + } + + if (ED_IS_SHORTCUT("spatial_editor/increase_fov", p_event)) { + scale_fov(0.05); + } + + if (ED_IS_SHORTCUT("spatial_editor/reset_fov", p_event)) { + reset_fov(); + } } // freelook uses most of the useful shortcuts, like save, so its ok @@ -2287,6 +2317,16 @@ void SpatialEditorViewport::set_freelook_active(bool active_now) { freelook_active = active_now; } +void SpatialEditorViewport::scale_fov(real_t p_fov_offset) { + cursor.fov_scale = CLAMP(cursor.fov_scale + p_fov_offset, 0.1, 2.5); + surface->update(); +} + +void SpatialEditorViewport::reset_fov() { + cursor.fov_scale = 1.0; + surface->update(); +} + void SpatialEditorViewport::scale_cursor_distance(real_t scale) { real_t min_distance = MAX(camera->get_znear() * 4, ZOOM_FREELOOK_MIN); real_t max_distance = MIN(camera->get_zfar() / 2, ZOOM_FREELOOK_MAX); @@ -3506,6 +3546,7 @@ void SpatialEditorViewport::_bind_methods() { ClassDB::bind_method(D_METHOD("_menu_option"), &SpatialEditorViewport::_menu_option); ClassDB::bind_method(D_METHOD("_toggle_camera_preview"), &SpatialEditorViewport::_toggle_camera_preview); ClassDB::bind_method(D_METHOD("_preview_exited_scene"), &SpatialEditorViewport::_preview_exited_scene); + ClassDB::bind_method(D_METHOD("_view_settings_confirmed"), &SpatialEditorViewport::_view_settings_confirmed); ClassDB::bind_method(D_METHOD("_update_camera"), &SpatialEditorViewport::_update_camera); ClassDB::bind_method(D_METHOD("update_transform_gizmo_view"), &SpatialEditorViewport::update_transform_gizmo_view); ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &SpatialEditorViewport::_selection_result_pressed); @@ -6497,6 +6538,9 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { ED_SHORTCUT("spatial_editor/align_transform_with_view", TTR("Align Transform with View"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_M); ED_SHORTCUT("spatial_editor/align_rotation_with_view", TTR("Align Rotation with View"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_F); ED_SHORTCUT("spatial_editor/freelook_toggle", TTR("Toggle Freelook"), KEY_MASK_SHIFT + KEY_F); + ED_SHORTCUT("spatial_editor/decrease_fov", TTR("Decrease Field of View"), KEY_MASK_CMD + KEY_EQUAL); // Usually direct access key for `KEY_PLUS`. + ED_SHORTCUT("spatial_editor/increase_fov", TTR("Increase Field of View"), KEY_MASK_CMD + KEY_MINUS); + ED_SHORTCUT("spatial_editor/reset_fov", TTR("Reset Field of View to Default"), KEY_MASK_CMD + KEY_0); PopupMenu *p; @@ -6645,7 +6689,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { settings_vbc->add_margin_child(TTR("View Z-Far:"), settings_zfar); for (uint32_t i = 0; i < VIEWPORTS_COUNT; ++i) { - settings_dialog->connect("confirmed", viewports[i], "_update_camera", varray(0.0)); + settings_dialog->connect("confirmed", viewports[i], "_view_settings_confirmed", varray(0.0)); } /* XFORM DIALOG */ diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index bba6d68d87aa..c5604a82eab2 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -378,7 +378,7 @@ class SpatialEditorViewport : public Control { struct Cursor { Vector3 pos; - float x_rot, y_rot, distance; + float x_rot, y_rot, distance, fov_scale; Vector3 eye_pos; // Used in freelook mode bool region_select; Point2 region_begin, region_end; @@ -388,6 +388,7 @@ class SpatialEditorViewport : public Control { x_rot = 0.5; y_rot = -0.5; distance = 4; + fov_scale = 1.0; region_select = false; } }; @@ -396,6 +397,8 @@ class SpatialEditorViewport : public Control { Cursor cursor; // Immediate cursor Cursor camera_cursor; // That one may be interpolated (don't modify this one except for smoothing purposes) + void scale_fov(real_t p_fov_offset); + void reset_fov(); void scale_cursor_distance(real_t scale); void set_freelook_active(bool active_now); @@ -412,7 +415,7 @@ class SpatialEditorViewport : public Control { void set_message(String p_message, float p_time = 5); - // + void _view_settings_confirmed(float p_interp_delta); void _update_camera(float p_interp_delta); Transform to_camera_transform(const Cursor &p_cursor) const; void _draw();