diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 1085d34c4e4..36786425218 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -32,6 +32,7 @@ #include "editor/editor_node.h" #include "editor_scale.h" +#include "scene/gui/view_panner.h" #include "scene/resources/text_line.h" float AnimationBezierTrackEdit::_bezier_h_to_pixel(float p_h) { @@ -216,6 +217,9 @@ void AnimationBezierTrackEdit::_draw_line_clipped(const Vector2 &p_from, const V } void AnimationBezierTrackEdit::_notification(int p_what) { + if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { + panner->set_control_scheme((ViewPanner::ControlScheme)EDITOR_GET("interface/editors/animation_editors_panning_scheme").operator int()); + } if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_ENTER_TREE) { close_button->set_icon(get_theme_icon(SNAME("Close"), SNAME("EditorIcons"))); @@ -610,6 +614,11 @@ void AnimationBezierTrackEdit::_select_at_anim(const Ref &p_anim, int void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { ERR_FAIL_COND(p_event.is_null()); + if (panner->gui_input(p_event)) { + accept_event(); + return; + } + if (p_event->is_pressed()) { if (ED_GET_SHORTCUT("animation_editor/duplicate_selection")->matches_event(p_event)) { duplicate_selection(); @@ -623,40 +632,24 @@ void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { } Ref mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_DOWN) { - const float v_zoom_orig = v_zoom; - if (mb->is_command_pressed()) { - timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05); - } else { + if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed()) { + // Alternate zoom (doesn't affect timeline). + if (mb->get_button_index() == MouseButton::WHEEL_DOWN) { + const float v_zoom_orig = v_zoom; if (v_zoom < 100000) { v_zoom *= 1.2; } + v_scroll = v_scroll + (mb->get_position().y - get_size().y / 2) * (v_zoom - v_zoom_orig); + update(); } - v_scroll = v_scroll + (mb->get_position().y - get_size().y / 2) * (v_zoom - v_zoom_orig); - update(); - } - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) { - const float v_zoom_orig = v_zoom; - if (mb->is_command_pressed()) { - timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05); - } else { + if (mb->get_button_index() == MouseButton::WHEEL_UP) { + const float v_zoom_orig = v_zoom; if (v_zoom > 0.000001) { v_zoom /= 1.2; } - } - v_scroll = v_scroll + (mb->get_position().y - get_size().y / 2) * (v_zoom - v_zoom_orig); - update(); - } - - if (mb.is_valid() && mb->get_button_index() == MouseButton::MIDDLE) { - if (mb->is_pressed()) { - int x = mb->get_position().x - timeline->get_name_limit(); - panning_timeline_from = x / timeline->get_zoom_scale(); - panning_timeline = true; - panning_timeline_at = timeline->get_value(); - } else { - panning_timeline = false; + v_scroll = v_scroll + (mb->get_position().y - get_size().y / 2) * (v_zoom - v_zoom_orig); + update(); } } @@ -934,22 +927,6 @@ void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { } Ref mm = p_event; - if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE) { - v_scroll += mm->get_relative().y * v_zoom; - if (v_scroll > 100000) { - v_scroll = 100000; - } - if (v_scroll < -100000) { - v_scroll = -100000; - } - - int x = mm->get_position().x - timeline->get_name_limit(); - float ofs = x / timeline->get_zoom_scale(); - float diff = ofs - panning_timeline_from; - timeline->set_value(panning_timeline_at - diff); - - update(); - } if (moving_selection_attempt && mm.is_valid()) { if (!moving_selection) { moving_selection = true; @@ -1038,6 +1015,28 @@ void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { } } +void AnimationBezierTrackEdit::_scroll_callback(Vector2 p_scroll_vec) { + _pan_callback(-p_scroll_vec * 32); +} + +void AnimationBezierTrackEdit::_pan_callback(Vector2 p_scroll_vec) { + v_scroll += p_scroll_vec.y * v_zoom; + v_scroll = CLAMP(v_scroll, -100000, 100000); + timeline->set_value(timeline->get_value() - p_scroll_vec.x / timeline->get_zoom_scale()); + update(); +} + +void AnimationBezierTrackEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin) { + const float v_zoom_orig = v_zoom; + if (p_scroll_vec.y > 0) { + timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05); + } else { + timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05); + } + v_scroll = v_scroll + (p_origin.y - get_size().y / 2) * (v_zoom - v_zoom_orig); + update(); +} + void AnimationBezierTrackEdit::_menu_selected(int p_index) { switch (p_index) { case MENU_KEY_INSERT: { @@ -1171,6 +1170,11 @@ void AnimationBezierTrackEdit::_bind_methods() { } AnimationBezierTrackEdit::AnimationBezierTrackEdit() { + panner.instantiate(); + panner->set_callbacks(callable_mp(this, &AnimationBezierTrackEdit::_scroll_callback), callable_mp(this, &AnimationBezierTrackEdit::_pan_callback), callable_mp(this, &AnimationBezierTrackEdit::_zoom_callback)); + panner->set_disable_rmb(true); + panner->set_control_scheme(ViewPanner::SCROLL_PANS); + play_position = memnew(Control); play_position->set_mouse_filter(MOUSE_FILTER_PASS); add_child(play_position); diff --git a/editor/animation_bezier_editor.h b/editor/animation_bezier_editor.h index d9bc85a258d..6a5b97a7da7 100644 --- a/editor/animation_bezier_editor.h +++ b/editor/animation_bezier_editor.h @@ -33,6 +33,8 @@ #include "animation_track_editor.h" +class ViewPanner; + class AnimationBezierTrackEdit : public Control { GDCLASS(AnimationBezierTrackEdit, Control); @@ -123,9 +125,10 @@ class AnimationBezierTrackEdit : public Control { Set selection; - bool panning_timeline = false; - float panning_timeline_from; - float panning_timeline_at; + Ref panner; + void _scroll_callback(Vector2 p_scroll_vec); + void _pan_callback(Vector2 p_scroll_vec); + void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin); void _draw_line_clipped(const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, int p_clip_left, int p_clip_right); void _draw_track(int p_track, const Color &p_color); diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index f4e719f5527..13e9d587447 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -32,12 +32,12 @@ #include "animation_track_editor_plugins.h" #include "core/input/input.h" -#include "core/os/keyboard.h" #include "editor/animation_bezier_editor.h" #include "editor/plugins/animation_player_editor_plugin.h" #include "editor_node.h" #include "editor_scale.h" #include "scene/animation/animation_player.h" +#include "scene/gui/view_panner.h" #include "scene/main/window.h" #include "scene/scene_string_names.h" #include "servers/audio/audio_stream.h" @@ -1458,6 +1458,10 @@ int AnimationTimelineEdit::get_name_limit() const { } void AnimationTimelineEdit::_notification(int p_what) { + if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { + panner->set_control_scheme((ViewPanner::ControlScheme)EDITOR_GET("interface/editors/animation_editors_panning_scheme").operator int()); + } + if (p_what == NOTIFICATION_ENTER_TREE) { add_track->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); loop->set_icon(get_theme_icon(SNAME("Loop"), SNAME("EditorIcons"))); @@ -1760,18 +1764,13 @@ void AnimationTimelineEdit::_play_position_draw() { void AnimationTimelineEdit::gui_input(const Ref &p_event) { ERR_FAIL_COND(p_event.is_null()); + if (panner->gui_input(p_event)) { + accept_event(); + return; + } + const Ref mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) { - get_zoom()->set_value(get_zoom()->get_value() * 1.05); - accept_event(); - } - - if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MouseButton::WHEEL_DOWN) { - get_zoom()->set_value(get_zoom()->get_value() / 1.05); - accept_event(); - } - if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) { if (track_edit) { track_edit->get_editor()->goto_prev_step(true); @@ -1796,29 +1795,19 @@ void AnimationTimelineEdit::gui_input(const Ref &p_event) { dragging_hsize = false; } if (mb.is_valid() && mb->get_position().x > get_name_limit() && mb->get_position().x < (get_size().width - get_buttons_width())) { - if (!panning_timeline && mb->get_button_index() == MouseButton::LEFT) { + if (!panner->is_panning() && mb->get_button_index() == MouseButton::LEFT) { int x = mb->get_position().x - get_name_limit(); float ofs = x / get_zoom_scale() + get_value(); emit_signal(SNAME("timeline_changed"), ofs, false, Input::get_singleton()->is_key_pressed(Key::ALT)); dragging_timeline = true; } - if (!dragging_timeline && mb->get_button_index() == MouseButton::MIDDLE) { - int x = mb->get_position().x - get_name_limit(); - panning_timeline_from = x / get_zoom_scale(); - panning_timeline = true; - panning_timeline_at = get_value(); - } } if (dragging_timeline && mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed()) { dragging_timeline = false; } - if (panning_timeline && mb.is_valid() && mb->get_button_index() == MouseButton::MIDDLE && !mb->is_pressed()) { - panning_timeline = false; - } - Ref mm = p_event; if (mm.is_valid()) { @@ -1839,17 +1828,29 @@ void AnimationTimelineEdit::gui_input(const Ref &p_event) { if (dragging_timeline) { int x = mm->get_position().x - get_name_limit(); float ofs = x / get_zoom_scale() + get_value(); - emit_signal(SNAME("timeline_changed"), ofs, false, Input::get_singleton()->is_key_pressed(Key::ALT)); - } - if (panning_timeline) { - int x = mm->get_position().x - get_name_limit(); - float ofs = x / get_zoom_scale(); - float diff = ofs - panning_timeline_from; - set_value(panning_timeline_at - diff); + emit_signal(SNAME("timeline_changed"), ofs, false, mm->is_alt_pressed()); } } } +void AnimationTimelineEdit::_scroll_callback(Vector2 p_scroll_vec) { + // Timeline has no vertical scroll, so we change it to horizontal. + p_scroll_vec.x += p_scroll_vec.y; + _pan_callback(-p_scroll_vec * 32); +} + +void AnimationTimelineEdit::_pan_callback(Vector2 p_scroll_vec) { + set_value(get_value() - p_scroll_vec.x / get_zoom_scale()); +} + +void AnimationTimelineEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin) { + if (p_scroll_vec.y < 0) { + get_zoom()->set_value(get_zoom()->get_value() * 1.05); + } else { + get_zoom()->set_value(get_zoom()->get_value() / 1.05); + } +} + void AnimationTimelineEdit::set_use_fps(bool p_use_fps) { use_fps = p_use_fps; update_values(); @@ -1926,10 +1927,14 @@ AnimationTimelineEdit::AnimationTimelineEdit() { add_track->get_popup()->connect("index_pressed", callable_mp(this, &AnimationTimelineEdit::_track_added)); len_hb->hide(); - panning_timeline = false; dragging_timeline = false; dragging_hsize = false; + panner.instantiate(); + panner->set_callbacks(callable_mp(this, &AnimationTimelineEdit::_scroll_callback), callable_mp(this, &AnimationTimelineEdit::_pan_callback), callable_mp(this, &AnimationTimelineEdit::_zoom_callback)); + panner->set_disable_rmb(true); + panner->set_control_scheme(ViewPanner::SCROLL_PANS); + set_layout_direction(Control::LAYOUT_DIRECTION_LTR); } @@ -4500,6 +4505,10 @@ MenuButton *AnimationTrackEditor::get_edit_menu() { } void AnimationTrackEditor::_notification(int p_what) { + if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { + panner->set_control_scheme((ViewPanner::ControlScheme)EDITOR_GET("interface/editors/animation_editors_panning_scheme").operator int()); + } + if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_ENTER_TREE) { zoom_icon->set_texture(get_theme_icon(SNAME("Zoom"), SNAME("EditorIcons"))); snap->set_icon(get_theme_icon(SNAME("Snap"), SNAME("EditorIcons"))); @@ -5212,18 +5221,13 @@ void AnimationTrackEditor::_box_selection_draw() { } void AnimationTrackEditor::_scroll_input(const Ref &p_event) { + if (panner->gui_input(p_event)) { + scroll->accept_event(); + return; + } + Ref mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) { - timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05); - scroll->accept_event(); - } - - if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed() && mb->get_button_index() == MouseButton::WHEEL_DOWN) { - timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05); - scroll->accept_event(); - } - if (mb.is_valid() && mb->is_pressed() && mb->is_alt_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) { goto_prev_step(true); scroll->accept_event(); @@ -5262,10 +5266,6 @@ void AnimationTrackEditor::_scroll_input(const Ref &p_event) { Ref mm = p_event; - if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE) { - timeline->set_value(timeline->get_value() - mm->get_relative().x / timeline->get_zoom_scale()); - } - if (mm.is_valid() && box_selecting) { if ((mm->get_button_mask() & MouseButton::MASK_LEFT) == MouseButton::NONE) { // No longer. @@ -5302,6 +5302,23 @@ void AnimationTrackEditor::_scroll_input(const Ref &p_event) { } } +void AnimationTrackEditor::_scroll_callback(Vector2 p_scroll_vec) { + _pan_callback(-p_scroll_vec * 32); +} + +void AnimationTrackEditor::_pan_callback(Vector2 p_scroll_vec) { + timeline->set_value(timeline->get_value() - p_scroll_vec.x / timeline->get_zoom_scale()); + scroll->set_v_scroll(scroll->get_v_scroll() - p_scroll_vec.y); +} + +void AnimationTrackEditor::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin) { + if (p_scroll_vec.y < 0) { + timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() * 1.05); + } else { + timeline->get_zoom()->set_value(timeline->get_zoom()->get_value() / 1.05); + } +} + void AnimationTrackEditor::_cancel_bezier_edit() { bezier_edit->hide(); scroll->show(); @@ -6088,6 +6105,11 @@ AnimationTrackEditor::AnimationTrackEditor() { timeline->connect("value_changed", callable_mp(this, &AnimationTrackEditor::_timeline_value_changed)); timeline->connect("length_changed", callable_mp(this, &AnimationTrackEditor::_update_length)); + panner.instantiate(); + panner->set_callbacks(callable_mp(this, &AnimationTrackEditor::_scroll_callback), callable_mp(this, &AnimationTrackEditor::_pan_callback), callable_mp(this, &AnimationTrackEditor::_zoom_callback)); + panner->set_disable_rmb(true); + panner->set_control_scheme(ViewPanner::SCROLL_PANS); + scroll = memnew(ScrollContainer); timeline_vbox->add_child(scroll); scroll->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index b5d44bc0d3f..2a2b20ada99 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -48,8 +48,8 @@ #include "scene_tree_editor.h" class AnimationPlayer; - class AnimationTrackEdit; +class ViewPanner; class AnimationTimelineEdit : public Range { GDCLASS(AnimationTimelineEdit, Range); @@ -81,9 +81,11 @@ class AnimationTimelineEdit : public Range { bool editing; bool use_fps; - bool panning_timeline; - float panning_timeline_from; - float panning_timeline_at; + Ref panner; + void _scroll_callback(Vector2 p_scroll_vec); + void _pan_callback(Vector2 p_scroll_vec); + void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin); + bool dragging_timeline; bool dragging_hsize; float dragging_hsize_from; @@ -374,6 +376,11 @@ class AnimationTrackEditor : public VBoxContainer { PropertyInfo _find_hint_for_track(int p_idx, NodePath &r_base_path, Variant *r_current_val = nullptr); + Ref panner; + void _scroll_callback(Vector2 p_scroll_vec); + void _pan_callback(Vector2 p_scroll_vec); + void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin); + void _timeline_value_changed(double); float insert_key_from_track_call_ofs; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index a8cb2e791c7..9b4b99b32d8 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -6039,8 +6039,10 @@ EditorNode::EditorNode() { EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle", PROPERTY_USAGE_DEFAULT)); EDITOR_DEF("run/auto_save/save_before_running", true); EDITOR_DEF("interface/editors/sub_editor_panning_scheme", 0); + EDITOR_DEF("interface/editors/animation_editors_panning_scheme", 1); // Should be in sync with ControlScheme in ViewPanner. EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/editors/sub_editor_panning_scheme", PROPERTY_HINT_ENUM, "Scroll Zooms,Scroll Pans", PROPERTY_USAGE_DEFAULT)); + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/editors/animation_editors_panning_scheme", PROPERTY_HINT_ENUM, "Scroll Zooms,Scroll Pans", PROPERTY_USAGE_DEFAULT)); const Vector textfile_ext = ((String)(EditorSettings::get_singleton()->get("docks/filesystem/textfile_extensions"))).split(",", false); for (const String &E : textfile_ext) { diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 9ebdede4e9f..10e2f5f1d05 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -732,6 +732,10 @@ void AnimationNodeBlendTreeEditor::_removed_from_graph() { } void AnimationNodeBlendTreeEditor::_notification(int p_what) { + if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { + graph->set_panning_scheme((GraphEdit::PanningScheme)EDITOR_GET("interface/editors/sub_editor_panning_scheme").operator int()); + } + if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index e272b96778b..c6d1d99c087 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -38,6 +38,8 @@ #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "scene/2d/skeleton_2d.h" +#include "scene/gui/scroll_container.h" +#include "scene/gui/view_panner.h" Node2D *Polygon2DEditor::_get_node() const { return node; @@ -63,9 +65,8 @@ int Polygon2DEditor::_get_polygon_count() const { void Polygon2DEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: - case NOTIFICATION_THEME_CHANGED: { - uv_edit_draw->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); - bone_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + uv_panner->set_control_scheme((ViewPanner::ControlScheme)EDITOR_GET("interface/editors/sub_editor_panning_scheme").operator int()); } break; case NOTIFICATION_READY: { button_uv->set_icon(get_theme_icon(SNAME("Uv"), SNAME("EditorIcons"))); @@ -88,6 +89,11 @@ void Polygon2DEditor::_notification(int p_what) { uv_vscroll->set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE); uv_hscroll->set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE); + [[fallthrough]]; + } + case NOTIFICATION_THEME_CHANGED: { + uv_edit_draw->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + bone_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); } break; case NOTIFICATION_VISIBILITY_CHANGED: { if (!is_visible()) { @@ -440,6 +446,11 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { return; } + if (uv_panner->gui_input(p_input)) { + accept_event(); + return; + } + Transform2D mtx; mtx.elements[2] = -uv_draw_ofs; mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom)); @@ -767,23 +778,13 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { } uv_edit_draw->update(); - - } else if (mb->get_button_index() == MouseButton::WHEEL_UP && mb->is_pressed()) { - uv_zoom->set_value(uv_zoom->get_value() / (1 - (0.1 * mb->get_factor()))); - } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN && mb->is_pressed()) { - uv_zoom->set_value(uv_zoom->get_value() * (1 - (0.1 * mb->get_factor()))); } } Ref mm = p_input; if (mm.is_valid()) { - if ((mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE || Input::get_singleton()->is_key_pressed(Key::SPACE)) { - Vector2 drag = mm->get_relative(); - uv_hscroll->set_value(uv_hscroll->get_value() - drag.x); - uv_vscroll->set_value(uv_vscroll->get_value() - drag.y); - - } else if (uv_drag) { + if (uv_drag) { Vector2 uv_drag_to = mm->get_position(); uv_drag_to = snap_point(uv_drag_to); // FIXME: Only works correctly with 'UV_MODE_EDIT_POINT', it's imprecise with the rest. Vector2 drag = mtx.affine_inverse().xform(uv_drag_to) - mtx.affine_inverse().xform(uv_drag_from); @@ -925,6 +926,23 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { } } +void Polygon2DEditor::_uv_scroll_callback(Vector2 p_scroll_vec) { + _uv_pan_callback(-p_scroll_vec * 32); +} + +void Polygon2DEditor::_uv_pan_callback(Vector2 p_scroll_vec) { + uv_hscroll->set_value(uv_hscroll->get_value() - p_scroll_vec.x); + uv_vscroll->set_value(uv_vscroll->get_value() - p_scroll_vec.y); +} + +void Polygon2DEditor::_uv_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin) { + if (p_scroll_vec.y < 0) { + uv_zoom->set_value(uv_zoom->get_value() / (1 - (0.1 * Math::abs(p_scroll_vec.y)))); + } else { + uv_zoom->set_value(uv_zoom->get_value() * (1 - (0.1 * Math::abs(p_scroll_vec.y)))); + } +} + void Polygon2DEditor::_uv_scroll_changed(real_t) { if (updating_uv_scroll) { return; @@ -1262,6 +1280,10 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_edit_mode[2]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select), varray(2)); uv_edit_mode[3]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select), varray(3)); + uv_panner.instantiate(); + uv_panner->set_callbacks(callable_mp(this, &Polygon2DEditor::_uv_scroll_callback), callable_mp(this, &Polygon2DEditor::_uv_pan_callback), callable_mp(this, &Polygon2DEditor::_uv_zoom_callback)); + uv_panner->set_disable_rmb(true); + uv_mode_hb->add_child(memnew(VSeparator)); uv_main_vb->add_child(uv_mode_hb); diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index a04179dcada..959c230d7b8 100644 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h @@ -32,7 +32,9 @@ #define POLYGON_2D_EDITOR_PLUGIN_H #include "editor/plugins/abstract_polygon_2d_editor.h" -#include "scene/gui/scroll_container.h" + +class ViewPanner; +class ScrollContainer; class Polygon2DEditor : public AbstractPolygon2DEditor { GDCLASS(Polygon2DEditor, AbstractPolygon2DEditor); @@ -78,6 +80,11 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { MenuButton *uv_menu; TextureRect *uv_icon_zoom; + Ref uv_panner; + void _uv_scroll_callback(Vector2 p_scroll_vec); + void _uv_pan_callback(Vector2 p_scroll_vec); + void _uv_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin); + VBoxContainer *bone_scroll_main_vb; ScrollContainer *bone_scroll; VBoxContainer *bone_scroll_vb; diff --git a/scene/gui/view_panner.cpp b/scene/gui/view_panner.cpp index 375b3732a49..ba5e8d4a170 100644 --- a/scene/gui/view_panner.cpp +++ b/scene/gui/view_panner.cpp @@ -36,11 +36,18 @@ bool ViewPanner::gui_input(const Ref &p_event, Rect2 p_canvas_rect) { Ref mb = p_event; if (mb.is_valid()) { + // Alt modifier is unused, so ignore such events. + if (mb->is_alt_pressed()) { + return false; + } + Vector2i scroll_vec = Vector2((mb->get_button_index() == MouseButton::WHEEL_RIGHT) - (mb->get_button_index() == MouseButton::WHEEL_LEFT), (mb->get_button_index() == MouseButton::WHEEL_DOWN) - (mb->get_button_index() == MouseButton::WHEEL_UP)); if (scroll_vec != Vector2()) { if (control_scheme == SCROLL_PANS) { if (mb->is_ctrl_pressed()) { + scroll_vec.y *= mb->get_factor(); callback_helper(zoom_callback, scroll_vec, mb->get_position()); + return true; } else { Vector2 panning; if (mb->is_shift_pressed()) { @@ -51,7 +58,6 @@ bool ViewPanner::gui_input(const Ref &p_event, Rect2 p_canvas_rect) panning.x += mb->get_factor() * scroll_vec.x; } callback_helper(scroll_callback, panning); - return true; } } else { @@ -65,16 +71,16 @@ bool ViewPanner::gui_input(const Ref &p_event, Rect2 p_canvas_rect) panning.x += mb->get_factor() * scroll_vec.x; } callback_helper(scroll_callback, panning); - return true; } else if (!mb->is_shift_pressed()) { + scroll_vec.y *= mb->get_factor(); callback_helper(zoom_callback, scroll_vec, mb->get_position()); return true; } } } - if (mb->get_button_index() == MouseButton::MIDDLE || (mb->get_button_index() == MouseButton::RIGHT && !disable_rmb) || (mb->get_button_index() == MouseButton::LEFT && (Input::get_singleton()->is_key_pressed(Key::SPACE) || !mb->is_pressed()))) { + if (mb->get_button_index() == MouseButton::MIDDLE || (mb->get_button_index() == MouseButton::RIGHT && !disable_rmb) || (mb->get_button_index() == MouseButton::LEFT && (Input::get_singleton()->is_key_pressed(Key::SPACE) || (is_dragging && !mb->is_pressed())))) { if (mb->is_pressed()) { is_dragging = true; } else { diff --git a/scene/gui/view_panner.h b/scene/gui/view_panner.h index e083d83de49..0a92cb3dfd3 100644 --- a/scene/gui/view_panner.h +++ b/scene/gui/view_panner.h @@ -38,6 +38,13 @@ class InputEvent; class ViewPanner : public RefCounted { GDCLASS(ViewPanner, RefCounted); +public: + enum ControlScheme { + SCROLL_ZOOMS, + SCROLL_PANS, + }; + +private: bool is_dragging = false; bool disable_rmb = false; @@ -46,17 +53,15 @@ class ViewPanner : public RefCounted { Callable zoom_callback; void callback_helper(Callable p_callback, Vector2 p_arg1, Vector2 p_arg2 = Vector2()); - -public: - enum ControlScheme { - SCROLL_ZOOMS, - SCROLL_PANS, - }; ControlScheme control_scheme = SCROLL_ZOOMS; +public: void set_callbacks(Callable p_scroll_callback, Callable p_pan_callback, Callable p_zoom_callback); void set_control_scheme(ControlScheme p_scheme); void set_disable_rmb(bool p_disable); + + bool is_panning() const { return is_dragging; } + bool gui_input(const Ref &p_ev, Rect2 p_canvas_rect = Rect2()); };