Add navigation control to the spatial editor viewport for the Android editor.
- m4gr3d
cc59e18c9b
This commit is contained in:
Relintai 2022-11-30 18:30:32 +01:00
parent 19efacc416
commit bdf4922a1e
2 changed files with 292 additions and 41 deletions

View File

@ -152,7 +152,7 @@ void ViewportRotationControl::_draw() {
Vector2i center = get_size() / 2.0; Vector2i center = get_size() / 2.0;
float radius = get_size().x / 2.0; float radius = get_size().x / 2.0;
if (focused_axis > -2 || orbiting) { if (focused_axis > -2 || orbiting_index != -1) {
draw_circle(center, radius, Color(0.5, 0.5, 0.5, 0.25)); draw_circle(center, radius, Color(0.5, 0.5, 0.5, 0.25));
} }
@ -225,39 +225,60 @@ void ViewportRotationControl::_get_sorted_axis(Vector<Axis2D> &r_axis) {
r_axis.sort_custom<Axis2DCompare>(); r_axis.sort_custom<Axis2DCompare>();
} }
void ViewportRotationControl::_process_click(int p_index, Vector2 p_position, bool p_pressed) {
if (orbiting_index != -1 && orbiting_index != p_index) {
return;
}
if (p_pressed) {
if (p_position.distance_to(get_size() / 2.0) < get_size().x / 2.0) {
orbiting_index = p_index;
}
} else {
if (focused_axis > -1) {
viewport->_menu_option(axis_menu_options[focused_axis]);
_update_focus();
}
orbiting_index = -1;
if (Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_CAPTURED) {
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
Input::get_singleton()->warp_mouse_position(orbiting_mouse_start);
}
}
}
void ViewportRotationControl::_process_drag(Ref<InputEventWithModifiers> p_event, int p_index, Vector2 p_position, Vector2 p_relative_position) {
if (orbiting_index == p_index) {
if (Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_VISIBLE) {
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
orbiting_mouse_start = p_position;
}
viewport->_nav_orbit(p_event, p_relative_position);
focused_axis = -1;
} else {
_update_focus();
}
}
void ViewportRotationControl::_gui_input(Ref<InputEvent> p_event) { void ViewportRotationControl::_gui_input(Ref<InputEvent> p_event) {
const Ref<InputEventMouseButton> mb = p_event; const Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) { if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) {
Vector2 pos = mb->get_position(); _process_click(100, mb->get_position(), mb->is_pressed());
if (mb->is_pressed()) {
if (pos.distance_to(get_size() / 2.0) < get_size().x / 2.0) {
orbiting = true;
}
} else {
if (focused_axis > -1) {
viewport->_menu_option(axis_menu_options[focused_axis]);
_update_focus();
}
orbiting = false;
if (Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_CAPTURED) {
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
Input::get_singleton()->warp_mouse_position(orbiting_mouse_start);
}
}
} }
const Ref<InputEventMouseMotion> mm = p_event; const Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) { if (mm.is_valid()) {
if (orbiting) { _process_drag(mm, 100, mm->get_global_position(), viewport->_get_warped_mouse_motion(mm));
if (Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_VISIBLE) { }
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
orbiting_mouse_start = mm->get_global_position(); // Touch events
} const Ref<InputEventScreenTouch> screen_touch = p_event;
viewport->_nav_orbit(mm, viewport->_get_warped_mouse_motion(mm)); if (screen_touch.is_valid()) {
focused_axis = -1; _process_click(screen_touch->get_index(), screen_touch->get_position(), screen_touch->is_pressed());
} else { }
_update_focus();
} const Ref<InputEventScreenDrag> screen_drag = p_event;
if (screen_drag.is_valid()) {
_process_drag(screen_drag, screen_drag->get_index(), screen_drag->get_position(), screen_drag->get_relative());
} }
} }
@ -397,6 +418,8 @@ void SpatialEditorViewport::_update_camera(float p_interp_delta) {
update_transform_gizmo_view(); update_transform_gizmo_view();
rotation_control->update(); rotation_control->update();
position_control->update();
look_control->update();
spatial_editor->update_grid(); spatial_editor->update_grid();
} }
} }
@ -2444,7 +2467,7 @@ void SpatialEditorViewport::_nav_pan(Ref<InputEventWithModifiers> p_event, const
real_t pan_speed = 1 / 150.0; real_t pan_speed = 1 / 150.0;
int pan_speed_modifier = 10; int pan_speed_modifier = 10;
if (nav_scheme == NAVIGATION_MAYA && p_event->get_shift()) { if (p_event.is_valid() && nav_scheme == NAVIGATION_MAYA && p_event->get_shift()) {
pan_speed *= pan_speed_modifier; pan_speed *= pan_speed_modifier;
} }
@ -2469,7 +2492,7 @@ void SpatialEditorViewport::_nav_zoom(Ref<InputEventWithModifiers> p_event, cons
real_t zoom_speed = 1 / 80.0; real_t zoom_speed = 1 / 80.0;
int zoom_speed_modifier = 10; int zoom_speed_modifier = 10;
if (nav_scheme == NAVIGATION_MAYA && p_event->get_shift()) { if (p_event.is_valid() && nav_scheme == NAVIGATION_MAYA && p_event->get_shift()) {
zoom_speed *= zoom_speed_modifier; zoom_speed *= zoom_speed_modifier;
} }
@ -2798,6 +2821,8 @@ void SpatialEditorViewport::_notification(int p_what) {
} }
call_deferred("update_transform_gizmo_view"); call_deferred("update_transform_gizmo_view");
rotation_control->set_visible(EditorSettings::get_singleton()->get("editors/3d/navigation/show_viewport_rotation_gizmo")); rotation_control->set_visible(EditorSettings::get_singleton()->get("editors/3d/navigation/show_viewport_rotation_gizmo"));
position_control->set_visible(EditorSettings::get_singleton()->get("editors/3d/navigation/show_viewport_navigation_gizmo"));
look_control->set_visible(EditorSettings::get_singleton()->get("editors/3d/navigation/show_viewport_navigation_gizmo"));
} }
if (p_what == NOTIFICATION_RESIZED) { if (p_what == NOTIFICATION_RESIZED) {
@ -3582,6 +3607,8 @@ void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) {
ERR_FAIL_COND(!p_activate && !previewing); ERR_FAIL_COND(!p_activate && !previewing);
rotation_control->set_visible(!p_activate); rotation_control->set_visible(!p_activate);
position_control->set_visible(!p_activate);
look_control->set_visible(!p_activate);
if (!p_activate) { if (!p_activate) {
previewing->disconnect("tree_exiting", this, "_preview_exited_scene"); previewing->disconnect("tree_exiting", this, "_preview_exited_scene");
@ -3603,6 +3630,8 @@ void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) {
void SpatialEditorViewport::_toggle_cinema_preview(bool p_activate) { void SpatialEditorViewport::_toggle_cinema_preview(bool p_activate) {
previewing_cinema = p_activate; previewing_cinema = p_activate;
rotation_control->set_visible(!p_activate); rotation_control->set_visible(!p_activate);
position_control->set_visible(!p_activate);
look_control->set_visible(!p_activate);
if (!previewing_cinema) { if (!previewing_cinema) {
if (previewing != nullptr) { if (previewing != nullptr) {
@ -4498,6 +4527,14 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
preview_node = nullptr; preview_node = nullptr;
_project_settings_change_pending = false; _project_settings_change_pending = false;
bottom_center_vbox = memnew(VBoxContainer);
bottom_center_vbox->set_anchors_preset(LayoutPreset::PRESET_CENTER);
bottom_center_vbox->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -20 * EDSCALE);
bottom_center_vbox->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -10 * EDSCALE);
bottom_center_vbox->set_h_grow_direction(GROW_DIRECTION_BOTH);
bottom_center_vbox->set_v_grow_direction(GROW_DIRECTION_BEGIN);
surface->add_child(bottom_center_vbox);
info_label = memnew(Label); info_label = memnew(Label);
info_label->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -90 * EDSCALE); info_label->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -90 * EDSCALE);
info_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -90 * EDSCALE); info_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -90 * EDSCALE);
@ -4518,28 +4555,47 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
previewing_cinema = false; previewing_cinema = false;
locked_label = memnew(Label); locked_label = memnew(Label);
locked_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -20 * EDSCALE);
locked_label->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -10 * EDSCALE);
locked_label->set_h_grow_direction(GROW_DIRECTION_END);
locked_label->set_v_grow_direction(GROW_DIRECTION_BEGIN);
locked_label->set_align(Label::ALIGN_CENTER); locked_label->set_align(Label::ALIGN_CENTER);
surface->add_child(locked_label); locked_label->set_h_size_flags(SIZE_SHRINK_CENTER);
bottom_center_vbox->add_child(locked_label);
locked_label->set_text(TTR("View Rotation Locked")); locked_label->set_text(TTR("View Rotation Locked"));
locked_label->hide(); locked_label->hide();
zoom_limit_label = memnew(Label); zoom_limit_label = memnew(Label);
zoom_limit_label->set_anchors_and_margins_preset(LayoutPreset::PRESET_BOTTOM_LEFT);
zoom_limit_label->set_margin(Margin::MARGIN_TOP, -28 * EDSCALE);
zoom_limit_label->set_text(TTR("To zoom further, change the camera's clipping planes (View -> Settings...)")); zoom_limit_label->set_text(TTR("To zoom further, change the camera's clipping planes (View -> Settings...)"));
zoom_limit_label->set_name("ZoomLimitMessageLabel"); zoom_limit_label->set_name("ZoomLimitMessageLabel");
zoom_limit_label->add_theme_color_override("font_color", Color(1, 1, 1, 1)); zoom_limit_label->add_theme_color_override("font_color", Color(1, 1, 1, 1));
zoom_limit_label->hide(); zoom_limit_label->hide();
surface->add_child(zoom_limit_label); bottom_center_vbox->add_child(zoom_limit_label);
top_right_vbox = memnew(VBoxContainer); top_right_vbox = memnew(VBoxContainer);
top_right_vbox->set_anchors_and_margins_preset(PRESET_TOP_RIGHT, PRESET_MODE_MINSIZE, 2.0 * EDSCALE); top_right_vbox->set_anchors_and_margins_preset(PRESET_TOP_RIGHT, PRESET_MODE_MINSIZE, 2.0 * EDSCALE);
top_right_vbox->set_h_grow_direction(GROW_DIRECTION_BEGIN); top_right_vbox->set_h_grow_direction(GROW_DIRECTION_BEGIN);
const int navigation_control_size = 200;
position_control = memnew(ViewportNavigationControl);
position_control->set_navigation_mode(SpatialEditorViewport::NAVIGATION_MOVE);
position_control->set_custom_minimum_size(Size2(navigation_control_size, navigation_control_size) * EDSCALE);
position_control->set_h_size_flags(SIZE_SHRINK_END);
position_control->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 0 * EDSCALE);
position_control->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -navigation_control_size * EDSCALE);
position_control->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_BEGIN, navigation_control_size * EDSCALE);
position_control->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0 * EDSCALE);
position_control->set_viewport(this);
surface->add_child(position_control);
look_control = memnew(ViewportNavigationControl);
look_control->set_navigation_mode(SpatialEditorViewport::NAVIGATION_LOOK);
look_control->set_custom_minimum_size(Size2(navigation_control_size, navigation_control_size) * EDSCALE);
look_control->set_h_size_flags(SIZE_SHRINK_END);
look_control->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -navigation_control_size * EDSCALE);
look_control->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, -navigation_control_size * EDSCALE);
look_control->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0 * EDSCALE);
look_control->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, 0 * EDSCALE);
look_control->set_viewport(this);
surface->add_child(look_control);
rotation_control = memnew(ViewportRotationControl); rotation_control = memnew(ViewportRotationControl);
rotation_control->set_custom_minimum_size(Size2(80, 80) * EDSCALE); rotation_control->set_custom_minimum_size(Size2(80, 80) * EDSCALE);
rotation_control->set_h_size_flags(SIZE_SHRINK_END); rotation_control->set_h_size_flags(SIZE_SHRINK_END);
@ -7435,7 +7491,8 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "editors/3d/manipulator_gizmo_size", PROPERTY_HINT_RANGE, "16,160,1")); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "editors/3d/manipulator_gizmo_size", PROPERTY_HINT_RANGE, "16,160,1"));
EDITOR_DEF("editors/3d/manipulator_gizmo_opacity", 0.9); EDITOR_DEF("editors/3d/manipulator_gizmo_opacity", 0.9);
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::REAL, "editors/3d/manipulator_gizmo_opacity", PROPERTY_HINT_RANGE, "0,1,0.01")); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::REAL, "editors/3d/manipulator_gizmo_opacity", PROPERTY_HINT_RANGE, "0,1,0.01"));
EDITOR_DEF("editors/3d/navigation/show_viewport_rotation_gizmo", true); EDITOR_DEF_RST("editors/3d/navigation/show_viewport_rotation_gizmo", true);
EDITOR_DEF_RST("editors/3d/navigation/show_viewport_navigation_gizmo", OS::get_singleton()->has_touchscreen_ui_hint());
current_hover_gizmo_handle = -1; current_hover_gizmo_handle = -1;
current_hover_gizmo_handle_secondary = false; current_hover_gizmo_handle_secondary = false;
@ -7597,3 +7654,163 @@ SpatialEditorPlugin::SpatialEditorPlugin(EditorNode *p_node) {
SpatialEditorPlugin::~SpatialEditorPlugin() { SpatialEditorPlugin::~SpatialEditorPlugin() {
Engine::get_singleton()->remove_global("SpatialEditor"); Engine::get_singleton()->remove_global("SpatialEditor");
} }
void ViewportNavigationControl::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
if (!is_connected("mouse_exited", this, "_on_mouse_exited")) {
connect("mouse_exited", this, "_on_mouse_exited");
}
}
if (p_what == NOTIFICATION_DRAW && viewport != nullptr) {
_draw();
_update_navigation();
}
}
void ViewportNavigationControl::_draw() {
if (nav_mode == SpatialEditorViewport::NAVIGATION_NONE) {
return;
}
Vector2 center = get_size() / 2.0;
float radius = get_size().x / 2.0;
const bool focused = focused_index != -1;
draw_circle(center, radius, Color(0.5, 0.5, 0.5, focused ? 0.25 : 0.05));
const Color c = focused ? Color(0.9, 0.9, 0.9, 0.9) : Color(0.5, 0.5, 0.5, 0.25);
Vector2 circle_pos = focused ? center.move_toward(focused_pos, radius) : center;
draw_circle(circle_pos, AXIS_CIRCLE_RADIUS, c);
draw_circle(circle_pos, AXIS_CIRCLE_RADIUS * 0.8, c.darkened(0.4));
}
void ViewportNavigationControl::_process_click(int p_index, Vector2 p_position, bool p_pressed) {
if (focused_index != -1 && focused_index != p_index) {
return;
}
if (p_pressed) {
if (p_position.distance_to(get_size() / 2.0) < get_size().x / 2.0) {
focused_pos = p_position;
focused_index = p_index;
update();
}
} else {
focused_index = -1;
if (Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_CAPTURED) {
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
Input::get_singleton()->warp_mouse_position(focused_mouse_start);
}
}
}
void ViewportNavigationControl::_process_drag(int p_index, Vector2 p_position, Vector2 p_relative_position) {
if (focused_index == p_index) {
if (Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_VISIBLE) {
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
focused_mouse_start = p_position;
}
focused_pos += p_relative_position;
update();
}
}
void ViewportNavigationControl::_gui_input(Ref<InputEvent> p_event) {
// Mouse events
const Ref<InputEventMouseButton> mouse_button = p_event;
if (mouse_button.is_valid() && mouse_button->get_button_index() == BUTTON_LEFT) {
_process_click(100, mouse_button->get_position(), mouse_button->is_pressed());
}
const Ref<InputEventMouseMotion> mouse_motion = p_event;
if (mouse_motion.is_valid()) {
_process_drag(100, mouse_motion->get_global_position(), viewport->_get_warped_mouse_motion(mouse_motion));
}
// Touch events
const Ref<InputEventScreenTouch> screen_touch = p_event;
if (screen_touch.is_valid()) {
_process_click(screen_touch->get_index(), screen_touch->get_position(), screen_touch->is_pressed());
}
const Ref<InputEventScreenDrag> screen_drag = p_event;
if (screen_drag.is_valid()) {
_process_drag(screen_drag->get_index(), screen_drag->get_position(), screen_drag->get_relative());
}
}
void ViewportNavigationControl::_update_navigation() {
if (focused_index == -1) {
return;
}
Vector2 delta = focused_pos - (get_size() / 2.0);
Vector2 delta_normalized = delta.normalized();
switch (nav_mode) {
case SpatialEditorViewport::NavigationMode::NAVIGATION_MOVE: {
real_t speed_multiplier = MIN(delta.length() / (get_size().x * 100.0), 3.0);
real_t speed = viewport->freelook_speed * speed_multiplier;
const SpatialEditorViewport::FreelookNavigationScheme navigation_scheme = (SpatialEditorViewport::FreelookNavigationScheme)EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_navigation_scheme").operator int();
Vector3 forward;
if (navigation_scheme == SpatialEditorViewport::FreelookNavigationScheme::FREELOOK_FULLY_AXIS_LOCKED) {
// Forward/backward keys will always go straight forward/backward, never moving on the Y axis.
forward = Vector3(0, 0, delta_normalized.y).rotated(Vector3(0, 1, 0), viewport->camera->get_rotation().y);
} else {
// Forward/backward keys will be relative to the camera pitch.
forward = viewport->camera->get_transform().basis.xform(Vector3(0, 0, delta_normalized.y));
}
const Vector3 right = viewport->camera->get_transform().basis.xform(Vector3(delta_normalized.x, 0, 0));
const Vector3 direction = forward + right;
const Vector3 motion = direction * speed;
viewport->cursor.pos += motion;
viewport->cursor.eye_pos += motion;
} break;
case SpatialEditorViewport::NavigationMode::NAVIGATION_LOOK: {
real_t speed_multiplier = MIN(delta.length() / (get_size().x * 2.5), 3.0);
real_t speed = viewport->freelook_speed * speed_multiplier;
viewport->_nav_look(nullptr, delta_normalized * speed);
} break;
case SpatialEditorViewport::NAVIGATION_PAN: {
real_t speed_multiplier = MIN(delta.length() / (get_size().x), 3.0);
real_t speed = viewport->freelook_speed * speed_multiplier;
viewport->_nav_pan(nullptr, -delta_normalized * speed);
} break;
case SpatialEditorViewport::NAVIGATION_ZOOM: {
real_t speed_multiplier = MIN(delta.length() / (get_size().x), 3.0);
real_t speed = viewport->freelook_speed * speed_multiplier;
viewport->_nav_zoom(nullptr, delta_normalized * speed);
} break;
case SpatialEditorViewport::NAVIGATION_ORBIT: {
real_t speed_multiplier = MIN(delta.length() / (get_size().x), 3.0);
real_t speed = viewport->freelook_speed * speed_multiplier;
viewport->_nav_orbit(nullptr, delta_normalized * speed);
} break;
case SpatialEditorViewport::NAVIGATION_NONE: {
} break;
}
}
void ViewportNavigationControl::_on_mouse_exited() {
update();
}
void ViewportNavigationControl::set_navigation_mode(SpatialEditorViewport::NavigationMode p_nav_mode) {
nav_mode = p_nav_mode;
}
void ViewportNavigationControl::set_viewport(SpatialEditorViewport *p_viewport) {
viewport = p_viewport;
}
void ViewportNavigationControl::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &ViewportNavigationControl::_gui_input);
ClassDB::bind_method(D_METHOD("_on_mouse_exited"), &ViewportNavigationControl::_on_mouse_exited);
}

