Path: blob/master/scene/debugger/view_3d_controller.h
45993 views
/**************************************************************************/1/* view_3d_controller.h */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#pragma once3132#ifndef _3D_DISABLED3334#include "core/object/ref_counted.h"3536namespace View3DControllerConsts {37constexpr float DISTANCE_DEFAULT = 4;3839constexpr float ZOOM_FREELOOK_MULTIPLIER = 1.08;40constexpr float ZOOM_FREELOOK_MIN = 0.01;41#ifdef REAL_T_IS_DOUBLE42constexpr double ZOOM_FREELOOK_MAX = 1'000'000'000'000;43#else44constexpr float ZOOM_FREELOOK_MAX = 10'000;45#endif4647constexpr float CAMERA_MIN_FOV_SCALE = 0.1;48constexpr float CAMERA_MAX_FOV_SCALE = 2.5;49} //namespace View3DControllerConsts5051class InputEvent;52class InputEventMouseMotion;53class InputEventWithModifiers;54class Shortcut;5556class View3DController : public RefCounted {57GDCLASS(View3DController, RefCounted);5859public:60enum NavigationMode {61NAV_MODE_NONE,62NAV_MODE_PAN,63NAV_MODE_ZOOM,64NAV_MODE_ORBIT,65NAV_MODE_LOOK,66NAV_MODE_MOVE,67};6869enum NavigationScheme {70NAV_SCHEME_GODOT,71NAV_SCHEME_MAYA,72NAV_SCHEME_MODO,73NAV_SCHEME_CUSTOM,74NAV_SCHEME_TABLET,75};7677enum NavigationMouseButton {78NAV_MOUSE_BUTTON_LEFT,79NAV_MOUSE_BUTTON_MIDDLE,80NAV_MOUSE_BUTTON_RIGHT,81NAV_MOUSE_BUTTON_4,82NAV_MOUSE_BUTTON_5,83};8485enum ZoomStyle {86ZOOM_VERTICAL,87ZOOM_HORIZONTAL,88};8990enum FreelookScheme {91FREELOOK_DEFAULT,92FREELOOK_PARTIALLY_AXIS_LOCKED,93FREELOOK_FULLY_AXIS_LOCKED,94};9596enum ViewType {97VIEW_TYPE_USER,98VIEW_TYPE_TOP,99VIEW_TYPE_BOTTOM,100VIEW_TYPE_LEFT,101VIEW_TYPE_RIGHT,102VIEW_TYPE_FRONT,103VIEW_TYPE_REAR,104};105106enum OrthogonalMode {107ORTHOGONAL_DISABLED,108ORTHOGONAL_ENABLED,109ORTHOGONAL_AUTO,110};111112enum ShortcutName {113SHORTCUT_FOV_INCREASE,114SHORTCUT_FOV_DECREASE,115SHORTCUT_FOV_RESET,116117SHORTCUT_PAN_MOD_1,118SHORTCUT_PAN_MOD_2,119120SHORTCUT_ORBIT_MOD_1,121SHORTCUT_ORBIT_MOD_2,122SHORTCUT_ORBIT_SNAP_MOD_1,123SHORTCUT_ORBIT_SNAP_MOD_2,124125SHORTCUT_ZOOM_MOD_1,126SHORTCUT_ZOOM_MOD_2,127128SHORTCUT_FREELOOK_FORWARD,129SHORTCUT_FREELOOK_BACKWARDS,130SHORTCUT_FREELOOK_LEFT,131SHORTCUT_FREELOOK_RIGHT,132SHORTCUT_FREELOOK_UP,133SHORTCUT_FREELOOK_DOWN,134SHORTCUT_FREELOOK_SPEED_MOD,135SHORTCUT_FREELOOK_SLOW_MOD,136137SHORTCUT_MAX,138};139140struct Cursor {141Vector3 pos;142real_t x_rot;143real_t y_rot;144real_t distance;145real_t fov_scale;146real_t unsnapped_x_rot;147real_t unsnapped_y_rot;148Vector3 eye_pos; // Used for freelook.149// TODO: These variables are not related to cursor manipulation, and specific150// to Node3DEditorPlugin. So remove them in the future.151bool region_select;152Point2 region_begin;153Point2 region_end;154155Cursor() {156// These rotations place the camera in +X +Y +Z, aka south east, facing north west.157x_rot = 0.5;158y_rot = -0.5;159unsnapped_x_rot = x_rot;160unsnapped_y_rot = y_rot;161distance = 4;162fov_scale = 1.0;163region_select = false;164}165};166167// Viewport camera supports movement smoothing,168// so one cursor is the real cursor, while the other can be an interpolated version.169Cursor cursor; // Immediate cursor.170171private:172Cursor cursor_interp; // That one may be interpolated (don't modify this one except for smoothing purposes).173Cursor previous_cursor; // Storing previous cursor state for canceling purposes.174bool navigating = false;175bool navigation_cancelled = false;176void cancel_navigation();177178protected:179static void _bind_methods();180181private:182HashMap<int, Ref<Shortcut>> inputs;183184NavigationScheme navigation_scheme = NAV_SCHEME_GODOT;185ViewType view_type = VIEW_TYPE_USER;186187NavigationMouseButton pan_mouse_button = NAV_MOUSE_BUTTON_MIDDLE;188189NavigationMouseButton orbit_mouse_button = NAV_MOUSE_BUTTON_MIDDLE;190float orbit_sensitivity = 0;191float orbit_inertia = 0;192193bool freelook = false;194FreelookScheme freelook_scheme = FREELOOK_DEFAULT;195float freelook_speed = 0;196float freelook_base_speed = 0;197float freelook_speed_zoom_link = 0;198float freelook_sensitivity = 0;199float freelook_inertia = 0;200bool freelook_invert_y_axis = false;201202ZoomStyle zoom_style = ZOOM_VERTICAL;203NavigationMouseButton zoom_mouse_button = NAV_MOUSE_BUTTON_MIDDLE;204float zoom_inertia = 0;205int zoom_failed_attempts_count = 0;206207float translation_sensitivity = 0;208float translation_inertia = 0;209210float angle_snap_threshold = 0;211bool warped_mouse_panning = false;212213bool emulate_3_button_mouse = false;214bool emulate_numpad = true;215216OrthogonalMode orthogonal = ORTHOGONAL_DISABLED;217bool auto_orthogonal_allowed = false;218219bool lock_rotation = false;220221float znear = 0;222float zfar = 0;223224bool invert_x_axis = false;225bool invert_y_axis = false;226227Point2 previous_mouse_position;228229Transform3D _to_camera_transform(const Cursor &p_cursor) const;230231struct ShortcutCheck {232bool mod_pressed = false;233bool not_empty = true;234int input_count = 0;235NavigationMouseButton mouse_preference = NAV_MOUSE_BUTTON_LEFT;236NavigationMode result_nav_mode = NAV_MODE_NONE;237238ShortcutCheck(bool p_mod_pressed, bool p_not_empty, int p_input_count, const NavigationMouseButton &p_mouse_preference, const NavigationMode &p_result_nav_mode) :239mod_pressed(p_mod_pressed), not_empty(p_not_empty), input_count(p_input_count), mouse_preference(p_mouse_preference), result_nav_mode(p_result_nav_mode) {240}241};242243struct ShortcutCheckSetComparator {244_FORCE_INLINE_ bool operator()(const ShortcutCheck &A, const ShortcutCheck &B) const {245return A.input_count > B.input_count;246}247};248249bool _is_shortcut_pressed(const ShortcutName p_name, const bool p_true_if_null = false);250bool _is_shortcut_empty(const ShortcutName p_name);251NavigationMode _get_nav_mode_from_shortcuts(NavigationMouseButton p_mouse_button, const Vector<ShortcutCheck> &p_shortcut_checks, bool p_not_empty);252253public:254bool gui_input(const Ref<InputEvent> &p_event, const Rect2 &p_surface_rect);255bool is_navigating() const { return navigating; }256257void cursor_pan(const Ref<InputEventWithModifiers> &p_event, const Vector2 &p_relative);258void cursor_look(const Ref<InputEventWithModifiers> &p_event, const Vector2 &p_relative);259void cursor_orbit(const Ref<InputEventWithModifiers> &p_event, const Vector2 &p_relative);260void cursor_zoom(const Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);261262void update_camera(const real_t p_delta = 0);263264void update_freelook(const float p_delta);265void scale_freelook_speed(const float p_scale);266267void scale_cursor_distance(const float p_scale);268269inline Transform3D to_camera_transform() const { return _to_camera_transform(cursor); }270inline Transform3D interp_to_camera_transform() const { return _to_camera_transform(cursor_interp); }271272void set_shortcut(const ShortcutName p_name, const Ref<Shortcut> &p_shortcut);273274void set_navigation_scheme(const NavigationScheme p_scheme) { navigation_scheme = p_scheme; }275276void set_view_type(const ViewType p_view);277ViewType get_view_type() const { return view_type; }278String get_view_type_name() const;279280void set_pan_mouse_button(const NavigationMouseButton p_button) { pan_mouse_button = p_button; }281282void set_orbit_sensitivity(const float p_sensitivity) { orbit_sensitivity = p_sensitivity; }283void set_orbit_inertia(const float p_inertia) { orbit_inertia = p_inertia; }284void set_orbit_mouse_button(const NavigationMouseButton p_button) { orbit_mouse_button = p_button; }285286void set_freelook_enabled(const bool p_enabled);287bool is_freelook_enabled() const { return freelook; }288void set_freelook_scheme(FreelookScheme p_scheme) { freelook_scheme = p_scheme; }289FreelookScheme get_freelook_scheme() const { return freelook_scheme; }290void set_freelook_base_speed(const float p_speed);291float get_freelook_speed() const { return freelook_speed; }292void set_freelook_sensitivity(const float p_sensitivity) { freelook_sensitivity = p_sensitivity; }293void set_freelook_inertia(const float p_inertia) { freelook_inertia = p_inertia; }294void set_freelook_speed_zoom_link(const bool p_enabled) { freelook_speed_zoom_link = p_enabled; }295void set_freelook_invert_y_axis(const bool p_enabled) { freelook_invert_y_axis = p_enabled; }296297void set_zoom_style(ZoomStyle p_style) { zoom_style = p_style; }298void set_zoom_inertia(const float p_inertia) { zoom_inertia = p_inertia; }299void set_zoom_mouse_button(const NavigationMouseButton p_button) { zoom_mouse_button = p_button; }300301void set_translation_sensitivity(const float p_sensitivity) { translation_sensitivity = p_sensitivity; }302void set_translation_inertia(const float p_inertia) { translation_inertia = p_inertia; }303304void set_angle_snap_threshold(const float p_threshold) { angle_snap_threshold = p_threshold; }305306void set_emulate_3_button_mouse(const bool p_enabled) { emulate_3_button_mouse = p_enabled; }307void set_emulate_numpad(const bool p_enabled) { emulate_numpad = p_enabled; }308309void set_orthogonal(const bool p_enabled) { orthogonal = p_enabled ? ORTHOGONAL_ENABLED : ORTHOGONAL_DISABLED; }310bool is_orthogonal() const { return orthogonal != ORTHOGONAL_DISABLED; }311OrthogonalMode get_orthogonal_mode() const { return orthogonal; }312void force_auto_orthogonal();313void set_auto_orthogonal_allowed(const bool p_enabled);314315void set_lock_rotation(const bool p_locked) { lock_rotation = p_locked; }316bool is_locking_rotation() { return lock_rotation; }317318void set_z_near(const float p_near) { znear = p_near; }319void set_z_far(const float p_far) { zfar = p_far; }320321void set_invert_x_axis(const bool p_invert) { invert_x_axis = p_invert; }322void set_invert_y_axis(const bool p_invert) { invert_y_axis = p_invert; }323324void set_warped_mouse_panning(const bool p_enabled) { warped_mouse_panning = p_enabled; }325Point2 get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_event, const Rect2 &p_surface_rect) const;326327int get_zoom_failed_attempts_count() const { return zoom_failed_attempts_count; }328};329330#endif // _3D_DISABLED331332333