summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRĂ©mi Verschelde <rverschelde@gmail.com>2017-11-21 13:03:32 +0100
committerGitHub <noreply@github.com>2017-11-21 13:03:32 +0100
commit5a23136d1bdc88589ee7082098dadf74afef53c2 (patch)
tree70f59ef74795849c2941db99d92ba61e36a5bf8a
parentec4d467b4c5edac86af6aaab0545770377294346 (diff)
parent80ad8afc85a90e6fda1b136b13c1eb42e35c115e (diff)
Merge pull request #12573 from poke1024/macostouchpad
Native pan and zoom for macOS + InputEventGesture
-rw-r--r--core/os/input_event.cpp90
-rw-r--r--core/os/input_event.h40
-rw-r--r--editor/animation_editor.cpp12
-rw-r--r--editor/code_editor.cpp38
-rw-r--r--editor/code_editor.h3
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp16
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp13
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp216
-rw-r--r--editor/plugins/spatial_editor_plugin.h5
-rw-r--r--main/input_default.cpp9
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp10
-rw-r--r--platform/osx/os_osx.mm54
-rw-r--r--scene/gui/graph_edit.cpp22
-rw-r--r--scene/gui/graph_edit.h1
-rw-r--r--scene/gui/item_list.cpp6
-rw-r--r--scene/gui/rich_text_label.cpp10
-rw-r--r--scene/gui/scroll_container.cpp11
-rw-r--r--scene/gui/text_edit.cpp97
-rw-r--r--scene/gui/text_edit.h3
-rw-r--r--scene/gui/tree.cpp6
-rw-r--r--scene/main/viewport.cpp24
21 files changed, 551 insertions, 135 deletions
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index 6b43f2c63b..103a8e82c2 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -177,6 +177,14 @@ bool InputEventWithModifiers::get_command() const {
return command;
}
+void InputEventWithModifiers::set_modifiers_from_event(const InputEventWithModifiers *event) {
+
+ set_alt(event->get_alt());
+ set_shift(event->get_shift());
+ set_control(event->get_control());
+ set_metakey(event->get_metakey());
+}
+
void InputEventWithModifiers::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_alt", "enable"), &InputEventWithModifiers::set_alt);
@@ -436,10 +444,7 @@ Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, co
mb->set_id(get_id());
mb->set_device(get_device());
- mb->set_alt(get_alt());
- mb->set_shift(get_shift());
- mb->set_control(get_control());
- mb->set_metakey(get_metakey());
+ mb->set_modifiers_from_event(this);
mb->set_position(l);
mb->set_global_position(g);
@@ -555,10 +560,7 @@ Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, co
mm->set_id(get_id());
mm->set_device(get_device());
- mm->set_alt(get_alt());
- mm->set_shift(get_shift());
- mm->set_control(get_control());
- mm->set_metakey(get_metakey());
+ mm->set_modifiers_from_event(this);
mm->set_position(l);
mm->set_global_position(g);
@@ -930,3 +932,75 @@ void InputEventAction::_bind_methods() {
InputEventAction::InputEventAction() {
pressed = false;
}
+/////////////////////////////
+
+void InputEventGesture::set_position(const Vector2 &p_pos) {
+
+ pos = p_pos;
+}
+
+Vector2 InputEventGesture::get_position() const {
+
+ return pos;
+}
+/////////////////////////////
+
+void InputEventMagnifyGesture::set_factor(real_t p_factor) {
+
+ factor = p_factor;
+}
+
+real_t InputEventMagnifyGesture::get_factor() const {
+
+ return factor;
+}
+
+Ref<InputEvent> InputEventMagnifyGesture::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
+
+ Ref<InputEventMagnifyGesture> ev;
+ ev.instance();
+
+ ev->set_id(get_id());
+ ev->set_device(get_device());
+ ev->set_modifiers_from_event(this);
+
+ ev->set_position(p_xform.xform(get_position() + p_local_ofs));
+ ev->set_factor(get_factor());
+
+ return ev;
+}
+
+InputEventMagnifyGesture::InputEventMagnifyGesture() {
+
+ factor = 1.0;
+}
+/////////////////////////////
+
+void InputEventPanGesture::set_delta(const Vector2 &p_delta) {
+
+ delta = p_delta;
+}
+
+Vector2 InputEventPanGesture::get_delta() const {
+ return delta;
+}
+
+Ref<InputEvent> InputEventPanGesture::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const {
+
+ Ref<InputEventPanGesture> ev;
+ ev.instance();
+
+ ev->set_id(get_id());
+ ev->set_device(get_device());
+ ev->set_modifiers_from_event(this);
+
+ ev->set_position(p_xform.xform(get_position() + p_local_ofs));
+ ev->set_delta(get_delta());
+
+ return ev;
+}
+
+InputEventPanGesture::InputEventPanGesture() {
+
+ delta = Vector2(0, 0);
+}
diff --git a/core/os/input_event.h b/core/os/input_event.h
index de3c0232ff..2cba60bede 100644
--- a/core/os/input_event.h
+++ b/core/os/input_event.h
@@ -213,6 +213,8 @@ public:
void set_command(bool p_enabled);
bool get_command() const;
+ void set_modifiers_from_event(const InputEventWithModifiers *event);
+
InputEventWithModifiers();
};
@@ -468,4 +470,42 @@ public:
InputEventAction();
};
+class InputEventGesture : public InputEventWithModifiers {
+
+ GDCLASS(InputEventGesture, InputEventWithModifiers)
+
+ Vector2 pos;
+
+public:
+ void set_position(const Vector2 &p_pos);
+ Vector2 get_position() const;
+};
+
+class InputEventMagnifyGesture : public InputEventGesture {
+
+ GDCLASS(InputEventMagnifyGesture, InputEventGesture)
+ real_t factor;
+
+public:
+ void set_factor(real_t p_factor);
+ real_t get_factor() const;
+
+ virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
+
+ InputEventMagnifyGesture();
+};
+
+class InputEventPanGesture : public InputEventGesture {
+
+ GDCLASS(InputEventPanGesture, InputEventGesture)
+ Vector2 delta;
+
+public:
+ void set_delta(const Vector2 &p_delta);
+ Vector2 get_delta() const;
+
+ virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
+
+ InputEventPanGesture();
+};
#endif
diff --git a/editor/animation_editor.cpp b/editor/animation_editor.cpp
index 7d877bdb8c..ae304ed0bc 100644
--- a/editor/animation_editor.cpp
+++ b/editor/animation_editor.cpp
@@ -2889,6 +2889,18 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input)
}
}
}
+
+ Ref<InputEventMagnifyGesture> magnify_gesture = p_input;
+ if (magnify_gesture.is_valid()) {
+ zoom->set_value(zoom->get_value() * magnify_gesture->get_factor());
+ }
+
+ Ref<InputEventPanGesture> pan_gesture = p_input;
+ if (pan_gesture.is_valid()) {
+
+ h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * pan_gesture->get_delta().x / 8);
+ v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * pan_gesture->get_delta().y / 8);
+ }
}
void AnimationKeyEditor::_notification(int p_what) {
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index c7012a0c14..216f2027fb 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -979,6 +979,23 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
}
}
+ Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
+ if (magnify_gesture.is_valid()) {
+
+ Ref<DynamicFont> font = text_editor->get_font("font");
+
+ if (font.is_valid()) {
+ if (font->get_size() != (int)font_size) {
+ font_size = font->get_size();
+ }
+
+ font_size *= powf(magnify_gesture->get_factor(), 0.25);
+
+ _add_font_size((int)font_size - font->get_size());
+ }
+ return;
+ }
+
Ref<InputEventKey> k = p_event;
if (k.is_valid()) {
@@ -999,14 +1016,15 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
void CodeTextEditor::_zoom_in() {
font_resize_val += EDSCALE;
-
- if (font_resize_timer->get_time_left() == 0)
- font_resize_timer->start();
+ _zoom_changed();
}
void CodeTextEditor::_zoom_out() {
font_resize_val -= EDSCALE;
+ _zoom_changed();
+}
+void CodeTextEditor::_zoom_changed() {
if (font_resize_timer->get_time_left() == 0)
font_resize_timer->start();
}
@@ -1067,16 +1085,25 @@ void CodeTextEditor::_complete_request() {
void CodeTextEditor::_font_resize_timeout() {
+ if (_add_font_size(font_resize_val)) {
+ font_resize_val = 0;
+ }
+}
+
+bool CodeTextEditor::_add_font_size(int p_delta) {
+
Ref<DynamicFont> font = text_editor->get_font("font");
if (font.is_valid()) {
- int new_size = CLAMP(font->get_size() + font_resize_val, 8 * EDSCALE, 96 * EDSCALE);
+ int new_size = CLAMP(font->get_size() + p_delta, 8 * EDSCALE, 96 * EDSCALE);
if (new_size != font->get_size()) {
EditorSettings::get_singleton()->set("interface/editor/source_font_size", new_size / EDSCALE);
font->set_size(new_size);
}
- font_resize_val = 0;
+ return true;
+ } else {
+ return false;
}
}
@@ -1285,6 +1312,7 @@ CodeTextEditor::CodeTextEditor() {
code_complete_timer->connect("timeout", this, "_code_complete_timer_timeout");
font_resize_val = 0;
+ font_size = -1;
font_resize_timer = memnew(Timer);
add_child(font_resize_timer);
font_resize_timer->set_one_shot(true);
diff --git a/editor/code_editor.h b/editor/code_editor.h
index 410dd99878..656ea4b47b 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -204,6 +204,7 @@ class CodeTextEditor : public VBoxContainer {
Timer *font_resize_timer;
int font_resize_val;
+ real_t font_size;
Label *error;
@@ -212,10 +213,12 @@ class CodeTextEditor : public VBoxContainer {
void _update_font();
void _complete_request();
void _font_resize_timeout();
+ bool _add_font_size(int p_delta);
void _text_editor_gui_input(const Ref<InputEvent> &p_event);
void _zoom_in();
void _zoom_out();
+ void _zoom_changed();
void _reset_zoom();
CodeTextEditorCodeCompleteFunc code_complete_func;
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 6cb4171f5a..3940dd9044 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1442,6 +1442,22 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
}
}
+ Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
+ if (magnify_gesture.is_valid()) {
+
+ _zoom_on_position(zoom * magnify_gesture->get_factor(), magnify_gesture->get_position());
+ return;
+ }
+
+ Ref<InputEventPanGesture> pan_gesture = p_event;
+ if (pan_gesture.is_valid()) {
+
+ const Vector2 delta = (int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom) * pan_gesture->get_delta();
+ h_scroll->set_value(h_scroll->get_value() + delta.x);
+ v_scroll->set_value(v_scroll->get_value() + delta.y);
+ return;
+ }
+
Ref<InputEventMouseButton> b = p_event;
if (b.is_valid()) {
// Button event
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index a525983c75..ebb5f57e99 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -339,6 +339,19 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
uv_edit_draw->update();
}
}
+
+ Ref<InputEventMagnifyGesture> magnify_gesture = p_input;
+ if (magnify_gesture.is_valid()) {
+
+ uv_zoom->set_value(uv_zoom->get_value() * magnify_gesture->get_factor());
+ }
+
+ Ref<InputEventPanGesture> pan_gesture = p_input;
+ if (pan_gesture.is_valid()) {
+
+ uv_hscroll->set_value(uv_hscroll->get_value() + uv_hscroll->get_page() * pan_gesture->get_delta().x / 8);
+ uv_vscroll->set_value(uv_vscroll->get_value() + uv_vscroll->get_page() * pan_gesture->get_delta().y / 8);
+ }
}
void Polygon2DEditor::_uv_scroll_changed(float) {
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 448daab226..921ba529a2 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -1694,92 +1694,78 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
switch (nav_mode) {
case NAVIGATION_PAN: {
+ _nav_pan(m, _get_warped_mouse_motion(m));
- real_t pan_speed = 1 / 150.0;
- int pan_speed_modifier = 10;
- if (nav_scheme == NAVIGATION_MAYA && m->get_shift())
- pan_speed *= pan_speed_modifier;
+ } break;
- Point2i relative = _get_warped_mouse_motion(m);
+ case NAVIGATION_ZOOM: {
+ _nav_zoom(m, m->get_relative());
- Transform camera_transform;
+ } break;
- camera_transform.translate(cursor.pos);
- camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
- camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot);
- Vector3 translation(-relative.x * pan_speed, relative.y * pan_speed, 0);
- translation *= cursor.distance / DISTANCE_DEFAULT;
- camera_transform.translate(translation);
- cursor.pos = camera_transform.origin;
+ case NAVIGATION_ORBIT: {
+ _nav_orbit(m, _get_warped_mouse_motion(m));
+
+ } break;
+
+ case NAVIGATION_LOOK: {
+ _nav_look(m, _get_warped_mouse_motion(m));
+
+ } break;
+
+ default: {}
+ }
+ }
+
+ Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
+ if (magnify_gesture.is_valid()) {
+
+ if (is_freelook_active())
+ scale_freelook_speed(magnify_gesture->get_factor());
+ else
+ scale_cursor_distance(1.0 / magnify_gesture->get_factor());
+ }
+
+ Ref<InputEventPanGesture> pan_gesture = p_event;
+ if (pan_gesture.is_valid()) {
+
+ NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int();
+ NavigationMode nav_mode = NAVIGATION_NONE;
+
+ if (nav_scheme == NAVIGATION_GODOT) {
+
+ int mod = _get_key_modifier(pan_gesture);
+
+ if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier"))
+ nav_mode = NAVIGATION_PAN;
+ else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier"))
+ nav_mode = NAVIGATION_ZOOM;
+ else if (mod == _get_key_modifier_setting("editors/3d/navigation/orbit_modifier"))
+ nav_mode = NAVIGATION_ORBIT;
+
+ } else if (nav_scheme == NAVIGATION_MAYA) {
+ if (pan_gesture->get_alt())
+ nav_mode = NAVIGATION_PAN;
+ }
+
+ switch (nav_mode) {
+ case NAVIGATION_PAN: {
+ _nav_pan(m, pan_gesture->get_delta());
} break;
case NAVIGATION_ZOOM: {
- real_t zoom_speed = 1 / 80.0;
- int zoom_speed_modifier = 10;
- if (nav_scheme == NAVIGATION_MAYA && m->get_shift())
- zoom_speed *= zoom_speed_modifier;
-
- NavigationZoomStyle zoom_style = (NavigationZoomStyle)EditorSettings::get_singleton()->get("editors/3d/navigation/zoom_style").operator int();
- if (zoom_style == NAVIGATION_ZOOM_HORIZONTAL) {
- if (m->get_relative().x > 0)
- scale_cursor_distance(1 - m->get_relative().x * zoom_speed);
- else if (m->get_relative().x < 0)
- scale_cursor_distance(1.0 / (1 + m->get_relative().x * zoom_speed));
- } else {
- if (m->get_relative().y > 0)
- scale_cursor_distance(1 + m->get_relative().y * zoom_speed);
- else if (m->get_relative().y < 0)
- scale_cursor_distance(1.0 / (1 - m->get_relative().y * zoom_speed));
- }
+ _nav_zoom(m, pan_gesture->get_delta());
} break;
case NAVIGATION_ORBIT: {
- Point2i relative = _get_warped_mouse_motion(m);
-
- real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity");
- real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel);
-
- cursor.x_rot += relative.y * radians_per_pixel;
- cursor.y_rot += relative.x * radians_per_pixel;
- if (cursor.x_rot > Math_PI / 2.0)
- cursor.x_rot = Math_PI / 2.0;
- if (cursor.x_rot < -Math_PI / 2.0)
- cursor.x_rot = -Math_PI / 2.0;
- name = "";
- _update_name();
+ _nav_orbit(m, pan_gesture->get_delta());
+
} break;
case NAVIGATION_LOOK: {
- // Freelook only works properly in perspective.
- // It technically works too in ortho, but it's awful for a user due to fov being near zero
- if (!orthogonal) {
- Point2i relative = _get_warped_mouse_motion(m);
-
- real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity");
- real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel);
-
- // Note: do NOT assume the camera has the "current" transform, because it is interpolated and may have "lag".
- Transform prev_camera_transform = to_camera_transform(cursor);
-
- cursor.x_rot += relative.y * radians_per_pixel;
- cursor.y_rot += relative.x * radians_per_pixel;
- if (cursor.x_rot > Math_PI / 2.0)
- cursor.x_rot = Math_PI / 2.0;
- if (cursor.x_rot < -Math_PI / 2.0)
- cursor.x_rot = -Math_PI / 2.0;
-
- // Look is like the opposite of Orbit: the focus point rotates around the camera
- Transform camera_transform = to_camera_transform(cursor);
- Vector3 pos = camera_transform.xform(Vector3(0, 0, 0));
- Vector3 prev_pos = prev_camera_transform.xform(Vector3(0, 0, 0));
- Vector3 diff = prev_pos - pos;
- cursor.pos += diff;
-
- name = "";
- _update_name();
- }
+ _nav_look(m, pan_gesture->get_delta());
} break;
@@ -1885,6 +1871,94 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
accept_event();
}
+void SpatialEditorViewport::_nav_pan(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative) {
+
+ const NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int();
+
+ real_t pan_speed = 1 / 150.0;
+ int pan_speed_modifier = 10;
+ if (nav_scheme == NAVIGATION_MAYA && p_event->get_shift())
+ pan_speed *= pan_speed_modifier;
+
+ Transform camera_transform;
+
+ camera_transform.translate(cursor.pos);
+ camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
+ camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot);
+ Vector3 translation(-p_relative.x * pan_speed, p_relative.y * pan_speed, 0);
+ translation *= cursor.distance / DISTANCE_DEFAULT;
+ camera_transform.translate(translation);
+ cursor.pos = camera_transform.origin;
+}
+
+void SpatialEditorViewport::_nav_zoom(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative) {
+
+ const NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int();
+
+ real_t zoom_speed = 1 / 80.0;
+ int zoom_speed_modifier = 10;
+ if (nav_scheme == NAVIGATION_MAYA && p_event->get_shift())
+ zoom_speed *= zoom_speed_modifier;
+
+ NavigationZoomStyle zoom_style = (NavigationZoomStyle)EditorSettings::get_singleton()->get("editors/3d/navigation/zoom_style").operator int();
+ if (zoom_style == NAVIGATION_ZOOM_HORIZONTAL) {
+ if (p_relative.x > 0)
+ scale_cursor_distance(1 - p_relative.x * zoom_speed);
+ else if (p_relative.x < 0)
+ scale_cursor_distance(1.0 / (1 + p_relative.x * zoom_speed));
+ } else {
+ if (p_relative.y > 0)
+ scale_cursor_distance(1 + p_relative.y * zoom_speed);
+ else if (p_relative.y < 0)
+ scale_cursor_distance(1.0 / (1 - p_relative.y * zoom_speed));
+ }
+}
+
+void SpatialEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative) {
+
+ real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity");
+ real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel);
+
+ cursor.x_rot += p_relative.y * radians_per_pixel;
+ cursor.y_rot += p_relative.x * radians_per_pixel;
+ if (cursor.x_rot > Math_PI / 2.0)
+ cursor.x_rot = Math_PI / 2.0;
+ if (cursor.x_rot < -Math_PI / 2.0)
+ cursor.x_rot = -Math_PI / 2.0;
+ name = "";
+ _update_name();
+}
+
+void SpatialEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative) {
+
+ // Freelook only works properly in perspective.
+ // It technically works too in ortho, but it's awful for a user due to fov being near zero
+ if (!orthogonal) {
+ real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity");
+ real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel);
+
+ // Note: do NOT assume the camera has the "current" transform, because it is interpolated and may have "lag".
+ Transform prev_camera_transform = to_camera_transform(cursor);
+
+ cursor.x_rot += p_relative.y * radians_per_pixel;
+ cursor.y_rot += p_relative.x * radians_per_pixel;
+ if (cursor.x_rot > Math_PI / 2.0)
+ cursor.x_rot = Math_PI / 2.0;
+ if (cursor.x_rot < -Math_PI / 2.0)
+ cursor.x_rot = -Math_PI / 2.0;
+
+ // Look is like the opposite of Orbit: the focus point rotates around the camera
+ Transform camera_transform = to_camera_transform(cursor);
+ Vector3 pos = camera_transform.xform(Vector3(0, 0, 0));
+ Vector3 prev_pos = prev_camera_transform.xform(Vector3(0, 0, 0));
+ Vector3 diff = prev_pos - pos;
+ cursor.pos += diff;
+
+ name = "";
+ _update_name();
+ }
+}
+
void SpatialEditorViewport::set_freelook_active(bool active_now) {
if (!freelook_active && active_now) {
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index ad11ec33df..14558fc878 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -170,6 +170,11 @@ private:
void _select_region();
bool _gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only = false);
+ void _nav_pan(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
+ void _nav_zoom(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
+ void _nav_orbit(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
+ void _nav_look(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
+
float get_znear() const;
float get_zfar() const;
float get_fov() const;
diff --git a/main/input_default.cpp b/main/input_default.cpp
index 2940f432d5..7cc7521686 100644
--- a/main/input_default.cpp
+++ b/main/input_default.cpp
@@ -319,6 +319,15 @@ void InputDefault::parse_input_event(const Ref<InputEvent> &p_event) {
set_joy_axis(jm->get_device(), jm->get_axis(), jm->get_axis_value());
}
+ Ref<InputEventGesture> ge = p_event;
+
+ if (ge.is_valid()) {
+
+ if (main_loop) {
+ main_loop->input_event(ge);
+ }
+ }
+
if (!p_event->is_echo()) {
for (const Map<StringName, InputMap::Action>::Element *E = InputMap::get_singleton()->get_action_map().front(); E; E = E->next()) {
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index 491adb31ee..3a5d0fd3fc 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -623,6 +623,16 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu
return do_input_action(p_camera, mm->get_position(), false);
}
+ Ref<InputEventPanGesture> pan_gesture = p_event;
+ if (pan_gesture.is_valid()) {
+
+ if (pan_gesture->get_command() || pan_gesture->get_shift()) {
+ const real_t delta = pan_gesture->get_delta().y;
+ floor->set_value(floor->get_value() + SGN(delta));
+ return true;
+ }
+ }
+
return false;
}
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 110cb776ee..cb6fff7855 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -85,6 +85,15 @@ static int prev_mouse_y = 0;
static int button_mask = 0;
static bool mouse_down_control = false;
+static Vector2 get_mouse_pos(NSEvent *event) {
+
+ const NSRect contentRect = [OS_OSX::singleton->window_view frame];
+ const NSPoint p = [event locationInWindow];
+ mouse_x = p.x * OS_OSX::singleton->_mouse_scale([[event window] backingScaleFactor]);
+ mouse_y = (contentRect.size.height - p.y) * OS_OSX::singleton->_mouse_scale([[event window] backingScaleFactor]);
+ return Vector2(mouse_x, mouse_y);
+}
+
@interface GodotApplication : NSApplication
@end
@@ -508,12 +517,9 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) {
mm->set_button_mask(button_mask);
prev_mouse_x = mouse_x;
prev_mouse_y = mouse_y;
- const NSRect contentRect = [OS_OSX::singleton->window_view frame];
- const NSPoint p = [event locationInWindow];
- mouse_x = p.x * OS_OSX::singleton->_mouse_scale([[event window] backingScaleFactor]);
- mouse_y = (contentRect.size.height - p.y) * OS_OSX::singleton->_mouse_scale([[event window] backingScaleFactor]);
- mm->set_position(Vector2(mouse_x, mouse_y));
- mm->set_global_position(Vector2(mouse_x, mouse_y));
+ const Vector2 pos = get_mouse_pos(event);
+ mm->set_position(pos);
+ mm->set_global_position(pos);
Vector2 relativeMotion = Vector2();
relativeMotion.x = [event deltaX] * OS_OSX::singleton->_mouse_scale([[event window] backingScaleFactor]);
relativeMotion.y = [event deltaY] * OS_OSX::singleton->_mouse_scale([[event window] backingScaleFactor]);
@@ -575,6 +581,15 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) {
OS_OSX::singleton->input->set_mouse_in_window(true);
}
+- (void)magnifyWithEvent:(NSEvent *)event {
+ Ref<InputEventMagnifyGesture> ev;
+ ev.instance();
+ get_key_modifier_state([event modifierFlags], ev);
+ ev->set_position(get_mouse_pos(event));
+ ev->set_factor([event magnification] + 1.0);
+ OS_OSX::singleton->push_input(ev);
+}
+
- (void)viewDidChangeBackingProperties {
// nothing left to do here
}
@@ -838,6 +853,18 @@ inline void sendScrollEvent(int button, double factor, int modifierFlags) {
OS_OSX::singleton->push_input(sc);
}
+inline void sendPanEvent(double dx, double dy, int modifierFlags) {
+
+ Ref<InputEventPanGesture> pg;
+ pg.instance();
+
+ get_key_modifier_state(modifierFlags, pg);
+ Vector2 mouse_pos = Vector2(mouse_x, mouse_y);
+ pg->set_position(mouse_pos);
+ pg->set_delta(Vector2(-dx, -dy));
+ OS_OSX::singleton->push_input(pg);
+}
+
- (void)scrollWheel:(NSEvent *)event {
double deltaX, deltaY;
@@ -856,11 +883,16 @@ inline void sendScrollEvent(int button, double factor, int modifierFlags) {
deltaX = [event deltaX];
deltaY = [event deltaY];
}
- if (fabs(deltaX)) {
- sendScrollEvent(0 > deltaX ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_LEFT, fabs(deltaX * 0.3), [event modifierFlags]);
- }
- if (fabs(deltaY)) {
- sendScrollEvent(0 < deltaY ? BUTTON_WHEEL_UP : BUTTON_WHEEL_DOWN, fabs(deltaY * 0.3), [event modifierFlags]);
+
+ if ([event phase] != NSEventPhaseNone || [event momentumPhase] != NSEventPhaseNone) {
+ sendPanEvent(deltaX, deltaY, [event modifierFlags]);
+ } else {
+ if (fabs(deltaX)) {
+ sendScrollEvent(0 > deltaX ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_LEFT, fabs(deltaX * 0.3), [event modifierFlags]);
+ }
+ if (fabs(deltaY)) {
+ sendScrollEvent(0 < deltaY ? BUTTON_WHEEL_UP : BUTTON_WHEEL_DOWN, fabs(deltaY * 0.3), [event modifierFlags]);
+ }
}
}
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 946a8c47a3..da52fb39e0 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -964,6 +964,19 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
emit_signal("delete_nodes_request");
accept_event();
}
+
+ Ref<InputEventMagnifyGesture> magnify_gesture = p_ev;
+ if (magnify_gesture.is_valid()) {
+
+ set_zoom_custom(zoom * magnify_gesture->get_factor(), magnify_gesture->get_position());
+ }
+
+ Ref<InputEventPanGesture> pan_gesture = p_ev;
+ if (pan_gesture.is_valid()) {
+
+ h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * pan_gesture->get_delta().x / 8);
+ v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * pan_gesture->get_delta().y / 8);
+ }
}
void GraphEdit::clear_connections() {
@@ -975,6 +988,11 @@ void GraphEdit::clear_connections() {
void GraphEdit::set_zoom(float p_zoom) {
+ set_zoom_custom(p_zoom, get_size() / 2);
+}
+
+void GraphEdit::set_zoom_custom(float p_zoom, const Vector2 &p_center) {
+
p_zoom = CLAMP(p_zoom, MIN_ZOOM, MAX_ZOOM);
if (zoom == p_zoom)
return;
@@ -982,7 +1000,7 @@ void GraphEdit::set_zoom(float p_zoom) {
zoom_minus->set_disabled(zoom == MIN_ZOOM);
zoom_plus->set_disabled(zoom == MAX_ZOOM);
- Vector2 sbofs = (Vector2(h_scroll->get_value(), v_scroll->get_value()) + get_size() / 2) / zoom;
+ Vector2 sbofs = (Vector2(h_scroll->get_value(), v_scroll->get_value()) + p_center) / zoom;
zoom = p_zoom;
top_layer->update();
@@ -992,7 +1010,7 @@ void GraphEdit::set_zoom(float p_zoom) {
if (is_visible_in_tree()) {
- Vector2 ofs = sbofs * zoom - get_size() / 2;
+ Vector2 ofs = sbofs * zoom - p_center;
h_scroll->set_value(ofs.x);
v_scroll->set_value(ofs.y);
}
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index 4656b50133..e8e530848d 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -179,6 +179,7 @@ public:
bool is_valid_connection_type(int p_type, int p_with_type) const;
void set_zoom(float p_zoom);
+ void set_zoom_custom(float p_zoom, const Vector2 &p_center);
float get_zoom() const;
GraphEditFilter *get_top_layer() const { return top_layer; }
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 5e4dedcb48..51ab49e643 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -713,6 +713,12 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
}
}
}
+
+ Ref<InputEventPanGesture> pan_gesture = p_event;
+ if (pan_gesture.is_valid()) {
+
+ scroll_bar->set_value(scroll_bar->get_value() + scroll_bar->get_page() * pan_gesture->get_delta().y / 8);
+ }
}
void ItemList::ensure_current_is_visible() {
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 71e02cb2f7..124c268c8a 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -817,6 +817,16 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
}
}
+ Ref<InputEventPanGesture> pan_gesture = p_event;
+ if (pan_gesture.is_valid()) {
+
+ if (scroll_active)
+
+ vscroll->set_value(vscroll->get_value() + vscroll->get_page() * pan_gesture->get_delta().y * 0.5 / 8);
+
+ return;
+ }
+
Ref<InputEventKey> k = p_event;
if (k.is_valid()) {
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index 9022d67a4a..a71a1c5f92 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -180,6 +180,17 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
time_since_motion = 0;
}
}
+
+ Ref<InputEventPanGesture> pan_gesture = p_gui_input;
+ if (pan_gesture.is_valid()) {
+
+ if (h_scroll->is_visible_in_tree()) {
+ h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * pan_gesture->get_delta().x / 8);
+ }
+ if (v_scroll->is_visible_in_tree()) {
+ v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * pan_gesture->get_delta().y / 8);
+ }
+ }
}
void ScrollContainer::_update_scrollbar_position() {
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 21842d4d58..2c47c4e827 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1777,46 +1777,10 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (mb->is_pressed()) {
if (mb->get_button_index() == BUTTON_WHEEL_UP && !mb->get_command()) {
- float scroll_factor = 3 * mb->get_factor();
- if (scrolling) {
- target_v_scroll = (target_v_scroll - scroll_factor);
- } else {
- target_v_scroll = (v_scroll->get_value() - scroll_factor);
- }
-
- if (smooth_scroll_enabled) {
- if (target_v_scroll <= 0) {
- target_v_scroll = 0;
- }
- scrolling = true;
- set_physics_process(true);
- } else {
- v_scroll->set_value(target_v_scroll);
- }
+ _scroll_up(3 * mb->get_factor());
}
if (mb->get_button_index() == BUTTON_WHEEL_DOWN && !mb->get_command()) {
- float scroll_factor = 3 * mb->get_factor();
- if (scrolling) {
- target_v_scroll = (target_v_scroll + scroll_factor);
- } else {
- target_v_scroll = (v_scroll->get_value() + scroll_factor);
- }
-
- if (smooth_scroll_enabled) {
- int max_v_scroll = get_total_unhidden_rows();
- if (!scroll_past_end_of_file_enabled) {
- max_v_scroll -= get_visible_rows();
- max_v_scroll = CLAMP(max_v_scroll, 0, get_total_unhidden_rows());
- }
-
- if (target_v_scroll > max_v_scroll) {
- target_v_scroll = max_v_scroll;
- }
- scrolling = true;
- set_physics_process(true);
- } else {
- v_scroll->set_value(target_v_scroll);
- }
+ _scroll_down(3 * mb->get_factor());
}
if (mb->get_button_index() == BUTTON_WHEEL_LEFT) {
h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor()));
@@ -1973,6 +1937,19 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
+ const Ref<InputEventPanGesture> pan_gesture = p_gui_input;
+ if (pan_gesture.is_valid()) {
+
+ const real_t delta = pan_gesture->get_delta().y;
+ if (delta < 0) {
+ _scroll_up(-delta);
+ } else {
+ _scroll_down(delta);
+ }
+ h_scroll->set_value(h_scroll->get_value() + pan_gesture->get_delta().x * 100);
+ return;
+ }
+
Ref<InputEventMouseMotion> mm = p_gui_input;
if (mm.is_valid()) {
@@ -3066,6 +3043,50 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
+void TextEdit::_scroll_up(real_t p_delta) {
+
+ if (scrolling) {
+ target_v_scroll = (target_v_scroll - p_delta);
+ } else {
+ target_v_scroll = (v_scroll->get_value() - p_delta);
+ }
+
+ if (smooth_scroll_enabled) {
+ if (target_v_scroll <= 0) {
+ target_v_scroll = 0;
+ }
+ scrolling = true;
+ set_physics_process(true);
+ } else {
+ v_scroll->set_value(target_v_scroll);
+ }
+}
+
+void TextEdit::_scroll_down(real_t p_delta) {
+
+ if (scrolling) {
+ target_v_scroll = (target_v_scroll + p_delta);
+ } else {
+ target_v_scroll = (v_scroll->get_value() + p_delta);
+ }
+
+ if (smooth_scroll_enabled) {
+ int max_v_scroll = get_total_unhidden_rows();
+ if (!scroll_past_end_of_file_enabled) {
+ max_v_scroll -= get_visible_rows();
+ max_v_scroll = CLAMP(max_v_scroll, 0, get_total_unhidden_rows());
+ }
+
+ if (target_v_scroll > max_v_scroll) {
+ target_v_scroll = max_v_scroll;
+ }
+ scrolling = true;
+ set_physics_process(true);
+ } else {
+ v_scroll->set_value(target_v_scroll);
+ }
+}
+
void TextEdit::_pre_shift_selection() {
if (!selection.active || selection.selecting_mode == Selection::MODE_NONE) {
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index b1c7b14e58..bb9ca87d06 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -328,6 +328,9 @@ class TextEdit : public Control {
void _update_selection_mode_word();
void _update_selection_mode_line();
+ void _scroll_up(real_t p_delta);
+ void _scroll_down(real_t p_delta);
+
void _pre_shift_selection();
void _post_shift_selection();
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 749ff51f57..9213296c55 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -2612,6 +2612,12 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
} break;
}
}
+
+ Ref<InputEventPanGesture> pan_gesture = p_event;
+ if (pan_gesture.is_valid()) {
+
+ v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * pan_gesture->get_delta().y / 8);
+ }
}
bool Tree::edit_selected() {
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 0a02f471c1..1f539041fd 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -2013,6 +2013,30 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
}
+ Ref<InputEventGesture> gesture_event = p_event;
+ if (gesture_event.is_valid()) {
+
+ Size2 pos = gesture_event->get_position();
+
+ Control *over = _gui_find_control(pos);
+ if (over) {
+
+ if (over->can_process()) {
+
+ gesture_event = gesture_event->xformed_by(Transform2D()); //make a copy
+ if (over == gui.mouse_focus) {
+ pos = gui.focus_inv_xform.xform(pos);
+ } else {
+ pos = over->get_global_transform_with_canvas().affine_inverse().xform(pos);
+ }
+ gesture_event->set_position(pos);
+ _gui_call_input(over, gesture_event);
+ }
+ get_tree()->set_input_as_handled();
+ return;
+ }
+ }
+
Ref<InputEventScreenDrag> drag_event = p_event;
if (drag_event.is_valid()) {