From 304a1f5b5a3ce6975952f5cd22d688a246367790 Mon Sep 17 00:00:00 2001 From: toger5 Date: Wed, 22 Feb 2017 00:45:31 +0200 Subject: [PATCH] Implemented scrolling factor for smooth trackpad scrolling Working platforms platform: OSX, Windows. Support for almost all ui elements, including project list. --- core/os/input_event.h | 6 +- editor/animation_editor.cpp | 18 +++++- editor/plugins/canvas_item_editor_plugin.cpp | 4 +- editor/plugins/polygon_2d_editor_plugin.cpp | 4 +- modules/gridmap/grid_map_editor_plugin.cpp | 4 +- platform/osx/os_osx.mm | 62 ++++++++------------ platform/windows/os_windows.cpp | 7 ++- scene/gui/graph_edit.cpp | 12 ++++ scene/gui/item_list.cpp | 4 ++ scene/gui/popup_menu.cpp | 4 +- scene/gui/rich_text_label.cpp | 6 +- scene/gui/scroll_container.cpp | 30 +++++++--- scene/gui/spin_box.cpp | 6 +- scene/gui/text_edit.cpp | 18 ++++-- scene/gui/tree.cpp | 4 +- 15 files changed, 118 insertions(+), 71 deletions(-) diff --git a/core/os/input_event.h b/core/os/input_event.h index eb5c5685e567..93cceac27c4b 100644 --- a/core/os/input_event.h +++ b/core/os/input_event.h @@ -188,6 +188,7 @@ struct InputEventMouse { struct InputEventMouseButton : public InputEventMouse { + double factor; int button_index; bool pressed; //otherwise released bool doubleclick; //last even less than doubleclick time @@ -272,7 +273,10 @@ struct InputEvent { InputEvent xform_by(const Transform2D &p_xform) const; bool operator==(const InputEvent &p_event) const; operator String() const; - InputEvent() { zeromem(this, sizeof(InputEvent)); } + InputEvent() { + zeromem(this, sizeof(InputEvent)); + mouse_button.factor = 1; + } }; #endif diff --git a/editor/animation_editor.cpp b/editor/animation_editor.cpp index 63ed27e60c2c..1e6562fcf2b0 100644 --- a/editor/animation_editor.cpp +++ b/editor/animation_editor.cpp @@ -1871,21 +1871,35 @@ void AnimationKeyEditor::_track_editor_gui_input(const InputEvent &p_input) { if (mb.button_index == BUTTON_WHEEL_UP && mb.pressed) { if (mb.mod.command) { + zoom->set_value(zoom->get_value() + zoom->get_step()); } else { - v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() / 8); + + v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * mb.factor / 8); } } if (mb.button_index == BUTTON_WHEEL_DOWN && mb.pressed) { if (mb.mod.command) { + zoom->set_value(zoom->get_value() - zoom->get_step()); } else { - v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() / 8); + + v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * mb.factor / 8); } } + if (mb.button_index == BUTTON_WHEEL_RIGHT && mb.pressed) { + + h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * mb.factor / 8); + } + + if (mb.button_index == BUTTON_WHEEL_LEFT && mb.pressed) { + + v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * mb.factor / 8); + } + if (mb.button_index == BUTTON_RIGHT && mb.pressed) { Point2 mpos = Point2(mb.x, mb.y) - ofs; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 430a5adeb1ab..27be6ea8f032 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -1049,7 +1049,7 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) { return; float prev_zoom = zoom; - zoom = zoom * 0.95; + zoom = zoom * (1 - (0.05 * b.factor)); { Point2 ofs(b.x, b.y); ofs = ofs / prev_zoom - ofs / zoom; @@ -1067,7 +1067,7 @@ void CanvasItemEditor::_viewport_gui_input(const InputEvent &p_event) { return; float prev_zoom = zoom; - zoom = zoom * (1.0 / 0.95); + zoom = zoom * ((0.95 + (0.05 * b.factor)) / 0.95); { Point2 ofs(b.x, b.y); ofs = ofs / prev_zoom - ofs / zoom; diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index e84e78258090..896a26c8e8bf 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -522,10 +522,10 @@ void Polygon2DEditor::_uv_input(const InputEvent &p_input) { } else if (mb.button_index == BUTTON_WHEEL_UP && mb.pressed) { - uv_zoom->set_value(uv_zoom->get_value() / 0.9); + uv_zoom->set_value(uv_zoom->get_value() / (1 - (0.1 * mb.factor))); } else if (mb.button_index == BUTTON_WHEEL_DOWN && mb.pressed) { - uv_zoom->set_value(uv_zoom->get_value() * 0.9); + uv_zoom->set_value(uv_zoom->get_value() * (1 - (0.1 * mb.factor))); } } else if (p_input.type == InputEvent::MOUSE_MOTION) { diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 39fe0a16758b..d8993710a4b1 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -519,12 +519,12 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const InputEve if (p_event.mouse_button.button_index == BUTTON_WHEEL_UP && (p_event.mouse_button.mod.command || p_event.mouse_button.mod.shift)) { if (p_event.mouse_button.pressed) - floor->set_value(floor->get_value() + 1); + floor->set_value(floor->get_value() + p_event.mouse_button.factor); return true; //eaten } else if (p_event.mouse_button.button_index == BUTTON_WHEEL_DOWN && (p_event.mouse_button.mod.command || p_event.mouse_button.mod.shift)) { if (p_event.mouse_button.pressed) - floor->set_value(floor->get_value() - 1); + floor->set_value(floor->get_value() - p_event.mouse_button.factor); return true; } diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index c6c2e6dab19e..7a914a88fbbf 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -788,6 +788,22 @@ static int translateKey(unsigned int key) { */ } +inline void sendScrollEvent(int button, double factor) { + InputEvent ev; + ev.type = InputEvent::MOUSE_BUTTON; + ev.mouse_button.button_index = button; + ev.mouse_button.factor = factor; + ev.mouse_button.pressed = true; + ev.mouse_button.x = mouse_x; + ev.mouse_button.y = mouse_y; + ev.mouse_button.global_x = mouse_x; + ev.mouse_button.global_y = mouse_y; + ev.mouse_button.button_mask = button_mask; + OS_OSX::singleton->push_input(ev); + ev.mouse_button.pressed = false; + OS_OSX::singleton->push_input(ev); +} + - (void)scrollWheel:(NSEvent *)event { double deltaX, deltaY; @@ -797,48 +813,21 @@ static int translateKey(unsigned int key) { deltaY = [event scrollingDeltaY]; if ([event hasPreciseScrollingDeltas]) { - deltaX *= 0.1; - deltaY *= 0.1; + deltaX *= 0.03; + deltaY *= 0.03; } - } else { + } else +#endif // MAC_OS_X_VERSION_MAX_ALLOWED + { deltaX = [event deltaX]; deltaY = [event deltaY]; } -#else - deltaX = [event deltaX]; - deltaY = [event deltaY]; -#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ - - if (fabs(deltaY)) { - - InputEvent ev; - ev.type = InputEvent::MOUSE_BUTTON; - ev.mouse_button.button_index = deltaY > 0 ? BUTTON_WHEEL_UP : BUTTON_WHEEL_DOWN; - ev.mouse_button.pressed = true; - ev.mouse_button.x = mouse_x; - ev.mouse_button.y = mouse_y; - ev.mouse_button.global_x = mouse_x; - ev.mouse_button.global_y = mouse_y; - ev.mouse_button.button_mask = button_mask; - OS_OSX::singleton->push_input(ev); - ev.mouse_button.pressed = false; - OS_OSX::singleton->push_input(ev); - } if (fabs(deltaX)) { - - InputEvent ev; - ev.type = InputEvent::MOUSE_BUTTON; - ev.mouse_button.button_index = deltaX < 0 ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_LEFT; - ev.mouse_button.pressed = true; - ev.mouse_button.x = mouse_x; - ev.mouse_button.y = mouse_y; - ev.mouse_button.global_x = mouse_x; - ev.mouse_button.global_y = mouse_y; - ev.mouse_button.button_mask = button_mask; - OS_OSX::singleton->push_input(ev); - ev.mouse_button.pressed = false; - OS_OSX::singleton->push_input(ev); + sendScrollEvent(0 > deltaX ? BUTTON_WHEEL_RIGHT : BUTTON_WHEEL_LEFT, fabs(deltaX * 0.3)); + } + if (fabs(deltaY)) { + sendScrollEvent(0 < deltaY ? BUTTON_WHEEL_UP : BUTTON_WHEEL_DOWN, fabs(deltaY * 0.3)); } } @@ -1630,7 +1619,6 @@ void OS_OSX::process_events() { void OS_OSX::push_input(const InputEvent &p_event) { InputEvent ev = p_event; - //print_line("EV: "+String(ev)); input->parse_input_event(ev); } diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 99b689091324..9dee2da21ead 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -509,10 +509,13 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (!motion) return 0; - if (motion < 0) + if (motion < 0) { mb.button_index = BUTTON_WHEEL_LEFT; - else + mb.factor = fabs((double)motion / (double)WHEEL_DELTA); + } else { mb.button_index = BUTTON_WHEEL_RIGHT; + mb.factor = fabs((double)motion / (double)WHEEL_DELTA); + } } break; /* case WM_XBUTTONDOWN: { diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 0bc48677dd3a..d5df3bac6730 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -962,6 +962,18 @@ void GraphEdit::_gui_input(const InputEvent &p_ev) { //too difficult to get right //set_zoom(zoom/ZOOM_SCALE); } + if (b.button_index == BUTTON_WHEEL_UP) { + h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * b.factor / 8); + } + if (b.button_index == BUTTON_WHEEL_DOWN) { + h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * b.factor / 8); + } + if (b.button_index == BUTTON_WHEEL_RIGHT) { + v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b.factor / 8); + } + if (b.button_index == BUTTON_WHEEL_LEFT) { + v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b.factor / 8); + } } if (p_ev.type == InputEvent::KEY && p_ev.key.scancode == KEY_D && p_ev.key.pressed && p_ev.key.mod.command) { diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 1dc4230d2a87..b79104ba392d 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -533,10 +533,14 @@ void ItemList::_gui_input(const InputEvent &p_event) { } if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == BUTTON_WHEEL_UP && p_event.mouse_button.pressed) { + scroll_bar->set_value(scroll_bar->get_value() - scroll_bar->get_page() * p_event.mouse_button.factor / 8); + scroll_bar->set_value(scroll_bar->get_value() - scroll_bar->get_page() / 8); } if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == BUTTON_WHEEL_DOWN && p_event.mouse_button.pressed) { + scroll_bar->set_value(scroll_bar->get_value() + scroll_bar->get_page() * p_event.mouse_button.factor / 8); + scroll_bar->set_value(scroll_bar->get_value() + scroll_bar->get_page() / 8); } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 6ac6eac655f2..9b9dd820b2bf 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -273,7 +273,7 @@ void PopupMenu::_gui_input(const InputEvent &p_event) { Point2 pos = get_position(); int s = (vseparation + font->get_height()) * 3; - pos.y -= s; + pos.y -= (s * b.factor); set_position(pos); //update hover @@ -293,7 +293,7 @@ void PopupMenu::_gui_input(const InputEvent &p_event) { Point2 pos = get_position(); int s = (vseparation + font->get_height()) * 3; - pos.y += s; + pos.y += (s * b.factor); set_position(pos); //update hover diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index e5a17298e4e8..6e5f218a6675 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -780,12 +780,14 @@ void RichTextLabel::_gui_input(InputEvent p_event) { if (b.button_index == BUTTON_WHEEL_UP) { if (scroll_active) - vscroll->set_value(vscroll->get_value() - vscroll->get_page() / 8); + + vscroll->set_value(vscroll->get_value() - vscroll->get_page() * b.factor * 0.5 / 8); } if (b.button_index == BUTTON_WHEEL_DOWN) { if (scroll_active) - vscroll->set_value(vscroll->get_value() + vscroll->get_page() / 8); + + vscroll->set_value(vscroll->get_value() + vscroll->get_page() * b.factor * 0.5 / 8); } } break; case InputEvent::KEY: { diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 9146fa939315..a89c2b27c9f7 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -85,20 +85,32 @@ void ScrollContainer::_gui_input(const InputEvent &p_gui_input) { const InputEventMouseButton &mb = p_gui_input.mouse_button; if (mb.button_index == BUTTON_WHEEL_UP && mb.pressed) { - if (h_scroll->is_visible_in_tree() && !v_scroll->is_visible_in_tree()) { - // only horizontal is enabled, scroll horizontally - h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() / 8); + // only horizontal is enabled, scroll horizontally + if (h_scroll->is_visible() && !v_scroll->is_visible()) { + h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() / 8 * mb.factor); } else if (v_scroll->is_visible_in_tree()) { - v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() / 8); + v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() / 8 * mb.factor); } } if (mb.button_index == BUTTON_WHEEL_DOWN && mb.pressed) { - if (h_scroll->is_visible_in_tree() && !v_scroll->is_visible_in_tree()) { - // only horizontal is enabled, scroll horizontally - h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() / 8); - } else if (v_scroll->is_visible_in_tree()) { - v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() / 8); + // only horizontal is enabled, scroll horizontally + if (h_scroll->is_visible() && !v_scroll->is_visible()) { + h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() / 8 * mb.factor); + } else if (v_scroll->is_visible()) { + v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() / 8 * mb.factor); + } + } + + if (mb.button_index == BUTTON_WHEEL_LEFT && mb.pressed) { + if (h_scroll->is_visible_in_tree()) { + h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * mb.factor / 8); + } + } + + if (mb.button_index == BUTTON_WHEEL_RIGHT && mb.pressed) { + if (h_scroll->is_visible_in_tree()) { + h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * mb.factor / 8); } } diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index ba8ca6372122..83d535a2e74a 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -115,13 +115,15 @@ void SpinBox::_gui_input(const InputEvent &p_event) { } break; case BUTTON_WHEEL_UP: { if (line_edit->has_focus()) { - set_value(get_value() + get_step()); + + set_value(get_value() + get_step() * mb.factor); accept_event(); } } break; case BUTTON_WHEEL_DOWN: { if (line_edit->has_focus()) { - set_value(get_value() - get_step()); + + set_value(get_value() - get_step() * mb.factor); accept_event(); } } break; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 3c8545bd7564..fb986cfb978d 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -334,7 +334,10 @@ void TextEdit::_update_scrollbars() { v_scroll->show(); v_scroll->set_max(total_rows); v_scroll->set_page(visible_rows); - v_scroll->set_value(cursor.line_ofs); + + if (fabs(v_scroll->get_value() - (double)cursor.line_ofs) >= 1) { + v_scroll->set_value(cursor.line_ofs); + } } else { cursor.line_ofs = 0; @@ -346,7 +349,9 @@ void TextEdit::_update_scrollbars() { h_scroll->show(); h_scroll->set_max(total_width); h_scroll->set_page(visible_width); - h_scroll->set_value(cursor.x_ofs); + if (fabs(h_scroll->get_value() - (double)cursor.x_ofs) >= 1) { + h_scroll->set_value(cursor.x_ofs); + } } else { @@ -1480,17 +1485,18 @@ void TextEdit::_gui_input(const InputEvent &p_gui_input) { } if (mb.pressed) { + if (mb.button_index == BUTTON_WHEEL_UP && !mb.mod.command) { - v_scroll->set_value(v_scroll->get_value() - 3); + v_scroll->set_value(v_scroll->get_value() - (3 * mb.factor)); } if (mb.button_index == BUTTON_WHEEL_DOWN && !mb.mod.command) { - v_scroll->set_value(v_scroll->get_value() + 3); + v_scroll->set_value(v_scroll->get_value() + (3 * mb.factor)); } if (mb.button_index == BUTTON_WHEEL_LEFT) { - h_scroll->set_value(h_scroll->get_value() - 3); + h_scroll->set_value(h_scroll->get_value() - (100 * mb.factor)); } if (mb.button_index == BUTTON_WHEEL_RIGHT) { - h_scroll->set_value(h_scroll->get_value() + 3); + h_scroll->set_value(h_scroll->get_value() + (100 * mb.factor)); } if (mb.button_index == BUTTON_LEFT) { diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 258e6c9a9f7f..67c97c2e5277 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2341,11 +2341,11 @@ void Tree::_gui_input(InputEvent p_event) { } break; case BUTTON_WHEEL_UP: { - v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() / 8); + v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b.factor / 8); } break; case BUTTON_WHEEL_DOWN: { - v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() / 8); + v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b.factor / 8); } break; }