View File

@ -97,6 +97,7 @@ class UndoRedo;
class VSplitContainer; class VSplitContainer;
class Viewport; class Viewport;
class SpinBox; class SpinBox;
class ViewportNavigationControl;
class ViewportRotationControl : public Control { class ViewportRotationControl : public Control {
GDCLASS(ViewportRotationControl, Control); GDCLASS(ViewportRotationControl, Control);
@ -117,7 +118,7 @@ class ViewportRotationControl : public Control {
Vector<Color> axis_colors; Vector<Color> axis_colors;
Vector<int> axis_menu_options; Vector<int> axis_menu_options;
Vector2i orbiting_mouse_start; Vector2i orbiting_mouse_start;
bool orbiting = false; int orbiting_index = -1;
int focused_axis = -2; int focused_axis = -2;
const float AXIS_CIRCLE_RADIUS = 8.0f * EDSCALE; const float AXIS_CIRCLE_RADIUS = 8.0f * EDSCALE;
@ -131,6 +132,8 @@ protected:
void _get_sorted_axis(Vector<Axis2D> &r_axis); void _get_sorted_axis(Vector<Axis2D> &r_axis);
void _update_focus(); void _update_focus();
void _on_mouse_exited(); void _on_mouse_exited();
void _process_click(int p_index, Vector2 p_position, bool p_pressed);
void _process_drag(Ref<InputEventWithModifiers> p_event, int p_index, Vector2 p_position, Vector2 p_relative_position);
public: public:
void set_viewport(SpatialEditorViewport *p_viewport); void set_viewport(SpatialEditorViewport *p_viewport);
@ -139,9 +142,10 @@ public:
class SpatialEditorViewport : public Control { class SpatialEditorViewport : public Control {
GDCLASS(SpatialEditorViewport, Control); GDCLASS(SpatialEditorViewport, Control);
friend class SpatialEditor; friend class SpatialEditor;
friend class ViewportNavigationControl;
friend class ViewportRotationControl; friend class ViewportRotationControl;
enum {
enum {
VIEW_TOP, VIEW_TOP,
VIEW_BOTTOM, VIEW_BOTTOM,
VIEW_LEFT, VIEW_LEFT,
@ -244,6 +248,9 @@ private:
Label *zoom_limit_label; Label *zoom_limit_label;
VBoxContainer *top_right_vbox; VBoxContainer *top_right_vbox;
VBoxContainer *bottom_center_vbox;
ViewportNavigationControl *position_control;
ViewportNavigationControl *look_control;
ViewportRotationControl *rotation_control; ViewportRotationControl *rotation_control;
Gradient *frame_time_gradient; Gradient *frame_time_gradient;
Label *fps_label; Label *fps_label;
@ -300,7 +307,8 @@ private:
NAVIGATION_PAN, NAVIGATION_PAN,
NAVIGATION_ZOOM, NAVIGATION_ZOOM,
NAVIGATION_ORBIT, NAVIGATION_ORBIT,
NAVIGATION_LOOK NAVIGATION_LOOK,
NAVIGATION_MOVE
}; };
public: public:
@ -861,4 +869,30 @@ public:
~SpatialEditorPlugin(); ~SpatialEditorPlugin();
}; };
class ViewportNavigationControl : public Control {
GDCLASS(ViewportNavigationControl, Control);
SpatialEditorViewport *viewport = nullptr;
Vector2i focused_mouse_start;
Vector2 focused_pos;
int focused_index = -1;
SpatialEditorViewport::NavigationMode nav_mode = SpatialEditorViewport::NavigationMode::NAVIGATION_NONE;
const float AXIS_CIRCLE_RADIUS = 30.0f * EDSCALE;
protected:
static void _bind_methods();
void _notification(int p_what);
void _gui_input(Ref<InputEvent> p_event);
void _draw();
void _on_mouse_exited();
void _process_click(int p_index, Vector2 p_position, bool p_pressed);
void _process_drag(int p_index, Vector2 p_position, Vector2 p_relative_position);
void _update_navigation();
public:
void set_navigation_mode(SpatialEditorViewport::NavigationMode p_nav_mode);
void set_viewport(SpatialEditorViewport *p_viewport);
};
#endif #endif